見出し画像

【GAS】Spreadsheets+GASで初歩的なアプリを作ってみよう

仕事で、GAS入門の話をしておくれ、と言われたので、その資料を作るための下準備記事です。テーマは「はじめてのGAS」「GASこわくない」です。

今回は、ハンドメイド作家向けの委託商品管理アプリという、私だけが嬉しいアプリを作っていきたいと思います。

どういうアプリかと言いますと、

画像1

こういう表にずらーっと商品を書いておいて、〇番から〇番を出力しまーす、って命令すると

画像2

こんな具合に納品書として出力してくれる、と言うものです。

納品の度に、シートコピーしてー、前回何番まで納品したか確認してー、前回と同じシリーズ納品する時は過去の説明文や金額確認してー…………ってのが結構面倒なので、過去の納品分全部一覧にしておいて、データ確認しながら入力したいなーーって思っていたので、これを機にこのアプリを作ってしまおうと思います。

1:SpredSheetsにデータを並べる

画像3

とりあえず取り扱いたいデータをわーっと表形式で並べておきます。

2:スクリプトを仕込めるようにする

画像4

拡張機能>Apps Scriptを選ぶと、自動的にプロジェクトが作られます。

ちなみにその下のAppSheetっていうのを今日見つけたんですが、ノーコードでアプリが作れるそうです。すげぇや。(でも全部英語でした。解読して使いこなすには時間が掛かりそうなので、またの機会か日本語化したら触って見ます)

今回はGASですGAS。

画像5

プロジェクトが表示されました。これでスクリプトが仕込めます。

3:ボタンを押したらHelloWorld

画像13

こんな感じでコードを記述していきます。以下コード表記してある部分はエディタのここで書いているということで。

function myFunction() {
    Browser.msgBox("hello","HelloWorld",Browser.Buttons.OK);
}

とだけ記入して、保存ボタンを押します。

次にボタンを作ります。SpreadSheetに戻って、

画像7

挿入>図形描画を選んで、ボタンを作ります。図形描画の挙動がちょっと特殊。

画像8

まあ、大体アイコン見れば使い方は分かるようになっていると思います。
ここで描画して、保存して終了を押すと、作ったアイコンが挿入されます。

画像9

作ったボタンを選択して、右上の三点メニューを開き、「スクリプトを割り当て」を選びます。するとスクリプト名を入力する画面が開くので、「myFunction」と入力。

そして、作ったボタンをクリックしてみると…………

画像11

最初の実行時だけこれが出てくるので、「続行」を押して、アカウントを選択します。

画像12

これが出てきたら、左下の「詳細」をクリックして、

画像13

「安全ではないページに移動」を押して、遷移先で「許可」を押します。公開していないアプリ(公開したくないアプリ)の場合はどうしてもこの手順が要る。

えー、ここまで終わらせて、改めてボタンを押して見ると、

画像10

やったー。

4:文字入力できるプロンプトを表示して、入力された数字を受け取る

function myFunction() {
 let start_num = Browser.inputBox("開始番号を入力してください");
 Browser.msgBox(start_num);
}

myFunctionを書き換えます。

入力値を受け取りたいときはBrowser.inputBox()を使います。

これで、start_numに入力値が入ります。
同様にend_numも受け取れるようにします。

function myFunction() {
 let start_num = Browser.inputBox("開始番号を入力してください");
 let end_num = Browser.inputBox("終了番号を入力してください");
 Browser.msgBox(start_num + "~" + end_num);
}

画像14

わーい。

ちなみに×ボタンで処理をキャンセルした場合、start_num(end_num)には文字列で「cancel」が入るので、キャンセルされたら終了する処理を入れておくと面倒がないです。

function myFunction() {
 let start_num = Browser.inputBox("開始番号を入力してください");
 if(start_num === "cancel"){return}
 let end_num = Browser.inputBox("終了番号を入力してください");
 if(end_num === "cancel"){return}
 Browser.msgBox(start_num + "~" + end_num);
}

5:入力された数字を反映した数式を各セルに入れる

今回は簡単に仕上げるため、出力用納品書の方に、

画像15

こんな感じの数式を入れて、必要行数コピーして解決するようにしたいと思います。

(記事書き終わってから、この方法だと私がやりたいことが本質的には実現できてねぇなって気付いたんですが、まあGASの使い方ご紹介なのでよしとします)

