Closed agustaf9 closed 8 years ago
You can do something like this:
def some_action
compressed_filestream = Zip::ZipOutputStream.write_buffer do |zos|
content = render_to_string xlsx: 'export', filename: filename, layout: false
zos.put_next_entry(filename)
zos.print content
# add other files
end
compressed_filestream.rewind
send_data compressed_filestream.read, filename: 'export.zip', type: 'application/zip'
end
I am assuming you are wanting to return the zip to a request. Let me know if you had something else in mind.
layout: false
may not be necessary; in some circumstances Rails tries to add a layout to axlsx files.
I do want to return a zip to a request but it is a zip that includes many different files. I have a method in my model that gets many local files and zips them into a single folder. I am wondering if there is a way to add the file that axlsx generates to that folder. Basically what I am wondering is if there is a way I can call axlsx from the model?
You can use the same render_to_string and dump it into a file in your directory:
content = render_to_string xlsx: 'export', filename: filename, layout: false
File.open('/tmp/axlsx_temp.xlsx', 'w') {|f| f.write(content) }
If you are calling this inside a model, then you may have a bit of an issue getting to render to string. There will likely be posts on the internet about that. I've not done it myself. You may have to do something like this.
It is possible to render a template directly without the overhead of ActionView. See this test.
I am going to close it because it works, but... can someone tell me if there is something really wrong with what I am doing here? (Note: model is the name of one of my models)
def download
tempfile = Tempfile.new
children = self.children_with_forms
Zip::OutputStream.open(tempfile) do |stream|
children.each do |child|
directory = "#{child.wide_reference[0,3]}/"
if child.model_name == "Position"
av = ActionView::Base.new(ActionController::Base.view_paths, {position: child, model: child.model})
stream.put_next_entry("#{directory}#{child.volume} #{child.title} TOC.xlsx")
stream.print av.render template: 'pages/toc.xlsx.axlsx'
end
stream.put_next_entry("#{directory}#{child.wide_reference} #{child.title.truncate(15, omission:'')} (#{child.short_name}).docx")
stream.print IO.read(child.download_form.path)
end
stream.put_next_entry("excel file.xlsx")
av = ActionView::Base.new(ActionController::Base.view_paths, {model: self})
stream.print av.render template: 'pages/excel_file.xlsx.axlsx'
end
tempfile
end
Thank you for your help! And thank you for this wonderful gem!
@agustaf9 Glad that worked! I don't see anything wrong in particular. As long as things are working I think you are ok.
You are welcome for the help and gem.
I am trying to get the spreadsheet after it is generated by axlsx into my model so I can zip it up with some other files. How would I go about doing this?
Edit: I know how to zip, I am just wondering how to generate the spreadsheet from my model.