Google Apps ScriptではじめてのRPA（Googleスプレッドシート編）

#はじめに
本記事では、GASを用いたGoogleスプレッドシートでの基本的なスクリプト操作を紹介します。

Googleが提供する無料サービス(Drive, Calendar, Mail, etc…)は、仕事の成果にも直結する強力なツールです。無料で誰でも使えることもあり、多くの作業時間を充てていることと思います。その中には冗長的な作業も多くあり、大規模なデータを扱うようになるとそれだけ冗長な作業は肥大化していきます。(Googleドライブ内のファイル管理など)

そういった冗長で規格化された作業を自動化(RPA)させることができるものが「Google Apps Script」です。

#Google Apps Script(GAS)とは

GAS(ガス、ギャス)は、Googleサービスを操作することができるGoogle独自のプログラミング言語です。しかし、一からGASについて学ぶ必要はありません。

GASのベースとなるプログラミング言語は、エンジニアの中で利用機会の多い「JavaScript」です。そのため**学習コストが低く**、すぐに使えるようになっているところが魅力です。もし、JavaScriptを使ったことがない人でも、GASを学べば自然とJavaScriptの知識が身についてくると思います。

また、**環境構築の必要もなく**Googleアカウントを持っていればすぐにコードを書くことができます。


#Googleスプレッドシート

Googleスプレッドシートとは、　グーグルが提供する表計算ソフトでデータファイルを複数のユーザで共有管理することができるサービスです。ビジュアルもExcelに近いこともありエンジニア、非エンジニアともに利用します。

また、使用環境の準備はGoogleアカウントの作成のみでブラウザ上で完結し、使用料金も一切かからないため、業務上でかならず必要になるといっても過言ではない存在になっています。

以下はGoogleスプレッドシートでよく使われる用語になります。

用語|意味|
---|---|
スプレッドシート|入力したデータを管理するファイル。このファイル内でデータやシートを入力する。|
シート|スプレッドシート内のシートを指す。画面左下から順に表示され複数のシートが表示される|
セル|データを入力する領域。マス目。|
セル番地|特定のセルを表す番号。行(A~)と列(1~)で表される。(3行目9列目のセル→C9)|

![スクリーンショット 2021-08-02 22.26.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1114592/bdbb31a1-9613-c78e-fb6a-55a40d1044e9.png)
↑Googleスプレッドシートのレイアウト

# 基本操作
JavascriptはWebページ上のクリックや入力などあらゆるアクションを取得し、それに応じた動作をさせることで動的な表現を可能にしています。スプレッドシートも同様でスクリプトを実行するために、様々なセルの値やシートなどを取得して処理を行うため相性が良く、JavaScriptとGoogleサービス用の関数でスクリプトを実装します。

そこで、GASを使うために必要になる代表的な取得に関する記述を、使い道を交えて紹介します。

## GASエディタの起動
はじめに、スプレッドシートを開き、左上のツールバーから「ツール」→「スクリプトエディタ」の順でエディタを起動します。

![スクリーンショット 2021-08-01 17.28.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1114592/dcc66126-2a08-93a6-ff2a-d5c9615d6c2b.png)
↑Googleスプレッドシートの編集画面

![スクリーンショット 2021-08-01 17.16.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1114592/2ea42503-c5d1-6d09-7b5a-36c52e2cef3f.png)
↑GASのスクリプトを書くたのエディタ画面

スクリプトを実行する際、無料アカウントの場合、以下のような画面が表示されることがあります。Googleの翻訳のせいか危なそうに見えますが、あまり問題ないので赤枠の**詳細**をクリックし、**GAS Bot(安全ではないページ)に移動**を選択すると、「ようこそ」が表示されます。
![スクリーンショット 2021-08-01 18.45.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1114592/f061314d-099f-57df-6097-96ce3fd2cc65.png)

↑初回実行時に表示されることがある画面

## 1. スプレッドシートの取得
### 説明
スクリプトの実行対象とするスプレッドシートのファイルを取得します。スプレッドシート上でGASを動作させるときには必ずといっていいほど必要となる操作なので、覚えておきたい操作です。スプレッドシートの取得にはいくつ方法があります。

