Why & What|はじめに
「作ったきかっけ」と「どんなものができたか」については、下記のnoteにまとめました。
先にご確認いただけると嬉しいです!
How|スクリプトの内容
GitHub
特に学びとなった部分の振り返り
メニューの作成
ui.gs
// サンプルコード
// スプレッドシートが開かれたら自動的に実行される関数
function onOpen() {
let ui = SpreadsheetApp.getUi();
ui.createMenu('[GAS]')
.addItem('実行する処理の名前', 'function名')
.addSeparator()
.addSubMenu(
ui.createMenu("設定")
.addItem('実行する処理の名前', 'function名')
.addItem('実行する処理の名前', 'function名'))
.addToUi();
}
- 過去、挿入した図形にスクリプトを割り当て「GAS実行ボタン」を作ったりしていましたが、Uiクラスからメニューを作成する方がスッキリしますね。
- 階層構造も作ることができて、とても便利。
配列から要素をランダムに選択する(Math.random)
sample-getRandomValue.gs
function getRandomValue(array, key) {
// [0以上 array.length 未満]のランダムな整数を生成
let randomIndex = Math.floor(Math.random() * array.length);
// [ランダムに選択されたインデックス]に対応する配列の要素を取得
let selectedElement = array[randomIndex];
// インデックスを指定して値を取り出す
let selectedValue = selectedElement[key];
// [選択された要素]と[そのプロパティの値]をオブジェクトとして返す
return { element: selectedElement, value: selectedValue };
}
// サンプル
const sampleArray = [
{ id: 1, value: "A" },
{ id: 2, value: "B" },
{ id: 3, value: "C" },
{ id: 4, value: "D" },
{ id: 5, value: "E" }
];
const result = getRandomValue(sampleArray, "value");
console.log("Selected Element:", result.element);
console.log("Selected Value:", result.value);
- Math.floor()
- 引数として与えられた数値以下で、最大の整数に切り捨てられた値を返す
- Math.random()*array.length
- Math.random()
- 「0~1」間の数字をランダムに生成する(「0.37654」などなど)
- array.length
- 配列の要素数
- Math.random()
こちらの記事が分かりやすかったです。
[ garagarapon.gs ]では、ランダムに取り出した値(ビンゴ文字/' item ')を書き込みなどに利用していますね。
garagarapon.gs
// ランダムに要素を1つ選択
let randomIndex = Math.floor(Math.random() * remainingItems.length);
let selectedItem = remainingItems[randomIndex];
let item = selectedItem[1];
配列全体をランダムに並べ替える(Fisher–Yates のシャッフル)
createBingoCards.gs
function fisherYatesShuffle(array) {
// 変数を宣言する時に同時に値を代入して初期化(array.length)
let currentIndex = array.length, temporaryValue, randomIndex;
// currentIndex : 配列内の現在の要素の位置を示す変数
// temporaryValue : 要素の交換時に一時的に値を保存するための変数
// randomIndex : ランダムに選択されたインデックスを保存する変数
// currentIndex が 0 になるまで繰り返す
while (currentIndex !== 0) {
// 配列の中からランダムにインデックスを選択
randomIndex = Math.floor(Math.random() * currentIndex);
// currentIndex をデクリメント(数値を1ずつ減少させる)
currentIndex -= 1;
// 現在の要素をtmp変数に保存
temporaryValue = array[currentIndex];
// 現在の要素とランダムに選択した要素を交換
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
// シャッフルされた配列を返す
return array;
}
// サンプル
let sampleArray = [1, 2, 3, 4, 5];
let shuffledArray = fisherYatesShuffle(sampleArray);
console.log(shuffledArray);
- 1つの配列のなかで、「入れ替え前」と「入れ替え後」の領域に分割して考える
- 1回目:元の配列から1つをランダムに選択し、配列の末尾の要素と入れ替える
- 2回目:末尾の要素は「入れ替え後」の領域なので、末尾-1の範囲から1つをランダム選択し、「入れ替え前」領域の末尾の要素と入れ替える
- 3回目:「入れ替え後」領域に2つの要素があるので、「入れ替え前」領域は元の配列の末尾-2の部分
- 「入れ替え前」領域が無くなるまで繰り返す
こちらの記事がとても分かりやすかったです。
抽選された要素を探し「済フラグ」を入れる
setDoneStatus.gs
function setDoneStatus(sheet, columnName, targetValue, setStatus) {
// シート上のすべての値を取得
let data = sheet.getDataRange().getValues();
// 列名が格納された最初の行を取得
let headerRow = data[0];
// columnNameに指定された列のインデックスを取得
let columnIndex = headerRow.indexOf(columnName);
// columnNameが見つからない場合はエラーを出力して終了
if (columnIndex === -1) {
console.error(`Column '${columnName}' not found.`);
return;
}
// データの行を走査( [iの初期値=1]なので2行目から処理を開始)
for (let i = 1; i < data.length; i++) {
// 対象の値が見つかったらステータスを設定してループ終了(break)
if (data[i][columnIndex] === targetValue) {
sheet.getRange(i + 1, columnIndex + 1).setValue(setStatus);
break;
}
}
}
// サンプル
// function setDoneStatus(sheet, columnName, targetValue, setStatus)
setDoneStatus(all_item_sheet, "name", item, "済");
- 要素をランダムに選択する処理と合わせて、事後処理として汎用性が高い。
サンプルコードとほぼ同じですが、[ garagarapon.gs ]では「要素シート」上のすべての値を取得して、各行の2番目の要素が、引数として渡された name と一致するかを確認しています。
garagarapon.gs
// 選ばれた要素に済フラグを入れる関数
function set_done(num_item_sheet, name) {
// num_item_sheet(要素シート)上のすべての値を取得
let num_item_data = num_item_sheet.getDataRange().getValues();
for (let i = 1; i < num_item_data.length; i++) {
// 各行の2番目の要素(num_item_data[i][1])が、引数として渡された name と一致するか確認
if (num_item_data[i][1] == name) {
// 一致した行の3番目の要素(num_item_data[i][2])に '済' を設定し、 break でループ終了
num_item_sheet.getRange(i + 1, 3).setValue('済');
break;
}
}
}
余談ですが、要素に数字を入れて実行してみると、シャッフルされているのが分かりやすいですね。
以上です!
参考記事
「情シスビンゴ」GAS作成の参考
スクリプト振り返りの参考