GASはプログラミング初学者が学ぶのにありかもしれない話

# はじめに

## 自己紹介

こんにちは。アベです。

普段はプロジェクトマネージャーをやりつつ自分でもコードを書いている、業界で言うところのプレイングマネージャーをやっています。
エンジニアとしては、Flutterを使ったスマホアプリ開発やNext.jsを使ったWebフロントエンド開発が得意分野です。

そんな僕に、最近プログラミング未経験者からプログラミング教えて的な相談が増えてきまして、
そこで、効率化も兼ねて**プログラミング初学者が学ぶのにあり**だと思う**GoogleAppsScript**という言語を紹介します。

## GoogleAppsScriptとは

通称**GAS**と言います。以下GASとします。
GASは、Googleスプレッドシート上で書けるプログラミング言語です。
JavaScriptという言語とほぼ同じ書き方ができるのが特徴です。

## なぜGASがいいのか

### JavaScriptライク

GASは、**JavaScriptという言語とほぼ同じ書き方**ができます。
JavaScriptは、今最もフロントエンドで使われている言語の１つで、バックエンドでも一部使われています。
つまり、GASを通してフロントエンド/バックエンド問わず**Web開発に入りやすい**というのが魅力になります。

### 環境構築が楽

通常の言語だと、言語自体もそうですが、プログラムを書くためのIDEやエディタ、プログラムを実行するためのコンパイラやVM（仮想マシン）などが必要になってきます。
また、それらのパッケージはバージョンによって構築方法などが異なる場合が多く、ネットで調べてもさまざまな情報が出てきてうまくいかないこともザラです。
そのため、「よし、実際にプログラムを書いてみよう！」とせっかく意気込んでも、その前の環境構築でつまづいてしまい、プログラムを書き始める前に挫折したなんて話も聞きます。

しかしGASの場合、Googleスプレッドシートにログインできれば最低限の環境は整っており、**Googleアカウントさえあれば**ログインできます。
なので、「よし、実際にプログラムを書いてみよう！」と**意気込んだ直後には書き始められる**というのが大きいですね。

### 成果がわかりやすい

実際にプログラムを書いて実行してみても、それで得られた成果がわかりにくいとその次に進みにくかったりします。
例えばいきなりバックエンドの開発をしたところで、「で、これで何ができるの？」となりかねません。

しかしGASの場合、**Googleスプレッドシートに結果を反映**できます。
業務でPCを使う民の場合、ほとんどはExcelを含むスプレッドシートを避けては通れません。そういう意味では誰でも使う**スプレッドシートであれこれできる**のはわかりやすいだろうと僕は考えています。

# 実践

## 準備する

早速使っていきましょう。

### Googleスプレッドシートを開く

1. Googleを開きます
1. 右上のルービックキューブのようなアイコンをクリックします
![スクリーンショット 2023-08-04 0.48.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500613/b87a47c1-0c2c-bb4c-0f64-001219dd8aaa.png)

1. スクロールすると出てくる「スプレッドシート」をクリックします
![スクリーンショット 2023-08-04 0.49.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500613/d4ec4266-ec39-8e08-904e-0b4e522311eb.png)

1. 「空白」をクリックして新しいスプレッドシートを作ります
![スクリーンショット 2023-08-04 0.49.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500613/00c4d9c9-185e-5278-957f-c1ea7c9f1cc4.png)

1. 新しいスプレッドシートを開きました
![スクリーンショット 2023-08-04 0.49.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500613/01ee583a-72cd-6963-f2d6-445ad4d5276e.png)


### GASのエディタを開く

エディタとは、実際にプログラムを書く部分のことです。

1. [拡張機能]-[Apps Script]をクリックします
![スクリーンショット 2023-08-08 0.30.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500613/b6e51be0-dc7c-34b2-a985-8e0176e37150.png)

1. GASのエディタが開きました
![スクリーンショット 2023-08-08 0.34.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500613/7a115570-d547-4ff6-9be5-b34904527090.png)

## 途中解説

### functionとは

