Ruby: How to generate CSV files that has Excel-friendly encoding

后端 未结 4 1027
暗喜
暗喜 2020-12-30 03:01

I am generating CSV files that needs to be opened and reviewed in Excel once they have been generated. It seems that Excel requires a different encoding than UTF-8.

相关标签:
4条回答
  • 2020-12-30 03:33
    config = {
    
      encoding: 'ISO-8859-1'
    }
    
    CSV.generate(config) { |csv|  csv << ["Text á", "Text é", "Text æ"] }
    
    0 讨论(0)
  • 2020-12-30 03:35

    Excel understands UTF-8 CSV if it has BOM. That can be done like:

    Use CSV.generate

    # the argument of CSV.generate is default string
    csv_string = CSV.generate("\uFEFF") do |csv|
      csv << ["Text a", "Text b", "Text æ", "Text ø", "Text å"]
    end
    

    Use CSV.open

    filename = "/tmp/example.csv"
    
    # Default output encoding is UTF-8
    CSV.open(filename, "w") do |csv|
      csv.to_io.write "\uFEFF" # use CSV#to_io to write BOM directly 
      csv << ["Text a", "Text b", "Text æ", "Text ø", "Text å"]
    end
    
    0 讨论(0)
  • 2020-12-30 03:36

    You should switch the encoding to ISO-8859-1 as following:

    CSV.generate(encoding: 'ISO-8859-1') { |csv|  csv << ["Text á", "Text é", "Text æ"] }
    

    For your context, you can do this:

    config = {
      col_sep: ';',
      row_sep: ';',
      encoding: 'ISO-8859-1'
    }
    
    CSV.generate(config) { |csv|  csv << ["Text á", "Text é", "Text æ"] }
    

    I had the same issue and that encoding fixed.

    0 讨论(0)
  • 2020-12-30 03:42

    The top voted answer from @joaofraga worked for me, but I found an alternative solution that also worked - no UTF-8 to ISO-8859-1 transcoding required.

    From what I've read, Excel, can indeed handle UTF-8, but for some reason, it doesn't recognize it by default. But if you add a BOM to the beginning of the CSV data, this seems to cause Excel to realise that the file is UTF-8.

    So, if you have a CSV like so:

    csv_string = CSV.generate(csv_config) do |csv|
      csv << ["Text a", "Text b", "Text æ", "Text ø", "Text å"]
    end
    

    just add a BOM byte like so:

    "\uFEFF" + csv_string
    

    In my case, my controller is sending the CSV as a file, so this is what my controller looks like:

    def show
      respond_to do |format|
        format.csv do
          #  add BOM to force Excel to realise this file is encoded in UTF-8, so it respects special characters
          send_data "\uFEFF" + csv_string, type: :csv, filename: "csv.csv"
        end
      end
    end
    

    I should note that UTF-8 itself does not require or recommend a BOM at all, but as I mentioned, adding it in this case seemed to nudge Excel into realising that the file was indeed UTF-8.

    0 讨论(0)
提交回复
热议问题