[GAS]Google Apps Script とポエム
ノンプロ研 の『ノンプロ研 Advent Calendar 2020』12 月 22 日の記事です。
ノンプロ件の紹介
ノンプロ研 とはノンプログラマーが 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 でのみ受け付けます。
お礼と最後に
いつも、こんなお題をくれる くのーる や ノンプロ研 には、いつも楽しませてもらってます。ありがとう。
それでは、本題のポエムです。絶対に買わないでください。
ポエム
新しい流行病が
すべてを変えた
偉い人たちが
変えられないと
あれだけ怒鳴り続けていたのに
使う道具たちが変わった
使い慣れた
形ある道具たちを
空の上へ運ぶ日々がはじまった
空の上に運んだ道具たちは
そのままでは機能しなかったので
調べ物をしながら
すべてを動くようにした
その作業は
思ったよりも大変だったので
道具すべてを運ぶことは
無理に
しなかった
気づけばそこは
ぼくたちが思い描いた桃源郷のようで
その作業をどれだけ繰り返しても
毎日が楽しかった
手伝ってくれる
いい仲間たちもいた
毎日が必死だった
ここから先は
¥ 500
Amazonギフトカード5,000円分が当たる
この記事が気に入ったらチップで応援してみませんか?