見出し画像

事前課題その2 ノンプロ研 初心者向けプログラミング講座【GASコース第9期】

↓これの続きです。

これまでのあらすじ

圧倒的業務に立ち向かうため遂にGASと向き合うことになったワーカーにノンプロ研GAS講座事前課題が語り掛ける。「変数と定数は恋と愛?」「お前はconsole.logの真価を分かっているのか?」「テンプレート文字列をうまく扱うのじゃ…」肚落ちしていない事柄を抱えながら、再びスクリプトエディタが開かれ、bot作成の儀が執り行われようとしていた。

さーて、いよいよ楽しい楽しいbot作成も興が乗ってきました。実際にすぐ動く成果物っていいよね!

講座の前に、事前課題として足並みを揃えるというか、反転学習、アクティブラーニングというか、そういう手法を取っているものよく考えられているなあと感心しきり。

7.【初心者向けGAS】スプレッドシートのシートを取得する2つの方法

<前回のおさらい>

前回はアクティブなスプレッドシートを取得するgetActiveSpreadsheetメソッドで、どのスプレッドシートを取得するのか、という大枠の記述でした。
基本的に、コンテナバインドしているスプレッドシートを取得するということで進みましたが、これは相対参照的で、今後、絶対参照的にコンテナバインドで結びついていない別のスプレッドシートを取得したいときはまた別のメソッドがありそう?絶対/相対は、おそらく今後のシート取得やレンジ取得でもそれ的なものがある予感。

getActiveSpreadsheetで下記ページでググってさっとGetメソッドのあたりを見てみるがよくわからんな。必要なときにまた考えることにして進む。

<シートの取得>

シートを取得する方法にはいくつありますが、その方法の一つとしてシート名を指定してシートを取得する方法があります。
getSheetByNameメソッドを使います。
Spreadsheetオブジェクト.getSheetByName(シート名)

ここでの注意点は、シート名をキーにしているので、シート名変えちゃうとだめだよとゆーこと。これ、実務でありがちパターン。ためしにシート名をシート1から適当なものに変えてスクリプトを実行すると↓こうなる。

画像1

「読み取れないよ!4行目がへんだよ!」と言っている。

ところで、コード書いて保存して実行して、というのは、左手をキーボード固定でCtrl+S→Ctrl+Rでやるといい感じ。SはSave、RはRunですね。
むかーし、illustratorやPhotoshopを教わったときに左手はキーボードに置けと言われたのを思い出す。そうは言いつつ、キーボードから手が離れちゃうんだけどね。ここにきて正確なタイピングを若いうちにしっかり身に着けておけばとぐぎぎぎしてる。

また、Spreadsheetオブジェクトを変数や定数で使う機会が他にないのであれば、以下のようにステートメントをひとまとめにすることもできます。
 const ss = SpreadsheetApp.getActiveSpreadsheet();
 const sheet = ss.getSheetByName('シート1');
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1');

これ、ちょっとよくわかってない。今後、コピペしたり改修、再利用すること考えると、前者にしておいておいたほうが事故がないような気もする。Spreadsheetオブジェクトの扱いがどうなのか、という点のほかに、実行速度の観点からは後者が良いんだろうか?

更には、コンテナバインドで且つアクティブなシートは下記のメソッドで直接取得できる。シートが複数で無いような場合にはこれも手。これだとシート名を変更しても問題ない。

SpreadsheetApp.getActiveSheet()

どのメソッドが適しているのか?の考え方、基準がまだ自分の中に無い、薄いので、いったん先に進む。


8.【初心者向けGAS】スプレッドシートのセル・セル範囲とその値を取得する方法

spreadシート>シートと取得できたので、次はgetRangeメソッドでセルでgetです。

getRangeメソッドは、以下の2通りの使い方があります。
・アドレスを指定してセル範囲を取得する
・行番号、列番号、行数、列数を指定してセル範囲を取得する

そして、値の取得には
・Rangeオブジェクト.getValue()
・Rangeオブジェクト.getValues()
複数のgetValues()で二次元配列になるのがミソだ。
例えば、メール送信ツールで複数の添付ファイルを付けたいときに使えそう。


9.【初心者向けGAS】for文を使ったスプレッドシートの繰り返しの超基本


for文。だいぶ記憶があやしいが、WordPressでテンプレート作るときにPHPでもそんなのやった気がする。条件分岐とかなんとか。swichとの違い、使い分けはよくわかってないが、まずは素直に進む。

 ​
for(初期化式; 条件式; 増減式) {
 // 繰り返す処理
}
for(let i = 2; 条件式; 増減式) {
 //処理
}
カウント用変数はよく「i」や「j」という変数が用いられます。

ちょっと寄り道。なんで「i」や「j」なんだと思ってぐぐってみた。
 「i」は index や integer(整数)iteration(反復)っぽい。
jとkは、単にiの次のアルファベットとか。諸説ありそう。
「i」や「j」は分かりにくくミスタイプ誘発するのでヤメロ派閥もいることを知った。



