【GAS】よく使うお作法、オレオレチートシートを作ってみました 〜 スプレッドシート、Gmail 〜

スプレッドシート関連

このようなデータを想定します。

ヘッダが1行、あとはデータが何かしら存在する、よくある表形式のデータですね。

シートの値を取得する

シートの値を取得する場合によくやるお作法です。

function getAllSheetData() {
  const sheetName = 'シート1';
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);

  const ranges = sheet.getDataRange();
  const values = ranges.getValues(); //もしくは ranges.getDisplayValues();

  values.forEach(record => console.log(record));

  return values;
}

実行結果は下記のようになります。

[ '項目1', '項目2', '項目3', '項目4' ]
[ 'aaa', 'ccc', 'eee', '' ]
[ 'bbb', 'ddd', 'fff', '' ]
[ 'aaa', 'ccc', 'eee', '' ]
[ 'bbb', 'ddd', 'fff', '' ]
[ 'aaa', 'ccc', 'eee', '' ]
[ 'bbb', 'ddd', 'fff', '' ]
[ 'aaa', 'ccc', 'eee', '' ]

セルを一つ一つ getRange() してしまうと、動作がとても遅くなります。
ので、シートの値は一気に取得してしまった方がよいです。
そんなときに便利な関数が、 getDataRange() です。
これはデータが存在するセルを全て包含する形で、 セルを取得できます。
この関数のいいところは、どんなにセルに空白があっても、最終行と最終列の表形式になるような二次元配列にしてくれるところです。
まずは、一気にシートのデータを変数に入れてしまって、そこから色々な処理につなげることをよくやります。

また、ヘッダを除く場合は、よく以下のように書きます。
ヘッダが2行以上の場合は、比較している部分の数字をいじればOKです。

function getAllSheetData() {
  const sheetName = 'シート1';
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
  const headerRowNum = 1;

  const ranges = sheet.getDataRange();
  const values = ranges.getValues(); //もしくは ranges.getDisplayValues();
  const values_withoutHeader = values.filter((r, i) => i >= headerRowNum);

  values_withoutHeader.forEach(record => console.log(record));

  return values_withoutHeader;
}

複数の値をスプレッドシートに挿入する

setValues()を使う時によくやるお作法です。

function setValuesFromVariable() {
  const sheetName = 'シート1';
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
  const headerRowNum = 1;

  const ranges = sheet.getDataRange();
  const values = ranges.getValues(); //もしくは ranges.getDisplayValues();
  const values_withoutHeader = values.filter((r, i) => i >= headerRowNum);

  sheet.getRange(10, 1, values_withoutHeader.length, values_withoutHeader[0].length).setValues(values_withoutHeader);
}

getRange() の引数は、左から順に「行開始位置」、「列開始位置」、「取得する行数」、「取得する列数」となっています。
この「取得する行数」、「取得する列数」を配列の length で指定してやるのが、 setValues() と付き合っていくコツな気がします。

特定の列の値を取得する

これは好き嫌いが分かれそうですが、最近はこの方法をよく使います。

function getItem1Index() {
  const sheetName = 'シート1';
  const itemName = '項目1';
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);

  const ranges = sheet.getDataRange();
  const values = ranges.getValues(); //もしくは ranges.getDisplayValues();

  // ヘッダの項目名でfindIndexする
  const item1Index = values[0].findIndex(v => v === itemName); // values[0]はヘッダである前提
  if (item1Index === -1) throw Error(`「${itemName}」の列番号が見つかりませんでした`);

  // 配列から任意の列を取り出したりできます
  values.forEach(r => console.log(r[item1Index]));

  return values.map(r => r[item1Index]);  
}

ログの出力はこんな感じです。

'項目1'
'aaa'
'bbb'
'aaa'
'bbb'
'aaa'
'bbb'
'aaa'

ヘッダの項目名でfindIndexをして、列番号を取得するやり方です。

もしくは列番号自体を変数として定義しておく方法もありますが、
シートのレイアウト変更にとても弱いです。
この方法であれば、「ヘッダ名を変更」しない限り、どの列にあっても問題なく動作します。
体感的には、ヘッダ名の変更よりも列変更の方が頻繁に行われる気がするので、よくこっちを使います。

Gmail関連

メールを取得する

これは鉄板です。

function getMail() {
  const start = 0;
  const max = 10;

  const threads = GmailApp.getInboxThreads(start, max);

  threads.forEach(thread => {
    const messages = thread.getMessages();

    messages.forEach(message => {
      const mailFrom = message.getFrom();
      const subject = message.getSubject();
      const body = message.getPlainBody();

      console.log({
        mailFrom,
        subject,
        body
      });
    });
  });
}

メールは、「スレッド」、「メッセージ」という単位で取得するのが、GASでの定番です。

終わりに

今後も余裕があるときにこのシリーズやりたいと思います。

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