2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-01-07

GAS関数をスプレで使用している場合

例えばこういう状態

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

image.png
image.png

GASで参照先、例えばシート名を変えても、再計算しない

image.png
image.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
image.png

【実行後】
image.png
image.png
image.png

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

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

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

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?