1.はじめに
今回はスプレットシートに登録しているデータをブラウザから修正できる仕組みを学ぶ。
スプレットシートのデータは以下のようになっているとする。
id | timestamp | productName | price | 更新日時 |
---|---|---|---|---|
5RAA9BPJ | 2025-10-17T05:11:28.795Z | バナナ | 200 | |
3F5G4ZHN | 2025-10-17T05:12:07.963Z | みかん | 150 | |
9UNCIYJY | 2025-10-17T05:12:31.427Z | パイナップル | 3000 | |
UC6HMXA0 | 2025-10-17T05:12:51.981Z | アボカド | 9999999 |
今回作成するプログラムではidからデータを検索したり編集をするようにする。
2.HTMLの骨格
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base target="_top">
<script>
</script>
</head>
<body>
<h2>商品検索</h2>
<label for="search_id">商品ID:</label>
<input id="search_id" value="">
<button id="search-btn" onclick="searchData()">検索</button><br>
<form hidden="hidden" id="edit_form">
<label for="product_name">商品名:</label>
<input id="product_name" value=""><br>
<label for="price">価格</label>
<input id="price" value="">
</form>
<button hidden="hidden" id="edit-btn" onclick="sendEditData()">編集</button>
</body>
</html>
商品IDを入力して検索ボタンを押したら該当する商品の編集フォームが作成される仕組みを作成する。
3.GASのベース
const FILE_ID = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
const ss = SpreadsheetApp.openById(FILE_ID);
const sheet = ss.getSheetByName('シート1');
function doGet() {
return HtmlService.createHtmlOutputFromFile('index');
}
function searchDataById(id) {
//console.log(id);
const targetRow = getIdRow(id, 'A:A');
if (!targetRow) {return null};
const lastCol = sheet.getLastColumn();
const headers = sheet.getRange(1, 1, 1, lastCol).getValues()[0];
const targetData = sheet.getRange(targetRow, 1, 1, lastCol).getValues()[0];
const obj = {};
headers.forEach((header, i) => {
obj[header] = targetData[i]
});
return obj;
}
// 商品情報をIDで検索して返す関数
function getIdRow(id, targetCol) {
const finder = sheet.getRange(targetCol).createTextFinder(id).matchEntireCell(true).findNext();
// 見つからなかった場合
if (!finder) {
console.log(`ID「${id}」が見つかりませんでした。`);
return;
}
// 見つかった場合
const targetRow = finder.getRow();
return targetRow;
}
searchDataById(id)
関数はブラウザから送られてきた商品IDがスプレットシートにある場合は商品情報をブラウザに返す仕組みになっている。
getIdRow(id, targetCol);
は商品IDの商品情報がスプレットシートの何行目にあるのかを返す関数。
const targetRow = getIdRow(id, 'A:A');
if (!targetRow) {return null};
これでgetIdRow
を実行し、もしデータがない場合はnull
を返す。2つ目の引数はスプレットシートの検索列。
関数の中身の
const finder = sheet.getRange(targetCol)
.createTextFinder(id)
.matchEntireCell(true)
.findNext();
が実際に検索をかけているメソッド。.matchEntireCell(true)
にすることで完全一致にしている。
if (!finder) {
console.log(`ID「${id}」が見つかりませんでした。`);
return;
}
もし見つかっている場合は何らかのデータがfinderに格納されているが、見つからなければデータがfinderに格納されていない。その場合はデータを渡さずに終了する。
// 見つかった場合
const targetRow = finder.getRow();
return targetRow;
もし見つかれば.getRow()
で行数を特定して結果を返す。
if (!targetRow) {return null};
データがsearchDataById(id)
に返されていなければnull
をブラウザに返す。
const lastCol = sheet.getLastColumn();
const headers = sheet.getRange(1, 1, 1, lastCol).getValues()[0];
const targetData = sheet.getRange(targetRow, 1, 1, lastCol).getValues()[0];
const obj = {};
headers.forEach((header, i) => {
obj[header] = targetData[i]
});
return obj;
データが見つかっていればヘッダーの値と該当商品情報の値を変数に格納し、オブジェクトに変換してブラウザに返す。
次はブラウザの処理を考える。
4.HTMLの編集フォームを作成するプログラムを作る
HTMLの<script>
タブの中に以下を記述する。
// データの取得
function searchData() {
const searccId = document.getElementById("search_id").value;
console.log("id: " + searccId + " で検索をしています。");
google.script.run
.withSuccessHandler(createEditForm)
.withFailureHandler(function(err) {
alert("エラーが起きました: " + err.message);
})
.searchDataById(searccId);
}
// 編集フォームを作成
function createEditForm(data) {
if (!data) {
alert("検索した商品IDは存在しません");
return;
}
console.log(data);
document.getElementById("edit_form").hidden = "";
document.getElementById("edit-btn").hidden = "";
document.getElementById("product_name").value = data.商品名;
document.getElementById("price").value = data.価格;
document.getElementById("edit_form").setAttribute("data_id", data.ID);
document.getElementById("edit_form").setAttribute("data_submit_date", new Date(data.登録日時).toLocaleString());
}
検索ボタンがクリックされたらsearchData()
関数が実行される。
const searccId = document.getElementById("search_id").value;
console.log("id: " + searccId + " で検索をしています。");
google.script.run
.withSuccessHandler(createEditForm)
.withFailureHandler(function(err) {
alert("エラーが起きました: " + err.message);
})
.searchDataById(searccId);
searccId
に検索する商品IDを格納する。
google.script.run
でサーバー側の.searchDataById(searccId);
を実行させ。成功すればcreateEditForm
が実行される。
function createEditForm(data) {
if (!data) {
alert("検索した商品IDは存在しません");
return;
}
console.log(data);
document.getElementById("edit_form").hidden = "";
document.getElementById("edit-btn").hidden = "";
document.getElementById("product_name").value = data.商品名;
document.getElementById("price").value = data.価格;
document.getElementById("edit_form").setAttribute("data_id", data.ID);
document.getElementById("edit_form").setAttribute("data_submit_date", new Date(data.登録日時).toLocaleString());
}
もしサーバーから何も返されなければ(!data
)アラートを出して終了する。
検索している商品が見つかっていた場合はHTMLを編集して編集フォームを作る。
document.getElementById("edit_form").setAttribute("data_id", data.ID);
でフォームタブにdata_id
として商品IDを登録しておく。この後登録ボタンを押した後の処理はこの値を参照することになる。
作成されたーフォームは以下のように表示される。
5.編集データをスプレットシートに登録するプログラム
HTMLの<script>
タブにsendEditData
関数を作成する。
function sendEditData() {
const productId = document.getElementById("edit_form").getAttribute("data_id");
const editedProductName = document.getElementById("product_name").value;
const editedPrice = document.getElementById("price").value;
console.log({ productId, editedProductName, editedPrice })
google.script.run
.withSuccessHandler((data) => {
alert("登録が完了しました。");
console.log(data);
})
.withFailureHandler((err) => {
alert("登録に失敗しました: " + err.message);
})
.submitEditedData({ productId, editedProductName, editedPrice })
}
入力されているデータと商品IDを取得し、google.script.run
でサーバのsubmitEditedData()
関数を実行させる。
6.スプレットシートに編集データを登録する。
GASファイルに次の関数を新たに作成する。
function getHeaderCol(header, targetRow) {
const finder = sheet.getRange(targetRow).createTextFinder(header).matchEntireCell(true).findNext();
// 見つからなかった場合
if (!finder) {
console.log(`Header:「${header}」が見つかりませんでした。`);
return;
}
// 見つかった場合
const targetCol = finder.getColumn();
return targetCol;
}
function submitEditedData(data) {
// 編集予定のセルを特定する
const targetRow = getIdRow(data.productId, 'A:A');
const productNameCol = getHeaderCol("商品名", '1:1');
const priceCol = getHeaderCol("価格", '1:1');
const updateDateCol = getHeaderCol("更新日時", '1:1');
if (!targetRow || !productNameCol || !priceCol || !updateDateCol) {return null};
// データを変更する
sheet.getRange(targetRow, productNameCol).setValue(data.editedProductName);
sheet.getRange(targetRow, priceCol).setValue(data.editedPrice);
sheet.getRange(targetRow, updateDateCol).setValue(new Date().toISOString());
return "Success"
}
getHeaderCol()
関数はヘッダーの何列目に任意のタイトルがあるかを調べる関数。構造はgetIdRow
関数と同じ。
submitEditedData()
関数でスプレットシートに登録する。
const targetRow = getIdRow(data.productId, 'A:A');
const productNameCol = getHeaderCol("商品名", '1:1');
const priceCol = getHeaderCol("価格", '1:1');
const updateDateCol = getHeaderCol("更新日時", '1:1');
変更したいデータがスプレットシートのどこにあるのかを確認するため該当の行数・列数を取得する。
sheet.getRange(targetRow, productNameCol).setValue(data.editedProductName);
sheet.getRange(targetRow, priceCol).setValue(data.editedPrice);
sheet.getRange(targetRow, updateDateCol).setValue(new Date().toISOString());
最後に.setValue()
メソッドで変更用のデータを登録する。