how to use spreadsheet gem in rails 4? - ruby-on-rails

Currently I am upgrading my Rails app from rails 3 to rails 4 and i am using spreadsheet(0.7.1)
after running server I got undefined method `send_file' for main::object
this is my code:
def financial_export_excel
book = Spreadsheet::Workbook.new
sheet = book.create_worksheet
sheet.merge_cells(5, 0, 6, 0)
sheet.merge_cells(5, 1, 6, 1)
sheet.merge_cells(5, 2, 6, 2)
sheet.merge_cells(5, 3, 6, 3)
sheet.merge_cells(5, 4, 6, 4)
sheet.merge_cells(5, 5, 6, 5)
sheet.merge_cells(5, 6, 6, 6)
sheet.merge_cells(5, 7, 6, 7)
sheet.merge_cells(5, 8, 6, 8)
book.write "sample.xls"
send_file "sample.xls"
File.delete "sample.xls"
end
any help on this?

It seems your are storing the file in location and send it for download and finally delete it.
Since you deleted the file you con't get it for download. If you remove the line
File.delete "sample.xls"
it will work.
or you can use send_data method instead of send_file method.
eg:
send_data book, :filename => "sample.xls", :type =>
"application/vnd.ms-excel"
reference
send_data

Related

Rails number_to_percentage and sub weird behaviour

I'm trying to replace big % numbers to shorters versions (10000% -> 10k%). Generally code works, but if number_to_percentage used it stop working (with TOTALY SAME string).
Loading development environment (Rails 5.1.2)
2.3.1 :001 > "10000.000%".bytes
=> [49, 48, 48, 48, 48, 46, 48, 48, 48, 37]
2.3.1 :002 > helper.number_to_percentage(10000).bytes
=> [49, 48, 48, 48, 48, 46, 48, 48, 48, 37] # totally same
2.3.1 :003 > helper.number_to_percentage(10000).sub(/(\d\d)\d\d\d(?:[.,]\d+)?\%$/){ "#{$1}k%" }
=> "k%" # doesn't work
2.3.1 :004 > "10000.000%".sub(/(\d\d)\d\d\d(?:[.,]\d+)?\%$/){ "#{$1}k%" }
=> "10k%" # works
What can cause this? Any ideas?
Because number_to_percentage returns an ActiveSupport::SafeBuffer and not a String.
helper.number_to_percentage(10000).class # => ActiveSupport::SafeBuffer
ActiveSupport::SafeBuffer (which is a subclass of String) does some magic around unsafe methods like sub. That's why you can have some surprises.
The key difference is:
"10000.000%".class #=> String
number_to_percentage(10000).class # => ActiveSupport::SafeBuffer
ActiveSupport::SafeBuffer is a subclass of String, and contains the concept of UNSAFE_STRING_METHODS (including sub and gsub). This concept is useful for rails views (which is where number_to_percentage is normally used!), in relation to security; preventing XSS vulnerabilities.
A workaround would be to explicitly convert the variable to a String:
number_to_percentage(10000).to_str.sub(/(\d\d)\d\d\d(?:[.,]\d+)?\%$/){ "#{$1}k%" }
=> "10k%"
(Note that it's to_str, not to_s! to_s just returns self, i.e. an instance of ActiveSupport::SafeBuffer; whereas to_str returns a regular String.)
This article, and this rails issue go into more detail on the issue.
Alternatively, you could write your code like this, and it works as expected:
number_to_percentage(10000).sub(/(\d\d)\d\d\d(?:[.,]\d+)?%$/, '\1k%')
#=> "10k%"
I would actually prefer this approach, since you are no longer relying on modification to the (non-threadsafe) global variable.

Rails Gem "Axlsx" - Rename Workbook

My workbook always named like my template "invoices_generate.xlsx".
How can i rename this File ?
Template "invoices_generate.xlsx.axlsx" :
wb = xlsx_package.workbook
wb.add_worksheet(:name => "Beleg") do |sheet|
.
.
.
sheet.column_widths 2 , 11, 11, 11, 11, 23, 3
end
Do you have the axlsx_rails gem added as well? If so:
wb = xlsx_package.workbook
wb.add_worksheet(name: "Beleg") do |sheet|
sheet.column_widths 2 , 11, 11, 11, 11, 23, 3
end
See https://github.com/straydogstudio/axlsx_rails#template for more details and if that doesn't work try setting the filename from the controller action rendering the xlsx template as described here: https://github.com/straydogstudio/axlsx_rails#file-name
For future references: In the controller, on the function where generate the workbook
def index
#users = User.all
render xlsx: 'export', filename: 'my_new_filename.xlsx' //Render with export and naming the file
respond_to do |format|
format.html
format.xlsx
end
end

rails prawn undefined method rowspan

I get the following error for the code below: undefined method 'rowspan=' for #<Prawn::Table::Cell::Text:0x9477540>
table [
[{content: "<b>control</b>", rowspan: 2},
{content: "time", colspan: 2},
"order",
{content: "count", colspan: 6}]
], cell_style: {size: 10, inline_format: true}
I followed the prawn manual, and can not see what I did wrong. I am using prawn 0.12.0.
According to the Prawn google group, colspan and rowspan were not introduced until a later release. https://groups.google.com/forum/#!searchin/prawn-ruby/rowspan/prawn-ruby/G-QHFUZheMI/3a4pNnLur0EJ
Updating to the lastest master gem from github worked for me:
git clone https://github.com/prawnpdf/prawn.git
Create a directory to test the manual example.
Run bundle init to create a Gemfile in that directory and add this line
gem 'prawn', :path=>'/path/to/your/local/prawn/git/clone/dir'
Create the span_example.rb file from the manual, and set it up to use bundler Gemfile like this:
require 'rubygems'
require 'bundler/setup'
Bundler.require
pdf = Prawn::Document.generate('span_example.pdf') do
table([
["A", {content: "2x1", colspan: 2}, "B"],
[{content: "1x2", rowspan: 2}, "C", "D", "E"],
[{content: "2x2", colspan: 2, :rowspan => 2}, "F"],
["G", "H"]
])
end
Then run
bundle install
ruby span_example.rb
open span_example.pdf
Viola!

ruby when we are passing more than 4 value in set how it arrange that value in set

Set.new
=> #<Set: {}>
irb(main):003:0> Set[1,2,3,4,5,6]
=> #<Set: {5, 6, 1, 2, 3, 4}>
irb(main):004:0> Set[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
=> #<Set: {5, 11, 6, 12, 1, 7, 13, 2, 8, 14, 3, 9, 15, 4, 10}>
irb(main):005:0> Set[1,2,3,4,5,6,7,8,9,10]
=> #<Set: {5, 6, 1, 7, 2, 8, 3, 9, 4, 10}>
irb(main):006:0> Set[1,2,3,4,5]
=> #<Set: {5, 1, 2, 3, 4}>
irb(main):007:0> Set[1,2,3,4]
=> #<Set: {1, 2, 3, 4}>
irb(main):008:0> Set[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
=> #<Set: {16, 5, 11, 17, 6, 12, 1, 18, 7, 13, 2, 19, 8, 14, 3, 20, 9, 15, 4, 10}>
irb(main):009:0> Set[1,2,4,5,3,7]
=> #<Set: {5, 1, 7, 2, 3, 4}>
I want to know which algorithm Ruby is using to enter value in sets
http://www.ruby-doc.org/stdlib-1.9.3/libdoc/set/rdoc/SortedSet.html
SortedSet implements a Set that guarantees that it's element are yielded in sorted order
You've said "in language nothing is generated without order" but that isn't true. Hashes are generated without order.
In Ruby 1.9, though, additional infrastructure has been added on top of hashes to give them an insertion order that is used when iterating (meaning that even though they are stored unordered, they essentially maintain a linked list they can use when being traversed). Since sets are implemented with hashes, they will be unordered in 1.8 and ordered in 1.9, but you should not rely on this order (otherwise it's not a set, it's a list -- array in Ruby speak).
Here is a simple example of implementing a hash.
This article discusses how the ordering is added.

prawnto displaying tables that don't break when new page

I have a variable number of tables with variable number of rows and I want to have them displaying one after the other but if a table doesn't fit on the current page put it on the next then continue on. I have put the table in a transaction so I can roll back then print it if the height will fit on curent page but how do I get the table height?
I have this code at the moment
pdf.transaction do
pdf.table #data,
:font_size => 12,
:border_style => :grid,
:horizontal_padding => 10,
:vertical_padding => 3,
:border_width => 2,
:position => :left,
:row_colors => ["FFFFFF","DDDDDD"]
pdf.move_down 20
#pdf.rollback
end
Any help on this would be great. Or any other way to do this ?
Best Regards
Rick
4 years later... :)
As #m-x wrote it, rollback was disabled for security reason, like "group", and is still not implemented. So, here how I deal with break pages for tables :
Big and simple table (one row per data)
Just use header option
pdf.table #data,
header: true, # You can use 'header: 2' if your header take two rows
font_size: 12,
border_style: :grid,
horizontal_padding: 10,
vertical_padding: 3,
border_width: 2,
position: :left,
row_colors: ["FFFFFF","DDDDDD"]
Small table or complexe table
make table
check if you need break page
draw table
With your example :
t = pdf.make_table #data,
font_size: 12,
border_style: :grid,
horizontal_padding: 10,
vertical_padding: 3,
border_width: 2,
position: :left,
row_colors: ["FFFFFF","DDDDDD"]
if cursor - t.height < 0
start_new_page
end
t.draw
Hope that helps
#current_page = pdf.page_count
#roll = pdf.transaction do
pdf.move_down 20
pdf.table #data,
:font_size => 12,
:border_style => :grid,
:horizontal_padding => 10,
:vertical_padding => 3,
:border_width => 2,
:position => :left,
:row_colors => ["FFFFFF","DDDDDD"]
pdf.rollback if pdf.page_count > #current_page
end
if #roll == false
pdf.start_new_page
pdf.table #data,
:font_size => 12,
:border_style => :grid,
:horizontal_padding => 10,
:vertical_padding => 3,
:border_width => 2,
:position => :left,
:row_colors => ["FFFFFF","DDDDDD"]
end
I hope this works for you as for me :-)
I'm a Prawn beginner, so this might not be the best solution, but it should work.
You can get the table height if you consider the font size and vertical padding and the number of records you have in #data and you can get the current cursor position by calling Prawn::Document.cursor method.
Having these two numbers you should be able to check whether the table fits on this page or not. If not, just start a new one (by calling Prawn::Document.start_new_page method).
Otherwise the table will break automatically and will continue on the next page.
Thanks Igor
I am currently setting the current page and then in the transaction after the new table has been rendered and before the roll back setting new_page variable. Then i can roll back and chek if the new page var > current page var and if it is start new page and print the table. See code below.
The problem is now the pdf.start_new_page says error but if i just take the pdf.rollback line out it works. See error below.
Any ideas any one or any easier ways, there must be one!!
thanks
rick
#current_page = pdf.page_count
pdf.transaction do
pdf.move_down 20
pdf.table #data,
:font_size => 12,
:border_style => :grid,
:horizontal_padding => 10,
:vertical_padding => 3,
:border_width => 2,
:position => :left,
:row_colors => ["FFFFFF","DDDDDD"]
#the_next_page = pdf.page_count
pdf.rollback
end
if #the_next_page > #current_page
pdf.start_new_page
pdf.table #data,
:font_size => 12,
:border_style => :grid,
:horizontal_padding => 10,
:vertical_padding => 3,
:border_width => 2,
:position => :left,
:row_colors => ["FFFFFF","DDDDDD"]
end
The error
> You have a nil object when you didn't expect it!
The error occurred while evaluating nil.identifier
Extracted source (around line #158):
155: end
RAILS_ROOT: C:/InstantRails/rails_apps/Macrotec-Application
Application Trace | Framework Trace | Full Trace
c:/InstantRails/ruby/lib/ruby/gems/1.8/gems/prawn-core-0.7.1/lib/prawn/document.rb:302:in `go_to_page'
c:/InstantRails/ruby/lib/ruby/gems/1.8/gems/prawn-core-0.7.1/lib/prawn/document/internals.rb:128:in `finalize_all_page_contents'
c:/InstantRails/ruby/lib/ruby/gems/1.8/gems/prawn-core-0.7.1/lib/prawn/document/internals.rb:127:in `each'
c:/InstantRails/ruby/lib/ruby/gems/1.8/gems/prawn-core-0.7.1/lib/prawn/document/internals.rb:127:in `finalize_all_page_contents'
c:/InstantRails/ruby/lib/ruby/gems/1.8/gems/prawn-core-0.7.1/lib/prawn/document.rb:344:in `render'
C:/InstantRails/rails_apps/Macrotec-Application/app/views/quotations/show.pdf.prawn:158:in `_run_prawn_app47views47quotations47show46pdf46prawn'

Resources