はじまり
HTMLって作るのめんどいよなあ〜。
スプレッドシートとかで編集したのをそのままHTMLで表記できれば楽なのに。
じゃあ、今行ったことをそのまま実現できてしまうツールを紹介しましょう。
おお・・・! ぜひ、授けたまえ!
今回のソース
以下が、今回のソースになります。
/**
* @param {string[]} values
* @param {string} textReplacingIfBlank
* @return {string}
*/
function getHtmlByValues(values, textReplacingIfBlank="💩"){
let prefix = "<table>";
let suffix = "</table>";
let html = `${prefix}\n`;
let tmp_tr = "";
let isTh = false;
for(let i = 0; i < values.length; i++){
isTh = false;
if(i === 0){
isTh = true;
}
tmp_tr = getTrByRow(values[i], isTh, textReplacingIfBlank);
html += `${tmp_tr}\n`;
}
html += suffix;
return html;
}
/**
* @param {string[]} row
* @param {boolean} isTh
* @param {string} textReplacingIfBlank
* @return {string}
*/
function getTrByRow(row, isTh, textReplacingIfBlank="💩"){
let element;
let tr = "";
let tagTd = "td";
if(isTh){
tagTd = "th";
textReplacingIfBlank = "";
}
const tagTr = "tr";
for(let i = 0; i< row.length; i++){
element = closeByTag(tagTd, row[i], textReplacingIfBlank);
tr += element;
}
tr = closeByTag(tagTr, tr, "");
return tr;
}
/**
* @param {string} tag without < and >
* @param {string} innerText
* @param {string} textReplacingIfBlank
* @return {string}
*/
function closeByTag(tag, innerText, textReplacingIfBlank="💩"){
if(tag[0] === "<"){
throw Error("Initial of tag mustn't be \"<\".");
}
if(tag[tag.length - 1] === ">"){
throw Error("End of tag mustn't be \">\".");
}
let initialOfTag = "<";
let endOfTag = ">";
let formerTag = `${initialOfTag}${tag}${endOfTag}`;
let latterTag = `${initialOfTag}/${tag}${endOfTag}`;
let displayText = innerText;
if(displayText === ""){
displayText = textReplacingIfBlank;
}
let element = `${formerTag}${displayText}${latterTag}`;
return element;
}
function getValuesBySelectedArea(){
const ss = SpreadsheetApp.getActive().getSheetByName(sheetName1st);
const activeValues = ss.getActiveRange().getValues();
console.log(activeValues);
return activeValues;
}
function main(){
const values = getValuesBySelectedArea();
const html = getHtmlByValues(values, "");
console.log(html);
}
テストコード
以下が、僕が作ったGoogle Apps Script用のテストツール「TestGAS」で使えるテストコードになります。
// let tester = new TestGAS.TestGasExecutor();
let tester = TestGAS.createExecutor();
class Test_main{
test_getHtmlByValues_1_1(){
const values = [ [ '', 'Python', 'GAS', 'GitHub', 'JavaScript' ]
, [ '', '', '', '', '' ]
];
const textReplacingIfBlank = "";
const actual = getHtmlByValues(values, textReplacingIfBlank);
const expected = `<table>
<tr><th></th><th>Python</th><th>GAS</th><th>GitHub</th><th>JavaScript</th></tr>
<tr><td></td><td></td><td></td><td></td><td></td></tr>
</table>`;
tester.assertEquals(actual, expected);
}
test_getHtmlByValues_1_2(){
const values = [ [ '', 'Python', 'GAS', 'GitHub', 'JavaScript' ] ];
const textReplacingIfBlank = "";
const actual = getHtmlByValues(values, textReplacingIfBlank);
const expected = `<table>
<tr><th></th><th>Python</th><th>GAS</th><th>GitHub</th><th>JavaScript</th></tr>
</table>`;
tester.assertEquals(actual, expected);
}
test_getHtmlByValues_1_3(){
const values = [ [ '' ] ];
const textReplacingIfBlank = "";
const actual = getHtmlByValues(values, textReplacingIfBlank);
const expected = `<table>
<tr><th></th></tr>
</table>`;
tester.assertEquals(actual, expected);
}
test_getHtmlByValues_2_1(){
const values = [ [ '', 'Python', 'GAS', 'GitHub', 'JavaScript' ]
, [ '', '', '', '', '' ]
];
const actual = getHtmlByValues(values);
const expected = `<table>
<tr><th></th><th>Python</th><th>GAS</th><th>GitHub</th><th>JavaScript</th></tr>
<tr><td>💩</td><td>💩</td><td>💩</td><td>💩</td><td>💩</td></tr>
</table>`;
tester.assertEquals(actual, expected);
}
test_getTrByRow_1_1(){
const row = [1, 2, 3];
const isTh = false;
const textReplacingIfBlank = "";
const actual = getTrByRow(row, isTh, textReplacingIfBlank);
const expected = "<tr><td>1</td><td>2</td><td>3</td></tr>";
tester.assertEquals(actual, expected);
}
test_getTrByRow_1_2(){
const row = [1, 2, 3];
const isTh = true;
const textReplacingIfBlank = "";
const actual = getTrByRow(row, isTh, textReplacingIfBlank);
const expected = "<tr><th>1</th><th>2</th><th>3</th></tr>";
tester.assertEquals(actual, expected);
}
test_closeByTag_1_1(){
const tag = "a";
const innerText = "test";
const textReplacingIfBlank = "";
const actual = closeByTag(tag, innerText, textReplacingIfBlank);
const expected = "<a>test</a>";
tester.assertEquals(actual, expected);
}
test_closeByTag_1_2(){
const tag = "a";
const innerText = "test";
const textReplacingIfBlank = "";
const actual = closeByTag(tag, innerText, textReplacingIfBlank);
const expected = "<a>test<//a>";
tester.assertNotEquals(actual, expected);
}
test_closeByTag_2_1(){
const tag = "<a href=";
const innerText = "test";
const textReplacingIfBlank = "";
tester.assertError(closeByTag, [tag, innerText, textReplacingIfBlank], Error);
}
test_closeByTag_2_2(){
const tag = "<a href=";
const innerText = "test";
tester.assertError(closeByTag, [tag, innerText], Error);
}
test_closeByTag_3_1(){
const tag = "a href=\"\">";
const innerText = "test";
const textReplacingIfBlank = "";
tester.assertError(closeByTag, [tag, innerText, textReplacingIfBlank], Error);
}
test_closeByTag_3_2(){
const tag = "a href=\"\">";
const innerText = "test";
tester.assertError(closeByTag, [tag, innerText], Error);
}
}
function execute_Test_main(){
let failureFuncs = tester.executeTestGas(Test_main);
}
ちなみに、TestGASのリポジトリはこちらになります。
解説
以下、今回のソースの解説になります。
その1:スプレッドシートの選択範囲を取得する
まず、getValuesBySelectedArea
関数でスプレッドシートで選択した範囲を取得します。
function getValuesBySelectedArea(){
const ss = SpreadsheetApp.getActive().getSheetByName(sheetName1st);
const activeValues = ss.getActiveRange().getValues();
console.log(activeValues);
return activeValues;
}
その2:thタグとtdタグ、そして、trタグを作成する
まず、thタグとtdタグを作成します。
その処理を行う関数は、closeByTag
関数になっています。
選択した範囲の1行目に対してはthタグを、それ以外の行にはtdタグを付与します。
そして、最後にtrタグで囲います。getTrByRow
関数です。
/**
* @param {string[]} row
* @param {boolean} isTh
* @param {string} textReplacingIfBlank
* @return {string}
*/
function getTrByRow(row, isTh, textReplacingIfBlank="💩"){
let element;
let tr = "";
let tagTd = "td";
if(isTh){
tagTd = "th";
textReplacingIfBlank = "";
}
const tagTr = "tr";
for(let i = 0; i< row.length; i++){
element = closeByTag(tagTd, row[i], textReplacingIfBlank);
tr += element;
}
tr = closeByTag(tagTr, tr, "");
return tr;
}
/**
* @param {string} tag without < and >
* @param {string} innerText
* @param {string} textReplacingIfBlank
* @return {string}
*/
function closeByTag(tag, innerText, textReplacingIfBlank="💩"){
if(tag[0] === "<"){
throw Error("Initial of tag mustn't be \"<\".");
}
if(tag[tag.length - 1] === ">"){
throw Error("End of tag mustn't be \">\".");
}
let initialOfTag = "<";
let endOfTag = ">";
let formerTag = `${initialOfTag}${tag}${endOfTag}`;
let latterTag = `${initialOfTag}/${tag}${endOfTag}`;
let displayText = innerText;
if(displayText === ""){
displayText = textReplacingIfBlank;
}
let element = `${formerTag}${displayText}${latterTag}`;
return element;
}
その3:thタグとtdタグを作成するとき、ブランクの代替文字を決める
tableを作る時に、ブランクのセルが存在する場合があるかと思います。
その場合は、closeByTag
関数のtextReplacingIfBlank
の引数に代替文字を指定するとその文字に置き換わります。デフォルトは「💩」です。
代替文字を””で指定した場合のHTMLの描画。(GitHubのリポジトリ)
代替文字を指定せずにデフォルト値の場合のHTMLの描画。(GitHubのリポジトリ)
その4:tableタグで囲む
そして、沢山生成したtrタグに対して、tableタグで囲みます。
その処理を、getHtmlByValues
関数で行っています。
/**
* @param {string[]} values
* @param {string} textReplacingIfBlank
* @return {string}
*/
function getHtmlByValues(values, textReplacingIfBlank="💩"){
let prefix = "<table>";
let suffix = "</table>";
let html = `${prefix}\n`;
let tmp_tr = "";
let isTh = false;
for(let i = 0; i < values.length; i++){
isTh = false;
if(i === 0){
isTh = true;
}
tmp_tr = getTrByRow(values[i], isTh, textReplacingIfBlank);
html += `${tmp_tr}\n`;
}
html += suffix;
return html;
}
その5:出力
こちらが、今まで解説した前処理の呼び出し部分と最終的な出力部分になります。
function main(){
const values = getValuesBySelectedArea();
const html = getHtmlByValues(values, "💩");
console.log(html);
}
例えば、このように選択した場合に、
このように出力されます。
おしまい
これで、スプレッドシートで楽々編集しながら、好きな時にHTMLに変換できるなあ。
うん、これはかなり助かるなあ!
以上になります!
コメント