関数名|意味|
---|---|
SpreadsheetApp.getActiveSpreadsheet( )|スクリプトエディタを起動した際のスプレッドシートを取得|
SpreadsheetApp.openById( '[ID]' )|ID(URLの一部)を指定してスプレッドシートを取得|


![スクリーンショット 2021-08-04 18.04.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1114592/45c3ed39-1267-8f62-fcf5-9f92339a6d55.png)

↑URLのeditまでがスプレッドシートのID


### 使用例
使用しているスプレッドシートの名前を表示する
![スクリーンショット 2021-08-01 23.03.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1114592/e8017389-799e-2770-23e2-ccc54dcb9d42.png)
↑スクリプトの実行結果
### スクリプト

```javascript
//アクティブなスプレッドシートを取得し、変数spreadsheet_aに代入
let spreadsheet_a = SpreadsheetApp.getActiveSpreadsheet();

//実行ログに取得したスプレッドシートのファイル名を表示させる
console.log(spreadsheet_a.getName());
```
１行目でスプレッドシートを取得し、2行目の命令でコンソール上に表示しています。get_Name()は、スプレッドシート名やシート名の情報を取得する関数です。console.logについては、記事の末尾の[x.補足](##-5)に詳しく説明しているのでそちらを参照してください。


## 2. シートの取得
### 説明
1でスプレッドシートを取得することができましたが、スプレッドシートには一枚以上のシートが存在します。

特定のシートもしくは全てのシートのデータに対して処理するのか。それともシート自体に対して、名前の変更・コピー・削除といった処理をするなど、様々な場面で利用される関数になります。

関数名|意味|
---|---|
.getActiveSheet()|現在開いているシートを取得|
.getSheetByName('シート名')|スプレッドシート内のシート名を指定して取得|
.getSheets()|スプレッドシート内のシートをすべて取得|

### 使用例
スプレッドシート内にあるシートを全て取得して、対象外を除く全てのシートを削除する
![スクリーンショット 2021-08-04 0.29.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1114592/1ef5081e-e087-a905-2ac3-19997256924d.png)
↑このスプレッドシートが持っているシートの「シートA」「シートC」以外を一括削除したい
![スクリーンショット 2021-08-04 0.12.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1114592/d617785e-e1f4-f519-e849-ddca52b19707.png)
↑スクリプトの実行結果
![スクリーンショット 2021-08-04 0.29.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1114592/640011ae-cce7-2e7d-8a3a-aa824378ce30.png)
スクリプト実行後のスプレッドシート

### スクリプト
```javascript
  //スプレッドシートの取得
  let spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  //スプレッドシート(spreadsheet)が持つシートを全て取得
  let sheets = spreadsheet.getSheets();
  //対象外にしたいシートを配列に格納
  let sheet_required = ['シートA', 'シートC']
  
  //スプレッドシートが持つ全てのシートをひとつずつ処理(シートA → シートB → ・・・ → シートE)
  for(let i=0;i<sheets.length;i++){

    //削除を実行するか判定するための変数 (1:削除する, 0:削除しない)
    let flag = 1;

    //対象外としたいシートをひとつずつ比較(シートAか → シートCか)
    for (let j=0;j<sheet_required.length;j++){

      //シートが対象外シートか比較
      if(sheets[i].getName() == sheet_required[j]){
        console.log(sheets[i].getName()+'は対象外です。')
        //flag=0にして削除する処理を行わない
        flag = 0;
      }

    }

    //flag=1なら削除する処理を実行
    if(flag){
      console.log(sheets[i].getName()+'を削除しました。')
      //spreadsheetが持つsheet[i]を削除
      spreadsheet.deleteSheet(sheets[i]);
    }

  }
```

## 3. セルの指定・取得
### 説明
セルの指定・取得の方法を下記のスプレッドシートを例に説明していきます。
![スクリーンショット 2021-08-02 23.40.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1114592/91638479-458c-53ee-44dd-6070008dc3ab.png)
↑サンプルのスプレッドシート

#### セルの指定
まずセルの値を取得する前に、取得したいセルはどれかを指定する必要があります。セルは値や書式といった様々な情報を持っているため、セルの**情報**を取得してセルの様々な**データ**を取得するといったほうがイメージが湧きやすいと思います。

関数名|意味|
---|---|
.getRange( 'A1' )|A1のセルを取得|
.getRange( 1, 1 )|A1のセルを取得(1行目1列目)|
.getRange( 'B1:B5' )|B1~B5のセルを範囲取得|
.getRange( 1, 2, 5 )|B1~B5のセルを範囲取得(1行目2列目~5行目2列目)|
※ .getRangeの引数は ( 行, 列, 行数, 列数) で行数と列数は省略が可能。

#### セルの取得
次に、取得したセル内の値を取得します。

関数名|意味|
---|---|
.getValue()|一つのセル内の値を取得|
.getValues()|複数のセル内の値を取得|
※複数のセルの値を取得した場合、配列に格納されており[n]で取得することが可能。

### 使用例
説明で紹介したセルの指定・取得を実際に行うと以下のようになります。
![スクリーンショット 2021-08-02 23.52.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1114592/e1138580-fdb8-0bfb-b3ed-9ca05745b89f.png)
↑取得したセルの値をコンソール上に出力
### スクリプト

```javascript
//スプレッドシートの取得
let spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
//スプレッドシート(spreadsheet)が持つ、シートを取得
let sheet = spreadsheet.getActiveSheet();

//シート(sheet)内にあるセルの状態を取得
let range_1 = sheet.getRange('A1')
let range_2 = sheet.getRange(1,1);
let range_3 = sheet.getRange('B1:B5');
let range_4 = sheet.getRange(1, 2, 5);

//取得したセルの状態からデータを取得
let value_1 = range_1.getValue();
let value_2 = range_2.getValue();
let value_3 = range_3.getValues();
let value_4 = range_4.getValues();

//取得したデータをコンソール上に表示
console.log(value_1);
console.log(value_2);
console.log(value_3);
console.log(value_4);
```

##x. 補足
### 変数宣言
JavaScriptやGASには、変数宣言する際にいくつか種類があります。
従来、varが多く使われていましたが、自由度の高さから意図しないエラーが起こることが想定されるため、letやconstなどが使われます。


| |var|let|const|
|---|---|---|---|
再代入|○|○|×|
再宣言|○|×|×|
関数スコープ|○|○|○|
ブロックスコープ|×|○|○|
再代入:一度、宣言した変数を更新すること
再宣言:一度、宣言した変数をもう一度宣言すること
関数スコープ:変数の有効範囲が関数の{}内であり、関数の{}外からアクセス不可
ブロックスコープ:変数の有効範囲が{}内であり、{}外からアクセス不可
### 出力
GASの出力には基本的に２種類の方法があります。
Browser.msgBox()は処理が衝突してエラーになることがあるため、console.logがおすすめです。

関数名|意味|
---|---|
console.log()|コンソール上に文字列を表示|
Browser.msgBox()|ブラウザ上に文字列を表示|

# まとめ
スプレッドシート上で動作するGASの基本的な使い方を使用例を交えて紹介しました。

これらのGAS関数の使い方が分かれば、あとはアイデア次第で様々な処理をつくることができます。コードを考えるのに時間がかかったとしても、コードがしっかりしていれば人為的ミスなどによる手戻りは発生せず、スプリプトを実行している間に他の作業をすることもできるので作業効率の向上間違いなしです！

簡単な作業は機械に任せて、人間にしかできないことに時間をかけましょう、

# 参考文献
GAS
https://anagrams.jp/blog/google-apps-script/
https://tonari-it.com/gas-script-approval/
https://uxmilk.jp/25841
https://tonari-it.com/gas-spreadsheet-get-sheet/
JS
https://tcd-theme.com/2021/04/javascript-let-const.html?gclid=CjwKCAjwr56IBhAvEiwA1fuqGik1MV-2nYQIycU7tNlT-IFB4QpGmucob4rnpbTYfXkTX_ttqYfR8hoCOTgQAvD_BwE