GASセルの操作まとめ

# はじめに
この記事は「[Ateam LifeDesign Advent Calendar 2023](https://qiita.com/advent-calendar/2023/ateam-life-design)」で完走賞を狙って25記事書いているうちの2日目の記事です。今年も完走目指して頑張るぞ！

# セルの操作
GASでなにかものを作るときによく使うセルの操作。今日はここにフォーカスをあててまとめていきます。
ステップは以下の通り。

1. スプレッドシート本体のオブジェクトを取得
2. 対象となるシートオブジェクトを取得
3. セルオブジェクトを取得
4. 該当のセルのオブジェクトを取得したり変更する

コードにするとこんな感じ。

```javascript:
function myFunction() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getActiveSheet();
  var range = sheet.getRange("A1");
  var value = range.getValue();
  Logger.log(value);
}
```

このシートに対して実行すると

![スクリーンショット 2023-11-19 20.51.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/a2547204-f60d-4727-efc8-ea87ebea45dd.png)

無事にリンゴが出力されました。

![スクリーンショット 2023-11-19 20.51.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/2d87e6d7-ac5a-4861-665c-580449236fc3.png)

今回はアクティブな（開いている）シートを対象として値を取得していますが、シート名をしていしたりファイル名を指定して別ファイルからデータを持ってくることも可能です。

# getRange
getRangeの引数の指定の仕方には4種類あるのでそれぞれ使い方を見ていきましょう。

## Sheetオブジェクト.getRange(“R1C1形式")
先程のサンプルで記載したように`getRange("A1")`のように指定する方法です。複数範囲の指定も可能で、`getRange(“A3:F6")`とするとA3からF6までのセルを取得することが出来ます。
ただこの指定の仕方は人が見るとわかりやすいものの、文字列（アルファベット順）で指定するため連続してとってくる指示などをプログラム中での指定がし辛く、使う頻度は少ないかも知れません。明示的に「この1つのセルをとってくる」という場合以外は使い道がないかも。

## Sheetオブジェクト.getRange(行番号, 列番号)
これは1つのセルを指定して値を取ってきたり値を入力するときに使う方法で、取得したいセルの行番号と列番号を引数に指定します。例えばB1セルを取得する場合は`getRange(1, 2)`のように指定します。
上述の通り1つのセルを指定することになるのでその後は`getValue`で値を取り出します。


```javascript:
function myFunction() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getActiveSheet();
  var range = sheet.getRange(1, 2);
  var value = range.getValue();
  Logger.log(value); // B1セルの値が出力される
}
```

## Sheetオブジェクト.getRange(行番号, 列番号, 行数)
先程のパターンに3つ目の引数として行数が追加されたかたちです。主にスプレッドシートでは行方向に情報を追加していくのでデータを1列を縦方向に取得する際に利用します。
`getRange(3,2,5)`とすると、B3:B7の合計5つのセル範囲がRnageオブジェクトとして取得されます。
今回の場合は複数のセルを取得しているため`getValue`ではなく`getValues`で値を取得します。ここで得られる配列は1次元ではなく2次元配列となるため扱う際は気をつけてください。

```javascript:
function myFunction() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getActiveSheet();
  var range = sheet.getRange(3,2,5);
  var value = range.getValues();
  Logger.log(value);
}
```

このシートに対して上記のスクリプトを実行すると

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/15280d8c-4e71-96fa-4fc0-12183f769359.png" width="400">

こんな実行結果が得られます。2次元配列になってますね。

![スクリーンショット 2023-11-19 21.15.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/afda0840-dbad-a5de-d985-3d2f1225a8d3.png)

でもこうやってとってきた値ってだいたい1次元配列で使いたいことのほうが多くないですか？そんなことない？？？
そんなときはこうしてやることで1次元配列に変換してやることができます。

```javascript:
var value = range.getValues().flat().filter(Number).map(Number);
```

1次元になった。

![スクリーンショット 2023-11-19 21.35.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/0957cd01-2535-ac4e-e7b7-7ec9949e5a01.png)


## Sheetオブジェクト.getRange(行番号, 列番号, 行数, 列数)
先程のものに4つ目の引数として列を追加しています。複数列を複数行に渡って取得します。実際にGASのコードを書いてて一番使うのがこのパターンです。
`getRange(3,2,5,2)`と引数を指定すると、B3:D7のセル範囲をRangeオブジェクトとして取得されます。

```javascript:
function myFunction() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getActiveSheet();
  var range = sheet.getRange(3,2,5,3);
  var value = range.getValues();
  Logger.log(value);
}
```

これを先程と同じシートに対して実行してみると

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/c752f6d0-8bca-23c0-f63c-b79e43e64091.png" width="400">


こんな結果が得られます。こちらも二次元配列で取得されます。

![スクリーンショット 2023-11-19 21.21.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/1eb2077f-d7c6-6759-5c83-2bd71b19837b.png)

:::note info

GASの実行時間は最大6分まで（GoogleWorkspace有料プランの場合は30分）、またセルから値を取得する関数は1日で最大50,000回までという制限があります。
これらの制限に引っかからないようにするためにも関数の呼び出し回数はなるべく最小限にしてプログラム側の処理でいい感じにしてあげるほうがいいので、複数セルを取得する場合は何度も単一セル指定のgetRangeとgetValueを繰り返すより範囲指定のgetRangeとgetValuesを使うほうがおすすめです。
:::

# setValue と setValues
上記では`getRange`でセル（の範囲）を指定してをそこの値を取ってきましたが、同様に`getRange`したものに対して`setValue`してやることで値を書き込むことが出来ます。単一のセル取得をした場合は`setValue`を、複数のセル取得をした場合は`setValues`を使います。

```javascript:
function myFunction() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getActiveSheet();
  var singleRange = sheet.getRange(1,1);
  singleRange.setValue("a");
  var multiRange = sheet.getRange(3,2,3,2);
  multiRange.setValues([["b", "c"], ["d", "e"], ["f", "g"]]);
}
```

実行結果はこちら。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/7c3164b2-693b-0a1b-b5cb-202bd5ee2267.png" width="500">


# 最後に
今日はGASの中でも利用頻度が高いセルの操作についてまとめました。
まだこれだけだとなかなか便利なものが出来るイメージが湧かないと思うので明日からは実際にものを作りながらその中で使った関数について説明していきます。