値の取得と書き込み(getValue/setValue)

値の取得と書き込み-getValue_setValueを図解している男性
目次

プログラミングの基本原則「IPOサイクル」:入力・処理・出力の理解

業務自動化システムの構築において、最も根源的であり、かつ最も重要な概念が「IPOサイクル」です。これはInput(入力)、Process(処理)、Output(出力)の頭文字を取ったもので、あらゆるコンピュータプログラムはこの3つの要素で構成されています。私たちがこれからGoogle Apps Script(GAS)を用いて構築しようとしているシステムも、例外ではありません。スプレッドシートにおける業務自動化の文脈では、「入力」とはスプレッドシート上のセルからデータを取り出すこと(Read)を指し、「処理」はそのデータに対して計算や加工、判定を行うこと、「出力」は加工されたデータを再びスプレッドシートのセルや別の場所に書き出すこと(Write)を指します。

これまでExcelのマクロや関数を利用してきた方にとって、この「入力」と「出力」の境界線は曖昧だったかもしれません。Excelのセルに関数を入力する場合、入力データ(参照セル)と処理(関数式)と出力結果(セルの表示値)が、一つのセルの中に混然一体となって存在しているからです。しかし、GASによる開発では、このプロセスを明確に分離して考える必要があります。「どのデータを材料として持ってくるのか(Input)」、「その材料をどう料理するのか(Process)」、「出来上がった料理をどこに盛り付けるのか(Output)」という手順を、一つひとつコードとして記述しなければなりません。

この章で学ぶ getValuesetValue は、まさにこのIPOサイクルの入り口と出口を司る最重要メソッドです。これらを使いこなすことは、単にセルを操作できるという以上の意味を持ちます。それは、スプレッドシートという「データの保管庫」と、GASという「処理エンジン」の間で、自由にデータを受け渡しできるパイプラインを開通させることを意味します。このパイプラインがなければ、どんなに高度なAIを用いたとしても、その知能を業務データに適用することはできません。開発者として、まずはこのデータの流れ(データフロー)を意識し、意図した通りにデータを吸い上げ、意図した場所にデータを着地させるコントロール能力を養うことが、本章の最大の目的です。

値を読み取る「getValue」メソッドのメカニズムと正確なアドレス指定

データを処理するためには、まずそのデータをGASの世界に引き込む必要があります。そのために使用されるのが getValue() メソッドです。このメソッドは、指定されたRangeオブジェクト(セル範囲)から、そのセルに入力されている「値」を取得する命令です。前章で学んだオブジェクトの階層構造を思い出してください。 SpreadsheetApp(管理者)から始まり、 Spreadsheet(ブック)、 Sheet(シート)を経て、ようやく Range(セル)にたどり着きます。 getValue() は、この特定された Range に対して「そこに何が書いてあるか教えてくれ」と問いかけるアクションです。

ここで重要なのは、 getValue() が取得するのはあくまで「単一の値」であるという点です。もし getRange("A1:B5") のように複数のセル範囲を指定した状態で getValue() を実行した場合、取得されるのはその範囲の左上端にあるセル(この場合はA1)の値だけです。初心者のうちは、範囲指定と取得メソッドの組み合わせで混乱することがありますが、 getValue() は「一つのセルの値を取るもの」と明確に定義づけておくことが肝要です(複数セルの取得には getValues() を使いますが、それは次章で扱います)。

また、 getValue() が取得する「値」には型があります。セルに「100」という数値が入っていれば数値型(Number)として、「こんにちは」という文字が入っていれば文字列型(String)として、日付が入っていれば日付型(Date)として取得されます。ExcelのVBAでは、セルの値を取得する際に .Value プロパティや .Text プロパティを使い分けることがありましたが、GASの getValue() はセルのデータ型に応じて自動的に適切なJavaScriptのデータ型に変換してくれます。この柔軟性は便利である反面、開発者が意識的にデータ型を把握しておかないと、後の計算処理で「数値だと思っていたら文字列だったため、足し算ではなく文字連結になってしまった」といったバグを生む原因にもなります。したがって、 getValue() でデータを取得する際は、そのセルにどのような種類のデータが入っているのかを常に意識する習慣をつけることが、プロフェッショナルな開発者への第一歩です。

