金蝶云星空数据导出(只读 · 自包含)
用途
按用户指定的单据、基础资料或账表,从金蝶云星空增量或全量拉取数据,落盘为 Excel/CSV, 并可基于已导出文件在本地生成图表报表。全程只调用查询接口,不对星空做任何写入。
硬性约束:只读
仅允许三个方法:ExecuteBillQuery、View、GetSysReportData。
禁止调用 Save、BatchSave、Submit、Audit、UnAudit、Delete、Push、Cancel、
CancelAssign、BillClose、BillUnClose、Draft、Execute、ExecuteOperation、
AttachmentUpload 等任何写操作或流程操作接口。
SDK 层对方法名做白名单校验,任何非白名单调用立即抛 PermissionError 并终止。
另需确认对接账号在星空中的角色无写入权限,形成双保险。
依赖分级与降级
任一依赖缺失时自动降级,绝不中断流程、绝不报错中止。
| 层级 | 依赖 | 能力 |
|---|---|---|
| L0 保底 | 仅 Python 标准库 | CSV 导出 + 终端打印汇总 |
| L1 标准 | + openpyxl | Excel 导出、样式、内嵌图表、透视表 |
| L2 增强 | + plotly | 额外输出交互式 HTML 图表 |
| L3 可选 | 外部分析 skill | 深度分析/看板,仅作提示,非必经步骤 |
L1 的 openpyxl 原生图表是默认方案:图表直接写入 xlsx,不需要 matplotlib、不需要图形库、 不需要浏览器,跨环境兼容性最好。
环境准备
- 必需:
requests(取数) - 推荐:
openpyxl(Excel 与内嵌图表)、pandas(数据处理) - 可选:
plotly(交互式图表) - 不依赖官方 SDK——官方 Python SDK 的
InitConfig无 password 参数,不支持用户名密码登录 - 业务代码只调用
scripts/kd_sdk/client.py,禁止直接发 HTTP 请求 - 首次接入新环境,先执行
scripts/probe.py完成三项探测,结果固化进references/sdk_notes.md:- 登录服务可用性:
AuthService.ValidateUser→AuthService.Login parameters传参格式:字符串数组{"parameters":["{...}"]}还是直接传 body- 目标 FormId 与字段是否有效——按
references/formids.md的准入规则回填状态
- 登录服务可用性:
前置配置(阻塞项,缺失先向用户索取)
从环境变量或运行时询问获取,禁止硬编码进脚本:
| 变量 | 说明 |
|---|---|
| KD_SERVER_URL | 形如 https://xxx.ik3cloud.com/k3cloud/,必须以 /k3cloud/ 结尾 |
| KD_ACCT_ID | 账套 ID / 数据中心 ID,一串 GUID |
| KD_USERNAME | 登录用户名 |
| KD_PASSWORD | 登录密码 |
| KD_LCID | 账套语系,默认 2052(简体中文) |
密码不进脚本、不进日志、不进 state.json。对接账号建议使用只读角色的专用账号。
注意星空默认单点登录,API 登录可能把已在线的同名用户踢下线,生产环境取数需避开业务时段。
配置写入两种方式,二选一即可:
python scripts/configure.py --set # 交互式录入,密码不回显
export KD_SERVER_URL=... KD_ACCT_ID=... KD_USERNAME=... KD_PASSWORD=... # 环境变量
python scripts/configure.py --show # 查看当前生效配置(密码打码)
执行流程
1. 登录
from kd_sdk.client import ReadOnlyKingdeeClient
sdk = ReadOnlyKingdeeClient(server_url, acct_id, username, password, lcid=2052)
sdk.login() # ValidateUser 失败自动降级 Login,成功后绑定 kdservice-sessionid
会话失效时 SDK 自动重登并重试一次,长任务无需手动处理。
2. 确认组织范围(不要跳过)
星空是多组织架构,同一单据在不同组织下数据不同,不指定组织很容易导出口径错误的数据。
python scripts/list_orgs.py # 列出全部组织编码与名称
python scripts/export.py -o sale_order --org 100 # 单组织
python scripts/export.py -o sale_order --org 100,200 # 多组织,各占一个 Sheet
python scripts/export.py -o sale_order --all-orgs # 自动读取组织清单逐组织导出
python scripts/export.py -o sale_order --all-orgs --merge-orgs # 多组织合并到一个 Sheet
组织编码拿不准时,先跑 list_orgs.py 把清单给用户确认,再执行导出。
组织很多时用 --merge-orgs,避免 Sheet 数量爆炸。
3. 分页取数
python scripts/export.py -o sale_order --start 2026-01-01 --end 2026-01-31 --org 100
- 默认每页 2000 行,
--page-size可调;--limit N限制每个组织的最大行数 - 排序默认
FID ASC(基础资料为FNumber ASC),保证翻页稳定 - 自定义
--order时务必选唯一字段,否则翻页可能重复或漏行 - 导出前先
--dry-run,确认 FilterString 与字段列表符合预期,尤其在不熟悉的账套上
4. 增量同步
水位线记在技能根目录 state.json(按对象隔离,只存水位值,不含任何业务数据):
| 对象类型 | 水位字段 | 策略 | 说明 |
|---|---|---|---|
| 单据 bill | FID | FID > 上次最大值 | 内码单调递增,不重不漏 |
| 基础资料 base | FNumber | FNumber > 上次最大值 | 编码新增可增量,改资料需全量 |
| 账表 report | — | 不支持 | 每次全量刷新 |
python scripts/export.py -o sale_order --incremental # 只取上次之后新增的单据
python scripts/export.py -o sale_order --incremental --reset-state # 清掉水位线,重新全量
python scripts/export.py -o sale_order --since 2026-08-01 # 临时按日期起算,不写 state.json
5. 中文字段映射落盘
- 表头默认用
scripts/catalog.py里的中文列名,无需用户逐字段翻译 --fields可覆盖,支持字段:中文表头写法:--fields "FNumber:物料编码,FName:物料名称"- 状态编码自动转中文(
FDocumentStatusC→已审核、FCloseStatus、FCancelStatus、FForbidStatus) - 值清洗:
2026-01-15T00:00:00→2026-01-15;0001-01-01视为空;数值字符串转数字便于 Excel 求和 - 导出前默认逐字段校验,账套里不存在的字段自动剔除并在终端列出,不会整单失败
- CSV 输出带 UTF-8 BOM,Excel 双击不乱码
6. 可选:生成图表报表
基于已导出的本地文件做聚合,不再访问星空:
python scripts/chart_builder.py -i 导出.xlsx --list-columns # 看可用列
python scripts/chart_builder.py -i 导出.xlsx --group-by 客户 --value 价税合计 --top 20
python scripts/chart_builder.py -i 导出.xlsx --trend 单据日期 --value 价税合计 --freq M --chart line
python scripts/chart_builder.py -i 导出.xlsx --group-by 单据状态 --agg count --chart pie
支持 --agg sum|avg|count、--chart bar|line|pie、--freq Y|M|D,
引擎 --engine auto|openpyxl|plotly|csv,auto 时按 L1→L2→L0 逐级降级。
6.1 导出时自动生成本地 HTML 报表(推荐)
export.py 在落盘 Excel/CSV 后默认额外生成一份自包含 HTML 报表(同名.html),
浏览器双击即可看,无需再跑 chart_builder.py:
- KPI 卡片:总记录数、金额合计、数量合计、时间范围、组织/Sheet 数(按中文表头自动识别)
- 自动多图:状态分布饼图、分类 Top10 柱状图(按金额合计)、按月趋势折线图
- 数据预览:前 50 行表格,完整数据见导出的表格文件
- 零依赖兜底:装了
plotly就出可交互图;没装则自动降级为纯 CSS 静态图(条形 + 表格),单文件离线可用
python scripts/export.py -o sale_order --org 100 --out 销售订单.xlsx # 同时得到 销售订单.html
python scripts/export.py -o sale_order --org 100 --no-html # 只要数据文件,不要报表
python scripts/export.py -o sale_order --org 100 --html-out 我的报表.html # 指定报表路径
# 也可对一份已有的本地文件单独补报表
python scripts/report.py -i 已导出.xlsx -o 报表.html
注:HTML 报表的图表维度完全靠表头自适应,不同业务对象(销售订单 / 采购订单 / 库存……) 都能自动出一套,无需为每张单据单独配置。
脚本索引
| 脚本 | 作用 |
|---|---|
| scripts/configure.py | 写入 / 查看 / 清除本地连接配置 |
| scripts/probe.py | 环境探测:登录服务、传参风格、FormId 与字段有效性 |
| scripts/list_orgs.py | 列出账套组织清单,供用户确认导出范围 |
| scripts/export.py | 主导出:按组织分页取数、增量同步、落盘 |
| scripts/chart_builder.py | 基于已导出文件生成内嵌图表报表 |
| scripts/report.py | 导出后自动生成自包含 HTML 报表(KPI + 自动多图 + 预览)|
| scripts/catalog.py | 业务对象目录(FormId、预设字段、中文表头、别名)|
| scripts/tablekit.py | 值清洗、状态映射、xlsx/csv 读写与降级 |
| scripts/kd_sdk/ | 只读 SDK 层:登录、白名单校验、分页、探测 |
所有脚本均支持 --help。
排障
| 现象 | 原因与处理 |
|---|---|
| 登录返回 -7 | 同一用户被其他会话挤下线。换专用只读账号,或避开业务时段 |
| HTTP 200 但响应不是 JSON | 地址缺少 /k3cloud/ 结尾,或被网关/WAF 拦截返回了 HTML |
| 提示字段不存在 | 二开账套字段名可能与预设不同。用 probe.py --form-id X --fields a,b 找真实字段名 |
| 数据条数为 0 | 检查日期范围、组织编码、过滤条件,以及账号是否有该组织的查询权限 |
| 翻页出现重复行 | --order 用了不唯一字段。改回 FID ASC |
| 字段校验全绿但业务对不上 | 目标表无数据时任何字段都会校验通过。造一条数据后重新探测 |
| openpyxl 不可用 | 自动降级 CSV。需 Excel 就 pip install -r requirements.txt |
| 报 PermissionError | 代码里出现了白名单外的方法调用。只读约束不可绕过,改回三个查询方法 |
参考文件
references/formids.md—— FormId 准入清单与字段规律,人工维护的长期经验references/sdk_notes.md—— 由probe.py自动生成的当前账套探测结果scripts/catalog.py—— 业务对象目录的唯一数据源
Scan to join WeChat group