こんにちは!
おでぃーです。
今回は、GASで頻出するあらゆる用途のソースコードをまとめていきます。
こんな経験ないでしょうか??
- 何度も実装しているのにコードを書けない。
- 「この処理どうやってやるんだっけ…?」と思ってことあるごとに調べる。
- 処理ごとに何度も同じ記事にたどり着き読み直す。
特に1つ目は私もそうで、簡単な処理であっても0から書こうとすると意外と苦労します。
なので調べるんですが、情報が散らばっていたり、余計な処理が入っていたりします。
読み解いて自分に必要な部分だけ持ってくるのが面倒くさい。。
ということで、
このページさえブックマークしておけば、いちいちググって調べる必要なし!
そんなページを目指して、コードを随時更新していきます。
また、ここで紹介しているスクリプトは、自作ライブラリにまとめています。
今後もどんどん追加していく予定なので、気になる方は保存しておいてくださいね!
スクリプトID:10AJatx_S37htnLUeooAFjE6dxN4OyJJFBXs9sisFwSECl-d7wig-9pv_
スプレッドシート取得
まずこれがなきゃ始まらないですね。
メジャーなのは「getActiveSheet」などのActive系メソッドだと思います。
コンテナバインド型であれば問題ないですが、スタンドアロン型のGASエディタの場合は上手く動きません。
なので私は基本的に「openById」などのopenBy系メソッドを使って確実に動作するようにしています。
下記のスクリプトは「getValues」でセル内の文字を取得する処理までとなります。
ちなみに範囲が単一セルの場合は、「getValue」でOK。
var spreadsheetId = 'スプレッドシートID';
var spreadsheet = SpreadsheetApp.openById('spreadsheetId');
var sheet = spreadsheet.getSheetByName('sheetName');
var Values = sheet.getRange('A1:C').getValues();
スプレッドシートIDは、スプレッドシートのURLに含まれているIDを指します。https://docs.google.com/spreadsheets/d/ここがスプレッドシートID/edit#gid=○○○
メニュー&実行ボタン作成
私の場合、個人で使用するだけなら用途は少ないですが、複数でスプレッドシートを共有する場合や、ツールとして他人に共有する場合は分かりやすいのでよく使います。
変数menu1をmenu2などと新たにつくれば、メニューを増やせます。
addItemを増やせば同一メニュー内のボタン数を増やせます。
function onOpen() {
var ui = SpreadsheetApp.getUi()
var menu1 = ui.createMenu("メニュー名");
menu1.addItem("実行ボタン名","関数名");
menu1.addToUi();
}
基本的には上記を設定してスプレッドシートをリロードすれば上部のメニューバーに反映されています。
しかし、反映されないときがあります。
そのようなときは、上記記事の方法で解決するか、もしくはトリガーを作成します。
左側メニューから「トリガー」を選択。
右下にある「トリガーを追加」を選択。
下の画像のように設定し、保存。
これでスプレッドシートをリロードするとメニューバーが表示されるようになります。
日時の整形
日時の操作に使います。
var date = new Date();
var formattedDate = Utilities.formatDate(date,"JST", "yyyy/MM/dd") //日付まで
var formattedDate = Utilities.formatDate(date,"JST", "yyyy/MM/dd hh:mm:ss") //秒数まで
月初の日にちを取得
引数として指定したdatetimeに対して、当月・前月・翌月の月初日を取得します。
月ごとのデータ集計などでよくお世話になっています。
function getFirstDay(today) {
// 今月の1日目
var firstDayOfCurrentMonth = new Date(today.getFullYear(), today.getMonth(), 1);
// 前月の1日目
var firstDayOfPreviousMonth;
if (today.getMonth() === 0) { // If current month is January, previous month is December of the previous year
firstDayOfPreviousMonth = new Date(today.getFullYear() - 1, 11, 1);
} else {
firstDayOfPreviousMonth = new Date(today.getFullYear(), today.getMonth() - 1, 1);
}
// 翌月の1日目
var firstDayOfNextMonth;
if (today.getMonth() === 11) { // If current month is December, next month is January of the next year
firstDayOfNextMonth = new Date(today.getFullYear() + 1, 0, 1);
} else {
firstDayOfNextMonth = new Date(today.getFullYear(), today.getMonth() + 1, 1);
}
return {
currentFirst: firstDayOfCurrentMonth,
previousFirst: firstDayOfPreviousMonth,
nextFirst: firstDayOfNextMonth
};
}
スクリプトプロパティ取得
私はツール販売をするときに、スプレッドシートIDを「○○.gsの何行目のこの場所に設定」というよりもスクリプトプロパティを設定してもらうほうが、いつも説明が同じで楽なのでこれを使っています。
ほかにもAPIキーを設定するとき、他人にソースコード上で見られたくないときなんかに使うと便利です。
const scriptProps = PropertiesService.getScriptProperties();
var spreadsheetId = scriptProps.getProperty('spreadsheetId');
トリガー作成
「GASエディタで設定できるじゃん」と言われればそうなのですが、
こちらもツールとしてお渡しするときに、スプレッドシートをコピーしてもらった後に再度設定してもらう必要があるので、メニューバーにトリガー作成ボタンを置くかたちで使用しています。
// 分ベースのトリガーを作成
function createEveryMinutesTrigger(triggerName, minute) {
ScriptApp.newTrigger(triggerName).timeBased().everyMinutes(minute).create();
}
// 日ベースのトリガーを作成
function createEveryDaysTrigger(triggerName, days, hours) {
ScriptApp.newTrigger(triggerName).timeBased().everyDays(days).atHour(hours).create();
}
//スプレッドシートを編集した時のトリガー設定
function createSpreadsheetEditTrigger(triggerName){
var ss = SpreadsheetApp.getActiveSpreadsheet();
ScriptApp.newTrigger(triggerName).forSpreadsheet(ss).onEdit().create();
}
//スプレッドシートを変更した時のトリガー設定
function createSpreadsheetChangeTrigger(triggerName){
var ss = SpreadsheetApp.getActiveSpreadsheet();
ScriptApp.newTrigger(triggerName).forSpreadsheet(ss).onChange().create();
}
//スプレッドシートを起動した時のトリガー設定
function createSpreadsheetOpenTrigger(triggerName){
var ss = SpreadsheetApp.getActiveSpreadsheet();
ScriptApp.newTrigger(triggerName).forSpreadsheet(ss).onOpen().create();
}
トリガー削除
こちらもメニューバーにトリガー作成ボタンを置くかたちでよく使用しています。
// トリガーを削除
function deleteTriggers() {
var triggers = ScriptApp.getProjectTriggers();
for (var i = 0; i < triggers.length; i++) {
ScriptApp.deleteTrigger(triggers[i]);
}
}
// 特定の名前のトリガーを削除
function deleteNamedTriggers(triggerName) {
var triggers = ScriptApp.getProjectTriggers();
for (var i = 0; i < triggers.length; i++) {
if(triggers[i].getHandlerFunction()===triggerName){
ScriptApp.deleteTrigger(triggers[i]);
}
}
}
メッセージボックス作成
たった1行ですが、メニューを使って実行するとログが見れないので、これがあるだけで安心させてくれます。
Browser.msgBox("Success!");
繰り返し処理(for)
いわゆるfor文です。
他にも記述の仕方はあるのですが、私は慣れてしまったのでいつもこれです笑
配列変数(下記の例だとdata)に対して「.length」をすると、その配列の要素数を出力できるので、
それを繰り返しの上限としています。
for(i = 0 ; i < data.length ; i++){
break
}
Vlookup関数のような処理
これめちゃくちゃ頻繁に使います。
ExcelでVlookup関数を使うようなものと考えると当然ですよね。
var searchValue = "検索文字列"
var range = sheet.getRange("A2:A");
var values = range.getValues()
for(i = 0 ; i < Values.length ; i++){
var Value = Values[i][0];
if(Value == searchValue){
sheet.getRange("B" +(i+2)).getValue();
break;
}
}
//検索文字列をA列から探し出して、同じ行のB列の値を取得
// =Vlookup(searchValue,A2:B,2,false)
値を含む連続するセルの最終行を取得(getNextDataCell)
実際には見出しのような使い方になりますが、正しく説明すると下記のようになります。
- 起点から見て、値を含む連続しているセルの最終行を取得
- 起点から見て、値を含まない連続しているセルの最終行の次の行を取得
注意しなければならないのは、
「データが連続しているセル最終行」
「値を含む連続しているセルの最終行」
だけではないので、このような表現で理解するのは誤っているということです。
上記のような、行ごと・列ごとにデータが含まれる最終行が異なるシートを例とします。
今回は、A列の値を含む最終行を取得したいとします。
この場合、該当するのは6行目もしくは9行目になりますよね。
どちらを取得したいかはシーンによって異なると思いますが、両方とも取得することできます。
var lastRow = sheet.getRange(1, 1).getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow();
Logger.log(lastRow); //6
//A1セル(1,1)を起点に下方向(DOWN)に進み、値の有無が連続しているセルの最終行を取得
var lastRow = sheet.getRange(sheet.getMaxRows(), 1).getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
Logger.log(lastRow); //9
//A列最終セル(getMaxRows)を起点に上方向(UP)に進み、値の有無が連続しているセルの最終行を取得
前者は、A1セルから見たときにA2:A6が値有りで連続していて、取得する行数は6です。
つまり1の使い方となります。
後者は、最終セルA15から見たときにA10:A14が値無しで連続していて、取得する行数は最終行である10の次の行の9となります。
つまり2の使い方となります。
他の例としてB列を見てみましょう。
画像を再掲します。
var lastRow = sheet.getRange(1, 2).getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow();
Logger.log(lastRow); //3
//B1セル(1,1)を起点に下方向(DOWN)に進み、値の有無が連続しているセルの最終行を取得
var lastRow = sheet.getRange(sheet.getMaxRows(), 2).getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
Logger.log(lastRow); //12
//B列最終セル(getMaxRows)を起点に上方向(UP)に進み、値の有無が連続しているセルの最終行を取得
前者は、B1セルから見たときにB2:B3が値有りで連続していて、取得する行数は3です。
つまり1の使い方となり、1つ目の例と同じ使い方でもあります。
後者は、最終セルB15から見たときにB12:A14が値有りで連続していて、取得する行数は12です。
つまりこれも1の使い方となります。
最後にC列を見てみましょう。
var lastRow = sheet.getRange(1, 3).getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow();
Logger.log(lastRow); //15
//C1セル(1,1)を起点に下方向(DOWN)に進み、値の有無が連続しているセルの最終行を取得
var lastRow = sheet.getRange(sheet.getMaxRows(), 3).getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
Logger.log(lastRow); //1
//C列最終セル(getMaxRows)を起点に上方向(UP)に進み、値の有無が連続しているセルの最終行を取得
前者は、C1セルから見たときにC2:C15が値無しで連続していて、取得する行数は最終行である15の次の行の16のはずですが、15までしか存在しないので15となります。
このとき取得行が1ではない点に注意です。
非常に分かりにくいですが、「起点とするセルは含まない」という仕様になっているようです。
使い方としては2のほうになります。
後者は、最終セルC15から見たときにC2:C14が値無しで連続していて、取得する行数は最終行である2の次の行の1となります。
つまりこれも2の使い方となります。
値を含む連続するセルの最終列を取得(getNextDataCell)
前項の最終列バージョンです。
1行目を例にします。
var lastCol = sheet.getRange(1, 1).getNextDataCell(SpreadsheetApp.Direction.NEXT).getColumn();
Logger.log(lastCol); //3
//A1セル(1,1)を起点に右方向(NEXT)に進み、値の有無が連続しているセルの最終行を取得
var lastCol = sheet.getRange(1, sheet.getMaxColumns()).getNextDataCell(SpreadsheetApp.Direction.PREVIOUS).getColumn();
Logger.log(lastCol); //6
//1行目最終列を起点に左方向(PREVIOUS)に進み、値の有無が連続しているセルの最終行を取得
前者は、A1セルから見たときにB1:C1が値有りで連続していて、取得する列数は3です。
つまり1の使い方となります。
後者は、最終セルH1から見たときにG1のみが値無しなので、取得する列数は最終列である7の次の列の6となります。
つまり2の使い方となります。
配列を1次元に変形&重複削除
使用例としては、スプレッドシートから取得した列単位の配列を、重複なしの配列にしたいときなどです。
function reshapeTo1dArrayAndEliminateDuplicates(array) {
function eliminateDuplicate(x, i, array) {
return array.indexOf(x) == i;
}
return array.flat().filter(eliminateDuplicate).filter(Boolean);
}
シートを複製&指定した位置に移動
引数には、複製元のシート名・新しいシート名・新しいシートの位置(左から何番目か)を指定します。
function duplicateSheet(fromSheetName, newSheetName, n) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
// シートが存在するか確認
if (ss.getSheetByName(newSheetName)) {
// 新しいシートが存在する場合は削除
ss.deleteSheet(ss.getSheetByName(newSheetName));
}
// 指定した名前のシートを複製
var originalSheet = ss.getSheetByName(fromSheetName);
var newSheet = originalSheet.copyTo(ss).setName(newSheetName);
//シートを指定した位置に移動
newSheet.activate();
if(n){
ss.moveActiveSheet(n);
}
return newSheet
}
まとめ
今回は、よく使うソースコードをまとめました。
テンプレートで使えるコードを増やして、開発を効率的に進めましょう!
コメント