TXT / Excel(CSV) / SHP 三种格式任意互转
支持 WGS84 / CGCS2000 / Xian80 / Beijing54 / Web Mercator 坐标系转换
由 Mapo 🗺️ 自动生成
73 lines
2.4 KiB
Python
73 lines
2.4 KiB
Python
"""
|
|
Excel/CSV file reader/writer using pandas + openpyxl.
|
|
"""
|
|
import os
|
|
from pathlib import Path
|
|
import pandas as pd
|
|
from core.data_model import CoordData, CoordPoint
|
|
|
|
|
|
class ExcelHandler:
|
|
EXTENSIONS = {".xlsx", ".xls", ".csv"}
|
|
|
|
@classmethod
|
|
def read(cls, path: str, sheet: str | None = None) -> CoordData:
|
|
ext = Path(path).suffix.lower()
|
|
if ext == ".csv":
|
|
df = pd.read_csv(path, encoding="utf-8-sig")
|
|
else:
|
|
df = pd.read_excel(path, sheet_name=sheet or 0, dtype_backend="numpy_nullable")
|
|
|
|
if df.empty:
|
|
raise ValueError(f"文件无数据: {path}")
|
|
|
|
records = df.to_dict(orient="records")
|
|
# Convert nan to None
|
|
for r in records:
|
|
for k, v in r.items():
|
|
if pd.isna(v):
|
|
r[k] = None
|
|
|
|
cols = list(df.columns)
|
|
x_col, y_col, z_col = cls._find_coord_cols(cols)
|
|
return CoordData.from_records(records, x_col=x_col, y_col=y_col, z_col=z_col)
|
|
|
|
@classmethod
|
|
def write(cls, data: CoordData, path: str, sheet: str = "坐标数据"):
|
|
records = data.to_records()
|
|
if not records:
|
|
raise ValueError("无数据可写入")
|
|
|
|
df = pd.DataFrame(records)
|
|
ext = Path(path).suffix.lower()
|
|
|
|
if ext == ".csv":
|
|
df.to_csv(path, index=False, encoding="utf-8-sig")
|
|
else:
|
|
with pd.ExcelWriter(path, engine="openpyxl") as writer:
|
|
df.to_excel(writer, sheet_name=sheet, index=False)
|
|
|
|
@staticmethod
|
|
def _find_coord_cols(cols: list[str]) -> tuple[str, str, str | None]:
|
|
"""Same logic as TxtHandler for column discovery."""
|
|
x_patterns = ["x", "lon", "经度", "lng", "easting"]
|
|
y_patterns = ["y", "lat", "纬度", "northing"]
|
|
z_patterns = ["z", "h", "高程", "高度", "alt"]
|
|
|
|
x_col = y_col = z_col = None
|
|
lower_cols = {c: c.lower().replace(" ", "").replace("_", "").replace("-","")
|
|
for c in cols}
|
|
|
|
for c, lc in lower_cols.items():
|
|
if any(p in lc for p in x_patterns):
|
|
x_col = c
|
|
elif any(p in lc for p in y_patterns):
|
|
y_col = c
|
|
elif any(p in lc for p in z_patterns):
|
|
z_col = c
|
|
|
|
if not x_col and len(cols) >= 2:
|
|
x_col, y_col = cols[0], cols[1]
|
|
|
|
return x_col, y_col, z_col
|