Nuxt.js(Vue.js)+ Buefy でCSVファイルをアップロードしてテーブル表示する

公開日:2019/09/22 更新日:2019/09/22
Nuxt.js(Vue.js)+ Buefy でCSVファイルをアップロードしてテーブル表示するのサムネイル

はじめに

Nuxt.jsでBuefyを使っており、csvファイルをアップロードして読み込ませる必要がったので実装してみました。この記事では、Buefyというコンポーネントセットを使っています。もしBuefyについて興味がある方は、以下に使い方などをまとめているので見てみてください。

www.virment.com

BuefyはBulmaというUIコンポーネントセットをベースにしたVue.js用のUIコンポーネントセットです。Bootstrapのようにあらかじめ用意されたHTMLタグやCSSクラスを使うことで簡単にそれなりの見た目になります。ここでは、Vue.jsアプリでBuefyを使えるようにするための準備手順と、最後にmarginやpadding用のクラスをBeufyに追加する方法をメモします。

できるようになること

以下のGIF画像のように、csvファイルをドロップすると、csvファイルの中身がテーブル表示されます。

upload-csv-demo.gif

アップロードしたcsvファイルの中身は以下です。

csv-for-upload.png

前提と環境

ここでは、Nuxt.jsにnuxt-buefyをインストールして使っている前提ですが、おそらくVue.jsや他のコンポーネントセットでも対応を見れば分かると思います。ただし、エラー処理などは実装しておりませんのでそれら処理は各自で実装の必要があると思います。

  • Nuxt.js : 2.9.0
  • nuxt-buefy: 0.3.14
nuxt-buefyの公式リポジトリは以下です。
github.com

It's really very simple to start with nuxt. But we can make it even simpler by adding nuxt-buefy.

csvファイルをアップロードして表示するコンポーネント

全体コードを以下に載せます。コード内にコメントを加えているのでおおまかに分かると思います。

<template>
  <section class="section">
    <b-field>
      <b-upload
        v-model="dropFile"
        drag-drop
      >
        <section class="section">
          <div class="content has-text-centered">
            <p>
              <b-icon
                icon="upload"
                size="is-large"
              />
            </p>
            <p>ファイルをドロップするか、ここをクリックしてアップロードするファイルを選択してください。</p>
          </div>
        </section>
      </b-upload>
    </b-field>
    <div v-if="dropFile" class="block">
      <div class="tags">
        <span class="tag is-primary">
          {{ dropFile.name }}
          <button
            class="delete is-small"
            type="button"
            @click="deleteDropFile(index)"
          />
        </span>
      </div>
      <button class="button is-primary" @click="uploadedData()">
        読み込む
      </button>
    </div>
    <div class="table-wrapper">
      <table class="table">
        <thead>
          <tr>
            <th>氏名</th>
            <th>カタカナ</th>
            <th>生年月日</th>
            <th>会社名</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="item in csvData" :key="item.id">
            <td>{{ item.lastname }} {{ item.firstname }}</td>
            <td>{{ item.lastkana }} {{ item.firstkana }}</td>
            <td>{{ item.birthday }}</td>
            <td>{{ item.company }}</td>
          </tr>
        </tbody>
      </table>
    </div>
  </section>
</template>

<script>
export default {
  name: 'UploadForm',
  data () {
    return {
      dropFile: null,
      csvData: [] // csvデータ格納用
    }
  },
  methods: {
    // アップロードしたファイル削除用
    deleteDropFile (index) {
      this.dropFile = null
    },
    // アップロードしたcsvファイルをcsvDataに格納する用
    uploadedData () {
      this.csvData = [] // csvDataを初期化
      const csvfile = this.dropFile
      const reader = new FileReader()

      const loadCSV = () => {
        const lines = reader.result.split('\n') // 改行毎にデータを分ける
        lines.shift() // csvファイルの先頭(ヘッダ)を削除
        // csvファイルの各行をcsvDataにオブジェクトとしてpushする
        lines.forEach((element, index) => {
          const workerData = element.split(',') // 区切り文字はカンマ
          if (workerData.length !== 6) { return } // 読み込んだ行のデータが欠けている場合は無視
          this.csvData.push(
            {
              id: index,
              lastname: workerData[0],
              firstname: workerData[1],
              lastkana: workerData[2],
              firstkana: workerData[3],
              birthday: new Date(workerData[4]),
              company: workerData[5]
            }
          )
        })
      }
      reader.onload = loadCSV
      reader.readAsText(csvfile)
    }
  }
}
</script>

上記のコードでは、HTML5から使用できるFile APIのFileReaderを使用しています。詳しくは以下に記載されています。

developer.mozilla.org

FileReader オブジェクトを使うと、ユーザーのコンピューター内にあるファイル (もしくはバッファ上の生データ) をウェブアプリケーションから非同期的に読み込むことが出来ます。読み込むファイルやデータは File ないし Blob オブジェクトとして指定します。

また、Buefyのアップロード部分については以下の公式ドキュメントをほぼそのまま使用しています。

buefy.org

Upload one or more files

まとめ

Nuxt.jsとBuefyの組み合わせによって大体のことは簡単に実装できおすすめです。

開発アプリ

nanolog.app

毎日の小さな出来事をなんでも記録して、ログとして残すためのライフログアプリです。