GAS（Google Apps Script）チートシート

## 概要

GASの良く使うパーツを書き溜めています。
個人用ですが参考になれば幸いです。
(const すべき所まで let で宣言しているのは大目に見てください･･･)

## スクリプト
##### ブック（スプレッドシート）を取得

~~~js
// 現在のブックを取得
let spreadsheet = SpreadsheetApp.getActiveSpreadsheet();

// IDを指定してブックを取得
// https://docs.google.com/spreadsheets/d/XXXXXXXXXXXXXXXXXXXX/edit#gid=0
let spreadsheet = SpreadsheetApp.openById('XXXXXXXXXXXXXXXXXXXX');

// URLを指定してブックを取得
let url = 'https://docs.google.com/spreadsheets/d/XXXXXXXXXXXXXXXXXXXX/edit#gid=0';
let spreadsheet = SpreadsheetApp.openByUrl(url);
~~~

##### ブック内のシートを取得

~~~js
// 現在のシートを取得
let spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
let sheet = spreadsheet.getActiveSheet();

// 現在のシートを取得（ブックを変数に格納する手順をスキップ）
let sheet = SpreadsheetApp.getActiveSheet();

// シート名を指定して取得
let spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
let sheet = spreadsheet.getSheetByName('hoge');

// シート名を指定して取得（ブックを変数に格納する手順をスキップ）
let sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('hoge'); 
~~~

##### 値を取得

~~~js
// A1の内容を取得
let a1_value = sheet.getRange( 1, 1 ).getValue();

// 1行目から最終行まで
let startRow = 1;
let startCol = 1;
let lastRow = sheet.getLastRow();
let lastCol = sheet.getLastColumn();
let list = sheet.getRange(startRow,startCol,lastRow,lastCol).getValues();
~~~

##### シートに書き込み

~~~js
// 1つのセルに書き込み
let sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange( 1, 1 ).setValue('hoge');

// 並んだセルに同時に書き込み
let sheet = SpreadsheetApp.getActiveSheet();
let obj = [
  ['a','b','c','d'],
  ['e','f','g','h']
];
// 開始列（開始Ｙ軸）
// 開始行（開始Ｘ軸）
// 行数（Ｙ軸範囲）
// 列数（Ｘ軸範囲）
sheet.getRange( 1, 1, 2, 4 ).setValues(obj);

// 最終行に追加
sheet.appendRow(['aa','bb']);
~~~

##### シート名を指定して 取得 OR 新規作成

~~~js
/**
 * 今日の日付のシート名を指定してセルに文字を書き込む
 */
function myFunction(){
  let date = new Date();
  let year = date.getFullYear();
  let month = date.getMonth() + 1;
  let day = date.getDate();
  let name = year + '-' + month + '-' + day;
  let sheet = createSheet(name);
  // シートに書き込み
  sheet.getRange(1,1).setValue('hoge');
}

/**
 * 指定された名前のシートが存在すれば返却
 * 無ければ新規作成
 */
function createSheet(name){
  let ss = SpreadsheetApp.getActiveSpreadsheet();
  let sheet = ss.getSheetByName(name);
  if(sheet){
    // シートが見つかればそのまま返却
    return sheet;
  } else {
    // シートが無ければ原本から複製して返却
    // 原本を取得
    let originSheet = ss.getSheetByName('原本');
    originSheet.showSheet();
    originSheet.activate();
    // 複製
    ss.duplicateActiveSheet().setName(name);
    let newSheet = ss.getSheetByName(name);
    // 原本を隠す
    originSheet.hideSheet();
    return newSheet;
  }
}
~~~

##### ポップアップ系

~~~js
let confirmation = Browser.msgBox('タイトル', '本文', Browser.Buttons.OK_CANCEL);
if(confirmation == 'cancel') {
  Browser.msgBox('キャンセルを押しました');
} else {
  Browser.msgBox('OKを押しました');
}
~~~

##### シートにメニューを追加

