diff options
| author | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-10-29 22:27:04 +0900 |
|---|---|---|
| committer | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-10-29 22:27:04 +0900 |
| commit | 1bed26135359e11d7b74ad46cd0abc661572773e (patch) | |
| tree | cf3c5d794d0ab0dd1abf031fe4e5fa0312899347 /scripts | |
| parent | f0df56b89d4644ec49d33d072c388e653c5ededa (diff) | |
park-editor: 未確認の公園をCSVで書き出す
確認チェックが付いていない行を、Excel / Googleスプレッドシートで編集できるCSV(UTF-8 BOM)として保存するボタンを追加した。確認・メモ列を先頭に置き、地図リンクも含める。
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/park-editor.html | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/scripts/park-editor.html b/scripts/park-editor.html index 23e537c..7648121 100644 --- a/scripts/park-editor.html +++ b/scripts/park-editor.html @@ -81,6 +81,7 @@ <span class="check-note" title="確認チェックはこのブラウザにのみ保存され、JSONには入りません">このブラウザのみ</span> <button id="clear-checks" title="このデータの確認チェックをすべて外す">確認をクリア</button> <button id="save">保存</button> + <button id="export-unchecked" title="確認チェックが付いていない行をCSVで保存します(Excel / Googleスプレッドシートで開けます)">未確認CSV</button> <button id="revert">再読込</button> <span id="status"></span> </div> @@ -560,6 +561,65 @@ function corruptLabel(inp) { return `${name} / ${label}: ${inp.value}`; } +const PARK_EXPORT_KEYS = [ + "公園名", "住所", "町名", "種別", "面積㎡", "設置者", "状態", + "トイレ", "水飲み場", "ベンチ・椅子", "テーブル", "シェルター等", + "草地広場", "多目的広場", "築山", "じゃぶじゃぶ池", + "防災用具", "ボール遊び", "遊具", "時計", "駐車場", "その他設備", "備考", + "緯度", "経度", +]; + +function csvCell(value) { + const text = value == null ? "" : String(value); + return /[",\r\n]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text; +} + +// 確認チェックが付いていない行を、Excel / Googleスプレッドシートで編集できるCSVにする。 +// 確認・メモの列を先頭に置き、外出先で入力しやすくする。 +function exportUncheckedCsv() { + const targets = []; + rows.forEach((row) => { + const props = isFC ? row.properties || {} : row; + if (isChecked(currentId, rowKey(props, currentId))) return; + targets.push({ row, props }); + }); + if (!targets.length) { + statusEl.textContent = "未確認の行はありません。"; + return; + } + + let headers; + let toCells; + if (currentId === "parks") { + headers = ["確認", "メモ", ...PARK_EXPORT_KEYS, "地図"]; + toCells = ({ row, props }) => [ + "", "", + ...PARK_EXPORT_KEYS.map((key) => props[key] ?? ""), + mapsUrl(row, props), + ]; + } else { + const cols = fields.filter((field) => !field.toy); + headers = [...cols.map((field) => field.label.replace(/<[^>]+>/g, "")), "地図"]; + toCells = ({ row, props }) => [...cols.map((field) => props[field.key] ?? ""), mapsUrl(row, props)]; + } + + const lines = [headers.map(csvCell).join(",")]; + for (const target of targets) lines.push(toCells(target).map(csvCell).join(",")); + const csv = "\uFEFF" + lines.join("\r\n") + "\r\n"; + const blob = new Blob([csv], { type: "text/csv;charset=utf-8" }); + const url = URL.createObjectURL(blob); + const link = document.createElement("a"); + link.href = url; + link.download = `未確認_${DATASETS[currentId].label}_${new Date().toISOString().slice(0, 10)}.csv`; + document.body.appendChild(link); + link.click(); + link.remove(); + setTimeout(() => URL.revokeObjectURL(url), 1000); + statusEl.textContent = `未確認 ${targets.length} 件をCSVで保存しました(Excel / Googleスプレッドシートで開けます)。`; +} + +document.getElementById("export-unchecked").onclick = exportUncheckedCsv; + function collect() { const toyValues = new Map(); Array.prototype.forEach.call(tbody.querySelectorAll("input[data-r][data-c]"), (inp) => { |
