GAS初心者向けに、コードの組み立て方からforEachとindexOfを含む知識まで解説します。
GASの基礎は理解したけれど、なかなかシステムづくりにつながらない・・とお悩みの方におすすめです。
1.コード全文【複数メモ位置検索】
まずは今回取り扱うコードの全文を紹介します。
関数findNotes()は、メモ(複数)と、シート名を引数にとります。
また戻り値はメモのある位置を{‘メモ’ : [ 行 , 列 ] , … }のオブジェクト形式で返します。
/** 複数ノートの位置検索
* @param {string[]} notes 検索対象のメモ名
* @param {String} sheetName 検索対象メモが存在するシート名
* @return {string:num[]} 検索対象が存在するセル位置 ex*{'note':[3,2]}
*/
function findNotes(notes,sheetName) {
let ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
let range = ss.getRange(1, 1, ss.getLastRow(), ss.getLastColumn()); //sheetと範囲の設定
let rangeNotes = range.getNotes();
let result = {};
for (i = 0; i < notes.length; i++) {
let trgCell = [];
rangeNotes.forEach(function (val, ind) {
if (val.indexOf(`${notes[i]}`) !== -1) {
// trgCell.push(val.indexOf(`${notes[i]}`) + 1, ind + 1); getRangeしたときに行列逆になっていたため修正
trgCell.push(ind + 1, val.indexOf(`${notes[i]}`) + 1);
}
})
result[`${notes[i]}`] = trgCell;
}
console.log(result);
//{ '$title': [ 1, 1 ], '$sender': [ 1, 2 ],'$receiver': [ 1, 3 ]・・ }
return result
}
2.forEach
ドキュメントの中では、forEachは以下のように表現されています。
forEach()
メソッドは、与えられた関数を、配列の各要素に対して一度ずつ実行します。
for文で関数が使えるようなイメージですね。
const array1 = ['あり', 'りんご', 'ごりら'];
array1.forEach(function(val ,ind ,arr){
console.log(val);
});
//あり
//りんご
//ごりら
getNotes()でとれた値は、geValues()をしたときのように二次元配列となっています。
forEach()で一行に複数存在するノートを、一行ずつチェックしていきます。
forEachをさらにforでくくっている理由は変数notesにあります。
変数notesは、検索したいメモ名が二次元配列に文字列で格納されています。
変数notesのなかの、ある一つのメモ名に対して、forEachで一行目にあるか、二行目にあるかを判定します。
同時に一行目のどの列にあるのかをindexOf()で判定します。
for (i = 0; i < notes.length; i++) {
let trgCell = [];
rangeNotes.forEach(function (val, ind) {
if (val.indexOf(`${notes[i]}`) !== -1) {
// trgCell.push(val.indexOf(`${notes[i]}`) + 1, ind + 1); getRangeしたときに行列逆になっていたため修正
trgCell.push(ind + 1, val.indexOf(`${notes[i]}`) + 1);
}
})
result[`${notes[i]}`] = trgCell;
}
3.indexOf
const beasts = ['あり', 'りくがめ', 'めがねざる'];
//見つかった場合は配列番号を返す
console.log(beasts.indexOf('あり'));
// 0
// 配列番号1から検索
console.log(beasts.indexOf('りくがめ', 1));
// 1
//配列に含まれない場合
console.log(beasts.indexOf('ねこ'));
// -1
今回はforEachで一行のメモをとりだして、それぞれのメモと変数notes[ i ]が一致するところを、indexOfで検索しています。
結果は配列番号なので、実際の行列数に合わせるため+1をしています。
for (i = 0; i < notes.length; i++) {
let trgCell = [];
rangeNotes.forEach(function (val, ind) {
if (val.indexOf(`${notes[i]}`) !== -1) {
// trgCell.push(val.indexOf(`${notes[i]}`) + 1, ind + 1); getRangeしたときに行列逆になっていたため修正
trgCell.push(ind + 1, val.indexOf(`${notes[i]}`) + 1);
}
})
result[`${notes[i]}`] = trgCell;
}
4.コードの組み立て方
コードを組み立てるときに、いきなり手を動かすのではなくある程度流れを考えます。
今回の場合はメモの位置を検索して、別の関数でgetRange()として使うことがゴールでした。
次に戻り値を利用しやすいオブジェクト型にして、getRangeの引数に合う形でデータを成形することを考えました。
それぞれの値をとるにはどのようなやり方ができそうか考え、最終的に前述のコードになりました。
まずゴールや、その先の関係などを考えてから手を動かすと、手直し少なくコードを書くことができます。
また迷ったときはメンターの指導を受けることも有効な手立てだといえます。
まとめ
・forEach()は配列に対して、関数を利用できるメソッド。
・indexOf()は配列の中身を検索して、配列番号(見つからない場合は-1)を返すメソッド。
・コードの組み立てはゴールを見据えて考えるとスムーズ。
Cloud Tree
Cloud Treeは中小企業向けDX・システム制作会社です。
中小企業DXツールであり、コストパフォーマンスが高いZohoを当社でも採用しております。
システムづくり、業務効率化、Zohoにご興味をお持ちの方は、問い合わせボタンまたはメニューよりお声がけください。
執筆者 佐伯 翔子
CloudTree所属
Zoho導入パートナー、webデザイナー、GASシステムアプリ制作
________________
現場の役に立つシステムを作る
DX導入の負担を減らす
________________