GAS関数をスプレで使用している場合
例えばこういう状態
/**
* シート名を取得
*/
function GET_SHEET_NAME() {
return SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getSheetName();
}
GASで参照先、例えばシート名を変えても、再計算しない
どうしたら再計算できる?
これがググってもなかなかわからなかったので、以下実験結果です。
他にも方法あるかもです。
【手動】
セルの数式をいったん削除し、手動で再入力する
【GAS】
セルの数式をいったん削除し、別のトランザクション(一度スプレを保存的な?)で再入力
スプレ全体のセルの座標を読み込みなおすような処理
たぶん、Excelでいうところの保存アクションを挟みたい。
【OKパターン】
(数式削除)→(保存アクション)→(再入力)
(行を追加)→(Excelがセルの座標?を再計算する)→(A1を参照してたらB1になったりする)→(GAS関数呼んでるセルも再計算される)
【NGパターン】
(数式削除)→(すぐさま再入力)
ということで、最も手っ取り早いのが、最上部に1行追加→すぐさま削除、です。
(再計算の影響で処理が重いかもだけど。。)
ということでデモ乗せときますね
/**
* メニューを追加
*/
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」ボタンによって、以下の処理を行います。
- 現シート(今回はtestシートでやります)をコピー
- コピーしたシートの名前を「NEW_SHEET」に変更
- コピーしたシートをアクティブ(表示するってこと)
- コピーしたシートを一番左にもってくる
- コピーしたシート上のGAS関数を再計算(1行追加+1行削除)
スプレ上の関数はこう
="this is ["&GET_SHEET_NAME()&"]"
="右隣のシートは「"&GET_PREV_SHEET_NAME()&"」です。"
=GET_SHEET_NAME()
それぞれ、自分のシート名や、隣のシート名を参照するようにしているので
シートをコピーした際(いちばん右に作成される)や、シート名更新したとき、シートを移動したときに再計算される必要があるが、
デフォルトだとしてくれないので、1行追加して1行削除してあげよう。
失敗版が見たい人は、refresh()の部分だけ消してためしてみてね