数式を一括入力して列ずれする前に|GASで参照先をdry-run監査
ツールおじ|GoogleアカウントをAIエージェント化
注文表や在庫表へ数式をまとめて入れたあと、参照列が1列ずれていることに気づく。そんな手戻りは、書き込み前の設計表を機械的に点検すると減らせます。
この記事では、数式をセルへ書き込まず、対象シート・出力列・参照列・行範囲を確認して、投入予定の式だけをログへ出す無料GASを紹介します。既存セルの値や数式は変更しません。
この例は数式を書き込まず、設計ミスだけを探します
- 対象は、自分が管理しているGoogleスプレッドシートです。
- FormulaPlanシートに数式の設計を1行ずつ記入します。
- 関数種別は IF_BLANK と SUM_RANGE の2種類に限定します。
- 対象シート、列記号、開始行、終了行を検証します。
- 確認結果は実行ログへ出します。セルへの書き込み、シート作成、メール送信、ファイル作成は行いません。
- セルの中身はログへ出しません。ログに残るのは設計表の行番号、判定、投入予定の式だけです。
数式が業務ルールとして正しいかどうかは、このコードだけでは判断できません。たとえば送料計算、税区分、在庫引当の条件は運用ごとに異なるため、担当者が仕様と照合してください。
FormulaPlanシートに6列を用意します
FormulaPlanという名前のシートを作り、1行目に次の見出しを入れます。
- 対象シート
- 出力列
- 関数種別
- 参照列
- 開始行
- 終了行
動きを確認するなら、対象シートに Orders、出力列に F、関数種別に IF_BLANK、参照列に E、開始行に 2、終了行に 20 と入力します。この場合は、E列が空なら空欄、値があれば「確認済み」と表示する式をF列へ入れる計画として検査されます。
SUM_RANGEは、指定した参照列の開始行から終了行までを合計する式を1件だけプレビューします。実データを使う前に、コピーしたシートと架空の少量データで試してください。
コピーして使えるdry-runコード
function auditFormulaPlanFree() {
const config = {
planSheetName: 'FormulaPlan',
dryRun: true,
maxPlans: 100,
allowedTypes: ['IF_BLANK', 'SUM_RANGE']
};
if (config.dryRun !== true) {
throw new Error('この無料例は dryRun: true のまま実行してください。');
}
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const planSheet = spreadsheet.getSheetByName(config.planSheetName);
if (!planSheet) {
throw new Error('FormulaPlanシートが見つかりません。');
}
const values = planSheet.getDataRange().getDisplayValues();
if (values.length < 2) {
throw new Error('見出しの下に設計行を1件以上入力してください。');
}
if (values.length - 1 > config.maxPlans) {
throw new Error('最初は100件以内に絞って確認してください。');
}
const expectedHeaders = ['対象シート', '出力列', '関数種別', '参照列', '開始行', '終了行'];
const headers = values[0].map(value => String(value).trim());
const missingHeaders = expectedHeaders.filter(name => !headers.includes(name));
if (missingHeaders.length > 0) {
throw new Error('不足している見出し: ' + missingHeaders.join(', '));
}
const index = Object.fromEntries(expectedHeaders.map(name => [name, headers.indexOf(name)]));
const results = [];
values.slice(1).forEach((row, offset) => {
const planRow = offset + 2;
const targetSheetName = String(row[index['対象シート']] || '').trim();
const outputColumn = normalizeColumnFree_(row[index['出力列']]);
const formulaType = String(row[index['関数種別']] || '').trim().toUpperCase();
const referenceColumn = normalizeColumnFree_(row[index['参照列']]);
const startRow = Number(row[index['開始行']]);
const endRow = Number(row[index['終了行']]);
if (![targetSheetName, outputColumn, formulaType, referenceColumn].every(Boolean)) {
results.push({ planRow, status: 'INPUT_HOLD', reason: '必須項目に空欄があります' });
return;
}
if (!config.allowedTypes.includes(formulaType)) {
results.push({ planRow, status: 'INPUT_HOLD', reason: '未対応の関数種別です' });
return;
}
if (!isSafeColumnFree_(outputColumn) || !isSafeColumnFree_(referenceColumn)) {
results.push({ planRow, status: 'INPUT_HOLD', reason: '列はA〜ZZZの範囲で指定してください' });
return;
}
if (!Number.isInteger(startRow) || !Number.isInteger(endRow) || startRow < 2 || endRow < startRow) {
results.push({ planRow, status: 'INPUT_HOLD', reason: '行範囲を確認してください' });
return;
}
if (endRow - startRow + 1 > 1000) {
results.push({ planRow, status: 'INPUT_HOLD', reason: '最初は1000行以内に絞ってください' });
return;
}
const targetSheet = spreadsheet.getSheetByName(targetSheetName);
if (!targetSheet) {
results.push({ planRow, status: 'INPUT_HOLD', reason: '対象シートが見つかりません' });
return;
}
const maxColumn = targetSheet.getMaxColumns();
const outputColumnNumber = columnToNumberFree_(outputColumn);
const referenceColumnNumber = columnToNumberFree_(referenceColumn);
if (outputColumnNumber > maxColumn || referenceColumnNumber > maxColumn) {
results.push({ planRow, status: 'INPUT_HOLD', reason: '対象シートの列数を超えています' });
return;
}
if (outputColumn === referenceColumn) {
results.push({ planRow, status: 'INPUT_HOLD', reason: '出力列と参照列が同じです' });
return;
}
const preview = buildFormulaPreviewFree_(formulaType, targetSheetName, referenceColumn, startRow, endRow);
results.push({
planRow,
status: 'PREVIEW_ONLY',
targetRange: outputColumn + startRow + ':' + outputColumn + endRow,
formulaPreview: preview
});
});
const summary = {
dryRun: config.dryRun,
checkedPlans: values.length - 1,
previewCount: results.filter(item => item.status === 'PREVIEW_ONLY').length,
holdCount: results.filter(item => item.status === 'INPUT_HOLD').length,
sourceUpdated: false,
formulaWritten: false
};
console.log(JSON.stringify(summary));
results.forEach(item => console.log(JSON.stringify(item)));
console.log('セル値・注文内容・顧客情報はログへ出していません。');
}
function normalizeColumnFree_(value) {
return String(value || '').trim().toUpperCase();
}
function isSafeColumnFree_(column) {
return /^[A-Z]{1,3}$/.test(column) && columnToNumberFree_(column) <= 18278;
}
function columnToNumberFree_(column) {
return column.split('').reduce((total, char) => total * 26 + char.charCodeAt(0) - 64, 0);
}
function quoteSheetNameFree_(name) {
return "'" + String(name).replace(/'/g, "''") + "'";
}
function buildFormulaPreviewFree_(type, sheetName, referenceColumn, startRow, endRow) {
const sheet = quoteSheetNameFree_(sheetName);
if (type === 'IF_BLANK') {
return '=IF(' + sheet + '!' + referenceColumn + startRow + '="","","確認済み")';
}
return '=SUM(' + sheet + '!' + referenceColumn + startRow + ':' + referenceColumn + endRow + ')';
}実行手順
- 元のスプレッドシートをコピーします。
- コピー側にFormulaPlanシートと6つの見出しを作ります。
- 設計行を1件だけ入力し、拡張機能からApps Scriptを開きます。
- コードを貼り付け、auditFormulaPlanFreeを実行します。
- 初回の権限画面では、対象がコピーしたスプレッドシートであることを確認します。
- 実行ログのINPUT_HOLDを先に直します。
- PREVIEW_ONLYのtargetRangeとformulaPreviewを、人が仕様書や既存の正しい数式と照合します。
- summaryのsourceUpdatedとformulaWrittenがfalseであることを確認します。
このコードは式を投入しないため、確認後に数式を書き込む作業は別途必要です。いきなり自動書き込みへ広げず、まず参照列と行範囲が合っている設計行だけを残してください。
失敗しやすい点と制限
対象シートがない、列記号が不正、終了行が開始行より前、対象範囲が1000行を超える、といった設計行はINPUT_HOLDになります。出力列と参照列が同じ場合も、循環参照や上書きの可能性があるため停止します。
IF_BLANKのプレビューは開始行の1件だけです。各行へ展開したときに参照が意図どおり動くか、2行目と3行目を手作業で比較してください。絶対参照や複数条件、ARRAYFORMULA、外部スプレッドシート参照はこの無料例の対象外です。
Google Apps Scriptには実行時間やサービス利用量の上限があります。設計行100件、対象範囲1000行を上限にしているのは、最初から大きな表を扱わないための安全策です。
公開前に6点を確認します
- dryRunがtrueのままになっている
- sourceUpdatedとformulaWrittenがfalseになっている
- INPUT_HOLDが1件も残っていない
- 対象シートと出力列が仕様書と一致している
- formulaPreviewを少なくとも2行分、人が照合した
- 実データの値や顧客情報をログへ出していない
数式の一括入力は、書く前の設計確認から始められます
数式のミスは、式そのものより「どのシートの、どの列を、何行目から参照するか」の取り違えで起きることがあります。この無料例は数式をセルへ入れず、設計表の不備と投入予定の式だけを先に確認します。
注文・入金・発送を同じスプレッドシートで管理したい方向けに、関連する有料Tipsがあります。
個人販売の注文・発送管理GAS Proを見る

Gasおじの他の商品もTips内で確認できます。
GasおじのTips商品一覧を見る

※この記事は学習・検証用の例です。実データへ適用する前にコピー環境で確認してください。Google公式・Google公認の商品ではありません。計算結果、在庫、売上、税額、発送判断などの正しさを保証するものではありません。