関数を定義するときに書きます。
関数とは、`{`から`}`までの処理を上から順に実行する塊です。
関数を定義すると、別の関数から呼び出すことができます。

###  myFunction()とは

関数の名前です。自由に定義できます。
`()`の中は空でも書けるし引数を定義することもできます。

引数を定義した場合、関数の呼び出し元で値を渡し、関数の中でその値を実行することができます。

## 簡単なプログラムを書いて実行してみる

### コンソールログにテキストと数値を出力する

> console.logとは、JavaScriptの標準的な実装に組み込まれている機能の一つで、実行環境に用意された文字による入出力画面（コンソール）に指定された文字列を出力（表示）するもの。

意味わかんないですよね、とりあえず書いてみましょう。

1. myFunction()の中にコンソールログの出力処理を書きます。

``` javascript
function myFunction() {
  // added
  console.log('ログだよ');
  console.log(5);
}
```

書いてみると途中で入力補助が出てくるので、全部手打ちしなくていいのは楽ですね。

「ログだよ」というテキストを`'`（シングルクォーテーション）で囲っていますが、これは`'`の中に書いたものがテキストであること示しています。
逆に、`5`は`'`で囲っていませんが、これは数値を表しています。`'5'`のように`'`で囲うとテキスト扱いになります。テキストと数値の違いは後述します。

また、各文末に`;`（セミコロン）がありますが、これはそのまま文末を表す記号です。ここでこの処理は終わりですよってことです。

![スクリーンショット 2023-08-08 1.33.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500613/60095423-7aae-a535-de45-c2a1a72c1828.png)

1. 「プロジェクトを保存」のアイコンをクリックします。

![スクリーンショット 2023-08-08 1.54.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500613/8114645a-b42b-be4a-f3b1-875d02c155a8.png)

エディタに書いたプログラムは、書いただけでは保存されないのでこれで保存されます。保存すると、「実行」から右のアイコンがクリックできるようになります。
また、「myFunction ▼」というドロップダウンがありますが、これはどの関数を実行するか？という設定です。

1. 「実行」をクリックします。

![スクリーンショット 2023-08-08 1.53.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500613/4124605e-4b88-f141-0b72-522a26c281d7.png)

実行すると、エディタの下に「実行ログ」というビューが生えてきます。
実行ログには、「実行開始」と「実行完了」のお知らせがあり、それぞれプログラムの実行と実行の完了を表しています。
「実行開始」と「実行完了」の間には「情報」とありますが、これが前述のコンソールログに値するものです。

`console.log()`の中に記載した`ログだよ`と`5`がそれぞれ出力されているのがわかります。

### 引数に数値を与え、倍の数を返す関数を作ってみる

1. myFunction()の下にgetDouble()を定義します。

``` javascript
function myFunction() {

}

// added
function getDouble() {

}
```

実行内容が空の新しい関数が定義できました。
予想はついていると思いますが、同じ名前の関数は2つ以上定義できません。

ちなみに、さっきからさらっと`// added`と書いていますが、これはコメントと言います。コメントは、エディタ内にプログラムのように書けるが実行されないテキストになります。
自分が書いたプログラムを見返したときに、例えば「これってどんなことする関数だっけ？」とならないように、適度にコメントを書いておくとわかりやすくなります。

1. getDouble()に引数を定義します。

``` javascript
function myFunction() {

}

// added
function getDouble(number) {

}
```

引数の名前も自分で定義できます。ここでは`number`とします。
これで呼び出し元から値を渡すことができます。

1. numberの値を倍にし、変数に入れます。

``` javascript
function myFunction() {

}

function getDouble(number) {
  // added
  let double = number * 2;
}
```

変数とは、値を格納する箱のようなものです。
ここでは`double`という名前の変数を定義し、`number`の数を倍にした値を格納しています。
`double`は`getDouble()`内に定義した変数のため、`myFunction()`など`getDouble()`外では使用できません。

変数を定義するには、主に`let`を使用します。
変数の定義には`let`の他に`var`があり、また`const`という定数の定義もありますが、ここは割愛します。

