aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com>2026-10-29 22:27:04 +0900
committerYasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com>2026-10-29 22:27:04 +0900
commit1bed26135359e11d7b74ad46cd0abc661572773e (patch)
treecf3c5d794d0ab0dd1abf031fe4e5fa0312899347
parentf0df56b89d4644ec49d33d072c388e653c5ededa (diff)
park-editor: 未確認の公園をCSVで書き出す
確認チェックが付いていない行を、Excel / Googleスプレッドシートで編集できるCSV(UTF-8 BOM)として保存するボタンを追加した。確認・メモ列を先頭に置き、地図リンクも含める。
-rw-r--r--scripts/park-editor.html60
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) => {