🚄

GAS 二次元配列を扱う

2022/07/27に公開

よくkintoneからスプレッドシートにレコード情報を出力して集計等を行いますが、データの量が多い場合は6分ルールもあるのでpythonでデータを出力しています。
でも、扱うデータが少なめであればGASで出力した方が共有しておけば誰でも実行できるため大変便利です。

少し前までは取得したレコード情報の入っているJson配列をループして、ループの中で一つ一つセルに値をセットしていましたが、やっぱり遅いので二次元配列にしてまるごと出力した方がいいに決まっています。
最近新しく書く機会があったので今ままでは早く作ってあげた方がいいと思いコピペしてちゃちゃっと終えていましたが、今回はちゃんと頭使って書いたのでアウトプットします。

配列と二次元配列

配列

配列は複数の値を持つことが出来る変数です。
値を扱うときは「変数名[インデックス番号]」と書きます。

const ary = ["A","B","C"];
console.log(ary[0]);

出力結果
"A"

二次元配列

配列の中の値が配列になっている変数です。
値を扱うときは「変数名[インデックス番号][インデックス番号]」で値を扱うことが出来ます。
インデックス番号が二つ登場するので少し複雑に感じてしまいます。
一つ目のインデックス番号では何番目の配列かを表して、二つ目のインデックス番号でそのさらに何番目の値かを指定します。

const ary = [["A","B","C"],["B","C","D"],["C","D","E"]];
console.log(ary[0]);
console.log(ary[0][0]);

出力結果
["A","B","C"]
"A"

スプレッドシートで下記のようなデータを取得した場合、二次元配列aryのようなデータとして扱うことができます。
※ヘッダー部分はインデックス番号です。

0 1 2
A B C
B C D
C D E

一つめのインデックス番号は行、二つ目列の番号と思えばOKです。

学んだこと

1行のデータを取得しても二次元になる

一行なんだからただの配列かと思いきや、二次元配列になります。

0 1 2
A B C

この値のある範囲を読み込んだら下記のようになります。

[["A","B","C"]];

初期化が必要

私がやりたかったのはkintoneから取得したjson配列を多次元配列にいれていくという処理でした。

コード.gs
/*こんなjson配列だとする*/
const records =  [
    {
        "レコード番号": {
        "type": "RECORD_NUMBER",
        "value": "1"
        },
        "ユーザー選択": {
        "type": "USER_SELECT",
        "value": [
            {
            "code": "sato",
            "name": "Noboru Sato"
            }
        ]
        }
    },
    {
        "レコード番号": {
            "type": "RECORD_NUMBER",
            "value": "2"
        },
        "ユーザー選択": {
            "type": "USER_SELECT",
            "value": [
                {
                "code": "ito",
                "name": "Taro ito"
                }
            ]
        }
    }
];
/*値を入れるための配列を宣言*/
let ary = [];
  records.forEach(function(record,index){
   /*↓↓これが必要!!*/
    ary[index] = [];
    ary[index][0] = record.レコード番号.value;
    ary[index][1] = record.ユーザー選択.value[0].name;
  });
  
  /*シートに出力する*/ 
  SpreadsheetApp.getActive().getSheetByName("sheet1").getRange(1,1,ary.length,ary[0].length).setValues(ary);

これが必要!!の部分↓

ary[index] = [];

これがないと、下記のようなエラーが出てしまいます。

ary[index][0] = record.レコード番号.value;

上記の部分で配列aryのindex番目の0番目にレコード番号を入れたいのに、そんな値はないというエラーになっています。
自動的に生成してくれないので用意してから代入する必要があるようです。

シートに出力する

コードの一番最後のところですが、

/*シートに出力する*/  
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange(1,1,ary.length,ary[0].length).setValues(ary);

getRange

二次元配列をsetValuesするのが目的なので、setValuesしようとしている配列の行、列の数ピッタリをgetRangeしないといけません。

二次元配列を出力する際のgetRangeは、下記のようにしたらokです。

シートオブジェクト.getRanage(開始行番号,開始列番号,出力したい配列の長さ(何行??),出力したい配列の中の配列の長さ(何列??))

これで一回のリクエストでドドッとデータを出力するための範囲の取得ができます。

●出力したい配列の長さ(何行??)
→ary.length

●出力したい配列の中の配列の長さ(何列??)
→ary[0].length
※インデックス番号が必ずしも0である必要はないけど、データが何個あるかわからないので無難に0にしている
※setValuesする配列

所感

実際はkitnoneのデータにテーブルが含まれていたりして配列用意するのに結構時間かかってしまいました。
二次元配列は最初は難しく思えて抵抗があるかと思いますが、扱えるようになれば処理速度まで意識してコーディングできるので、処理速度が遅めのGASでは積極的に使いたいと思いました。

Discussion