~~~js
/**
 * シートにメニューを追加
 */
function onOpen(){
//メニュー配列
  let myMenu=[
    {name: '関数1', functionName: 'myFunction1'},
    {name: '関数2', functionName: 'myFunction2'}
  ];
  SpreadsheetApp.getActiveSpreadsheet().addMenu('スクリプト',myMenu);
}
function myFunction1(){
  Browser.msgBox('関数1 を実行しました。');
}
function myFunction2(){
  Browser.msgBox('関数2 を実行しました。');
}
~~~

##### 日付関係（ GAS というよりは js ）

~~~js
function dateTestFunction(){
  let date = new Date();
  let a = formatYmd(date); // 2020-1-1
  let b = formatYmdJp(date); // 2020年1月1日（水）
  let c = getTimeStamp(); // 2020-1-1 3:3:3
}
/**
 * ex. 2020-1-1
 */
function formatYmd(date){
  if(date==''){return '';}
  let year = date.getFullYear();
  let month = date.getMonth() + 1;
  let day = date.getDate();
  return year + '-' + month + '-' + day;
}
/**
 * ex. 2020年1月1日（水）
 */
function formatYmdJp(date){
  if(date==''){return '';}
  let year = date.getFullYear();
  let month = date.getMonth() + 1;
  let day = date.getDate();
  let dayOfWeekStr = [ "日", "月", "火", "水", "木", "金", "土" ][date.getDay()] ;
  return year + '年' + month + '月' + day + '日（' + dayOfWeekStr + '）';
}
/**
 * ex. 2020-1-1 3:3:3
 */
function getTimeStamp(){
  let date = new Date();
  let year = date.getFullYear();
  let month = date.getMonth() + 1;
  let day = date.getDate();
  let hour = date.getHours();
  let minute = date.getMinutes();
  let second = date.getSeconds();
  return year+'-'+month+'-'+day+' '+hour+':'+minute+':'+second;
}
~~~

##### メール送信

~~~js
let to = 'hoge@example.com';
let subject = 'テストメール';
let body = 'テストメールです。';
let options = {
  name: 'hoge事務局',
  cc: 'hoge2@example.com',
  bcc: 'hoge3@example.com'
};
GmailApp.sendEmail(to , subject, body, options);
~~~

##### CURL

~~~js
function curl() {
  let url = "https://example.com";
  let headers = {
    Accept: "application/json",
    "Content-type": "application/json"
  };

  let data = {
    a: 1,
    b: 2 
  };

  let options = {
    method: "post",
    payload: JSON.stringify(data),
    headers: headers
  };
  UrlFetchApp.fetch(url, options);
}
~~~

##### HTTP エンドポイント（JSON）

~~~js
/**
 * A1~B2 の値を配列で返す
 */
function getDatas() {
  let sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('データ');

  let startRow = 1;
  let startCol = 1;
  let rowNum = 2;
  let colNum = 2;
  let datas = sheet.getRange(startRow, startCol, rowNum, colNum).getValues();
  return datas;
}

/**
 * GETリクエストの場合のレスポンス
 */
function doGet(e) {
  // ログシートに記録
  let sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('get_log');
  let params = e.parameter;
  sheet.appendRow([new Date(), params]);

  // データを取得
  let responseAry = getDatas();

  // レスポンス
  let output = ContentService.createTextOutput();
  output.setMimeType(ContentService.MimeType.JSON);
  output.setContent(JSON.stringify( responseAry ));
  return output;
}

/**
 * POSTリクエストの場合のレスポンス
 */
function doPost(e) {
  // ログシートに記録
  let sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('post_log');
  let json = e.postData.getDataAsString();
  let params = JSON.parse(json);
  sheet.appendRow([new Date(), params]);
  
  // データを取得
  let responseAry = getDatas();

  // レスポンス
  let output = ContentService.createTextOutput();
  output.setMimeType(ContentService.MimeType.JSON);
  output.setContent(JSON.stringify( responseAry ));
  return output;
}
~~~

