10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RubyXLを使ってExcelを編集してクライアントに返す

Last updated at Posted at 2019-03-02

railsでエクセルを編集してクライアントに返そうとしたときのやり方を残しておきます。

作るもの

  1. クライアントがエクセルファイルをアップロードする
  2. サーバが受け取ったエクセルに何かしらの変更を加える
  3. クライアントが変更されたファイルをダウンロードする

といった動きになる機能をRailsで作ります。
出来上がったソースコードはこちら

Excelの編集

RubyXLというgemを使います。

他にもエクセルを開けるgemはあるのですが、

  • Roo: 読み込みのみ
  • AXSLX: 新規作成のみ

という感じで用途が絞られています。
今回は、編集ができるRubyXLを使います。

単体だと、以下のような感じで使えます。


require 'rubyXL'

# ファイルを読み込んでRubyXL::Workbookにデシリアライズ
workbook = RubyXL::Parser.parse("path/to/Excel/file.xlsx")
# ブック→シート→行→セルという構造になっている
worksheet1 = workbook[0]
row1 = worksheet1[0]
cell1 = row1[0]
# 書き込むときはWorksheetのメソッドが使える
worksheet1.add_cell 0, 0, 'changed'
# 保存
workbook.save

rails new

railsプロジェクトを作ります。
今回は横着してモデルを作らないので、ActiveRecordなどいらないモジュールを生成しないようオプションを付けます。

rails new -MOCJ

ルーティング

excelリソースへのルートを作ります。
加えて、ルートをexcelsにします。

下記とおりルーティングされます

  • GET / -> ExcelsController#show
  • GET /excels -> ExcelsController#show
  • POST /excels -> ExcelsController#create

GET /excelsでファイルを受け取るフォームを表示し、POST /excelsでサーバへのファイルアップロードと編集後ファイルの送信を行います。

Rails.application.routes.draw do
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  root to: "excels#show"
  resource :excel, only: [:show, :create]
end

コントローラ

showメソッドでは何もせず、ページを表示するだけです。
createにはエクセルファイルが送られて来るので、ファイルの編集とクライアントへの送信を行います。

class ExcelsController < ApplicationController
 def show
 end

 def create
   file = params[:file]
   # ファイルを開く
   workbook = RubyXL::Parser.parse file.path
   # 編集する
   workbook[0].add_cell 0, 0, 'changed'
   # 編集したファイルを送る
   send_data workbook.stream.string, type: file.content_type, filename: 'modified.xlsx'
 end
end

アップロードされたファイルはUploadedFileオブジェクトとして受け取ることができます。
RubyXL::Parser.parseはFileオブジェクトではなくパスを引数に取るので、アップロードされたファイルのパスを指定してRubyXL::Workbookオブジェクトに変換します。
アップロードされたファイルは、tempfileとして保存されていて、
UploadedFile#pathでこのtempfileのパスを取得できます。

編集したファイルは、send_dataメソッドを使って送信します。

データとして渡すのは、Workbook#streamで取得できるバイナリのストリームを、Stream#stringで文字列にしたものです。
コンテントタイプを指定する必要がありますが、UploadedFileは受信したときのContent-Typeを記録しているので、同じものを指定しておけばいいでしょう。

ビュー

エクセルファイルをアップロードするためのビューを作ります。

<%= form_tag({action: :create}, multipart: true) do %>
  <div>
  <%= file_field_tag :file %>
  </div>
  <div>
  <%= submit_tag "Send" %>
  </div>
<% end %>

ファイル選択と送信ができます。
送信したファイルはExcelsController#createで処理します。

image.png

試してみる

このようなEXCELファイルを用意し、

image.png

送ってみます。

image.png

編集されたファイルのダウンロードが始まります。

image.png

開いてみます。期待通り編集されたエクセルをダウンロードできました。

image.png

まとめ

  • RubyXLでエクセルの編集ができる
  • アップロードされたファイルはUploadedFileオブジェクトに記録される
  • RubyXLで保存したワークブックは、保存しなくてもデータ送信できる

UploadedFileの存在を知らなかったので、うまくいくかわからなかったのですが、うまくrailsと一緒に使うことができました。

10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?