データの一時保管場所としての「変数」という箱の役割と定義

getValue() メソッドを使ってセルから値を取り出した後、その値はどこへ行くのでしょうか。もし、単に sheet.getRange("A1").getValue(); と書いただけでは、取得した値はプログラムの中で誰にも受け取られず、虚空へと消えてしまいます。取得した値を後の処理(加工や別のセルへの書き込み)で利用するためには、その値を一時的に保存しておく場所が必要です。そのための保管箱が「変数」です。

変数は、プログラミングにおいてデータを扱うための最も基本的な道具です。GAS(JavaScript)では、 constlet というキーワードを使って変数を宣言します。例えば、 const salesData = sheet.getRange("A1").getValue(); と記述することで、「A1セルの値を取得し、それを salesData という名前の箱に入れておく」という操作になります。一度変数に格納してしまえば、以降の行では salesData という名前を使うだけで、何度でもその値を取り出して利用することができます。また、 salesData という具体的な名前をつけることで、そのデータが何を意味しているのか(この場合は売上データであること)がコード上で明示され、可読性が飛躍的に向上します。

開発者の中には、変数を経由せずに sheet.getRange("B1").setValue(sheet.getRange("A1").getValue()); のように、取得と書き込みを一行でまとめて書いてしまう人もいます。確かにコードは短くなりますが、これは推奨されません。なぜなら、処理の途中でデータの中身を確認したり(デバッグ)、計算を加えたりすることが難しくなるからです。また、可読性の観点からも、「入力」「処理」「出力」の各ステップが視覚的に分離されている方が、後からコードを見返した際にロジックを追いやすくなります。本講座では、「取得した値は必ず一度変数に格納する」という作法を徹底します。これは、単なるルールではなく、複雑なシステム構築に耐えうる堅牢なコードを書くための、開発者としての重要なマナーです。

データ型の概念と型変換:取得した値は「文字」なのか「数値」なのか

先ほど少し触れましたが、 getValue() で取得したデータには「型(Type)」という属性が付与されます。人間がスプレッドシートを見るときは、「100」と書いてあればそれが金額なのか個数なのか、あるいは住所の一部(1-100など)なのかを文脈で判断できます。しかし、コンピュータは文脈を理解しません。そのため、データ型という厳格な区分けが必要になります。GASで主に扱われるデータ型には、数値(Number)、文字列(String)、真偽値(Boolean)、日付(Date)などがあります。

特に注意が必要なのが、数値と文字列の違いです。スプレッドシート上で「100」と入力されていても、セルの書式設定が「テキスト」になっていれば、GASはそれを文字としての「”100″」として取得します。この状態で + 1 という処理を行うと、数値計算の「101」ではなく、文字連結としての「”1001″」という結果になってしまうことがあります。逆に、郵便番号や電話番号のように、先頭に「0」がつくデータを数値として取得してしまうと、「090…」が「90…」になってしまうといった問題も発生します。

開発者は、スプレッドシートから getValue() でデータを引き上げた瞬間、そのデータがどの型として認識されているかを確認し、必要であれば適切な型に変換(キャスト)する責任があります。例えば、数値として計算したい場合は Number() 関数で明示的に数値化したり、日付として扱いたい場合は Utilities.formatDate() を使って整形したりします。AIにコードを書かせる際も、「A列は金額なので数値として扱って」「B列は商品コードなので文字列として扱って」といった具体的な指示を与えることで、型にまつわるトラブルを未然に防ぐことができます。データの「中身」だけでなく「型」まで意識を向けること、これがExcelユーザーからGAS開発者へと脱皮するための重要な視点です。

値を書き込む「setValue」メソッドの挙動と上書きのルール

データの取得(Input)と変数への格納ができたら、次はいよいよ出力(Output)です。スプレッドシートのセルに値を書き込むために使用するのが setValue() メソッドです。使い方は getValue() と対になっており、 Range オブジェクトに対して setValue(書き込みたい値) という形式で記述します。書き込みたい値には、数値、文字列、日付などのデータ、あるいはそれらが格納された変数を指定します。

