PDF保存後に範囲ずれへ気づく前に|GASで出力設定をdry-run監査
ツールおじ|GoogleアカウントをAIエージェント化
月次レポートをPDFにしてから「右端の列が切れた」「対象シートを間違えた」「ファイル名に使えない文字が入っていた」と気づくと、確認と作り直しが発生します。
この記事では、PDFを作成する前に、対象シート・出力範囲・用紙・向き・余白・ファイル名を検査し、確認計画だけを別シートへ出す無料GASを紹介します。コードはPDF作成やDrive保存を行わず、元シートも変更しません。
先に知っておきたいこと
- できること: PDF出力設定の空欄、存在しないシート、範囲外指定、用紙や向きの表記ミス、危険なファイル名、余白の上限超過を事前に確認できます。
- できないこと: PDFの見た目を完全に再現したプレビュー、改ページ位置の保証、PDF作成、Drive保存、メール送信は行いません。
- 安全設計: dry-run固定です。入力元を更新せず、個別のセル値もログへ出しません。
- 必要な権限: 対象スプレッドシートの閲覧・編集権限が必要です。DriveやGmailの権限は使いません。
準備するシート
スプレッドシートに「PDF設定」シートを作り、1行目へ次の見出しを置きます。
- 対象シート
- 出力範囲
- ファイル名
- 用紙
- 向き
- 上余白mm
- 下余白mm
- 左余白mm
- 右余白mm
- 有効
入力例は「売上サマリ」「A1:H45」「月次売上_2026-09」「A4」「横」「10」「10」「8」「8」「TRUE」です。出力範囲を空欄にすると、そのシートのデータ範囲を確認対象にします。
コピーして使える最小コード
function previewPdfExportPlanFree() {
const config = {
dryRun: true,
settingsSheetName: 'PDF設定',
resultSheetName: 'PDF_確認計画',
maxRows: 200,
allowedPaperSizes: ['A4', 'A3', 'LETTER'],
allowedOrientations: ['縦', '横'],
maxMarginMm: 30
};
if (config.dryRun !== true) {
throw new Error('安全のためdryRun=true以外では実行できません。');
}
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const settingsSheet = spreadsheet.getSheetByName(config.settingsSheetName);
if (!settingsSheet) {
throw new Error('PDF設定シートが見つかりません。');
}
const values = settingsSheet.getDataRange().getDisplayValues();
if (values.length < 2) {
throw new Error('PDF設定シートに確認対象の行がありません。');
}
if (values.length - 1 > config.maxRows) {
throw new Error('一度に確認できるのは' + config.maxRows + '行までです。');
}
const requiredHeaders = [
'対象シート', '出力範囲', 'ファイル名', '用紙', '向き',
'上余白mm', '下余白mm', '左余白mm', '右余白mm', '有効'
];
const headerIndexes = buildHeaderIndexes_(values[0], requiredHeaders);
const plan = [];
values.slice(1).forEach(function(row, offset) {
const rowNumber = offset + 2;
const enabled = parseBoolean_(row[headerIndexes['有効']]);
if (!enabled) {
plan.push([rowNumber, 'SKIP', '', '', '', '有効がTRUEではありません']);
return;
}
const sheetName = row[headerIndexes['対象シート']].trim();
const requestedRange = row[headerIndexes['出力範囲']].trim();
const fileName = row[headerIndexes['ファイル名']].trim();
const paperSize = row[headerIndexes['用紙']].trim().toUpperCase();
const orientation = row[headerIndexes['向き']].trim();
const issues = [];
if (!sheetName) issues.push('対象シートが空欄');
const targetSheet = sheetName ? spreadsheet.getSheetByName(sheetName) : null;
if (sheetName && !targetSheet) issues.push('対象シートが存在しない');
if (!fileName) {
issues.push('ファイル名が空欄');
} else if (/[\\/:*?"<>|]/.test(fileName)) {
issues.push('ファイル名に使用しにくい記号を含む');
} else if (fileName.length > 120) {
issues.push('ファイル名が120文字を超える');
}
if (config.allowedPaperSizes.indexOf(paperSize) === -1) {
issues.push('用紙はA4・A3・LETTERのいずれか');
}
if (config.allowedOrientations.indexOf(orientation) === -1) {
issues.push('向きは縦または横');
}
const marginLabels = ['上余白mm', '下余白mm', '左余白mm', '右余白mm'];
marginLabels.forEach(function(label) {
const raw = row[headerIndexes[label]].trim();
const margin = Number(raw);
if (raw === '' || !Number.isFinite(margin) || margin < 0 || margin > config.maxMarginMm) {
issues.push(label + 'は0〜' + config.maxMarginMm + 'の数値');
}
});
let checkedRange = '';
let sizeSummary = '';
if (targetSheet) {
try {
const range = requestedRange
? targetSheet.getRange(requestedRange)
: targetSheet.getDataRange();
checkedRange = range.getA1Notation();
sizeSummary = range.getNumRows() + '行 × ' + range.getNumColumns() + '列';
if (range.getNumRows() === 1 && range.getNumColumns() === 1 && range.isBlank()) {
issues.push('出力範囲が空白セルのみ');
}
} catch (error) {
issues.push('出力範囲をA1形式で確認');
}
}
plan.push([
rowNumber,
issues.length ? 'HOLD' : 'READY',
sheetName,
checkedRange,
sizeSummary,
issues.join(' / ') || 'PDF作成前の確認へ進めます'
]);
});
writePdfPlan_(spreadsheet, config.resultSheetName, plan);
const readyCount = plan.filter(function(row) { return row[1] === 'READY'; }).length;
const holdCount = plan.filter(function(row) { return row[1] === 'HOLD'; }).length;
const skipCount = plan.filter(function(row) { return row[1] === 'SKIP'; }).length;
console.log(JSON.stringify({
dryRun: true,
checkedRows: plan.length,
readyCount: readyCount,
holdCount: holdCount,
skipCount: skipCount
}));
}
function buildHeaderIndexes_(headerRow, requiredHeaders) {
const normalized = headerRow.map(function(value) { return String(value).trim(); });
const duplicateHeaders = normalized.filter(function(value, index, all) {
return value && all.indexOf(value) !== index;
});
if (duplicateHeaders.length) {
throw new Error('同名の見出しがあります。');
}
const missingHeaders = requiredHeaders.filter(function(header) {
return normalized.indexOf(header) === -1;
});
if (missingHeaders.length) {
throw new Error('不足している見出し: ' + missingHeaders.join(', '));
}
return requiredHeaders.reduce(function(indexes, header) {
indexes[header] = normalized.indexOf(header);
return indexes;
}, {});
}
function parseBoolean_(value) {
return ['TRUE', '1', 'はい', '有効'].indexOf(String(value).trim().toUpperCase()) !== -1;
}
function writePdfPlan_(spreadsheet, sheetName, rows) {
let resultSheet = spreadsheet.getSheetByName(sheetName);
if (!resultSheet) resultSheet = spreadsheet.insertSheet(sheetName);
resultSheet.clearContents();
const output = [[
'設定行', '判定', '対象シート', '確認範囲', '範囲サイズ', '確認事項'
]].concat(rows);
resultSheet.getRange(1, 1, output.length, output[0].length).setValues(output);
resultSheet.setFrozenRows(1);
}実行手順
- 元ファイルではなく、まずコピーしたスプレッドシートで試します。
- 拡張機能からApps Scriptを開き、コードを貼り付けて保存します。
- 「PDF設定」へ少量のサンプルを入力します。
- previewPdfExportPlanFreeを実行します。
- 初回の権限画面を確認し、対象スプレッドシートへの権限だけであることを確かめます。
- 「PDF_確認計画」でREADY・HOLD・SKIPと確認事項を読みます。
- HOLDが0件になってから、実際のPDF作成処理を別工程として検討します。
このコードが勝手に行わないこと
- PDFファイルの作成
- Google Driveへの保存や既存ファイルの上書き
- メール送信や外部サービスへの通信
- 元データの削除、書式変更、並べ替え
- 時間主導トリガーの作成
結果用の「PDF_確認計画」だけは毎回クリアして書き直します。既存の同名シートを使っている場合は、実行前に名前を変えてください。
失敗しやすい点と制限
- 出力範囲はA1形式で入力します。名前付き範囲や複数の離れた範囲は、この無料例では扱いません。
- 画面上の列幅、改ページ、画像、グラフ、結合セルによって、実際のPDFの見え方は変わります。
- 200行を超える設定は停止します。分割して確認してください。
- ログには件数だけを出します。シート名、ファイル名、セル値をログへ追加しない方が安全です。
- Apps Scriptやスプレッドシートの実行上限・仕様は変更される場合があります。
- 実際のPDF作成を追加する場合も、既存ファイルの上書きや自動送信を初期値にしないでください。
公開前チェックリスト
- 元ファイルのコピーで試した
- PDF設定の見出しに不足や重複がない
- 出力範囲が意図した行列数になっている
- ファイル名へ機密情報や個人情報を入れていない
- HOLDが0件になるまでPDF作成へ進まない
- 自動送信・自動削除・上書きを追加していない
- 実ファイルを少数だけ作り、目視確認する工程を別に用意する
まとめ
PDF出力の失敗は、保存処理そのものより、対象・範囲・用紙・向き・余白・ファイル名の組み合わせで起こりやすくなります。先に設定だけをdry-run監査し、HOLDを人が直してから作成工程へ進むと、元データやDriveを変更せずに確認できます。
作成後のPDFを含むDriveファイルを一覧で整理したい方は、関連する有料Tipsも確認できます。
DriveFileList Pro|Google Driveのファイル一覧化GASテンプレ

GasおじのTips商品一覧

※この記事は学習・検証用の無料例です。Google公式・Google公認の商品ではありません。実データへ適用する前に、コピー環境と少量データで確認してください。