5-1:すでに入力されている値をクリア

A5セル~E29セルまでの記入内容を削除します。書式は維持したい。

const activeSheet = SpreadsheetApp.getActiveSpreadsheet();
const output_sheet = activeSheet.getSheetByName("納品書出力用シート");
output_sheet.activate();
const reset_range = output_sheet.getRange("A6:E29")

reset_range.clear({contentsOnly: true});

SpreadsheetApp(アプリ全体)からSpreadsheet(開いてるファイル)オブジェクトを取得して、Spreadsheetオブジェクトからsheet(使うシート)を取得して、sheetオブジェクトからRange(範囲)オブジェクトを取得して、消す。という流れ。

で、毎回毎回SpreadsheetApp.ごにょごにょ.うにゃうにゃ()って書くの大変なので逐一変数に入れてあげると後が楽です。

Rangeを取得できたら

reset_range.clear({contentsOnly: true});

で消します。clear()に{contentsOnly: true}オプションを渡してあげると、書式を維持したまま数値だけ消してくれる。

5-2:一行目の数式をオートフィルする

const source_address = "B5:E5"  // もとになる数式が入っている、一行目の範囲
const source_range = output_sheet.getRange(source_address);

const destination_address = "B5:E" +(end_num + 4);  // 一行目を含む、数式をコピーする範囲
const destination = output_sheet.getRange(destination_address);

// オートフィルを実行
source_range.autoFill(destination, SpreadsheetApp.AutoFillSeries.DEFAULT_SERIES);

ソースが入っている範囲と、終端までの範囲をそれぞれ取得し、ソースとなるRangeオブジェクトのautoFillメソッドを使う。

autoFill()に渡すのは、一つ目が終端までの範囲を示すRangeオブジェクト、二つ目は「デフォルトモードでオートフィルしてね」のおまじない。

ここまで作って実行してみると……

画像16

やったー。

まとめ

他にも、Gmailと連携させて一斉メール送信したり、受信メールの一覧を作ったり、CloudFirestoreと連携させて他のWebアプリと連携させたり、色々な事ができます。

また、今回はボタンを押したら発火するようにしましたが、「セルに入力があったら」とか、「ファイルが開かれたら」とかを切っ掛けにすることも可能です。

注意事項としては、無料アカウントの場合、「セルの入力を感知する機能」とか「セルに書き込みをする回数」とか諸々に1日あたりの回数制限があります。大体数万回とかの単位なので、個人で使うアプリをこまこま作っているうちは全く問題ありませんが、大規模にメールを一斉送信する、とか、仕事でヘビーに使うようなAPPを作る時はちょっと注意が必要です。

また、一回の起動上限が6分間という掟があるので、何万件ものデータを処理するなどの時間の掛かる処理をさせる場合、分割する工夫が必要です。

いい加減長くなりすぎるのでこの辺で。

ココまでのソースのまとめはこんな感じ。

function myFunction() {
 // Spreadsheetとsheetを取得しておく
 const activeSheet = SpreadsheetApp.getActiveSpreadsheet();
 const output_sheet = activeSheet.getSheetByName("納品書出力用シート");
 const input_sheet = activeSheet.getSheetByName("商品管理シート");
 
 // 入力値を受け取る
 let start_num = Browser.inputBox("開始番号を入力してください");
 if(start_num === "cancel"){return}
 let end_num = Browser.inputBox("終了番号を入力してください");
 if(end_num === "cancel"){return}
 
 // 納品書出力シートをリセット 
 output_sheet.activate();
 const reset_range = output_sheet.getRange("A6:E29")
 reset_range.clear({contentsOnly: true});

 // 数式を入力
 const source_address = "B5:E5"
 const source_range = output_sheet.getRange(source_address);
 const destination_address = "B5:E" +(end_num + 4);
 const destination = output_sheet.getRange(destination_address);
 source_range.autoFill(destination, SpreadsheetApp.AutoFillSeries.DEFAULT_SERIES);
}

わーーっと1つのfunctionに書いてしまった(よくない)のでちょっと長いですが、1つ1つの処理はほんの数行の処理で実装できるのでらくちんです。

でも、仕事で話す時はHelloWorldくらいまでにしておこ。

リファレンスはここ。




この記事が気に入ったらサポートをしてみませんか?