【GAS小ネタ】getRangeで指定するセルを定数定義するときの工夫

【GAS小ネタ】getRangeで指定するセルを定数定義するときの工夫

スプレッドシートでセルの操作をするときには、次のようにgetRangeメソッドで、セルを指定します。

たとえば、1行1列目から4行、3列分のセルの値を取得するには、次のように入力します。

const values = SpreadsheetApp.getActiveSheet()
  .getRange(3, 1, 4, 5)
  .getValues();

ただ、このように、セルの場所(=getRangeメソッドの引数である「3」「1」「4」「5」)を直接入力してしまうと、シート構成が変わったときの修正が大変になりがちです。

このような数字は、あらかじめ、プログラムの先頭で、定数で定義をすると楽になります。

普通に定数定義をすると、変数の数が増えて大変

とはいえ、1つ1つ定数で定義していくと、変数の数が増えてしまい、逆に管理が大変になります。

//入力欄の場所
const rowStart = 3;
const columnStart = 1;
const rowLength = 4;
const columnLength = 5;

//入力欄に入力された内容を取得
const values = SpreadsheetApp.getActiveSheet()
  .getRange(rowStart, columnStart, rowLength, columnLength)
  .getValues();

さらに、定数として定義したいセルが複数あると、別々の変数名を付けなければいけないので、非常に大変です。

//入力欄の場所
const inputRowStart = 3;
const inputColumnStart = 1;
const inputRowLength = 4;
const inputColumnLength = 5;

//処理に必要な情報が入力されている場所
const configRowStart = 1;
const configColumnStart = 1;

//入力欄に入力された内容を取得
const values = SpreadsheetApp.getActiveSheet()
  .getRange(
    inputRowStart,
    inputColumnStart,
    inputRowLength,
    inputColumnLength
  )
  .getValues();

//処理に必要な情報を取得
const config = SpreadsheetApp.getActiveSheet()
  .getRange(configRowStart, configColumnStart)
  .getValue();

いくら、定数で定義したほうが良いといっても、ここまでくると手間をかけすぎているように感じます。

オブジェクトを使って同じ変数名を使いまわす

別々の変数名を付けないといけない問題については、次のように、オブジェクトを使って、それぞれの変数をひとまとめにすることで改善します。

//入力欄の場所
const inputRange = {
  rowStart: 3,
  columnStart: 1,
  rowLength: 4,
  columnLength: 5,
};

//処理に必要な情報が入力されている場所
const configRange = {
  rowStart: 1,    // 同じ変数名が使える
  columnStart: 1, // 同じ変数名が使える
};

//入力欄に入力された内容を取得
const values = SpreadsheetApp.getActiveSheet()
  .getRange(
    inputRange.rowStart,
    inputRange.columnStart,
    inputRange.rowLength,
    inputRange.columnLength
  )
  .getValues();

//処理に必要な情報を取得
const config = SpreadsheetApp.getActiveSheet()
  .getRange(configRange.rowStart, configRange.columnStart)
  .getValue();

とはいえ、プログラムは相変わらず長いままです。

(おすすめ)配列で定義してスプレッド構文を使う

V8ランタイムを使っている場合には、次のように「配列」を使ってセルの範囲を定義すると、簡潔にプログラムを書くことができます。

const inputRange = [3, 1, 4, 5];
const configRange = [1, 1];

//入力欄に入力された内容を取得
const values = SpreadsheetApp.getActiveSheet()
  .getRange(...inputRange)
  .getValues();

//処理に必要な情報を取得
const config = SpreadsheetApp.getActiveSheet()
  .getRange(...configRange)
  .getValue();

セルの範囲は、配列を使って定義をします(1行目、2行目)。

そして、スプレッド構文を使ってgetRangeの引数に設定しましょう(6行目、11行目)。

こうすることで、簡潔に、getRangeメソッドに引数を指定することができます。

なお、スプレッド構文を使うためには、V8ランタイムを使う必要があるので、注意してください。

clasp環境でTypeScriptを使って書く場合、上の書き方では、getRangeメソッドの行で「Expected 1-4 arguments, but got 0 or more.」というエラーが出るときがあります。

そのときには、配列の定義時に「as const」を付けてください。これで、エラーが消えます。

const inputRange = [3, 1, 4, 5] as const;
const configRange = [1, 1] as const;
  
//入力欄に入力された内容を取得
const values = SpreadsheetApp.getActiveSheet()
  .getRange(...inputRange)
  .getValues();
  
//処理に必要な情報を取得
const config = SpreadsheetApp.getActiveSheet()
  .getRange(...configRange)
  .getValue();

getLastRow()を使う場合の書き方

実際のプログラムでは、セルの範囲を完全に固定せず、「Range.getLastrow()」を使って、表に入力された最終行までの値を取得したい場合もあると思います。

その場合は、次のように書くことができます。

//最終行取得
const lastRow = SpreadsheetApp.getActiveSheet().getLastRow();

//変数lastRowを使って範囲を指定
const inputRange = [3, 1, lastRow - 2, 5];
const configRange = [1, 1];
  
//入力欄に入力された内容を取得
const values = SpreadsheetApp.getActiveSheet()
  .getRange(...inputRange)
  .getValues();
  
//処理に必要な情報を取得
const config = SpreadsheetApp.getActiveSheet()
  .getRange(...configRange)
  .getValue();

「変数inputRange」を定義するときに「getLastRowメソッドの計算結果」を参照することで、シートの状況に合わせて何行取得するかを決めることができます。

まとめ

getRangeメソッドで指定するセル範囲は、配列を使って定義しましょう。