# -*- coding: utf-8 -*-”””野外坐标表 -> 规范成果一键整理功能:把野外手簿 / 记录表导出的 Excel,整理成 ① 坐标交换文件 CSV ② 点之记 Excel ③ 控制台整理报告依赖:pandas, openpyxl用法:python 坐标整理.py (同目录放一份 野外坐标表.xlsx)”””import pandas as pdimport reINPUT_FILE = ”野外坐标表.xlsx”# 待整理的原始表SHEET = 0# 工作表序号,0 = 第一个工作表OUT_CSV = ”坐标交换文件.csv”# 输出:坐标交换文件OUT_DOC = ”点之记.xlsx”# 输出:点之记# ---- 1. 读取(先全按文本,避免 001 变 1、长数字变科学计数)----raw = pd.read_excel(INPUT_FILE, sheet_name=SHEET, dtype=str)print(f”[1] 读入原始行数:{len(raw)},列名:{list(raw.columns)}”)# ---- 2. 列名标准化(兼容各种叫法)----def find_col(columns, candidates): ”””在列名里模糊匹配候选名,返回第一个命中的列名;都找不到返回 None””” cols = [str(c) for c in columns] for cand in candidates: for c in cols: if cand.lower() in c.lower(): return c return NoneCOL = { ”id”: find_col(raw.columns, [”点号”, ”点名”, ”序号”, ”编号”, ”id”, ”name”]), ”x”: find_col(raw.columns, [”纵坐标”, ”北坐标”, ”north”, ”x坐标”, ”x”]), ”y”: find_col(raw.columns, [”横坐标”, ”东坐标”, ”east”, ”y坐标”, ”y”]), ”h”: find_col(raw.columns, [”高程”, ”海拔”, ”elev”, ”z”, ”h”]), ”memo”: find_col(raw.columns, [”备注”, ”说明”, ”注释”, ”remark”, ”描述”, ”地类”]),}print(f”[2] 识别到的列映射:{COL}”)if not COL[”id”] or not COL[”x”] or not COL[”y”]: raise SystemExit(”缺少关键列(点号 / 纵坐标X / 横坐标Y),请检查表头。”)# ---- 3. 提取并清洗 ----df = pd.DataFrame()df[”点号”] = raw[COL[”id”]].astype(str).str.strip()df[”点名”] = df[”点号”]df[”X”] = raw[COL[”x”]].astype(str).str.strip().str.replace(”,”, ””, regex=False)df[”Y”] = raw[COL[”y”]].astype(str).str.strip().str.replace(”,”, ””, regex=False)df[”H”] = raw[COL[”h”]].astype(str).str.strip().str.replace(”,”, ””, regex=False) if COL[”h”] else ””df[”备注”] = raw[COL[”memo”]].astype(str).str.strip() if COL[”memo”] else ””# 去掉点号为空/NaN 的行(Excel 空单元格读成 NaN,astype(str) 会变 'nan')df[”点号”] = df[”点号”].mask(df[”点号”].str.lower().isin([”nan”, ”none”, ”nat”]), ””)df = df[df[”点号”].str.len() > 0].reset_index(drop=True)print(f”[3] 去除空行后剩余:{len(df)} 行”)# ---- 4. 数值化与告警 ----df[”Xn”] = pd.to_numeric(df[”X”], errors=”coerce”)df[”Yn”] = pd.to_numeric(df[”Y”], errors=”coerce”)df[”Hn”] = pd.to_numeric(df[”H”], errors=”coerce”)bad = df[df[”Xn”].isna() | df[”Yn”].isna()]if len(bad) > 0: print(f”[!] 警告:{len(bad)} 行的 X/Y 不是数字,已保留原文本并标'坐标异常':”) for _, r in bad.iterrows(): print(f” 点号 {r['点号']}:X={r['X']} Y={r['Y']}”)# ---- 5. 坐标系粗判(高斯公里网 vs 经纬度)----def guess_crs(x, y): if pd.isna(x) or pd.isna(y): return ”未知”# 经纬度:纬度(X)一般<90,经度(Y)一般<180 if abs(x) < 90 and abs(y) < 180: return ”疑似经纬度(WGS84/GCJ02)”# 高斯坐标:X(北)=2.9e6~5.6e6,Y(东,带号+500km)=3.0e7~5.0e7 if 2.9e6 < abs(x) < 6e6 and 3.0e7 < abs(y) < 5.0e7: return ”疑似高斯投影(3°/6°带·CGCS2000/54/80)” return ”数值异常或自定义”crs = guess_crs(df[”Xn”].median(), df[”Yn”].median())print(f”[4] 坐标系粗判:{crs}(如有疑问请人工核对)”)# ---- 6. 去重(按点号,保留首次出现)----dups = df[df[”点号”].duplicated(keep=”first”)]if len(dups) > 0: print(f”[!] 发现重复点号 {len(dups)} 个,保留首次出现:{list(dups['点号'])}”)df = df.drop_duplicates(subset=[”点号”], keep=”first”).reset_index(drop=True)# ---- 7. 点号自然排序(提取末尾数字)----def sort_key(s): m = re.findall(r”\d+”, str(s)) return (0, 0) if not m else (len(str(s)), int(m[-1]))df[”_k”] = df[”点号”].apply(sort_key)df = df.sort_values(”_k”).drop(columns=[”_k”]).reset_index(drop=True)# ---- 8. 输出坐标交换文件 CSV ----csv_df = df[[”点号”, ”点名”, ”X”, ”Y”, ”H”, ”备注”]].copy()csv_df.to_csv(OUT_CSV, index=False, encoding=”utf-8-sig”)print(f”[5] 已写出坐标交换文件:{OUT_CSV}({len(csv_df)} 个点)”)# ---- 9. 输出点之记 Excel ----from openpyxl import Workbookfrom openpyxl.styles import Font, Alignment, PatternFill, Border, Sidewb = Workbook()ws = wb.activews.title = ”点之记”hdr_font = Font(name=”Microsoft YaHei”, bold=True, size=11)fill_head = PatternFill(”solid”, fgColor=”1F4E79”)fill_alt = PatternFill(”solid”, fgColor=”DDEBF7”)thin = Side(style=”thin”, color=”B0B0B0”)border = Border(left=thin, right=thin, top=thin, bottom=thin)headers = [”点号”, ”坐标(X 北)”, ”坐标(Y 东)”, ”高程 H”, ”点位描述/备注”, ”坐标系”]ws.append(headers)for c in range(1, len(headers) + 1): cell = ws.cell(row=1, column=c) cell.font = hdr_font cell.fill = fill_head cell.alignment = Alignment(horizontal=”center”, vertical=”center”) cell.border = borderfor i, (_, r) in enumerate(df.iterrows(), start=2): vals = [ r[”点号”], r[”X”], r[”Y”], r[”H”] if r[”H”] != ”” else ”—”, r[”备注”] if r[”备注”] != ”” else ”(待补)”, crs, ] ws.append(vals) for c in range(1, len(headers) + 1): cell = ws.cell(row=i, column=c) cell.border = border cell.alignment = Alignment(horizontal=”left”, vertical=”center”) if i % 2 == 0: cell.fill = fill_altws.column_dimensions[”A”].width = 14ws.column_dimensions[”B”].width = 18ws.column_dimensions[”C”].width = 18ws.column_dimensions[”D”].width = 12ws.column_dimensions[”E”].width = 30ws.column_dimensions[”F”].width = 28wb.save(OUT_DOC)print(f”[6] 已写出点之记:{OUT_DOC}({len(df)} 个点)”)# ---- 10. 汇总报告 ----print(”\n===== 整理报告 =====”)print(f”原始行数:{len(raw)} -> 有效点:{len(df)}”)print(f”重复点号已合并:{len(dups)}”)print(f”坐标异常行:{len(bad)}”)print(f”坐标系粗判:{crs}”)print(f”输出文件:{OUT_CSV} / {OUT_DOC}”)print(”完成。”)