[GAS]Google Apps Script とポエム

画像2

ノンプロ研 の『ノンプロ研 Advent Calendar 2020』12 月 22 日の記事です。

ノンプロ件の紹介

画像1

ノンプロ研 とはノンプログラマーが VBA・GAS・Python などのプログラミング スキルを身に着けるためのコミュニティ「ノンプログラマーのためのスキルアップ研究会」です。

自己紹介

ほぼ GAS しか書けない、生粋のノンプログラマーです。公開 Evernote と揶揄される ブログ に普段は GAS 関連の記事をメインに書いています。
コードを書く上で、今一番に考えていることを、今年のまとめとして以下に書いていきます 🤓

コードを書くにあたり意識していること

コードの強さ
ノンプログラマーにおける、コードの強さ・弱さとは、汎用性の有無と考えています。
「そのコードは、改変せずに使い回すことができるのか?」という問いに「Yes」と答えられれば、それは強いコードです。
残念ながら、実際のコードは特化型となり、汎用性に乏しく、一般的な強さとは同義になりえません。また、コードの対象となるデータ自体が構造化されていないため、コード自体が冗長になってしまうことも、コードを弱くしてしまう要因となります。

ノンプログラマーの仕事とノンプログラマーのコードのあるべき姿
そもそもノンプログラマーの仕事は、コードを書くことではなく、メインの仕事をコードを用いて効率化することです。
そんなノンプログラマーには、バグの少ないコードを短い時間で書くことが求められます。当然、それをおこなうには、相応の知識量が必要になります。
「ノンプログラマー」と「ノンプログラマーが書くべきコード」は両立できないように思えます。

スニペットという解決策
GAS の場合、function を宣言することで、コードを関数化することができます。V8 環境であれば、グローバル領域にアロー関数を用いて直接宣言することも可能です。この関数をベースに、汎用性のあるスニペットを作ることで上記の問題は解決できます。
コードを弱くする原因となる非構造化データに対しても、そのデータから構造化されたデータを作るコードを新しく書き、それ以外の部分はスニペットに頼ることで、コードを書く時間を圧縮できます。

スニペットの作り方
『コピペ ダメ。ゼッタイ。』の信念は揺らぎません。
スニペットは自身で考え、作り、育てていくものだと思っています。
また、世に出回っているスニペットに関しても、自分の知識以上のスニペットを使うことは、コピペをおこなうことと同様の行為です。使う場合には完全に理解することをおすすめします。

最近のがんばったスニペット

いつも自分自身を褒め散らかしてしまうきらいがありますが、このコードはなかなかの逸品です、ご賞味ください。
ちなみに、いつもならば あのブログ に、ササッと適当なコメントとコードだけをおいてくるのですが、Twitter で報告したところ売れそうだったため、急遽この note に書こうと思い直しました。
課金部分はポエムの後半 2 行ですので、スニペットを見たい方はご安心ください。

Gmail 本文部分にスプレッドシートの表を、そのまま表記する際の html テーブルを返してくれる関数です。仮引数にはシート オブジェクトと、わかりやすいので A1 表記の対象範囲を受けるようにしました。

/**
 * スプレッドシートから htmlTable を生成する関数
 *
 * @param  {Object} sheet - シート 
 * @param  {string} a1Notation - A1 表記で書かれた対象範囲 
 * @return {string} htmlBody
 */
function createHtmlTable_(sheet, a1Notation) {
 
 const range      = sheet.getRange(a1Notation);
 const values     = range.getDisplayValues();
 const fontSizes  = range.getFontSizes();
 const fontColors = range.getFontColors();
 const fontStyles = range.getFontStyles();
 const colors     = range.getBackgrounds();
 const hAligns    = range.getHorizontalAlignments();
 const vAligns    = range.getVerticalAlignments();
 const nums       = [...Array(values[0].length).keys()];
 const colWidths  = nums.map(num => sheet.getColumnWidth(num + 1));
 let   htmlTable  = "<table border='1' style='border-collapse: collapse'>";
 
 for (const [i, record] of values.entries()) {
   
   htmlTable = htmlTable + "<tr>";
   
   for (const [j, value] of record.entries()) {
     
     htmlTable += "<td style = 'overflow-wrap:break-word; "
     htmlTable += "width:"            + colWidths[j]     + "px; ";
     htmlTable += "text-align:"       + hAligns[i][j]    + "; ";
     htmlTable += "vertical-align:"   + vAligns[i][j]    + "; ";
     htmlTable += "font-size:"        + fontSizes[i][j]  + "; ";
     htmlTable += "color:"            + fontColors[i][j] + "; ";
     htmlTable += "font-style:"       + fontStyles[i][j] + "; ";
     htmlTable += "background-color:" + colors[i][j]     + ";'>";
     htmlTable += value               + "</td>";
     
   }
   htmlTable += "</tr>";
 }
 return htmlTable += "</table>";
 
}

getColumnWidth メソッドについては Sheet クラスのメソッドのため、少し工夫しましたが、他の Range クラスに属する二次元配列を返すメソッドは各値が、セルに対応した二次元配列で取得できていることを考えれば、特に難しいところはないと思います。
本コードに関する質問は、 ノンプロ研 Slack でのみ受け付けます。

お礼と最後に

いつも、こんなお題をくれる くのーるノンプロ研 には、いつも楽しませてもらってます。ありがとう。

それでは、本題のポエムです。絶対に買わないでください。

ポエム


新しい流行病が
すべてを変えた

偉い人たちが
変えられないと
あれだけ怒鳴り続けていたのに

使う道具たちが変わった

使い慣れた
形ある道具たちを
空の上へ運ぶ日々がはじまった

空の上に運んだ道具たちは
そのままでは機能しなかったので
調べ物をしながら
すべてを動くようにした

その作業は
思ったよりも大変だったので
道具すべてを運ぶことは
無理に
しなかった

気づけばそこは
ぼくたちが思い描いた桃源郷のようで
その作業をどれだけ繰り返しても
毎日が楽しかった

手伝ってくれる
いい仲間たちもいた

毎日が必死だった

ここから先は

15字

¥ 500

期間限定 PayPay支払いすると抽選でお得に!

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