numberは数値が来る想定なので計算ができます。それが前述したテキストと数値の違いになります。テキストはこのような計算ができません。
四則演算で言うと、足し算は`+`、引き算は`-`、掛け算は`*`、割り算は`/`を使います。他にも計算記法がありますが、これも割愛します。

1. myFunction()からgetDouble()を実行してみる

``` javascript
function myFunction() {
  // added
  getDouble(2);
}

function getDouble(number) {
  let double = number * 2;
}
```

![スクリーンショット 2023-08-08 2.19.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500613/87c1bceb-b358-7f9d-f4c7-ef0d2036d23f.png)

無事に実行されました。しかし`cosole.log()`を書いてないため実行ログで値が見れません。
これでは計算内容が合っているかわかりませんね。

ただ、`getDouble()`内に`cosole.log()`を書いたのではあまり意味がありません。`getDouble()`は「引数に数値を与え、倍の数を返す」ための関数であり、返してほしいのは`myFunction()`だからです。

では、どのように`getDouble()`の中で計算された値を返すのでしょうか。

1. getDouble()の計算結果を返す

``` javascript
function myFunction() {
  // added
  let double2 = getDouble(2);
  console.log(double2);
}

function getDouble(number) {
  let double = number * 2;
  // added
  return double;
}
```

関数の中の値をどのように返すか、それは`return`を使います。
`getDouble()`の中で計算した結果を格納した結果`double`を`return`で返しています。
そうすると、`getDouble()`を実行している`myFunction()`で受け取れるようになります。
これを**戻り値**といいます。

ただ、それだけだと受け取れるようになっただけで実際には受け取っていません。
なので`let double2 = getDouble(2);`のように`getDouble()`の戻り値を`double2`という変数に格納しています。
そして`double2`をコンソールログとして出力しています。

実行結果を見てみましょう。

![スクリーンショット 2023-08-08 2.30.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500613/0c503d8b-8e5f-dfbb-24af-955095ccccd5.png)

引数として渡した`2`の倍の数である`4`が出力されました。
これで「引数に数値を与え、倍の数を返す」関数の実行と確認ができましたね。

これまではmyFunction()内で完結するプログラムを書いてきましたが、これではまだ「それで何ができるの？」という状態です。
ここからは実際に何ができるかの部分に触れていきます。

## スプレッドシートと連携する

GASの特徴として、Googleスプレッドシートと連携しシートからデータを取得して加工しシートに反映することができます。
そこまでできれば実用的な使い方もできると思いますので、実際にやっていきましょう。

### スプレッドシートの特定のセルから値を取得する

セルA1から値を取得する処理を書きます。

1. あらかじめセルA1に値を入れておく

セルA1の値をGASで取得するため、あらかじめ値を入れておきます。

![スクリーンショット 2023-08-08 19.24.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500613/548fb7e2-059f-88bd-9607-1580facfdc13.png)

1. セルA1から値を取得する

先ほどセルに入れた値をGASから取得してみます。
SpreadsheetAppのActiveSheetのRangeの中にある`getValue()`という関数を使います。

``` javascript
function myFunction() {
  // テキストでセル位置（A1）を引数として渡し、そのセルの値を取得
  let value = getSellValue('A1');
  console.log('A1', value);
}

// 指定したセル位置の値を返す関数
function getSellValue(sell) {
  // 1. 現在のスプレッドシートを取得
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  // 2. 現在のシートを取得
  var sheet = spreadsheet.getActiveSheet();
  // 3. 引数で指定したセルの範囲を取得
  var range = sheet.getRange(sell);
  // 4. 値を取得する
  var value = range.getValue();
 
  return value;
}
```

ちなみにSpreadsheetAppからgetValue()までを1行で書くこともできますが、メンテ性と可読性が悪いのでちゃんと分けましょう。

![スクリーンショット 2023-08-09 23.36.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500613/068b38b5-8443-7f29-1e2b-30c75ce50852.png)

無事にセルA1の値を取得できました。
次はセルへの書き込みをしてみましょう。

### スプレッドシートの特定のセルに値を書き込む

セルA2に値を書き込む処理を書きます。

