2024.11.14
いまさらNode.jsを知ろう~環境構築も~
2023.01.30
開発環境・ツール【GAS】GASを触ってみる!〜SpreadSheet編〜
本ブログをお読みになってくださっている皆様、こんにちは。
お久しぶりです。MTです。
皆様はいかがお過ごしでしょうか。私は年始の思い出しで苦しんでいました、、
本日は触ってみたいな〜と思っていた技術【GAS】
だいぶ出遅れ感はありますが触る機会があったので、そのことを記事にさせていただきました。
今回触ってみるGASは、Google Workspaceと強く連携していて、社内環境改善ととても相性がいい!
ということで、これを利用して何か環境改善案を提示したいな、と思います。
そこで私が選んだ業務は、 「稼働報告の作成」
稼働報告の作成は、管理において必須、しかし正直手間も多い作業ですよね。
更に会社文化ごとに異なるフォーマットがあることも度々あり、楽できるならしたい業務だと思います。
さあ、ではいきなり実装!といきたいところですが、知見もないので一歩ずつ解決してきましょう。
ということで今回はこういった集計表を作るなら必須の「スプレッドシート」と、「GAS」を組み合わせて
使い方を調べていきたいと思います。
スプレッドシートは、よくある表計算ソフトです。
実をいうと私は、あまりマクロだ関数だと機能をフルに使ったことはなく、
単純にセルベースであるから分かりやすい表が作れるよね。と表の作成に用いています。
今回はその表の作成で、最終目標に向かってあるテストケースを考えて
実際にものを作ってみたいと思います。
自分の作業を紹介形式で書いているので、よければ試しにやってみてください!
業務の場で度々、表形式のドキュメントの提出を求められる事があると思います。
しかもそれは基本的にフォーマットが定められている、、
「仕方のない事だけど、フォーマットに沿って作るのは面倒だなぁ」誰でも思う事だと思います。
「雑多にただ羅列したシートの内容を提出用に整形してくれないかなぁ」ん?これは出来るかもしれません!
ということで今回は、あるシートに列挙した内容を、提出用にまとめることを目標にしてみたいと思います。
今回の目標を以下のようにまとめます。
・今回は日記(日報)をつけられるようにします。
・その日記の日付、タイトル、本文を1行に並べ、それを列挙していきます。
・その日毎の日記が、報告書スタイルで別シートに並べられていきます。
今回はこれを作ってみましょう!
まずGASのエディタを開きます。
GASの開き方は2通りあり、それぞれGoogleDriveから開く「スタンドアロン型」、
スプレッドシートなど各サービスから開く「コンテナバインド型」です。
今回は、スプレッドシートの操作を行いたいので、
スプレッドシートからコンテナバインド型で開きましょう。
手順は以下の通りです。
1. スプレッドシートを開く
2. ツールバーの「拡張機能」から「Apps Script」を選択
3. エディタが開く
これで開発の準備が整いました!
スプレッドシートの操作を行うのに必要な情報は、
・スプレッドシートの情報
・シートの情報
・操作する場所(セル)の情報
です。
それぞれの取得の仕方は以下の通りです。
■ スプレッドシートの情報
今回は、スプレッドシートはスクリプトに紐づいた一つのみを利用します。
この場合、以下のコードで情報を取得できます!
“`
const spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
“`
このgetActiveSpreadSheet()は、文字通りアクティブなスプレッドシートを取得する関数です。
この場合、「アクティブな」という文言は、
スクリプトが紐づいているスプレッドシートの認識で問題ありません。
IDを利用してのスプレッドシートの取得も可能です。が、今回の記事では割愛いたします。
■ シートの情報
シートの情報は、基本的に名前で管理します。
なのでSpreadSheetクラスの持つ、getSheetByNameメソッドで取得することができます!
“`
const inputSheet = spreadSheet.getSheetByName(‘記入シート’);
“`
また、新しいシートを定義して、そのシートを操作することもできます。
“`
const diarySheet = spreadSheet.insertSheet(‘日記帳’);
“`
■ 操作する場所(セル)の情報
操作する場所、セルの情報は、典型的なものがありますよね。
そう、番地です。A1やB2などの数字とアルファベットの組み合わせで指定しているやり方です。
それを勿論GASでも利用出来ます!さらに、m列目のn行目といった形で指定することもできます!
範囲の指定は基本的にsheetクラスの持つgetRangeメソッドで行います。
“`
inputSheet.getRange(“A1”) // 記入シートのA1の範囲
inputSheet.getRange(1, 1) // 記入シートの1列目1行目(=A1)の範囲
inputSheet.getRange(“A1:C3”) // 記入シートのA1:C3の範囲
inputSheet.getRange(1, 1, 3) // 記入シート1列目の1行目から3行目の範囲
inputSheet.getRange(1, 1, 3, 3) // 記入シート1列目から3列目の1行目から3行目の範囲
“`
さらっと流してしまいましたが、勿論範囲を指定するものなので、
複数のセルを含む範囲を指定することもできちゃいます。
指定方法は他にも値のある最後の列を選ぶ、などいろいろあるのですが、
多過ぎても困るので、今回はシンプルに以上のメソッドでいきましょう
ここまでで、セルを指定する方法までは分かっていただけたかと思います。
ではあとは値の操作さえわかれば、もうなんだってできます!
というわけで値の取得とセットについて紹介します。
■ セルの値の取得
セルの値の取得は、Rangeクラスの持つgetValue, getValuesメソッドで行います。
“`
inputSheet.getRange(1, 1, 3, 3).getValue() //A1の値だけ
inputSheet.getRange(1, 1, 3, 3).getValues() //値が二次元配列で取得される
“`
気をつける必要があるのは、getValueメソッドは最も左上の値のみを取得する、ということです。
なので基本的に明確にここの値だけ取得します!といった用途がない限りは
getValuesで良いのかなと思います。
また、getValuesはObjectの二次元配列なので、
indexは[0][0]が左上の値を指すことに気をつけてください。
■ セルの値の設定
セルの値の設定は、先ほどとほぼ同じで、setValue, setValuesメソッドで行います
“`
inputSheet.getRange(1, 1, 3, 3).setValue(‘値’) //A1:C3の値が全て「値」になる
inputSheet.getRange(1, 1, 3, 3).setValues(
[
[1,2,3],
[4,5,6],
[7,8,9]
]) //二次元配列の値がセットされる
“`
こちらの関数の注意点は、記載の通り、setValueは範囲が1つのセルでなくても動くので、
選択範囲が全部同じ値になること、
setValuesは指定範囲の次元が正しく一致してないと動作しないことの2点くらいではないかなと思います。
なお、手入力と同じで、「=」から始まる入力は数式として、処理されます。
これで、もう表計算ソフトで普段やっていることは何でもできるんじゃないでしょうか!
(関数を知っているか、などの問題はあるかもしれませんが、、、)
少なくとも自分が普段やっているような、このセルにこの値を入れて〜といった入力は完璧に出来ますね!
あとは頭の中のイメージを形に落とし込むだけです!早速やってみましょう!
では、まず要件をまとめます。
日記を行ごとに書いて、それを別シートにフォーマットして書き出す
今回の要件はざっくりいうとこんな感じですよね。
これを実装出来そうなレベルに落とし込んでいきます。
– スプレッドシート:紐づいているシートのみ
別シートにフォーマットして書き出せたらいいのでスプレッドシートは一個だけでよさそうです。
– シート:入力用のシート、とフォーマット後のシート
入力をつらつらとしていくだけのシートと、綺麗に整形した後のシートがあればひとまずよさそうです。
– フォーマット
フォーマットに関しては入力は定められていて、一行に日付、タイトル、本文を含むことになっていますね。
なのでA列に日付、B列にタイトル、C列に本文を入力する、としましょう。
フォーマットに関して、とりあえず読みやすくできればいいかなと思うので、シンプルに
1行目:空行
2行目:日付+タイトル
3行目:本文
となるようにして、これを繰り返す形で作ってみましょう。
現時点で、スプレッドシートは紐づいているものがあり、デフォルトでシートは1つあると思うので、
シート名を「入力シート」にして使うことにしましょう。
では、これをGASで扱えるように、スクリプト内の定数として定義します。
“`
const spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
const inputSheet = spreadSheet.getSheetByName(‘記入シート’);
“`
次に、フォーマット後のシートを用意しましょう
あまり美しくない書き方かもしれないですが、さっと作ってしまうため、
変数として、sheetを定義して、名前で取得しましょう。
“`
let formattedSheet = spreadSheet.getSheetByName(‘日記帳’);
“`
え?日記帳なんてシートは作ってない?
そうですね、変数にした理由がこれなのですが、
今回は、シートがあったらそれを使って、なかったら新しく作る、といった方針で進めます。
GASの実行は、一回とは限りませんからね。(先にシート作ればいい、というのは一回置いときましょう)
“`
if (!formattedSheet) {
formattedSheet = spreadSheet.insertSheet(‘日記帳’)
}
“`
これで使いたいシートの用意は完了です。
では、まず入力シートから必要な情報を取得する方法を考えましょう。
入力シートは前提として、A列、B列、C列がn行(n >= 0)存在しているものですね。
ではその範囲を指定して、getValuesすればよさそうですね!
あれ、困りました、、何行あるかわからないから行数の指定ができません、、、
ここで、紹介していなかったメソッドが役立ちます。
Sheetクラスには、「コンテンツが含まれる最後の行を返す」メソッドが存在します。
それを使うとRangeの指定から値の取得は以下のようにセットすることができます。
“`
// コンテンツが含まれる最後の行を返す
const max_rows = inputSheet.getLastRow();
if (max_rows < 1) { return; } // エラー回避
const inputData = inputSheet.getRange(1, 1, max_rows, 3).getValues();
“`
これでinputDataには、
[
[A1, B1, C1],
[A2, B2, C2],
~
[An, Bn, Cn],
]
の値が入っているはずですね。
あとはこれを書き写すだけ!
単純にループさせて、フォーマットに合わせて書き写していきましょう。
やりたい処理は、
行数だけループして、
まず空行が入って
次の行に、An, Bnの値を入力(今回は入力値の形式は特に気にしないので’An:Bn’で記載します)
次の行に、Cnの値を入力
1回のループで3行使って、転記は1行目から始まります。
とまとめることが出来ます。
ではこれを処理に落とし込んでいきます
“`
inputData.forEach((arr, index) => {
// row行目は空行
const row = index * 3 + 1;
// row+1行目はAn:Bn_日付型はデフォルトだと全て出てくるので調整
formattedSheet.getRange(row+1, 1).setValue(arr[0].getMonth()+1 +
‘/’ + arr[0].getDate() + ‘:’ + arr[1]);
// row+2行目はCn
formattedSheet.getRange(row+2, 1).setValue(arr[2]);
});
“`
※ Date型のgetMonthは0から始まるため+1が必要
以上で、コーディングは完了です!お疲れ様でした!!
では早速実行してみましょう。
今回は特にトリガー(自動実行のきっかけ)を設定せずに、手動で動かします。
手動で動かすのは簡単で、作成したコードを保存して、エディタの上にある実行を押しましょう!
その前に、「入力シート」に適当な値を入力することを忘れずに!
実行すると、コンソールが出てくるので、「実行完了」と表示されればOKです!
※ 権限のリクエストを求められた場合は、表示に従って権限を許可すれば基本的に問題ありません。
自分のスプレッドシートを見て、
1. 「日記帳」シートが増えている
2. 入力シートの値が指定のフォーマットで転記されている
以上が正常に確認できたら完成です!おめでとうございます!
結構簡単にできてしまうものですね!普段やっていることを別のやり方でやっているので、
これができた、できなかったが分かりやすくて結構楽しみながら勉強できる気がします!
本当はもう少しちゃんと報告書っぽく体裁を整えるなどしたかったのですが、
少し執筆に時間を取れず、雑な形になってしまい申し訳ございません。
このまま自分の執筆分はしばらく、
GASを使って当初の目標物を作ることに焦点を当てていくつもりなので、
よければ次回の記事も目を通していただけると嬉しいです!
それでは、最後までお付き合い頂きありがとうございました。MTでした。
次回記事: 【GAS】GASを触ってみる!~Forms編~
【記事への感想募集中!】
記事への感想・ご意見がありましたら、ぜひフォームからご投稿ください!【テクノデジタルではエンジニア/デザイナーを積極採用中です!】
下記項目に1つでも当てはまる方は是非、詳細ページへ!Qangaroo(カンガルー)
【テクノデジタルのインフラサービス】
当社では、多数のサービスの開発実績を活かし、
アプリケーションのパフォーマンスを最大限に引き出すインフラ設計・構築を行います。
AWSなどへのクラウド移行、既存インフラの監視・運用保守も承りますので、ぜひご相談ください。
詳細は下記ページをご覧ください。
最近の記事
タグ検索