caxlsx/caxlsx_rails

Another Missing Template Issue

crjackso opened this issue · 11 comments

I'm trying to send Excel files as email attachments just as @gagalago tried in issue #12 . After trying to implement the listed solution, I'm still getting a 'missing template' error. Here's my code:

class Notifier < ActionMailer::Base
  default :from => 'noreply@company.com'

  def instructions(report)
    @report = report
    attachments["report.xlsx"] = {mime_type: Mime::XLSX, content: save_xlsx report}
    mail :to => 'user@email.com', :subject => 'Instructions'
  end

  private

  def save_xlsx(report)
    av = ActionView::Base.new
    av.view_paths = ActionController::Base.view_paths
    av.assign report: report
    av.render handlers: [:axlsx], template: '/reports/test_report'
  end
end

In the directory, views/reports, I have a template named test_report.xls.axlsx. However, I'm still getting the error:

WARN: Missing template reports/test_report with {:locale=>[:en], :formats=>[:html, :text, :js, :css, :ics, :csv, :png, :jpeg, :gif, :bmp, :tiff, :mpeg, :xml, :rss, :atom, :yaml, :multipart_form, :url_encoded_form, :json, :pdf, :zip, :xlsx], :handlers=>[:axlsx]}. Searched in:

  • "/Users/me/development/repositories/myproject/app/views"

I know I'm doing something stupid, I just need another pair of eyes. Does anything jump out at anybody? Thanks.

@crjackso Is your template really named test_report.xls.axlsx? Try test_report.xlsx.axlsx. Note the xlsx instead of xls.

Good point @straydogstudio. Here's what I have now.

class Notifier < ActionMailer::Base
  default :from => 'noreply@company.com'

  def instructions(report)
    @report = report

    # creating own view
    av = ActionView::Base.new
    av.view_paths = ActionController::Base.view_paths
    av.assign report: @report
    xlsx = av.render handlers: [:axlsx], template: "reports/test_report"

    attachments['myreport.xls'] = {mime_type: Mime::XLSX, content: xlsx}
    mail :to => 'test@mail.com', :subject => 'My Report', :template_path => 'reports', :template_name => 'test_report'
  end
end

In the directory, /views/reports, I've updated the template name to be /views/reports/test_report.xlsx.axlsx. After making the change, I'm getting the following error when sending the email.

ArgumentError: invalid byte sequence in UTF-8

Can you render the report standalone? Try duplicating your report in the console, just using the axlsx gem, running the template commands one at a time. That will tell you if you have unexpected character set problems in your data.

It isn't likely that axlsx_rails is the problem now, but it could be. Keep me informed.

Just in case it isn't obvious, start with xlsx_package = Axlsx::Package.new, then get your report data, and run each command in text_report.xlsx.axlsx.

Thanks for that clarification. Here's what I tried in a rails console.

> @report = MyReport.new
> xlsx_package = Axlsx::Package.new
> wb = xlsx_package.workbook
> wb.add_worksheet(name: "Overview") do |sheet|
>   sheet.add_row ['Total Count', 'Unique Count']
>   sheet.add_row [@report.total_count, @report.unique_email_count]
> end

This didn't seem to yield any errors in the console. After running the add_worksheet block, I got a huge print out of the Axlsx::Workbook object graph.

In the console, end with xlsx_package.to_stream.read.

Can you output the spreadsheet to view with a controller action?

So, I got this working. I noticed something with my ActionMailer settings within smtp_settings. I'm not sure why I got the invalid byte sequence error. It seems like a misleading error message. Anyways, I'm getting the axlsx-generated attachment to send correctly with the code I sent earlier. For clarity, I'll include the final form of the code below. Thanks for working on this with me @straydogstudio!

class Notifier < ActionMailer::Base
  default :from => 'noreply@company.com'

  def instructions(report)
    @report = petition_report

    xlsx = render handlers: [:axlsx], template: 'reports/test_report', layout: false
    attachments['myreport.xls'] = {mime_type: Mime::XLSX, content: xlsx }

    mail :to => 'test@mail.com',
         :body => 'test',
         :subject => 'My Report',
         :template_path => 'reports',
         :template_name => 'test_report'
  end
end

Within the directory /views/reports, I have a template named test_report.xlsx.axlsx.

Strange. What was the change that fixed it? (I may have missed it above.)

And you're welcome.

For the record, please comment on the actual fix sometime.

Hi
I suppose trouble is in send_data
ruby 2.1.0
rails 3.2.18
Code fragment from a controller

        xlsx_package = Axlsx::Package.new
        wb = xlsx_package.workbook
        wb.add_worksheet(name: "Translations") do |sheet|
          sheet.add_row ['Key', 'Url', 'Original', 'Translation']
        end
        #raise invalid byte sequence in UTF-8
        send_data xlsx_package.to_stream.read

another failed case with code above

        # sends corrupted unreadable zip file
        send_data xlsx_package.to_stream.read.force_encoding('BINARY')

working one

        xlsx_package.serialize("/tmp/translations-export.xlsx")
        send_file "/tmp/translations-export.xlsx"

@aivils All three examples work for me in a Rails 3.2.18 app with Ruby 2.0.0. I doubt Ruby 2.1.0 is the issue, but I will check at some point.

What Rails settings do you have for UTF-8? Do you have a gem that might be involved?