【簡単】RailsでCSVを入力(インポート)する

大量の情報を入力させたい時などに、CSVインポート機能を付けたい場合があったので、そのやり方をまとめました。

スポンサーリンク

開発環境

開発環境 cloud9

ruby 2.6.3
Rails 5.1.7

CSV入力のやり方

Railsアプリの作成とルーティング

アプリを作成し、そのディレクトリに移動します。

rails new csv
cd ./csv

CSVファイルを読み込むためのgemを導入します。

gem 'roo'

bundleを忘れずに。

bundle install

コントローラーを作成します。

rails g controller csv index

コントローラの作成時にエラーが出ることがあります。その場合、Gemfileの以下の部分を書き換えることで解決する場合があります。bundle installを忘れずに。

#この部分を
gem 'sqlite3'
#このように書き換える
gem 'sqlite3', "~> 1.3.6"

ルーティングをあらかじめいじっておきます。

routes.rbをすべて消して以下のように書き換えてください。

Rails.application.routes.draw do
  get "/"=> "csv#index"
  post "/data" =>"csv#data"
end

ユーザーにCSVファイルをアップロードさせる

CSVファイルをアップロードできるフォームを作成します。

csvコントローラのViewファイルを書き換えます。


<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>CSVをインポートする</title>
  </head>
  <body>
    <%=form_tag'/data', method: 'post', multipart: true do %>
      <div class="form-group row">
         <label>CSVファイル</label>
        <div class="col-sm-10">
         <input type="file" name="csv" accept=".csv,.xlsx,.xls"></input>
        </div>
      </div>
      <br>
        <button type="submit">実行</button>
    <%end%>
  </body>
</html>

今の段階で、実行すると、こんな感じです。「実行」ボタンを押すとエラーが吐かれます。

rails s


エラーを吐かれないように、CSVコントローラとViewファイルをいじっていきます。

indexの下に、dataの部分を追加します。

class CsvController < ApplicationController
  def index
  end
  def data
  end
end

「/csv/app/views/csv」の直下に、新規ファイル「data.html.erb」を作成します。

(つまり、/csv/app/views/csv/data.html.erbを新規作成)

そのうえで、今作ったファイルを書き換えます。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>CSVを出力する</title>
  </head>
  <body>
   <h1>HELLOWORLD</h1>
  </body>
</html>

では、再度実行してみると、

HELLOWORLDが出力されました。

データの読み込みと出力

今回用意したCSVファイルは、こんな感じです。

(ページ最下部のサンプルデータからインストールできます。)

このデータをRailsで読み込んでいきます。

まず、CSVコントローラをいじります。def data ~ endを書き換えます。

class CsvController < ApplicationController
  def index
  end
  def data
    require 'csv'
    @path = params[:csv].path
    csv = CSV.table("#{@path}", encoding: "Shift_JIS:UTF-8")
    @name = csv[:name]
    @class = csv[:class]
    @score = csv[:score]
 end
end

Viewファイルも書き換えます。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>CSVを出力する</title>
  </head>
  <body>
   <table border="1" width="300" cellspacing="0" cellpadding="5" bordercolor="#333333">
    <tr>
    <th bgcolor="#EE0000"><font color="#FFFFFF">名前</font></th>
    <th bgcolor="#EE0000" width="100"><font color="#FFFFFF">クラス</font></font></th>
    <th bgcolor="#EE0000" width="100"><font color="#FFFFFF">スコア</font></th>
    </tr>

    <%for i in 0...@namesize%>
    <tr>
    <td bgcolor="#99CC00" align="right" nowrap><%=@name[i]%></td>
    <td bgcolor="#FFFFFF" valign="top" width="100"><%=@class[i]%></td>
    <td bgcolor="#FFFFFF" valign="top" width="100"><%=@score[i]%></td>
    </tr>
    <%end%>
  </table>
  </body>
</html>

<!--SpecialThanks http://www.htmq.com/html/table.shtml-->

実行してみると、

CSVファイルの中身が出力されました。

おまけ(平均値の出力)

例えば、コントローラとViewをこんな感じにいじると、

class CsvController < ApplicationController
  def index
  end
  def data
    require 'csv'
    
    @path = params[:csv].path
    csv = CSV.table("#{@path}", encoding: "Shift_JIS:UTF-8")
    @name = csv[:name]
    @class = csv[:class]
    @score = csv[:score]
    
    @namesize = @name.size.to_i
    
    add1,num1,add2,num2 = 0,0,0,0
    
    for i in 0...@namesize do
      if @class[i] == 1
        add1 += @score[i].to_i
        num1 += 1
      elsif @class[i] == 2
        add2 += @score[i].to_i
        num2 += 1
      end
    end 
    @avg1 = add1 / num1
    @avg2 = add2 / num2
  end
end
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>CSVを出力する</title>
  </head>
  <body>
   <table border="1" width="300" cellspacing="0" cellpadding="5" bordercolor="#333333">
    <tr>
    <th bgcolor="#EE0000"><font color="#FFFFFF">名前</font></th>
    <th bgcolor="#EE0000" width="100"><font color="#FFFFFF">クラス</font></font></th>
    <th bgcolor="#EE0000" width="100"><font color="#FFFFFF">スコア</font></th>
    </tr>

    <%for i in 0...@namesize%>
    <tr>
    <td bgcolor="#99CC00" align="right" nowrap><%=@name[i]%></td>
    <td bgcolor="#FFFFFF" valign="top" width="100"><%=@class[i]%></td>
    <td bgcolor="#FFFFFF" valign="top" width="100"><%=@score[i]%></td>
    </tr>
    <%end%>
  </table>
  <br>
    <div>1組のスコアの平均は<%=@avg1%>点です。</div><br>
    <div>2組のスコアの平均は<%=@avg2%>点です。</div><br>
  </body>
</html>

<!--SpecialThanks http://www.htmq.com/html/table.shtml-->

平均点が表示されるようになりました。

まとめ

いかがだったでしょうか。CSVの入力についてまとめてみました。

CSV入力を扱えるとRailsでできることが増えると思います。

上手に使ってみてください。

サンプルデータ

この記事で使っていたCSVファイルは以下からダウンロードしてください。

この記事で作成したRailsのコードは、Githubで公開しています。

参考文献

ファイルをアップロード

HTMLタグリファレンス <TABLE> …… テーブル(表)を作成する

このブログが良いと思ってくださったら、ご支援をお願いします!

※OFUSEは登録不要で、50円から簡単にクリエイターを支援できるサービスです。

OFUSEで支援する

CSV入出力Ruby on Rails技術メモ
スポンサーリンク
asyano.jp

コメント

タイトルとURLをコピーしました