開発メモ rails excel操作

#Ruby on Rails で Excelファイル操作

業務で必要だったのでメモ書き。

excel操作には「spreadsheet」を使用。

excelを取り込むときは、「form_tag」で「:multipart=>true」を設定しておかないとparamsで受け取った時、「ファイル」として受け取れず、文字列で受け取るので注意

以下source

```_form.html.erb
<%= form_tag(User_path, :method=>"get", :multipart=>true) do %>
  <%= file_field_tag :upload_file %>
  <%= submit_tag "取込" %>

  <%= submit_tag "出力" %>
<% end %>
```

```User.controller.rb
  def index
    if params[:commit] == "出力"
       output_user_list()
    elsif params[:commit] == "取込"
       import_user_list(params[:upload_file])
    end
  end
  #出力処理
  def output_user_list(params)
    #出力対象のリストを取得
    users = User.new(params)
    @output_user_list = user.search()

    filename = "user_lists_#{Time.now.strftime('%y%m%d%H%M%S')}.xls"
    tempfilename = "temp_user_lists_#{Time.now.strftime('%y%m%d%H%M%S')}.xls"
    
    #  IE対応：ファイル名のエンコード
    filename = filenameEncode(filename)
    Spreadsheet.client_encoding = 'UTF-8'

    book = Spreadsheet.open("public/user_lists.xls")

    sheet1 = book.worksheet(0) #レイアウトを指定
    #カウンター
    row_count = 0
    col_count = 0
    begin
      #セルに値をセット
      @output_user_list .each do |user|
          sheet1[row_idx + row_count, col_count] = user.name
          col_count += 1
          sheet1[row_idx + row_count, col_count] = user.age
          col_count += 1
          
          #########################
          # 出力処理 省略
          #########################

          # 一列処理終了
          col_count = 0
          row_count += 1
      end
    rescue => e
      #エラー処理
      #エラーの内容と行数をwibrickに出力
      logger.debug "書き込み時エラー:#{e}"
      err = Array.new
      e.backtrace.each do |e|
        err << e.to_s if e.include?("#{railsのプロジェクト名}")
      end
      logger.debug "バックトレース:#{err.inspect}"
      @notice = "出力に失敗しました"
      return false
    else
      # ファイルを生成、ダウンロード
      # ------------------------------------------------
      # TempFileの作成
      # ------------------------------------------------
      tempfile = Tempfile.new(tempfilename,"#{Rails.root}/public/")
      book.write(tempfile)
      # ------------------------------------------------
      # ファイルの転送
      # ------------------------------------------------
      tempfile.open
      tempfile.binmode
      send_data(
                tempfile.read,
                :disposition => 'attachment',
                :type => 'application/octet-stream',
                :filename => filename
                )
      tempfile.close(true)
    end
  end

  #取込処理
  def import_user_list(import_excel)
    #渡されたファイルの情報は以下の要素で取得可能
    #一時的にtmpファイルに保存される
    excel_original_filename = import_excel.original_filename
    excel_content_type = import_excel.content_type
    excel_headers = import_excel.headers
    excel_tempfile = import_excel.tempfile
    begin
      spreadsheet = Spreadsheet.open(excel_tempfile)
      sheet = spreadsheet.worksheet(0) #出力レイアウトを指定

      sheet.each_with_index do |row, idx|
        #A列に値がなければスキップ
        if row[0].to_s != ""
          logger.debug "#{idx}行目: #{row[0]} #{row[1]} #{row[2]}"
        end
      end
      #sheet.count で総行数取れるので、forでもeachでも。
      logger.debug "sheet : " + sheet.count.to_s

    rescue => e
      logger.debug "読み込み時エラー:#{e}"
      #エラーの内容と行数をwibrickに出力
      logger.debug "書き込み時エラー:#{e}"
      err = Array.new
      e.backtrace.each do |e|
        err << e.to_s if e.include?("#{railsのプロジェクト名}")
      end
      logger.debug "バックトレース:#{err.inspect}"
      @notice = "出力に失敗しました"
      return false
    else
      return true
    end
  end
```


ruby 1.9.2
rails 3.0.5
spreadsheet

バージョン古すぎぃ！
もうちょい新しいバージョンを使うときは再確認すること
多分使えるんじゃないかな

参考
https://qiita.com/Kta-M/items/02a2c41c5624f75498aa