setValue() を実行すると、指定されたセルに即座に値が入力されます。ここで最も注意すべき点は、 setValue() は「上書き」の動作をするということです。もし指定したセルに既に別のデータや計算式が入っていたとしても、 setValue() は問答無用で新しい値で上書きし、元のデータは消え去ります。Excelのように「元に戻す(Ctrl+Z)」で簡単に操作を取り消すことは、スクリプトによる変更に対しては基本的にできません(履歴から復元するなどの手間がかかります)。そのため、書き込み先のセル指定には細心の注意を払う必要があります。

また、 setValue()getValue() と同様に、単一のセルに対する操作を基本とします。ループ処理の中で setValue() を何度も呼び出して1セルずつ書き込むようなコード(例えば1000行のデータを1行ずつ書き込むなど)は、GASにおいて最も避けるべき「アンチパターン」の一つです。なぜなら、GASとスプレッドシートの間の通信はインターネットを経由するため、1回の通信ごとにわずかな待機時間が発生するからです。1回なら無視できる時間でも、1000回積み重なれば数分単位のロスとなり、最悪の場合、GASの実行時間制限(6分)を超えてエラー終了してしまいます。この「通信コスト」の感覚を持つことは、クラウドネイティブな開発者にとって必須の素養です。本章では基礎として単一セルの書き込みを学びますが、この「1回ごとの重み」を常に意識しておいてください。

「参照」と「転記」の決定的な違い:Excel関数との比較

スプレッドシートのセルに =A1 と入力すれば、A1セルの値を別のセルに表示させることができます。これは「参照」です。参照の特徴は、元のセル(A1)の値が変われば、参照先のセルの値も自動的に連動して変わるという「動的」な性質にあります。常に最新の状態を保ちたい場合には、この関数の機能は非常に優れています。

一方、GASの getValue()setValue() を使ってA1の値をB1に書き込んだ場合、それは「転記(コピー&ペースト)」となります。GASが実行された「その瞬間」のA1の値がB1に書き込まれますが、その後A1の値が変更されても、再度GASを実行しない限り、B1の値は変わりません。これは「静的」な性質です。一見すると不便に思えるかもしれませんが、業務システムにおいては、この「静的であること(値が勝手に変わらないこと)」が極めて重要な価値を持つ場面が多々あります。

例えば、「月末時点での売上数値を確定させて保存したい」「請求書を発行した時点での単価を記録しておきたい」といったケースです。関数による参照では、元データが修正されると過去の記録まで変わってしまい、証跡としての意味をなさなくなってしまいます。GASによる「値の転記」は、流動的なデータを特定のスナップショットとして切り取り、固定化(フィックス)する機能と言えます。Excel脳では「常に関数で繋いでおく」ことが正義とされがちですが、GAS脳では「あえて値を固定化する」ことで、データの整合性や履歴管理を実現します。この「参照」と「転記」の使い分けこそが、自動化設計の肝となります。

実践:AIに「A1の値をB1にコピーする」コードを書かせる

理屈を理解したところで、実際にAIを使ってコードを生成し、動作を確認してみましょう。ここでのポイントは、単に「コピーして」と言うのではなく、これまで学んだ「変数への格納」や「階層構造」を意識したプロンプトを作成することです。AIに対して、処理の意図を明確に伝える練習でもあります。

以下のプロンプトを使用してください。

あなたはGoogle Apps Scriptの専門家です。
現在開いているスプレッドシートの「シート1」にある「A1」セルの値を取得し、
それを変数 `originalData` に格納してください。
その後、その変数の値を同じシートの「B1」セルに書き込む関数 `copyValue` を作成してください。
コード内には、各処理(取得、変数への代入、書き込み)が何をしているかわかる日本語のコメントを追加してください。

このプロンプトを実行すると、AIは概ね以下のようなコードを出力するはずです。

function copyValue() {
  // アクティブなスプレッドシートを取得
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  // 「シート1」を取得
  const sheet = ss.getSheetByName('シート1');

  // A1セルの値を取得して変数に格納(Input)
  const originalData = sheet.getRange('A1').getValue();

  // 取得した値を確認(ログ出力)
  console.log('取得した値: ' + originalData);

  // 変数の値をB1セルに書き込む(Output)
  sheet.getRange('B1').setValue(originalData);
}

