GAS を使って SpreadSheet のデータを csv に変換して Google Drive に保存する

3 min read読了の目安(約2800字

これは Google Apps Script Advent Calendar 2020 20日目の記事です

はじめに

趣味で作ってるゲームのマスターデータを SpreadSheet で管理しています。
Unity の方ではそれを json に変換したものを使ってデータを読み込んでいます。
SpreadSheet から json へ変換は GAS で行っていました。
今回はその GAS を使った方法について説明したいと思います。

コード全文は Gist に上げています。
説明では一部省略しているので詳細はこちらを確認してください。

https://gist.github.com/orange634nty/16455979ece86fecee139df2d0faef82

実装

前提

マスターデータ用の SpreadSheet を作成します。
自分は以下のようにしています。

また後で使うので SpreadSheet の Id を控えておきましょう。
url が https://docs.google.com/spreadsheets/d/xxxxxxxxxxx/edit#gid=yyyyyy の場合 xxxxxxxxxxx が ID です。

生成した json を保存するファイルを Drive にフォルダを作成します。
こちらのフォルダの Id も控えておきます。
url が https://drive.google.com/drive/u/0/folders/zzzzzzzzzzz の場合 zzzzzzzzzzz が ID です。

SpreadSheet から json に変換する

const lastRow = sheet.getLastRow()
const lastColumn = sheet.getLastColumn()
const rows = sheet.getRange(1, 1, lastRow, lastColumn).getValues()

でデータが入力されている範囲を列ごとに配列で取得します。
つまり

の場合

 [ [ 'id', 'name', 'hp', 'attack', 'defence' ],
  [ 1, 'スライム', 20, 5, 5 ],
  [ 2, 'ゴブリン', 30, 8, 5 ],
  [ 3, 'オオカミ', 40, 12, 10 ],
  [ 4, 'ヘビ', 20, 20, 10 ],
  [ 5, '魔王', 1000000, 10000, 10000 ] ]

のような配列でデータを取得出来ます。
これを以下のような感じで object に変換します。

const keys = rows.shift()
for (const row of rows) {
  const tmpObj = {}
  for (let i = 0; i < row.length; i++) {
    tmpObj[keys[i]] = row[i]
  }
  json_data.push(tmpObj)
}

Google Drive にファイルを書き出す

先ほど生成した json を GoogleDrive に保管します。
ファイルは folder.createFile(fileName, jsonStr, MimeType.PLAIN_TEXT) で生成できます。
fileName はファイル名、jsonStr はファイルに書き込む内容、MimeType.PLAIN_TEXT はデータの種類(今回はテキストファイルとして保存)を指定します。
注意が必要なのは、createFile は同一ファイル名でも上書きせず、同じファイル名で新しいファイルを生成します。
なので、事前にファイルが既にあるか調べて、ある場合は file.setContent(jsonStr) で上書き保存、ない場合は folder.createFile(fileName, jsonStr, MimeType.PLAIN_TEXT) で新規作成する必要があります。
なので以下のようにしています。

const file = getFileFromFolder(folder, fileName)
if (file !== null) {
  file.setContent(jsonStr)
} else {
  folder.createFile(fileName, jsonStr, MimeType.PLAIN_TEXT)
}

// フォルダから指定された名前のファイルがあるか調べる
// ある場合はファイル、ない場合はnullを返す
const getFileFromFolder = (folder, fileName) => {
  const files = folder.getFilesByName(fileName)
  while (files.hasNext()) {
    const file = files.next();
    if(fileName === file.getName()) {
      return file
    }
  }
  return null
}

おわりに

これで大体コードは完了です。convert 関数を実行してみましょう。
問題なく json ファイルが生成されていたら成功です。
SpreadSheet を編集して再度実行して内容が更新されていていることも確認しておくといいでしょう。
今回はこれで終わりですが、変換の利便性を考えて SpreadSheet にボタンをつけて実行したり、シートが増えたときの処理時間を短縮する為に前回生成した後から編集したシートのみ json を生成するようにしたりなど工夫をするとより使いやすくなると思います。