GASが最も活躍する場所はスプレッドシート
GAS(Google Apps Script)が業務で使われる理由の多くは、スプレッドシートを自動で操作できる点にあります。
「転記」「チェック」「集計」「定型フォーマットへの書き込み」など、人がやると地味に時間を取られる作業が、GASで一気に短縮できます。
ただし、スプレッドシート操作は“壊しやすい”領域でもあります。
存在しないシート名を指定してしまう、IDを間違える、権限が足りない、想定外の値が入っている──こうした理由で簡単にエラーが出ますし、書き込みは上書きで戻せないこともあります。
そこで第2部の最初となるこの記事では、スプレッドシート操作の最も基本となる「考え方」を整理しながら、1セル取得・1セル書き込みを確実に理解していきます。
さらに、GAS010で学んだ try-catch を活かした、安全な読み取り・書き込みの実務サンプルも紹介します。
目次
SpreadsheetAppの役割(階層構造)
GASでスプレッドシートを操作するとき、必ず登場するのが SpreadsheetApp です。
SpreadsheetAppは「スプレッドシート操作の入口」であり、ここからファイル(Spreadsheet)やシート(Sheet)やセル(Range)へ降りていくイメージになります。
まずは、この階層構造を暗記する価値があるレベルで押さえてください。
- SpreadsheetApp:スプレッドシート操作の入口
- Spreadsheet:1つのスプレッドシートファイル
- Sheet:ファイル内の1枚のシート
- Range:セル、またはセル範囲(1セルもRange)
この構造が頭に入ると、コードを読んだときに「今どのレベルを触っているか」が分かり、ミスが減ります。
逆に、ここが曖昧だと「取れているはずの値が取れていない」「どこでエラーが出たか分からない」が起きやすくなります。
スプレッドシート取得の基本(openById)
最初にやることは、「どのスプレッドシートを操作するか」を決めることです。
最もよく使われるのは、スプレッドシートIDを指定して開く方法です。
const ss = SpreadsheetApp.openById('スプレッドシートID');
スプレッドシートIDはURLの /d/(ここ)/edit の部分に入っています。
実務では、IDをコードに直書きせず、GAS009で扱った PropertiesService に保存して参照する設計が定番です。
「IDだけ差し替えれば同じ処理を別環境に使える」「共有時にIDを晒さない」などのメリットが出ます。
シートを取得する(getSheetByName)
スプレッドシートを取得したら、次は「どのシートを操作するか」を選びます。
初心者のうちは、シート名で取得する方法が最も分かりやすく、事故も少ないです。
const sheet = ss.getSheetByName('Sheet1');
重要なポイントは、存在しないシート名を指定したとき null が返ることです。
このまま sheet.getRange(...) を呼ぶと、そこでエラーになります。
なので実務では、後述のtry-catchや存在チェックで守るのが基本です。
セル(Range)の考え方
GASでは、セルはすべて Range として扱われます。
「1セル」も実は「1行×1列の範囲」です。
const range = sheet.getRange(1, 1); // A1
Row(行)と Column(列)は1始まりです。
A1は「1行目・1列目」、B1は「1行目・2列目」になります。
また、Rangeは文字指定もできます。
この方が人間には読みやすいことも多いです。
const rangeA1 = sheet.getRange('A1');
以後の章では、基本として行列指定(getRange(row, col))を中心に説明します。
1セルの値を取得する(getValue)
1セルの値を取得する最も基本は getValue() です。
const value = sheet.getRange(1, 1).getValue();
戻り値の型は、セルの内容によって変わります。
- 数値 → number
- 文字列 → string
- 日付 → Date
- 空欄 → 空文字(または状況により空に準ずる値)
この「型が変わる」という点が、スプレッドシート操作の落とし穴になりがちです。
たとえば、数値が入っている想定で計算したら、実際は文字列で入っていて結合されてしまう、といった事故が起きます。
実務では、取得後に「空か」「型が想定どおりか」をチェックする癖をつけるのが安全です。
1セルに値を書き込む(setValue)
1セルに値を書き込む基本は setValue() です。
sheet.getRange(1, 1).setValue('完了');
これは上書きなので、「既存データを消す」可能性があります。
実務では、次のような考え方で安全性を上げます。
- 書き込み対象のセルが正しいか(行・列がズレていないか)
- 上書きして良い条件か(空欄のときだけ等)
- 失敗したときに原因が追えるか(ログ)
これらを支えるのが、GAS010で扱った try-catch です。
次の章で「安全に書き込む」例を見ていきます。
try-catchで安全に「書き込む」例
スプレッドシート操作では、「シートが存在しない」「権限がない」「IDが違う」などの理由でエラーが発生します。
そのため実務では、重要な書き込み処理ほど try-catch で守ります。
function writeStatusSafe() {
try {
// 本来はPropertiesServiceから取得するのが定番(ここでは例として直書き)
const ss = SpreadsheetApp.openById('スプレッドシートID');
const sheet = ss.getSheetByName('Sheet1');
// シート存在チェック
if (!sheet) {
throw new Error('Sheet1 が存在しません');
}
// 「A1が空欄のときだけ書き込む」など条件を入れると事故が減る
const a1 = sheet.getRange(1, 1);
const current = a1.getValue();
if (current === '' || current === null) {
a1.setValue('完了');
Logger.log('書き込み成功:A1=完了');
} else {
Logger.log('書き込みスキップ:A1は既に値あり(' + current + ')');
}
} catch (e) {
Logger.log('エラー発生(writeStatusSafe):' + e.message);
}
}
ポイントは3つです。
- 存在チェックをして、想定外の状態なら自分でエラーを投げる
- 上書き事故を防ぐため、条件分岐で書き込み可否を決める
- catchでは「何が起きたか」をログに残して、原因追跡できる状態にする
「書き込めたか/スキップしたか/失敗したか」がログで分かるだけでも、運用が段違いで楽になります。
try-catchで安全に「読み取る」例(追加)
次は、今回追加する取得系(読み取り)のサンプルです。
読み取りは書き込みより安全に見えますが、実務では「値が空」「型が違う」「入力ルール違反」といった問題が多く、放置すると後段処理で大きく崩れます。
ここでは、次の要件で安全に読み取ってみます。
- Sheet1 の B2 から「数値(例:金額)」を取得する
- 空欄や数値以外ならエラーにする
- エラー時はログに原因を残す
function readAmountSafe() {
try {
const ss = SpreadsheetApp.openById('スプレッドシートID');
const sheet = ss.getSheetByName('Sheet1');
if (!sheet) {
throw new Error('Sheet1 が存在しません');
}
const cell = sheet.getRange(2, 2); // B2
const value = cell.getValue();
// 1) 空欄チェック
if (value === '' || value === null) {
throw new Error('B2が空欄です(数値を入力してください)');
}
// 2) 数値チェック(スプレッドシートは型が揺れるため厳密に見る)
// 数値ならOK。文字列なら数値変換を試みる。ダメならエラー。
let amount;
if (typeof value === 'number') {
amount = value;
} else if (typeof value === 'string') {
const trimmed = value.trim();
amount = Number(trimmed);
if (!trimmed || Number.isNaN(amount)) {
throw new Error('B2が数値ではありません:' + value);
}
} else {
throw new Error('B2の型が想定外です:' + Object.prototype.toString.call(value));
}
// 3) 業務ルール例(マイナス禁止など)
if (amount < 0) {
throw new Error('B2がマイナスです:' + amount);
}
Logger.log('読み取り成功:B2=' + amount);
return amount;
} catch (e) {
Logger.log('エラー発生(readAmountSafe):' + e.message);
// 実務では null を返す/再スローする など方針を決める
return null;
}
}
この例で伝えたいのは、「読み取り時点で入力を検証する」ことです。
読み取った値が怪しいまま後続の処理に渡ると、もっと分かりにくい場所で落ちます。
“入力に近いところで止める”のが、運用しやすいGASの鉄則です。
また、ここでは説明のためIDを直書きしていますが、実務ではGAS009のとおり、スプレッドシートIDやシート名はPropertiesServiceに寄せると保守が楽になります。
PropertiesServiceを使った実務向けスプレッドシート取得
ここまでの例では説明を分かりやすくするため、
スプレッドシートIDやシート名をコードに直接書いてきました。
しかし実務では、IDやシート名をコードに直書きしない設計が基本です。
理由は次のとおりです。
- 環境(本番・検証)ごとに差し替えやすい
- 誤ってIDを共有・公開してしまうリスクを減らせる
- 設定変更時にロジックを触らずに済む
これを実現するのが、GAS009で解説した PropertiesService です。
事前準備:プロパティに設定値を登録
まずは一度だけ実行する初期化関数で、設定値を登録します。
function initSpreadsheetSettings() {
const props = PropertiesService.getScriptProperties();
props.setProperty('SPREADSHEET_ID', 'スプレッドシートID');
props.setProperty('SHEET_NAME', 'Sheet1');
}
この関数は初回設定専用です。
設定が終わったら削除して問題ありません。
設定値を安全に取得する関数
次に、PropertiesServiceから設定値を取得する専用関数を用意します。
ここで「未設定」を検知しておくのが重要です。
function getSpreadsheetSettings() {
const props = PropertiesService.getScriptProperties();
const spreadsheetId = props.getProperty('SPREADSHEET_ID');
const sheetName = props.getProperty('SHEET_NAME');
if (!spreadsheetId) {
throw new Error('SPREADSHEET_ID が設定されていません');
}
if (!sheetName) {
throw new Error('SHEET_NAME が設定されていません');
}
return { spreadsheetId, sheetName };
}
このように「設定取得」を1か所にまとめておくと、
設定ミスの検知と修正が非常に楽になります。
PropertiesService+try-catchを組み合わせた実務例
最後に、これまでの記事内容を統合した実務向けの例です。
function writeStatusUsingProperties() {
try {
// 設定取得
const { spreadsheetId, sheetName } = getSpreadsheetSettings();
// スプレッドシート・シート取得
const ss = SpreadsheetApp.openById(spreadsheetId);
const sheet = ss.getSheetByName(sheetName);
if (!sheet) {
throw new Error('シートが存在しません:' + sheetName);
}
const range = sheet.getRange(1, 1); // A1
const current = range.getValue();
if (current === '' || current === null) {
range.setValue('完了');
Logger.log('書き込み成功:A1=完了');
} else {
Logger.log('書き込みスキップ:既に値あり(' + current + ')');
}
} catch (e) {
Logger.log('エラー発生(writeStatusUsingProperties):' + e.message);
}
}
この形にしておくと、
ロジック・設定・例外処理がきれいに分離されます。
実務ではこの構成をベースに、
次回の記事で扱う「Range一括操作」や「高速化処理」へ拡張していきます。
実務で意識すべき注意点
ここまでで「1セル操作」は理解できたはずです。
ただし実務では、1セルをループで何百回も触ると遅くなります。
よくある失敗と対策をまとめます。
- 大量セルを1つずつgetValue/setValue → 次回のRange一括操作で解決
- 存在しないシート名で落ちる → 存在チェック+try-catch
- 型が揺れて後段で壊れる → 読み取り時点で入力検証
- 上書き事故 → 条件付き書き込み(空欄のみ等)
次回(GAS012)では、パフォーマンス改善にも直結するRangeの一括操作を扱います。
「遅いGAS」を「実務で耐えるGAS」に変える重要回です。
まとめ
この記事では、GASでスプレッドシートを操作するための基本として、
SpreadsheetApp → Spreadsheet → Sheet → Range の階層構造と、1セルの取得・書き込み方法を解説しました。
さらに try-catch を使った「安全な書き込み」「安全な読み取り」の例を通して、
実務で事故を減らすための考え方(存在チェック/入力検証/ログ)も整理しました。
次回は、複数セルをまとめて扱うRange一括操作へ進みます。
0 件のコメント:
コメントを投稿