どうも。つじけ(tsujikenzo)です。このシリーズでは、2021年2月から始まりました「ノンプロ研GAS初級講座8期」について、講座内では伝えきれなかったことなどを、全8回でお届けします。今日は第6回(Day5)です。
前回のおさらい
前回は、「オブジェクト・GASの世界」についてでした。受講生の方から「オブジェクトってどんなときに使うの?」という質問がありました。TAのかにみそ先生の回答が素晴らしかったので、ご紹介させていただきます。
実務では、APIの返答がオブジェクト形式であったり、スクリプトプロパティを取得するとオブジェクトが返ってきたりしますので、そういった場合に使用します。APIやスクリプトプロパティについては初級講座の範囲外ですが、そういった発展をさせていくために必要なオブジェクトの構造の理解とfor…in文の動作の理解が、この演習の目的かなと感じました。
中級講座卒業がんばります かに
前回のおさらいはこちらです。
今日は、「スプレッドシート操作の基礎」です。いよいよスプレッドシートを操作します。
今日のアジェンダ
- Spreadsheet
- Sheet
- Range
- セルの値
今日のテーマは『3つ(みっつ)』です。いったい何が「みっつ」なのか紐解いていきましょう。
GASの世界とトップレベルオブジェクト
前回の授業では、Googleさんが用意してくれている「Google Workspace Servicies」というサービス一覧があることをご紹介しました。
そして、サービスの中身は「クラス」と呼ばれる「オブジェクトの集まり」になっています。クラスはとても複雑な構造をしておりますが、おおむね図のような「階層構造」になっています。
この階層の中で、それぞれのサービスの頂点に君臨するのが「トップレベルオブジェクト」です。いわば、「サービスを操作するための出発点」になります。
オブジェクトの後ろに「○○App」がついていることが多いですので、「○○App」を見かけたら「これは○○サービスのトップレベルオブジェクトなんだな」と思うようにしましょう。
SpreadSheetサービスのトップレベルオブジェクト
ということで、今回はスプレッドシートを操作していきますので、トップレベルオブジェクトの[SpreadSheetApp](=スプレッドシートサービス)を指定する(掴む、宣言する、指定する、など表現はさまざま自由です。)ことからスタートします。
SpreadSheetApp~
SpreadSheetオブジェクト
スプレッドシートサービスを掴んだら、次はスプレッドシートです。スプレッドシートを掴む方法は『3つ』あります。
- アクティブなスプレッドシートを取得 =バインドしているスプレッドシート
- URLで取得
- IDで取得
スプレッドシートのURLを指定する時は、ブラウザに表示されているURLを全部コピペして問題ありません。
https://docs.google.com/spreadsheets/d/{ID}/edit#gid=0
ただ、厳密に言うとスプレッドシートのURLは/editまでです。 #(シャープ)以降はシートIDを示すものになっており、シートを追加すると新しいIDが付与されます(デフォルトは#gid=0)。
Sheetオブジェクト
Sheetを掴む方法も『3つ』です。SpreadSheetオブジェクトに続けて記述します。
- シート名で取得
- 配列を取得しインデックスで指定
- アクティブなシートを取得 =バインドしているスプレッドシートのアクティブなシート
3つありますが、特別な理由が無い場合はほとんどシート名で取得することが多いです。
const ss = SpreadsheetApp.getActiveSpreadsheet(); const sheetByName = ss.getSheetByName('シート1');
シートが何枚あっても構わないけど、常に先頭のシートを取得したい場合は配列タイプで取得する場合もあります。
const ss = SpreadsheetApp.getActiveSpreadsheet(); const sheetByIndex = ss.getSheets()[0];
シートが絶対1枚しかない場合はアクティブシートで取得することがあります。(後はonEdit()トリガーの時に使うと便利かもしれません)
const sheetActive = SpreadsheetApp.getActiveSheet();
なぜ.getActiveSheet()がトップレベルオブジェクトのSpreadSheetAppから呼び出せるのか
getActiveSheet()メソッドはシートを掴むためのメソッドなので、シートの一つ上の階層であるSpreadSheetオブジェクトに対してじゃないのか?という疑問があると思います。
今までの流れですと、シートを掴むなら、
SpreadSheetApp.getActiveSpreadSheet().getActiveSheet()
のように、SpreadSheetApp(トップレベルオブジェクト)→SpreadSheet→Sheetという順番で掴まないといけないはずです。
答え:SpreadSheetAppにメンバーとして定義されてるから
リファレンスで確認してみましょう。
特に理由は書いていないようですね。恐らく.getActiveSheet()メソッドの内部にはちゃんと.getActiveSpreadSheet()が書かれていて、私たちは省略できるんだと思います。
Rangeオブジェクト
Rangeを掴む方法も『3つ』です。Sheetオブジェクトに続けて記述します。
- アドレスで取得
- 行番号,列番号,行数,列数で取得
- データ範囲を取得
これは場面によってどれも使う機会が出てくるので、3種類慣れていた方がいいです。変則的なものは無いので、使えば使うほど慣れると思います。比較的わかりやすいので補足は割愛します。
A1形式と絶対的なR1C1形式
ExcelのR1C1方式に慣れている方への補足ですが、GASではRangeを掴む方法として相対位置としてのR1C1形式は使えません。(A1セルをR1C1とする絶対的なRangeとして取得する方法はありますが、Rangeオブジェクトを相対位置としてR1C1方式で掴むメソッドは用意されていません。)
しかしこれもアドレスで取得(A1形式)で統一した方がいいので、R1C1形式でRangeを掴む意味はありません💦(Sheetオブジェクト.getRange(‘R1C1’)なんて書き方はしないという意味です。Sheetオブジェクト.getRange(‘A1’)でよいでしょう。)
セルの値
セルに入力されている値の取得はgetValue()かgetValues()メソッドです。対象が単体のセルか複数のセルかによってメソッドが変わります。
これらのメソッドはRangeオブジェクトに対して使います。(言い換えるとgetValue()とgetValues()メソッドはRangeオブジェクト(クラス)のメンバーです。)getValue()メソッドは単体のセルに対して有効なメソッドなので、Rangeオブジェクトも必然と単体のセルであることがイメージできると思います。
const ss = SpreadsheetApp.getActiveSpreadsheet(); const sheet = ss.getSheets()[0]; sheet.getRange(‘A1’).getValue(); //A1に入力されている値を取得する
対象が複数のセルに渡る場合、Rangeオブジェクトもセル範囲を示す記述であることがポイントです。
const ss = SpreadsheetApp.getActiveSpreadsheet(); const sheet = ss.getSheets()[0]; sheet.getRange(1,1,5,5).getValues(); //A1:E5に入力されている値を2次元配列で取得する
複数のセル範囲のRangeオブジェクトに対して、getValue()をしてしまうミスなどはよくありますので、気を付けてください。(エラーは出ないけど何もログを返さない)
const ss = SpreadsheetApp.getActiveSpreadsheet(); const sheet = ss.getSheets()[0]; sheet.getRange(1,1,5,5).getValue(); //
この4つのメソッドは単体か複数か、getかsetかという組み合わせになっていますので、覚えやすいです。大事なのは「それぞれのメソッドの対象となるRangeオブジェクトはどう指定すべきなのか」というポイントです。復習頑張ってください!
getValue() getValues()
setValue() setValues()
再頻出コード
色々説明しましたが、再頻出コードはこの2つかもしれません。いつでも呼び出せるように反復練習しましょう。
sheet.getDateRange().getValues(); sheet.getRange(row, column, array.length, array[0].length).setValues(array);
いつか使うかもしれないメソッド達
あまり使わないかもしれないけど知ってると便利なメソッドです。
Range.getA1Notation()・・・・セル範囲をA1形式で取得
Range.getDisplayValue()・・・Dateオブジェクトで入力されている”12月20日”などの値を見た目のまま取得する
Range.getFormula()・・・表示されている式の結果(値)ではなく、式(Formula)を取得する
Range.getFormulaR1C1()・・・Formulaを取得した際にセル範囲があればR1C1形式で表示する。
console.log(range.getFormula()); //=SUM(A2:A3) console.log(range.getFormulaR1C1()); //=SUM(R[-2]C[0]:R[-1]C[0])
まとめ
以上で、「スプレッドシート操作の基礎」をお送りしました。
今日のキーワードは『3つ』とお伝えしましたが、SpreadSheetオブジェクトもSheetオブジェクトもRangeオブジェクトも、掴み方は3つずつです。沢山覚えないといけないことがありそうですが、「3つずつ」って思うとなんだか気が楽ですね。
授業の最後に補足しましたが、自分や他人が読みやすい変数に行を分割することもコツです。1行で書くのがカッコイイわけではありません。
const ss = SpreadsheetApp.getActiveSpreadsheet(); const sheet = ss.getSheetByName('シート1'); const range = sheet.getDataRange(); const values = range.getValues(); //どちらが見やすい? const values = SpreadsheetApp.getActiveSheet().getDataRange().getValues();
次回は、いよいよ最終回です。「スプレッドシートの操作(実践編)」です。お楽しみに。
このシリーズの目次
- [ノンプロ研]GAS初級講座8期 事前課題
- [ノンプロ研]GAS初級講座8期DAY1補講 はじめてのGAS、変数、演算、データ型
- [ノンプロ研]GAS初級講座8期DAY2補講 制御構文
- [ノンプロ研]GAS初級講座8期DAY3補講 関数・配列
- [ノンプロ研]GAS初級講座8期DAY4補講 オブジェクト・GASの世界
- [ノンプロ研]GAS初級講座8期DAY5補講 スプレッドシートの操作 基本編
- [ノンプロ研]GAS初級講座8期DAY6補講 スプレッドシートの操作・実践編
- [GAS]スプレッドシートのセル考察 ~A1Notationってなに~ [前編]
- [GAS]スプレッドシートのセル考察 ~getRange()メソッドとセルアドレスリテラル~ [後編]