GASからセルに値を書き込みます。
SpreadsheetAppのActiveSheetのRangeの中にある`setValue()`という関数を使います。

``` javascript
function myFunction() {
  // テキストでセル位置（A1）を引数として渡し、そのセルの値を取得
  let value = getSellValue('A1');
  console.log('A1', value);

  // テキストでセル位置（B1）と書き込む値を引数として渡し、指定のセルに指定の値を書き込む
  setSellValue('B1', 'A1:' + value);
}

// 指定したセル位置の値を返す関数
function getSellValue(sell) {
  //1. 現在のスプレッドシートを取得
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  //2. 現在のシートを取得
  var sheet = spreadsheet.getActiveSheet();
  //3. 指定するセルの範囲（A1）を取得
  var range = sheet.getRange(sell);
  //4. 値を取得する
  var value = range.getValue();
 
  return value;
}

// 指定したセル位置に値を書き込む関数
function setSellValue(sell, value) {
  //1. 現在のスプレッドシートを取得
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  //2. 現在のシートを取得
  var sheet = spreadsheet.getActiveSheet();
  //3. 指定するセルの範囲（B1）を取得
  var range = sheet.getRange(sell);
  //4. 値を書き込む
  range.setValue(value); 
}

```

ここで`'A1:' + value`という引数を渡していますが、テキストとテキストを`+`で繋ぐと文字列が結合されます。数値の時と`+`の挙動が違いますね。

それでは実行します。今回は書き込みがメインなので、コンソールログの確認はしません。

![スクリーンショット 2023-08-09 23.56.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500613/1840b4f8-1267-99c1-c9bb-60fa7f596bea.png)

無事にセルB1に値が書き込まれました。
これでスプレッドシートとGASとの連携はバッチリですね。

### 【おまけ】処理を共通化する

先ほど書いたプログラム、動作的には問題ないですが構造的には少し微妙なところがあります。
`getSellValue`と`setSellValue`の手順1〜3の処理がまったく同じなんですよね。手順が同じ複数の処理があるのならば、同じコードを2つ書いていることになります。無駄ですし、メンテ性も悪いです。

ここで「共通化」をすることで、この問題を解消します。

``` javascript
function myFunction() {
  // テキストでセル位置（A1）を引数として渡し、そのセルの値を取得
  let value = getSellValue('A1');
  console.log('A1', value);

  // テキストでセル位置（B1）と書き込む値を引数として渡し、指定のセルに指定の値を書き込む
  setSellValue('B1', 'A1:' + value);
}

// 指定したセル位置を返す関数
function getSellRange(sell) {
  //1. 現在のスプレッドシートを取得
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  //2. 現在のシートを取得
  var sheet = spreadsheet.getActiveSheet();
  //3. 指定するセルの範囲（A1）を取得
  return sheet.getRange(sell);
}

// 指定したセル位置の値を返す関数
function getSellValue(sell) {
  // 指定したセル位置を返す
  var range = getSellRange(sell);
  // 値を取得し、返す
  return range.getValue();
}

// 指定したセル位置に値を書き込む関数
function setSellValue(sell, value) {
  // 指定したセル位置を返す
  var range = getSellRange(sell);
  // 値を書き込む
  range.setValue(value); 
}
```

関数`getSellRange()`を新しく作り共通化した処理を入れました。
こうすることで、`getSellValue`と`setSellValue`の中身はすっきりしたかと思います。

「指定したセル位置を返す関数」と「指定したセル位置の値を返す関数」、「指定したセル位置に値を書き込む関数」のそれぞれに役割を明確にし、責任を持たせるという意図があります。

これらのフローで何かバグがあった場合、箇所を特定しやすかったり、修正箇所が少なく済んだりします。最高ですね。

# さいごに

ここまで読んでくださった方、なんなら試してくださった方、ありがとうございました。

プログラミング初学者向けの記事でしたが、いかがでしょうか。
これを読んだことでエンジニアを目指してみたり、エンジニアを目指さなくとも便利なツールとして使ってみたりと、何かのきっかけになればと思います。

それではさいなら。