このコードを実行し、実際にA1セルの値がB1セルに転写されることを確認してください。そして、A1セルの値を書き換えても、B1セルの値が(再度スクリプトを実行するまでは)変わらないことを確認し、「転記」の性質を体感してください。

プロセスを分離する意識:読み取りと書き込みを分けて考える

生成されたコードを見て、改めて「読み取り(Input)」と「書き込み(Output)」が別の命令として記述されていることに注目してください。この「プロセスの分離」は、将来的に間に「処理(Process)」を挟み込むためのスペースを確保しているという意味でもあります。

例えば、今は単に右から左へデータを流すだけですが、「もしA1の値が100以上ならB1に書き込む、そうでなければ書き込まない」といった条件分岐や、「A1の値に消費税を加算してB1に書き込む」といった計算処理を追加したい場合、変数 originalData があるおかげで、書き込み処理の前にコードを挿入するだけで簡単に実現できます。もし、 sheet.getRange('B1').setValue(sheet.getRange('A1').getValue()); のように一行で書いてしまっていたら、ロジックを追加するためにコード全体を書き直さなければなりません。

システム開発において、「変更に強いコード」を書くことは非常に重要です。業務要件は常に変化します。「やっぱりこうしてほしい」という要望が出た時に、既存のコードを壊さずに最小限の修正で対応できる構造にしておくこと。それが、読み取りと書き込みを変数で分けるという単純な行為の中に込められた、開発者としての知恵です。この章で学ぶスクリプトは数行の短いものですが、そこには大規模なシステム開発にも通じる設計思想が詰まっています。

空白セルの扱いとデータ取得時の挙動について

実務データでは、必ずしもすべてのセルに値が入っているわけではありません。空白のセルに対して getValue() を行った場合、GASはどのような値を返すのでしょうか。基本的には、空文字 ""(長さ0の文字列)が返されます。これは nullundefined とは異なる点に注意が必要です。

例えば、「A1セルの値を取得し、何かしらの計算をしてB1に書き込む」という処理を作る際、もしA1が空白だったらどうすべきでしょうか。そのまま計算しようとするとエラーになったり、意図しない「0」という結果が表示されたりするかもしれません。そのため、値を getValue() した直後に、「もし値が空文字だったら処理を中断する」あるいは「デフォルト値を設定する」といったガード処理(エラーハンドリング)を入れるのが一般的です。

const value = sheet.getRange('A1').getValue();
if (value === "") {
  console.log("セルは空白です");
  return; // 処理を終了
}

このように、入力データが常に完全であるとは限らないという前提に立ち、予期せぬデータ(この場合は空白)が来た場合の挙動をあらかじめ決めておくことも、安定したシステムを作る上で欠かせない視点です。AIにコードを書かせる際も、「セルが空白の場合はスキップしてください」と一言添えるだけで、より実務に適したコードが生成されます。

開発者としての第一歩:データの流れをコントロールする

本章では、 getValuesetValue という、GASの中で最も基本的かつ頻繁に使用されるメソッドについて、その動作原理から実務的な注意点まで深掘りしました。たった一つの値を移動させるだけの処理に見えるかもしれませんが、そこには「オブジェクトの特定」「データの取得」「メモリ上での保持」「型への意識」「静的な書き込み」という、プログラミングの要素が凝縮されています。

これまでのExcel作業では、マウスで選択してコピーし、別の場所をクリックしてペーストするという身体的な動作で行っていたことを、論理的な命令文として記述する。この転換こそが、自動化への入り口です。あなたが書いたコードによって、データがあなたの意図した通りに動き、スプレッドシート上を移動する様子を確認できたなら、あなたはもうスプレッドシートの「ユーザー」ではなく、スプレッドシートを操る「コントローラー(制御者)」です。

次章では、この単一セルの操作を拡張し、複数のデータをまとめて扱う「配列」と高速処理の世界へと足を踏み入れます。1つずつ処理していては日が暮れてしまうような大量のデータも、GASの作法に従えば一瞬で処理できるようになります。ここからが、真の業務効率化のスタートです。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次