こんにちは。GAS勉強しめがねの谷口(@khtax16)です。
「GASでスプレッドシートを思うがままに操作したい!」
という欲望をもってわたくし現在GASを勉強中なのですが、どうもクラスについてちゃんと理解できていない様子。
そのため、自分の理解度を言葉にして整理するためにまとめてみました。
ということで、勉強中の私が自分の考えを整理するためのもの が当記事であります。
初心者まっただなかのため、必ずしも合っているとは保証ができず、記事中で階段をたとえに使ったのですが、それが適切かも現段階では定かではありません。
実際はもっと複雑な気がします。
ただ、「検索してもどんなコードが書いてあんのかちっとも理解できねぇよっほぉーん!」とお嘆きの方には、もしかしたら資するものもあるかもしれなくもないような気もいたします(あやふや)
中級~上級者の方は、「それってこうなんじゃないの?」という部分があれば、やさしく、決して声を荒らげずに(ちょっと漏らしちゃうからね!)そっと教えていただけると泣いて漏らしながら喜びます。結局漏らすんかい。
目次
【初心者向け】GAS スプレッドシートのクラスの概念の整理
スプレッドシートの4つのクラス 階段みたいなもの?
では早速行きましょう。
ものすごく簡単なコードとして、
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getRange('A1');
var value = range.getValue();
}
と、スプレッドシートの「A1の値を取得する」というコード を用意しました。
わかりやすいよう、省略せずに分けたのですが、「4つの行がある」ことがおわかりいただけるのではないでしょうか。
この「4つの行がある」というのは、つまり「4つの段階に分かれている」ことを意味します。
(『【GAS】for文をわかりやすく理解する方法【めがね式】』と同じく、概念の解説なのでコードよりも画像中心で行きます)
ほかのものはまだわからんのですが、少なくともスプレッドシートに関しては、
- SpreadsheetApp クラス
- Spreadsheet クラス
- Sheet クラス
- Range クラス
という4つのクラスがあって、この順番がそのまま上下関係を表してもいます。
なのでこれを図にしたとき、私は「クラスというものは階段みたいなもんなのかな」という理解をいまのところしています。
↓下の画像みたいな感じのやつです。
この2つをくっつけると↓下の画像のようになります。
また、クラスの階層とひもづけた場合、↓下の画像のようになります。
(ただし、コードとしては見にくくなるので、見やすいほうを見てください)
基本的にクラスは順番に指定していってあげる
それで、多分なんですが、基本的にこのクラスは飛ばしちゃダメで、上からひとつずつ順番に指定してあげる と考えると私のような初心者はわかりやすいんではないかと思います、
(後述しますが、あくまで「基本的に」です)
たとえば、上のコードを、
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var value = sheet.getValue('A1');
}
みたいに、上から3行目の「Sheetクラス」をすっ飛ばすとエラーが発生します。
これは私が書いたことあるコードです。
このエラーは、Sheet クラスをすっ飛ばしていることでセル範囲の指定(どこのデータを取得するかの指定)ができていないことが原因です。
が、もう少し解像度を上げると、「クラスの順番(構造)がまったく理解できていなかったこと」、そのために「えーと、値を取得するのは getValue メソッドだから」と「構造ではなく該当のメソッドをぼんやり思い浮かべながらでしか書けなかった」こと、がこうしたコードを書いた原因だったのではないか、と現在は解釈しています。
(ただ、下の「注意点・例外」にも書きましたが、1行目の「SpreadsheetApp クラス」と2行目の「Spreadsheet クラス」は飛ばせる場合もちょいちょいあるっぽいです。むずい)
とはいえ、必ずしも下のクラスまですべて指定あげないといけないわけではなく、自分がどのクラス(階段のどの階層)の操作をしたいのかで記述内容は変わります。
たとえば「シートのコピーをつくりたい」とかなら、「Spreadsheet クラス」あたりでできそうなので、それより下の「Sheet クラス」や「Range クラス」は特に記述しなくてもよいわけです。
GASはクラスごとに使えるメソッドが決まっている模様
「メソッドとは何か」
みたいな話をすると超絶長くなるし私も説明できるほどわかっていないので飛ばします。すみません。
で、言葉が正しいかはわかりませんが、どうも「クラスごとに使えるメソッドが決まっている」ということのようです。
(正確にはメソッドというより、メソッドとプロパティをあわせた「メンバー」)
以下、クラスごとに、私が使ったことあるものを中心にざっくりとまとめます。
SpreadsheetAppクラス
SpreadsheetAppクラスで私が使ったことあるものを挙げると、
- getActiveSpreadsheet()
- openById()
- openByUrl()
などです。
Spreadsheetクラス
Spreadsheetクラスで私が使ったことあるものを挙げると、
- getActiveSheet()
- getSheets()
- getSheetByName()
などです。
Sheetクラス
Sheetクラスで私が使ったことあるものを挙げると、
- getRange()
- getDataRange()
- getLastRow()
などです。
(かなり種類多い)
Rangeクラス
Rangeクラスで私が使ったことあるものを挙げると、
- getValues()
- setValues()
- getLastRow()
などです。
(めっちゃ種類多い)
なお、「Sheet クラス」と「Range クラス」の両方で例に挙げた「getLastRow メソッド」のように、複数のクラスで存在するメソッドもあるようです。
ただ、
- Sheet クラスでのgetLastRow メソッドは「シートのデータがある最後の行番号を返す」
- Range クラスでのgetLastRow メソッドは「セル範囲の最終行の位置を取得する」
と、どのクラスで使うかによって効果が変わる 模様。
よくよく理解して使わないと混乱するかもしれません。
クラスの注意点・例外 省略されることもよくある
なお、例外も多々あり、たとえば「getActiveSheet メソッド」を使うと「SpreadsheetApp クラス」をすっ飛ばせます。
なので、「var ss」からはじめず、いきなり
var sheet = SpreadsheetApp.getActiveSheet();
みたいなこともできてしまいます。
(1つしかシートがないときは便利なのだけど、ちゃんとこの構造を理解していないと混乱する気もします)
そのほかも、
var sheet = SpreadsheetApp.getActiveSheet();
var value = sheet.getRange(‘A1’).getValue();
のように、「上段:いきなり Spreadsheet クラスから入力」「下段:Sheet クラスと Range クラスを一気に入力」といった 省略形も数多く見られます。
慣れた方はこうした書き方がよく見られ、インターネットで検索していると普通に出てくるので、エラーで困ったとき、私のような初心者の方は「今どのクラスか?(階段のどの部分か?)」というのを考えてみる(あえて分けて1段ずつ書いてみる)と解決の糸口になるかもしれません。
唐突な宣伝
ちなみに、メンバーの例はタカハシさんの書かれたGAS本をめちゃくちゃ参考にさせていただきました。
メンバーの種類が豊富にのっててわかりやすいです!
(スプレッドシートは第8章)
getSheet メソッドは getActiveSheet メソッドの後だとエラー発生する問題【GAS】
ここまでが全体像と、個別のクラスごとのメソッドの話でした。
つまり、「クラスというものは階段になっていて、そのコードのその部分がいまどの部分(階層)にいるのか理解していないと、思わぬエラーに苦しむことになるよ!」というのが論旨です。
以降は余談というか、私がそのエラーに苦しんだ具体例というか発端というか、そんな感じの話です。
もともと、私が「どうもこれはクラスとかいうものが影響しているらしい」とうすぼんやり思ったのが、Spreadsheet クラスの「getSheets メソッド(スプレッドシートのすべてのシートを取得するメソッド)」を使おうとしたときでした。
【事例A】
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
というコードを書くと、最後の「.getSheets()」が予測候補に出てきてちゃんと使えたのに、
【事例B】
var sheet = SpreadsheetApp.getActiveSheet();
var sheets = sheet.getSheets();
というコードだと、最後の「.getSheets()」が予測候補に出てこないうえに、むりやり書くとエラーが発生したためでした。
文字で書くとわかりにくいですが、上段の
- getActive Spread sheet メソッド(SpreadsheetApp クラス)
- getActiveSheet メソッド(Spreadsheet クラス)
が事例AとBの違いです。
「Spread」の文字があるかどうかが違うのですが、この「Spread」の有無で階段の階層が変わってしまいます。
原因を考えてみて推測できたのがこの「クラス」というもので、いま考えると、事例Aは順序をちゃんと踏まえているのでOKなんですね。
(↓下の画像参照)
しかし、事例Bのほうは、「Spreadsheet クラスの getActiveSheet メソッド」を先に指定しまっている ので、もう「Sheetクラス」に降りてしまってるんですね。
で、「Sheet クラス」には、「getSheets メソッド」は登録されていないわけです。
つまり、意図せず「Sheet クラスの階層で Spreadsheet クラスの getSheets メソッドを使ってしまっていた」ことがエラーの原因だったようです。
これが、エラーの原因を考えているうちにクラスの話とつながったため、「だからエラーが起きたのか!」とわずかながらも理解できた(できていると思いたい)ので、それを整理するためにこの記事を書いたのでした。
整理できると「そりゃエラー起きるわ」という感じなのですが、書いてエラーに苦しんでる最中(さなか)だとなかなか原因がわからないんですよね。。
最後 GASのスプレッドシートのクラスの理解まとめ
話が少々とっちらかってしまったので、最後にまとめます。
1.スプレッドシートには階段のようなクラスがある
(階段のたとえが適切かは、今後の学習を踏まえて修正する可能性もあります。また、図はスプレッドシートの例)
2.原則として上からひとつずつ順番に指定してあげると初心者はわかりやすい
(あくまで原則で、上の「クラスの注意点・例外」でも書いたように、省略できるものもあるしまとめて記述されることもよくあります)
3.この順番をすっ飛ばしたり、そのクラスで使えないメソッドを書いたりするとエラーが発生する
(getSheet メソッドが getActiveSheet メソッドの後だとエラーが発生する問題など、「そのクラスで使えるメソッドかどうか」の理解が必要)
という感じです。
上にも書きましたが、もっと複雑な気もするので、階段のたとえが適切かは今後の学習を踏まえて適宜修正していく つもりです。
この記事が、GASでつまずいている方の理解の一助となればうれしいです!
2020.2.27追記
受講している講座の先生に「こんな感じっすかね」と聞いたら「うーん、階段にしちゃうとまた違うんだよなー」という回答をいただきました。クラスむずい。
ただスプレッドシートのスクリプトを記述するときの理解としてはそんなに間違ってもない様子。
今後勉強を進めて、理解が深まったら追記 or 新規作成いたします!
「役に立った!」「ニヤニヤした」など、もし「こいつ応援してやろうかな」という菩薩のごときお心が芽生えましたら、Amazonか楽天でお買い物するときに、下のリンクを踏んでからお買い物をしていただけますと私にジュース代なんぞが入ります。とても嬉しい。(なぜかメガネの検索画面が出てきますが無視してお好きなものを!)
▷Amazonでお買い物
▷楽天市場でお買い物