#!/usr/bin/env python3 """导入成品提货表到数据库""" import os, sys, re import openpyxl import pymysql from config import DB_CONFIG EXCEL_PATH = "/home/gxd/.openclaw/workspace-dingtalk-assistant/media/inbound/成品提货表(跟单)6-17-1781683586060.xlsx" COLUMNS = [ ("序号", "INT"), ("品类", "VARCHAR(100)"), ("货品编号", "VARCHAR(100)"), ("货品名称", "VARCHAR(500)"), ("供应商", "VARCHAR(200)"), ("可用库存", "INT"), ("昨日销量", "VARCHAR(50)"), ("3天均销量", "VARCHAR(50)"), ("7天均销量", "VARCHAR(50)"), ("15天均销量", "VARCHAR(50)"), ("支撑天数", "VARCHAR(50)"), ("采购总数量", "INT"), ("生产在途", "INT"), ("采购在途", "INT"), ("国内下单表进度", "VARCHAR(200)"), ("海外下单表进度", "VARCHAR(200)"), ("产品进度", "VARCHAR(200)"), ("包材库存", "INT"), ("采购跟单", "VARCHAR(500)"), ("采购计划", "VARCHAR(200)"), ("备注", "TEXT"), ] CREATE_SQL = """ CREATE TABLE IF NOT EXISTS finished_products ( id INT AUTO_INCREMENT PRIMARY KEY, {fields}, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci """ def main(): conn = pymysql.connect(**DB_CONFIG) cur = conn.cursor() field_defs = ", ".join([f"`{name}` {dtype} DEFAULT NULL" for name, dtype in COLUMNS]) cur.execute(CREATE_SQL.format(fields=field_defs)) print("✅ 表 finished_products 已就绪") cur.execute("TRUNCATE TABLE finished_products") print("✅ 已清空旧数据") wb = openpyxl.load_workbook(EXCEL_PATH, data_only=True) ws = wb.active headers = [] for col in range(1, ws.max_column + 1): val = ws.cell(row=1, column=col).value headers.append(str(val).strip() if val else "") expected = [c[0] for c in COLUMNS] mismatch = [] for i, (h, e) in enumerate(zip(headers, expected)): if h != e: mismatch.append(f" 列{i+1}: 期望'{e}' 实际'{h}'") if mismatch: print("⚠️ 表头不匹配:") for m in mismatch: print(m) return col_types = [c[1] for c in COLUMNS] def clean_val(val, dtype): if val is None: return None s = str(val).strip() if not s: return None if dtype.startswith('INT'): nums = re.sub(r'[^0-9\-]', '', s) if nums and nums != '-': try: return int(nums) except: return None return None if dtype.startswith('DECIMAL'): clean = re.sub(r'[^0-9\.\-]', '', s) if clean and clean != '.': try: return float(clean) except: return None return None return s if s else None placeholders = ", ".join(["%s"] * len(COLUMNS)) col_names = ", ".join([f"`{c[0]}`" for c in COLUMNS]) insert_sql = f"INSERT INTO finished_products ({col_names}) VALUES ({placeholders})" total = 0 batch = [] for row_idx in range(2, ws.max_row + 1): row_data = [] has_data = False for col_idx in range(1, len(COLUMNS) + 1): val = ws.cell(row=row_idx, column=col_idx).value cleaned = clean_val(val, col_types[col_idx - 1]) row_data.append(cleaned) if cleaned is not None: has_data = True if not has_data: continue batch.append(tuple(row_data)) total += 1 if len(batch) >= 500: cur.executemany(insert_sql, batch) conn.commit() print(f" 已导入 {total} 行...") batch = [] if batch: cur.executemany(insert_sql, batch) conn.commit() print(f"✅ 导入完成,共 {total} 行") cur.execute("SELECT COUNT(*) FROM finished_products") print(f"📊 数据库记录数: {cur.fetchone()[0]}") cur.execute("SELECT `货品编号`,`货品名称`,`可用库存`,`供应商`,`品类` FROM finished_products WHERE `货品编号` IS NOT NULL AND `货品编号` != '' ORDER BY `序号` LIMIT 5") print("\n前5条记录:") for r in cur.fetchall(): print(f" {r[0]} | {r[1][:25]}... | 库存{r[2]} | {r[3]} | {r[4]}") conn.close() if __name__ == "__main__": main()