スプレッドシートのデータを連想配列化する話

ご無沙汰しております。
相変わらず定期的な更新が続かないカインです。

実は4月に転職しまして、新しいことに挑戦している毎日です。
ブログネタも沢山出来たので少しずつアウトプットしていきたいと思います!

今回はスプレッドシートのデータをGASで取得し、連想配列化する話です。
以前は連想配列とはなんぞやといった感じでしたが、理解が進むにつれてその便利さに魅了されつつあります。
データを弄るのにとても便利なのでかなり汎用的に使えて重宝しています。

機能


データサンプルはこちらから一部引用

↑このようなデータを↓のような連想配列にします。
JSON文字列化しています。

[
    {
        "entrydate": "2020-04-27T15:00:00.000Z",
        "userid": "OD77412",
        "name": "オソミハ",
        "seibetsu": "men",
        "age": 32,
        "totalmoney": 52000,
        "birthday": "1988-03-04T15:00:00.000Z"
    },
    {
        "entrydate": "2019-10-26T15:00:00.000Z",
        "userid": "QS19455",
        "name": "トムアシテキ",
        "seibetsu": "men",
        "age": 70,
        "totalmoney": 59000,
        "birthday": "1949-10-12T15:00:00.000Z"
    },
    {
        "entrydate": "2019-11-30T15:00:00.000Z",
        "userid": "HY60274",
        "name": "オンウ",
        "seibetsu": "men",
        "age": 54,
        "totalmoney": 71000,
        "birthday": "1966-02-02T15:00:00.000Z"
    },
    {
        "entrydate": "2020-07-17T15:00:00.000Z",
        "userid": "TA49387",
        "name": "レコスソニ",
        "seibetsu": "men",
        "age": 80,
        "totalmoney": 63000,
        "birthday": "1940-05-28T15:00:00.000Z"
    },
    {
        "entrydate": "2019-09-01T15:00:00.000Z",
        "userid": "PK56576",
        "name": "コミトハム",
        "seibetsu": "men",
        "age": 81,
        "totalmoney": 87000,
        "birthday": "1939-07-23T15:00:00.000Z"
    }
]

※注
日付はJSON.stringifyを使用した際にタイムゾーン情報が失われてUTCに置き換わっています。
以下のコードをJSON変換前に記述しておくことで無理やり回避できます。

Date.prototype.toJSON = function () { return this.getFullYear() + '/' + ('0' + (this.getMonth() + 1)).slice(-2) + '/' + ('0' + this.getDate()).slice(-2) + ' ' + ('0' + this.getHours()).slice(-2) + ':' + ('0' + this.getMinutes()).slice(-2) + ':' + ('0' + this.getSeconds()).slice(-2); }

コード全体

// こちらを実行
function sample() {
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  // const spreadsheet = SpreadsheetApp.openById("スプレッドシートのID") //スタンドアロン型の場合はこちらを使用
  const sheet = spreadsheet.getSheetByName("抽出したいシート名");

  const sheet_data = changeAssociativeArray(sheet);

  Logger.log(JSON.stringify(sheet_data)); // 生成した連想配列をログに表示
}

// sheet情報を引数で渡すと連想配列が返される関数
function changeAssociativeArray(sheet){
  // スプレッドシートから値を取得し、二次元配列へ格納
  let data_array = sheet.getDataRange().getValues();

  // 項目名と値を分離
  let keys = data_array[0]; //項目名を取得しkeysに格納
  data_array.shift(); // 項目名をdata_arrayから削除

  // 二次元配列を連想配列に変換
  let new_data_array = data_array.map(function(values){
    let hash = {};
    values.map((value, index)=>hash[keys[index]] = value);
    return hash;
  });

  return new_data_array;
}

連想配列化して何が嬉しいか

一番のメリットはデータの扱いやすさです。
mapやfilter、forEach等の各種配列用の関数も使用できますし、データを項目名で取得できるので可読性が段違いです。

生成した連想配列(sheet_data)から名前(name)の一覧を取り出す例

  for (let i = 0; i < sheet_data.length; i++) {
    Logger.log(sheet_data[i]["name"]);
  }


配列用の関数(map、filter、forEach等)も使用でき、項目名の指定もドットで区切るだけでも可能なので、コードをより簡潔に書くこともできます。
ただし、項目名が日本語や一部記号を含む場合は ["項目名"] で指定する必要があります。

※↑のfor文と同じ内容を簡潔に書いた場合

  sheet_data.forEach((value)=>Logger.log(value.name));

まとめ

このGASはスプレッドシートのデータを取得して活用するケースが増えたので多用しています。
課題や応用もいくつかあるので後日記事にします!