【Google Apps Script出張版】鈍速でスプレッドシートにクリスマスツリーを自動描画する

この記事は[エイチームブライズアドベントカレンダー](https://qiita.com/advent-calendar/2017/a-t-brides)12日目の記事です。

筆者個人の活動として、マジメなGoogle Apps Script解説アドベントカレンダーもやっていますので、興味のある方は是非。
[Google Apps Scriptを実例交えて基礎からざっくり学ぶ Advent Calendar 2017](https://qiita.com/advent-calendar/2017/gas_beginner)

※5倍速の録画です。実際はもっとモッサリです。

![movie.gif](https://qiita-image-store.s3.amazonaws.com/0/199678/bea7613c-5211-a677-d595-150b4f47e26c.gif)

# はじめに

自宅PCが低スペのせいか、全然爆速じゃなかったですがGoogle Apps Scriptでクリスマスツリーを描いてみました。
正確に言うと、絵心ゼロの筆者がスプレッドシート方眼紙にクリスマスツリーを描いた後、コードを自力でガリガリ書きました。
GASの勉強にはなりましたが、このプログラムが何の役に立つのか全く分かりません。

# 1．スプレッドシートを新規作成する

Google Driveを開き、スプレッドシートを新規作成。ファイル名は付けても付けなくてもOKです。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/199678/29d394f3-e2fb-7d10-312b-ce543208b3f5.png)

# 2．スクリプトエディタを開く

ツール→スクリプトエディタを選択。

![2.png](https://qiita-image-store.s3.amazonaws.com/0/199678/797a0a74-cb15-dcbc-50c4-8deb54dd56d2.png)

# 3．おもむろに以下ソースをコピペ

```javascript:christmas_tree.gs

var sheet = SpreadsheetApp.getActiveSheet();
var COLUMN_NUM = 26;
var ROW_NUM = 37;

function onOpen(){
  var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
  var menus = [{name: '1)ツリーを描く', functionName: 'drawChristmasTree'},
               {name: '2)飾り付けをする', functionName: 'decoration'},
               {name: '3)★を乗せる', functionName: 'putStar'},
               {name: '4)ライトを点ける', functionName: 'turnOnLights'},
               {name: 'all)一度に全て実行', functionName: 'drawAll'}
              ];
  spreadSheet.addMenu('クリスマス特別メニュー', menus);
}

function getAllRange() {
  return sheet.getRange(1, 1, ROW_NUM, COLUMN_NUM);
}

// 1)ツリーを描く
function drawChristmasTree() {
  reset();
  for (var i = 1; i <= COLUMN_NUM; i++) { // Excel方眼紙にする為に列幅揃える
    sheet.setColumnWidth(i, 24);
  }
  for (var i = 1; i <= ROW_NUM; i++) { // Excel方眼紙にする為に列幅揃える
      sheet.setRowHeight(i, 24);
  }

  getAllRange().setHorizontalAlignment('center').setVerticalAlignment('middle'); // 全部センター　★とか◉を真ん中に寄せる為
  
  paintTree('#5c7a07', '#3f5209');
  // 幹
  sheet.getRange('I35:K37').setBackground('#61380B');
  Browser.msgBox('クリスマスツリーを用意しました！');
}

function paintTree(color1, color2) {
  // 薄い緑
  var ranges = ['I5:K32', 'H6:L6', 'H8:L31', 'G9:M9', 'G11:M31', 'F12:N12', 'F14:N31', 'E15:O15', 'E17:O30', 'D18:P18', 'D21:P29', 'C23:Q29', 'B26:R27'];
  for (var i in ranges) {
    sheet.getRange(ranges[i]).setBackground(color1);
  }
  // 濃い緑
  ranges = ['J4', 'I7', 'K7', 'J8', 'H10:I10', 'K10:L10', 'J11', 'G13', 'M13', 'H14:L14', 'F16', 'N16', 'G17:I17', 'K17:M17', 'J18', 'E19', 'O19',
                'F20:G20', 'M20:N20', 'H21:L21', 'J22', 'C24:C25', 'Q24:Q25', 'D25', 'P25', 'D26:F26', 'N26:P26', 'F27:H27', 'L27:N27', 'I28:K28',
                'A28:B29', 'R28:S29', 'B30:D30', 'P30:R30', 'C31:E31', 'O31:Q31', 'E32:H32', 'L32:O32', 'G33:M33', 'I34:K34'];
  for (var i in ranges) {
    sheet.getRange(ranges[i]).setBackground(color2);
  }
}

// 2)飾り付けをする
function decoration() {
  
  getAllRange().setFontSize(12);

  // 各種ライン
  var colorCode = '#CCCCCC';
  var ranges = ['I6', 'K8', 'L9', 'H8', 'I9', 'K11', 'H11', 'I12', 'K14', 'L14', 'N15', 'F14', 'H15', 'L17', 'M17', 'N17', 'O18', 'E19', 'F19',
                'G20', 'H20', 'L21', 'M21', 'N22', 'O22', 'P22', 'C23', 'D24', 'E24', 'F25', 'G25', 'M27', 'N27', 'O27', 'P27', 'Q26', 'R26'];
  setDecoration(ranges, colorCode, '＼');
  ranges = ['K6', 'I8', 'H9', 'L8', 'K9', 'I11', 'L11', 'K12', 'I14', 'H14', 'F15', 'N14', 'L15', 'H17', 'G17', 'F17', 'E18', 'O19', 'N19',
  'M20', 'L20', 'H21', 'G21', 'F22', 'E22', 'D22', 'Q23', 'P24', 'O24', 'N25', 'M25', 'G27', 'F27', 'E27', 'D27', 'C26', 'B26'];
  setDecoration(ranges, colorCode, '／');
  ranges = ['J7', 'J10', 'J13', 'J16', 'G15', 'M15'];
  setDecoration(ranges, colorCode, '×');
  ranges = ['H26:L26'];
  setDecoration(ranges, colorCode, '―');
  ranges = ['I16', 'K16'];
  for (var i in ranges) {
    sheet.getRange(ranges[i]).setBorder(true, false, true, false, false, false, colorCode, SpreadsheetApp.BorderStyle.SOLID);
  }    
  ranges = ['I20:K20'];
  for (var i in ranges) {
    sheet.getRange(ranges[i]).setBorder(false, false, true, false, false, false, colorCode, SpreadsheetApp.BorderStyle.SOLID);
  }
  
  // ●
  var value = '●';
  ranges = ['E17', 'O17', 'B28', 'R28'];
  setDecoration(ranges, colorCode, value);
  colorCode = '#FF0000';
  ranges = ['G10', 'M10', 'H19', 'L19', 'G30', 'M30'];
  setDecoration(ranges, colorCode, value);
  colorCode = '#00BFFF';
  ranges = ['J9', 'H25', 'L25', 'C32', 'Q32'];
  setDecoration(ranges, colorCode, value);
  colorCode = '#FFBF00';
  ranges = ['H12', 'L12', 'C22', 'Q22'];
  setDecoration(ranges, colorCode, value);
  
  // ◉
  value = '◉';
  ranges = ['G24', 'M24', 'J31'];
  setDecoration(ranges, colorCode, value);
  colorCode = '#00BFFF';
  ranges = ['D29', 'P29'];
  setDecoration(ranges, colorCode, value);
  

  // ★
  ranges = ['H13', 'L13', 'F18', 'N18', 'E21', 'O21', 'F23', 'N23', 'J25', 'C28', 'Q28', 'F31', 'N31'];
  colorCode = '#FFFF99';
  setDecoration(ranges, colorCode, '★');
  Browser.msgBox("飾り付けを用意しました！\\n飾り付けが小さいので、フォントを「MS Pゴシック」に手動で変更してください（GAS上で変更できず）");
}

// 3)★を乗せる
function putStar() {
  sheet.getRange('I1:K3').merge().setValue('★').setFontSize(48).setFontColor('#FACC2E');
  Browser.msgBox("てっぺんに★を用意しました！");
}

// 4)ライトを点ける
function turnOnLights() {
  sheet.getRange('N7:T9').merge().setHorizontalAlignment('left').setFontSize(36).setValue('Merry').setFontColor('#FF8000').setFontFamily('Comic Sans MS');
  sheet.getRange('Q10:Z12').merge().setHorizontalAlignment('left').setFontSize(36).setValue('Christmas!').setFontColor('#FA5858').setFontFamily('Comic Sans MS');
  sheet.getDataRange().setFontWeight("bold");
  paintTree('#688A08', '#4B610B');
  var colorCode = '#CCCC33';
  var ranges = ['D2', 'R3', 'P5', 'C6', 'V7', 'A12', 'S15', 'V17', 'B19', 'Q19', 'Y21', 'T22', 'Z28'];
  setDecoration(ranges, colorCode, "'+");
  ranges = ['N3', 'V3', 'E5', 'C11', 'A17', 'T18', 'W23', 'V27'];
  setDecoration(ranges, colorCode, "*");
  Browser.msgBox("Merry Christmas!!\\nクリスマスツリーの完成です！！");
}

// all)一度に全て実行
function drawAll() {
  drawChristmasTree();
  decoration();
  putStar();
  turnOnLights();
}

// ほぼ初期状態に戻す
function reset() {
  getAllRange().setBackground('#FFFFFF').setFontWeight('normal').setValue('').setBorder(false, false, false, false, false, false);
}

// デコレーションする
function setDecoration(ranges, colorCode, value) {
  for (var i in ranges) {
    sheet.getRange(ranges[i]).setFontColor(colorCode).setValue(value);
  }
}

```

コピペして保存（Ctrl+s）してください。プロジェクト名は無題でもOKです。

# 4．スプレッドシートで実行

## 1)ツリーを描く

スプレッドシートに戻りF5で画面更新してください。
するとメニューバーに *クリスマス特別メニュー* というものが追加されているはずです。

![menu.png](https://qiita-image-store.s3.amazonaws.com/0/199678/519b09ee-9f7e-0729-2ef1-a33e66c46dcd.png)

*1)ツリーを描く* をクリックすると、 *承認が必要* というアラートが出るので、 *続行* を押して自分のGoogleアカウントを選択します。

以下のような画面が出たら左下の *詳細* をクリックし、 *無題のプロジェクト（安全ではないページ）に移動* をクリック。
![5.png](https://qiita-image-store.s3.amazonaws.com/0/199678/43353550-0a71-a8e0-a6e3-32981a51f4d0.png)

更にメッセージが出るので *次へ* と入力し次へをクリック。最後に「許可」を選択すればOK。
クリスマスツリーの描画が始まるはずです。

![t1.png](https://qiita-image-store.s3.amazonaws.com/0/199678/0f4df18f-72e6-ecbb-d4f7-56fd2aa26068.png)

## 2)飾り付けをする

このままではただの木なので、飾り付けをしましょう。
*2)飾り付けをする* をクリックすると飾りが付きます。この処理が一番時間かかります。

![t2.png](https://qiita-image-store.s3.amazonaws.com/0/199678/65affa4d-34b7-ab63-de0a-e09780030433.png)

なお、終わった後に手動で「MS Pゴシック」にフォントを変えていただいた方が飾りのサイズにインパクトが付きます。
GASでやりましたが、そのフォントに存在する文字しかセットできないのか、うまくMS Pゴシックに切り替わりませんでした。

## 3)★を乗せる

クリスマスツリーと言えば頭の★は必須ですね。付けましょう。
*3)★を乗せる* をクリック。

![t3.png](https://qiita-image-store.s3.amazonaws.com/0/199678/3f31b80c-bdb3-a0ac-0841-f34f79efb9c9.png)

## 4)ライトを点ける

最後にライトを付けましょう。

![tree.PNG](https://qiita-image-store.s3.amazonaws.com/0/199678/5c147486-1029-4f0c-4d4e-4caa1667ea86.png)

ちなみにクリスマスツリーといえばライトの点滅なので、なんとか頑張ってGASで点滅アニメーションをやろうとしましたが…うまくいかず。
Utilies.sleepは実行中完全に動きが停止するし、setIntervalは当然使えず。いっそのこと2シートに書き込んで交互に画面切り替え…とかもやりましたが無駄でした。
**手動でCtrl+bを連打して太字切り替えをすると、気持ち点滅してるように見えます。**

# 終わりに

メニューを1つずつポチポチやるのがしんどい方向けに *all)一度に全て実行* というものもご用意しております。

# お知らせ

エイチームブライズでは一緒に活躍してくれる優秀な人材を募集中です。
興味のある方はぜひとも[エイチームグループ採用ページ](http://www.a-tm.co.jp/recruit/)（[Webエンジニア詳細ページ](http://www.a-tm.co.jp/recruit/requirements/career/lifestylesupport-webengineer/)）よりお問い合わせ下さい。

# 宣伝

繰り返しになりますが、筆者個人の活動としてマジメなGoogle Apps Script解説アドベントカレンダーもやっていますので、興味のある方は是非。
[Google Apps Scriptを実例交えて基礎からざっくり学ぶ Advent Calendar 2017](https://qiita.com/advent-calendar/2017/gas_beginner)

# 明日

エイチームブライズアドベントカレンダー12日目の記事は、いかがでしたでしょうか。
明日は @t-nagata が「SQLアンチパターン を見直す」とのことです。
きっとステキな記事を書いてくれるはずです。楽しみですね！