GAS関数をスプレ上で再計算する

## GAS関数をスプレで使用している場合
例えばこういう状態

```gas.js
/**
 * シート名を取得
 */
function GET_SHEET_NAME() {
  return SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getSheetName();
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/c61256e9-4c25-1bcf-e97a-2a4afb992e23.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/e07d5442-f481-fd8d-9934-f647d8a6ad18.png)

## GASで参照先、例えばシート名を変えても、再計算しない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/59b6c9b4-da28-0250-0048-1964d2734d69.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/20860541-7dc5-daab-9a74-17248cb9fa32.png)

## どうしたら再計算できる？
これがググってもなかなかわからなかったので、以下実験結果です。
他にも方法あるかもです。

【手動】
セルの数式をいったん削除し、手動で再入力する

【GAS】
セルの数式をいったん削除し、別のトランザクション(一度スプレを保存的な?)で再入力
スプレ全体のセルの座標を読み込みなおすような処理

たぶん、Excelでいうところの保存アクションを挟みたい。

【OKパターン】
(数式削除)→(保存アクション)→(再入力)
(行を追加)→(Excelがセルの座標?を再計算する)→(A1を参照してたらB1になったりする)→(GAS関数呼んでるセルも再計算される)

【NGパターン】
(数式削除)→(すぐさま再入力)

ということで、最も手っ取り早いのが、最上部に1行追加→すぐさま削除、です。
(再計算の影響で処理が重いかもだけど。。)

## ということでデモ乗せときますね

```sample_gas.js
/**
 * メニューを追加
 */
function onOpen() {
  var ui = SpreadsheetApp.getUi()
  var menu = ui.createMenu("test");
  menu.addItem("test","function1");
  menu.addToUi();
}

/**
 * シートをコピー、リネーム、最前に移動
 */
function function1() {
  let book = SpreadsheetApp.getActiveSpreadsheet();
  let currentSheet = book.getActiveSheet();
  let newSheet = currentSheet.copyTo(book);
  // コピーされた段階で、シート内のGAS関数は計算が終わっている
  // 追加でシート名とか順番変えても、適用されない
  newSheet.setName('NEW_SHEET');
  newSheet.activate();
  book.moveActiveSheet(1);
  refresh();
}

/**
 * シート名を取得
 */
function GET_SHEET_NAME() {
  return SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getSheetName();
}

/**
 * 自分の右のシート名を取得
 */
function GET_PREV_SHEET_NAME() {
  let currentName = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getSheetName();
  let allSheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
  let currentIndex = allSheets.findIndex(v => v.getName() == currentName);
  return allSheets[currentIndex + 1].getName();
}

/**
 * シート名を読み込むGAS関数などを再読み込みさせる
 */
function refresh() {
  let sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  // 行追加などのアクションによってシート全体のGASが再計算される
  sheet.insertRows(1, 1);
  sheet.deleteRows(1, 1);
  // 以下は本来不要。
  // 別の方法として
  // セルの値をそのまま再代入しても、GAS関数は再計算されないが
  // 別のセルに一度Formulaをうつして、再度戻せばGAS関数を再計算できる
  let tmp = sheet.getRange('A1').getFormula();
  sheet.getRange('A1').setValue(null);
  sheet.getRange('B1').setValue(tmp);
  let tmp2 = sheet.getRange('B1').getFormula();
  sheet.getRange('B1').setValue(null);
  sheet.getRange('A1').setValue(tmp2);
  // これだと他のセルを作業場所として犠牲にしちゃう。
  // じゃあ行追加して作業場所を一時的に作ろう→行追加だけで再計算されるので不要
}

```

メニューバーに追加した「test」ボタンによって、以下の処理を行います。
1. 現シート(今回はtestシートでやります)をコピー
2. コピーしたシートの名前を「NEW_SHEET」に変更
3. コピーしたシートをアクティブ(表示するってこと) 
4. コピーしたシートを一番左にもってくる
5. コピーしたシート上のGAS関数を再計算(1行追加+1行削除)

【実行前】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/b5d4bbb0-0d6a-f09b-7922-f1722374393f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/704b56db-bdd2-84b1-1454-c5842686dbe8.png)

【実行後】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/96059534-4665-6bc3-4798-8854966b0b58.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/b55bd9e2-f91c-2e0f-1779-1ba7edce52ea.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/c8428d8a-4e8f-30aa-7282-3f2befc6d11e.png)

スプレ上の関数はこう
`="this is ["&GET_SHEET_NAME()&"]"`
`="右隣のシートは「"&GET_PREV_SHEET_NAME()&"」です。"`
`=GET_SHEET_NAME()`

それぞれ、自分のシート名や、隣のシート名を参照するようにしているので
シートをコピーした際(いちばん右に作成される)や、シート名更新したとき、シートを移動したときに再計算される必要があるが、
デフォルトだとしてくれないので、1行追加して1行削除してあげよう。

失敗版が見たい人は、refresh()の部分だけ消してためしてみてね