function myFunction({
 const sheet = SpreadsheetApp.getActiveSheet();
 const lastRow = sheet.getLastRow();
 for(let i = 2; i <= lastRow; i++) {
   console.log(sheet.getRange(i, 1).getValue());
 }
}

さて、for文。上記では、
spreadシート>シートを取得して、
最終行を定義/取得して、
for文で 
 初期化式 i =2, 2行目から
 条件式 i <= lastRow 最終行までを 
 増減式 i++(「i = i + 1」)どれだけ増加しながら、というような

 ​
if(sheet.getRange(i, 4).getValue() === ''){ 
 console.log(sheet.getRange(i, 1).getValue());
}し

↑素直に書くとこうなるが、スマートな書き方はこう↓

if(!sheet.getRange(i, 4).getValue()){ 
 console.log(sheet.getRange(i, 1).getValue());
}
「!」は条件式の結果を反転する論理演算子と呼ばれる記号です。「ではない」という意味ですね。

なるほ。

空文字つまり長さゼロの文字列は暗黙的にfalse
長さが1以上の文字列は暗黙的にtrue

if文をさっきのfor文の中に入れていく。シートのD列に適当な数字などいれて、確かにD列に値のあるものは出力されていないことを確認。

画像2

11.【初心者向けGAS】スプレッドシートのセルに値を入力する基礎の基礎

D列に値が入っていなければ出力する、という条件判定ができるようになったので、次はD列に値を入れていく処理。setValueメソッドを使う。getではなくset。

画像3

実行して勝手(というと語弊があるかもしれないが)に、自動的にシートにデータ入っていくと、お~プログラム走ってるぅ~!フゥ~!とテンション上がります。

この処理が時間がかかるとのことだが、テストデータとして名言データを3行くらいしかコピーしていなかったので、体感的にはわからなかった。実行ログでも0.01秒差くらい?3行でそれなら、確かに行数が多いとロスしそうな気配。では処理速度のためにはどうするのか、それはこの時点ではいったん脇におき、ここではゲッター&セッターを頭に入れて次に進む。あれだな、ゲームと一緒だな、あの扉を開くためには魔法の鍵が必要なんだが、まずは目の前をお題をこなしていく的な。

12.【初心者向けGAS】条件に応じてループを制御する2つの方法~break文とwhile文~

・if文が成立したときにbreak文でループを抜ける
・while文で条件式が成立している間繰り返す

breakでループを抜ける、この言葉だけでループものストーリの数々が脳裏をよぎります。最初の条件に合致したらループを抜ける、というのがセオリーのよう。breakは書いて実行して、すぐにその意味、結果が理解しやすいように思う。

画像4

対してwhileはちょっと曲者だ。一度説明を読んで、実行しても、どうもまだすっきり理解できていない。一行ずつ再度読み解いてみる。
3行目までは以前と同じなので、5行目letから。

カウント用変数iを初期値2で用意して、D列に何らかの値が格納されている間は単純にプラス1をします。
文字列は空文字でなければtrueを返しますからね。
i行目がD列に何も入力されてなければ、ループを終了します。
ループを抜けたとき、i行目は初めてD列が空文字だった行になります。
ですから、その行について、名言をBotしてtrueを書き込めばOKというわけです。

<おさらい>
空文字つまり長さゼロの文字列は暗黙的にfalse
長さが1以上の文字列は暗黙的にtrue

i=1にしても動くが、これはデータシートの2行目からカウントするということ。2行目から下に向かってデータを走査していく。5に書き換えると5行目スタートとなる。

whileの中で、getRangeとしてデータシートからi行の4列目の値を取得getし、4列目D列が空白であればコンソールログに出力し、4列目D列に1を追加していく。D列が埋まる=空白で無くなったとき、条件式が成立していないのでループを抜けてコードの11行目にたどり着く。???

うーん、ちょっとまだ理解しきれてないなあ...。いったんここまでにして進んでしまおう。

ここで注意するのが無限ループである。i++の処理がないとずっと条件を満たし続けることになる。


うーん、延々と実行すると、空白行にもTRUEが書き込まれてしまったりする。breakだとこうはならない。

画像6

画像5




13.【初心者向けGAS】スプレッドシートのセル範囲を行数・列数を使って取得する

すべてのD列にTRUEが書き込まれたあとにどうにかしたい、ということで進めていく。

Sheetオブジェクト.getRange(行番号, 列番号, 行数, 列数)

ちょっと疲れてきた。まずはサンプルコードをこぴって実行してみる。......あれー範囲がログ出力されない??と思ったら、前提条件としてデータシートの最終行だけ空白というのを満たしていなかった。

画像7

ちゃんと出た。引数の理解がまだ定着していないが、ひとまず...。

ここまで掛かった時間

事前課題に掛かった時間は、概ね4~6時間ってところかなあ。
ざっくり時間メモ。
・自己紹介&やりたいこと→スライド作成のため30分~1時間程度。 このあとスライド転用していくと思うので、まあこんなもんか。
・ビデオ視聴→二倍速で 30分~1時間程度。
・【課題3-1】1~6,2時間~ note書きながら
・【課題3-2】7~13,2時間~ note書きながら 一つのセクションで20分前後といったところか。

★whileは引き続き課題。

続く。はず。

↓つづき




いただいたサポートで、書籍代や勉強費用にしたり、美味しいもの食べたりします!