##### HTTP エンドポイント（Webページ）

~~~js
function doGet(e) {
  let html = '<p>htmlです</p>';
  let htmlOutput = HtmlService.createHtmlOutput(html);
  htmlOutput.setTitle('GASで構築したページ');
  htmlOutput.setFaviconUrl('https://example.com/favicon.png');
  
  return htmlOutput; 
}
~~~

##### 別ページにリダイレクト
※Chromeの仕様変更により使えなくなりました

~~`function doGet(e) {`~~
~~`let url = 'https://exapmle.com';`~~
~~`html = "<script>window.top.location.href=\"" + url + "\";</script>"`~~
~~`return HtmlService.createHtmlOutput(html);`~~
~~`}`~~

iframeの中でWebページを開きます

~~~js
function doGet(e) {
  let url = 'https://exapmle.com';
  html = '<script>window.onload = function() {location.href="' + url + '";};</script>'

  let htmlOutput = HtmlService.createHtmlOutput(html);
  htmlOutput.setTitle('iframeの中で表示');
  htmlOutput.setFaviconUrl('https://example.com/favicon.png');
  
  return htmlOutput; 
}
~~~

iframeの中で開きたくない場合はこちら

~~~js
  let html = ''
  + '<body>'
  + '  <div>'
  + '    <a href="' + url + '" target="_blank">自動で遷移しない場合はこのボタンをクリックしてください</a>'
  + '  </div>'
  + '  <script>window.open("' + url + '", "_blank");</script>'
  + '<style>'
  + '  body {background: #e9e9e9;}'
  + '  div {width: 100%; display: flex;}'
  + '  a { margin: 40px auto; padding: 30px 50px; background: #fff; display: inline-block; border: solid 1px #b3b3b3; border-radius: 10px; font-size: 21px; text-decoration: none; color: #1015ab;}'
  + '</style>'
  + '</body>'
  ;
  
  let htmlOutput = HtmlService.createHtmlOutput(html);
  htmlOutput.setTitle('転送ページ');
  htmlOutput.setFaviconUrl('https://example.com/favicon.png');
  
  return htmlOutput; 
~~~

##### for（v8ランタイム対応）

~~~js
// 配列
let datas = [500,800,200];
for (let i = 0; i < datas.length; i++) {
  let data = datas[i];
  console.log(i);
  console.log(data);
}

// 配列(foreachライク)
let datas = [500,800,200];
for (let data of datas) {
  console.log(data);
}

// 連想配列
let datas = {color:'red', name:'apple'};
for (let idx in datas) {
  let data = datas[idx];
  console.log(idx);
  console.log(data);
}
~~~

##### ランダムな文字列を生成

~~~js
/**
 * ランダム生成した文字を返す
 * @param int type 1:アルファベット 2:数字
 * @param int len 桁数
 * @retrun string
 */
function getPWD(type,len){
  let c = (type==1) ? "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz" : "23456789";  
  let cl = c.length;
  let pwd = "";
  for(let i=0; i<len; i++){
    pwd += c[Math.floor(Math.random()*cl)];
  }
  return pwd;
}
~~~

##### ドライブ内のCSVファイルを読込

~~~js
function readCsv() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheets = ss.getSheets();

  let dirName = "test";
  let filename = "aaa.csv";
 
  try {
    //csvファイルを取得＋配列化
    let dir = DriveApp.getFoldersByName(dirName);  
    let file = DriveApp.getFilesByName(filename).next();
    let data = file.getBlob().getDataAsString('shift-jis');
    let csv = Utilities.parseCsv(data);

    // シートに書き込み
    let sheet = SpreadsheetApp.getActiveSheet();
    sheet.getRange( 1, 1, csv.length, csv[0].length ).setValues(csv);

  } catch(e) {
    MailApp.sendEmail('hoge@example.com', 'csvインポート失敗。',e.message);
  } 
}
~~~