Export CSV z polskimi znakami do Excel'a w Rails 2.x, może się przyda

Cześć,

Wczoraj musiałem do aplikacji Rails 2.3.15 dołożyć eksport danych do Excel’a. Chwilę zajęło (głównie polskie znaki oraz prawidłowe otwieranie w Excelu) ale udało mi się osiągnąć cel.
Oczywiście rozwiązanie jest sumą tego co znalazłem (łatwo wygooglować biorąć kawałki kodu) + tego co wymyśliłem.

Korzystałem między innymi z

Opis przykładu:

  • mam model Participant (np. uczestnik szkolenia). Chcę obsłużyć pobierania w CSV z otwarciem Excel’a i jednoczesną translacją atrybutów na takie nad którymi mam kontrolę i mogę pokazać użytkownikowi (np. po polsku ze spacjami pomiędzy słowami).

Przepis

  1. Lokalizacja
  • w config/initializers/locale.rb

[code]
I18n.load_path += Dir[Rails.root.join(‘lib’, ‘locales’, ‘*.{rb,yml}’)]

I18n.default_locale = :pl[/code]

  • w lib/locales/pl.yml w gałęzi pl/attributtes/participant/ ustawione tłumaczenia atrybutów na takie jakie chcemy prezentować użytkownikom

przykładowo:

pl: attributes: participant: first_name: "Imię"
2. Widok index.html.erb w app/views/participant (fragment z linkiem do pobierania). Rails zareaguje na url w postaci …/participants.csv

[code]


Pobierz:
<%= link_to “CSV”, participants_path(:format => “csv”) %>

[/code] 3. Kontroler - Iconv załatwia problem kodowania polskich znaków poprze zamianę utf-8 na utf-16le BOM (le to (Little Endian, preambułę BOM zwraca pierwszy Iconv ) które następnie wysyłane jest jako iso-8859-1 :cool: - :col_sep => "\t" w otwieranym Excelu rozrzuca prawidłowo kolumny CSV do oddzielnych kolumn Excel'a (, ; i inne powodują pobranie całej zawartości do jednej kolumny)

@participants = Participant.all respond_to do |format| format.html # index.html.erb format.xml { render :xml => @participants } format.csv { send_data \ Iconv.conv("utf-16le", "utf-8", "\xEF\xBB\xBF") \ + Iconv.conv("utf-16le", "utf-8", \ Participant.to_csv(@participants, :col_sep => "\t")), :type => 'text/csv; charset=iso-8859-1; header=present'} end
4. Model

  • dodaje metodę klasową to_csv w której skleja się CSV (przy okazji zamieniając oryginalne nazwy atrybutów na czytelne dla użytkownika)

def self.to_csv(all_participants, options = {}) FasterCSV.generate(options) do |csv| csv << column_names.collect {|col_name| Participant.human_attribute_name(col_name)} all_participants.each do |participant| csv << participant.attributes.values_at(*column_names) end end end
5. FasterCSV

  • zainstalować gem’a (np. sudo gem install fastercsv)

w config/environment.erb

require 'fastercsv'

Mam nadzieję że nie porobiłem literówek i zadziała od razu jak ktoś będzie chciał tego użyć.
Jakby coś nie było jasne lub nie działało, dajcie znać.

Pozdrawiam
Artur

1 Like