
CSVで商品を登録してHTMLで取得、Javascriptで金額計算させてみる
カテゴリ:WEB制作
タグ:

最近、提供しているサービスの一つで大量の商品をフォームでデータを引き取り、金額計算をさせるという機能を実装したのでその忘備録で『CSVで商品を登録してHTMLで取得、Javascriptで金額計算させる方法』を紹介します。
商品の追加があってもCSVファイルを更新するだけで可能で、データベースも使用しないため作りも簡単です。
コードを紹介
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>カート計算</title> </head> <body> <h1>カート計算</h1> <table border="1"> <thead> <tr> <th>商品名</th> <th>価格</th> <th>個数</th> <th>合計価格</th> </tr> </thead> <tbody> </tbody> </table> <div> <dl> <dt>合計金額</dt> <dd>0円</dd> </dl> </div> <script> fetch("product_list.csv") .then((response) => response.text()) .then((data) => { const rows = data.split("\n").filter((row) => row.trim() !== ""); const tbody = document.querySelector("tbody"); const totalElement = document.querySelector("dl dd"); rows.forEach((row, index) => { const matches = row.match(/"([^"]+)"|([^,]+)/g).map((item) => item.replace(/"/g, "").trim()); const name = matches[0]; const price = matches[1]; const parsedPrice = parseFloat(price.replace(/,/g, "")); const tr = document.createElement("tr"); tr.innerHTML = ` <td>${name}</td> <td>${parsedPrice.toLocaleString()}円</td> <td> <select name="products${index + 1}" data-price="${parsedPrice}"> ${Array.from({ length: 11 }, (_, i) => `<option value="${i}">${i}</option>`).join("")} </select> </td> <td class="subtotal">0円</td> `; tbody.appendChild(tr); }); const selects = tbody.querySelectorAll("select"); selects.forEach((select) => { select.addEventListener("change", (event) => { const select = event.target; const price = parseFloat(select.dataset.price); const quantity = parseInt(select.value, 10); const subtotal = price * quantity; const subtotalElement = select.closest("tr").querySelector(".subtotal"); subtotalElement.textContent = subtotal.toLocaleString(undefined, { minimumFractionDigits: 0 }) + "円"; calculateTotal(); }); }); function calculateTotal() { let totalPrice = 0; selects.forEach((select) => { const price = parseFloat(select.dataset.price); const quantity = parseInt(select.value, 10); totalPrice += price * quantity; }); totalElement.textContent = totalPrice.toLocaleString(undefined, { minimumFractionDigits: 0 }) + "円"; } }) .catch((error) => { console.error("CSVの読み込み中にエラーが発生しました:", error); }); </script> </body> </html>
コードを解説
HTMLを解説
単純なテーブルタグになりますが『tbody』内はJavascriptで動的に取得するので空にしておきます。
また、テーブルの直下には合計金額を出力する箇所です。
<table border="1"> <thead> <tr> <th>商品名</th> <th>価格</th> <th>個数</th> <th>合計価格</th> </tr> </thead> <tbody> </tbody> </table> <div> <dl> <dt>合計金額</dt> <dd>0円</dd> </dl> </div>
Javascriptの解説
タグの生成
fetch APIを使用してファイルを取得していきます。
fetch("product_list.csv")
レスポンスボディをテキスト形式で取得します。
.then((response) => response.text())
データを取得が成功した場合、エラーがあった場合で処理を分けます。
取得できた場合は『then』の中に処理を書いていきます。
エラーはcatchの中に処理を書きます。
.then((data) => { }) .catch((error) => { console.error("CSVの読み込み中にエラーが発生しました:", error); });
取得したCSVを行ごとに分割し、空行を除外します。
const rows = data.split("\n").filter((row) => row.trim() !== "");
空欄にしていたtbody、合計金額表示部分を取得します。
const tbody = document.querySelector("tbody"); const totalElement = document.querySelector("dl dd");
CSVから取得した商品名、商品単価をループで各行に追加していきます。
rows.forEach((row, index) => { });
カンマ区切りで分割し、ダブルクォーテーションを削除します。
const matches = row.match(/"([^"]+)"|([^,]+)/g).map((item) => item.replace(/"/g, "").trim()); const name = matches[0]; // 商品名 const price = matches[1]; // 価格 const parsedPrice = parseFloat(price.replace(/,/g, "")); // カンマを削除して数値に変換
HTMLタグを作成します。
『document.createElement(“”)』でタグを生成、金額部分は『toLocaleString』で通貨のカンマ区切り、セレクトボックスは反復メソッドの『Array.from』を使用して10個生成しています。
最後の『.appendChild()』でtbody内に出力しています。
const tr = document.createElement("tr"); tr.innerHTML = ` <td>${name}</td> <td>${parsedPrice.toLocaleString()}円</td> <td> <select name="products${index + 1}" data-price="${parsedPrice}"> ${Array.from({ length: 11 }, (_, i) => `<option value="${i}">${i}</option>`).join("")} </select> </td> <td class="subtotal">0円</td> `; tbody.appendChild(tr);
小計の計算と表示
個数を選択するセレクトボックスを取得します。
const selects = tbody.querySelectorAll("select");
ループで全てのセレクトボックスに対して処理を行います。
selects.forEach((select) => { });
変更されたら実行、単価取得、セレクトボックス内の個数を習得します。
const select = event.target; const price = parseFloat(select.dataset.price); const quantity = parseInt(select.value, 10);
取得したデータから小計の計算を行います。
const subtotal = price * quantity;
小計を表示します。
const subtotalElement = select.closest("tr").querySelector(".subtotal"); subtotalElement.textContent = subtotal.toLocaleString(undefined, { minimumFractionDigits: 0 }) + "円";
最後に合計計算を行うための関数を書いておきます。
これで合計金額の計算関数に処理を引き継ぎます。
合計の計算と表示
関数名を設定します。
function calculateTotal() { }
合計を初期化して、セレクトボックス全てにループ処理で数値を取得していきます。
let totalPrice = 0; // 合計を初期化 selects.forEach((select) => { const price = parseFloat(select.dataset.price); const quantity = parseInt(select.value, 10); totalPrice += price * quantity; });
最後に合計金額を表示します。
totalElement.textContent = totalPrice.toLocaleString(undefined, { minimumFractionDigits: 0 }) + "円";
以上で実装完了です。
まとめ
一度、コードを作成してしまえばあとはCSVで商品登録をしていくだけなので、データベースを使用するより簡単に更新可能です。
CSVの編集はエクセルで行えば視覚的に分かりやすく編集もできますのでパソコン操作に慣れていない方が行うのは比較的簡単になります。
弊社のような制作会社であればお客様にCSVで商品を追加してもらって、ファイルを入れ替えるだけで反映ができてしまいます。
使えるケースは限られてきますが作業の簡易化が実現できます。
ぜひ、ご参考ください。