GoogleAppsScript屋さん

GoogleAppsScript のサンプルコードなどを載せていきます

Rangeオブジェクトをfor文で処理する

はじめに

今回は、タイトルの通り「Range オブジェクトを for 文で処理する」サンプルコードを紹介します。

複数のセルに対して同じ処理を行いたい場合、セルの開始位置から終了位置までを for文 で繰り返し、そのループ内で getRange(row, column) とするコードが一般的ではないでしょうか。

もちろんそれでも問題ないのですが、同じ処理でも Range オブジェクトに対する for 文で実現すると、ソースコードの意味が分かりやすくなったり読みやすくなったりします。

どちらが良いかはケースバイケースの面もあるかと思いますが、このような書き方が出来ることを知っておけばコーディングの幅も広がりますので是非読んでみてください。

サンプルコード

コード.gs

function myFunction() {
  var range = SpreadsheetApp.getActive().getSheetByName("シート1").getRange("B3:C5");
  checkRange(range);
}

// Rangeオブジェクトの値をチェックして結果をメモに設定する
function checkRange(range) {
  
  // Rangeオブジェクトを左上から右下に捜査する
  for(var row = 1; row <= range.getNumRows(); row++) {
    for (var column = 1; column <= range.getNumColumns(); column++) {
      
      // 処理対象のセルを取得
      var cell = range.getCell(row, column);
      
      // 値に問題がないかチェックし、結果をメモに設定する
      var result = checkNumber(cell.getValue());
      cell.setNote(result);
      
      // 値に問題があった場合は背景色を黄色、ない場合は白を設定する
      if (result != "") {
        cell.setBackground("yellow")
      } else {
        cell.setBackground("white")
      }
      
    }
  }
}

// 値のチェック結果を返却する(問題ない場合は空白を返す)
function checkNumber(value) {
  
  // 半角数字のみチェック
  if (/[^0-9]/.test(value)) return "半角数字以外が入力されています。";
  
  // 0~100の範囲チェック
  if (value < 0 || 100 < value ) return "0~100の範囲で入力してください。";
  
  // チェックにひっかからなければ問題ないと判断し空白を返す
  return "";
}

実行の流れ

  1. B3:C5 の範囲に処理対象データを用意します。今回は値が 0~100の範囲でないものはエラーにする想定でデータを用意しました。 f:id:rokuni62:20171019111915p:plain

  2. スクリプトエディタより myFunction を実行すると、不正な値は背景色が黄色になり、不正な理由がメモに設定されます。 f:id:rokuni62:20171019111924p:plain

解説

(1) まず myFunction() を実行します。

function myFunction() {
  var range = SpreadsheetApp.getActive().getSheetByName("シート1").getRange("B3:C5");
  checkRange(range);
}

ここでは B3:C5 の範囲を Range オブジェクトとして取得し、そのまま checkRange(range) メソッドに渡しています。 渡す引数が range だけで済むのでコードをスッキリ見せることが出来ます。

もし for 文の中で getRange(row, column) するやり方だと、以下5つの引数を用意することになるでしょう。

  1. Sheetオブジェクト
  2. 開始行(3行目)
  3. 開始列(2列目)
  4. 終了行(5行目)
  5. 終了列(3列目)

(2) 次に Range オブジェクトを for 文で処理します。

// Rangeオブジェクトの値をチェックして結果をメモに設定する
function checkRange(range) {
  
  // Rangeオブジェクトを左上から右下に捜査する
  for(var row = 1; row <= range.getNumRows(); row++) {
    for (var column = 1; column <= range.getNumColumns(); column++) {
      
      // 処理対象のセルを取得
      var cell = range.getCell(row, column);
      
      …(中略)…
      
    }
  }
}

Range オブジェクトは Cell が二次元配列のように格納されているイメージなので、二次元配列と同じような形の for 文になります。

二次元配列をループさせる時との違いは以下の 3 つです。

  1. ループが 1 から始まる(配列は 0 から)
  2. ループの終点は getNumRows()getNumColumns() で取得する
  3. セル は getCell(row, column) で取得する

(3) 最後にループ内で各セルのチェック処理を行っています。

      // 値に問題がないかチェックし、結果をメモに設定する
      var result = checkNumber(cell.getValue());
      cell.setNote(result);
      
      // 値に問題があった場合は背景色を黄色、ない場合は白を設定する
      if (result != "") {
        cell.setBackground("yellow")
      } else {
        cell.setBackground("white")
      }
// 値のチェック結果を返却する(問題ない場合は空白を返す)
function checkNumber(value) {
  
  // 半角数字のみチェック
  if (/[^0-9]/.test(value)) return "半角数字以外が入力されています。";
  
  // 0~100の範囲チェック
  if (value < 0 || 100 < value ) return "0~100の範囲で入力してください。";
  
  // チェックにひっかからなければ問題ないと判断し空白を返す
  return "";
}

この記事の本筋ではないため簡単な説明になりますが、ここでは以下処理を行っています。

  1. 値のチェック処理を行う

    1. 半角数字以外が入力されているとエラー
    2. 0~100の範囲でない場合はエラー
  2. チェック結果をもとに処理を行う

    1. エラー内容をセルのメモに設定(エラーがない場合は空白になる)
    2. エラーの場合は背景色を黄色、そうでない場合は白に設定

メモの設定は setNote(note)、背景色の設定は setBackground(color) で行っており、どちらも Range クラスに属するメソッドですが、Cell も Range クラスに属しているため問題なく使用できます。

Range と Cell は用途によって呼び分けられているだけで、どちらも Range オブジェクトです。Cell は Range の中でも単一セルを指す場合に使用されます。

さいごに

Range オブジェクトを for 文で処理する方法の説明は以上となります。

繰り返しになりますが、この方法を使えば Range オブジェクト関連の処理をメソッドにする場合に引数を少なくできますし、「Range オブジェクトに対して処理をする」という意味合いが強まり、コードが読みやすくなるかと思いますので、是非試してみてください。