Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -204,4 +204,95 @@ def _make_folium_map(df_points: pd.DataFrame, base_name: str, cluster: bool, hei
|
|
| 204 |
link_url = "data:text/html;base64," + base64.b64encode(html.encode("utf-8")).decode("ascii")
|
| 205 |
iframe = (
|
| 206 |
f'<iframe src="{data_url}" style="border:0;width:100%;height:{height_px}px"></iframe>'
|
| 207 |
-
f'<div style="margin-top:6px;"><a href="{link_url}" target="_blank" rel="noopener">↗
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 204 |
link_url = "data:text/html;base64," + base64.b64encode(html.encode("utf-8")).decode("ascii")
|
| 205 |
iframe = (
|
| 206 |
f'<iframe src="{data_url}" style="border:0;width:100%;height:{height_px}px"></iframe>'
|
| 207 |
+
f'<div style="margin-top:6px;"><a href="{link_url}" target="_blank" rel="noopener">↗ 地図を新しいタブで開く</a></div>'
|
| 208 |
+
)
|
| 209 |
+
return iframe
|
| 210 |
+
|
| 211 |
+
# ----------------------------
|
| 212 |
+
# 実行パイプライン
|
| 213 |
+
# ----------------------------
|
| 214 |
+
def _parse_indexer(x):
|
| 215 |
+
try:
|
| 216 |
+
return int(x)
|
| 217 |
+
except Exception:
|
| 218 |
+
return x
|
| 219 |
+
|
| 220 |
+
def run(excel_file, sheet_name, header_row, address_col, power_col, use_inet, base_name, cluster):
|
| 221 |
+
# Excel 読み込み
|
| 222 |
+
if excel_file is None or not hasattr(excel_file, "name"):
|
| 223 |
+
table_df = pd.DataFrame(columns=["address_input", "CF", "lat", "lon"])
|
| 224 |
+
return "", table_df, "Excelファイルを指定してください。"
|
| 225 |
+
|
| 226 |
+
try:
|
| 227 |
+
df = pd.read_excel(excel_file.name, sheet_name=sheet_name, header=int(header_row))
|
| 228 |
+
except Exception as e:
|
| 229 |
+
empty_df = pd.DataFrame(columns=["address_input", "CF", "lat", "lon"])
|
| 230 |
+
return "", empty_df, f"Excel の読み込みに失敗しました: {e}"
|
| 231 |
+
|
| 232 |
+
# 列参照
|
| 233 |
+
addr_series = df.iloc[:, address_col] if isinstance(address_col, int) else df[address_col]
|
| 234 |
+
cf_series = df.iloc[:, power_col] if isinstance(power_col, int) else df[power_col]
|
| 235 |
+
|
| 236 |
+
addresses = addr_series.astype(str).tolist()
|
| 237 |
+
cfs = cf_series.tolist()
|
| 238 |
+
|
| 239 |
+
geo_df = geocode_with_cache(addresses, cfs, use_internet=bool(use_inet))
|
| 240 |
+
table_df = geo_df[["address_input", "CF", "lat", "lon"]].copy()
|
| 241 |
+
|
| 242 |
+
# Folium 地図
|
| 243 |
+
try:
|
| 244 |
+
html_map = _make_folium_map(table_df, base_name=base_name, cluster=bool(cluster), height_px=640)
|
| 245 |
+
info = [f"ポイント数(有効座標): {int(table_df[['lat','lon']].dropna().shape[0])} / {len(table_df)}"]
|
| 246 |
+
except Exception as e:
|
| 247 |
+
html_map = f"<p>地図描画に失敗しました: {e}</p>"
|
| 248 |
+
info = []
|
| 249 |
+
|
| 250 |
+
return html_map, table_df, "\n".join(info)
|
| 251 |
+
|
| 252 |
+
# ----------------------------
|
| 253 |
+
# Gradio UI
|
| 254 |
+
# ----------------------------
|
| 255 |
+
with gr.Blocks(title="Excel住所 → Folium(無料タイル・Mapbox不要)") as demo:
|
| 256 |
+
gr.Markdown("## Excelの住所を国土地理院APIでジオコーディング → Folium(Leaflet)で地図表示(無料タイル・Mapbox不要)")
|
| 257 |
+
|
| 258 |
+
with gr.Row():
|
| 259 |
+
xlsx_in = gr.File(label="Excelファイル(住所付き)", file_count="single", file_types=[".xlsx", ".xls"])
|
| 260 |
+
|
| 261 |
+
with gr.Row():
|
| 262 |
+
sheet = gr.Textbox(label="シート名", value="認定設備")
|
| 263 |
+
header_row = gr.Number(label="ヘッダー行番号(0始まり)", value=2, precision=0)
|
| 264 |
+
|
| 265 |
+
with gr.Row():
|
| 266 |
+
address_col = gr.Textbox(label="住所列(列名 or 0始まり列番号)", value="発電設備の所在地")
|
| 267 |
+
power_col = gr.Textbox(label="数値列(任意:列名 or 0始まり列番号)", value="発電出力(kW)")
|
| 268 |
+
|
| 269 |
+
with gr.Row():
|
| 270 |
+
use_inet = gr.Checkbox(label="国土地理院APIに問い合わせ(オフでキャッシュのみ使用)", value=True)
|
| 271 |
+
base_name = gr.Dropdown(choices=list(TILE_CATALOG.keys()), value="GSI 標準地図", label="ベースマップ")
|
| 272 |
+
cluster = gr.Checkbox(label="マーカーをクラスタ表示", value=True)
|
| 273 |
+
|
| 274 |
+
run_btn = gr.Button("描画")
|
| 275 |
+
|
| 276 |
+
out_html = gr.HTML(label="地図(Folium / Leaflet)")
|
| 277 |
+
out_table = gr.Dataframe(label="ジオコーディング結果(住所・緯度・経度・CF)", wrap=True)
|
| 278 |
+
out_info = gr.Textbox(label="メタ情報", lines=2)
|
| 279 |
+
|
| 280 |
+
def _parse(x):
|
| 281 |
+
try:
|
| 282 |
+
return int(x)
|
| 283 |
+
except Exception:
|
| 284 |
+
return x
|
| 285 |
+
|
| 286 |
+
def app_run(xls, s, h, a, p, inet, base, cl):
|
| 287 |
+
return run(
|
| 288 |
+
xls, s, int(h), _parse(a), _parse(p), inet, base, cl
|
| 289 |
+
)
|
| 290 |
+
|
| 291 |
+
run_btn.click(
|
| 292 |
+
fn=app_run,
|
| 293 |
+
inputs=[xlsx_in, sheet, header_row, address_col, power_col, use_inet, base_name, cluster],
|
| 294 |
+
outputs=[out_html, out_table, out_info],
|
| 295 |
+
)
|
| 296 |
+
|
| 297 |
+
if __name__ == "__main__":
|
| 298 |
+
demo.launch()
|