VBA SignTb 字段赋值对照文档¶
对照 VBA
print.vb子程序「将打印内容添加到Access数据库」与 PythonCertificatePrintService.record_print_log, 逐一检查 51 个 Br(1..51) 字段的赋值逻辑是否一致。
VBA 源文件: data/print.vb
Python 服务: src/certflow/services/certificate_print_service.py
Python 模型: src/certflow/models/print_log.py
VBA 子程序入口: 第 2211 行 Sub 将打印内容添加到Access数据库(...)
VBA Br 数组与 Access SignTb 字段映射总览¶
Br# |
SignTb 字段名 |
类型 |
说明 |
|---|---|---|---|
Br(1) |
JiHuaRiQi |
Date |
计划日期 |
Br(2) |
DingHuoDanWei |
Text |
订货单位 |
Br(3) |
XiangMuMingCheng |
Text |
项目名称 |
Br(4) |
ChanPinMingCheng |
Text |
产品名称 |
Br(5) |
ChanPinXingHao |
Text |
产品型号 |
Br(6) |
DN |
Text |
公称通径 |
Br(7) |
PN |
Text |
公称压力 |
Br(8) |
ShiYongJieZhi |
Text |
适用介质 |
Br(9) |
ShiYongWenDu |
Text |
适用温度 |
Br(10) |
ChuChangRiQiYear |
Int |
出厂日期年 |
Br(11) |
ChuChangRiQiMonth |
Int |
出厂日期月 |
Br(12) |
SN |
Text |
出厂编号(短编码) |
Br(13) |
KKS |
Text |
KKS编码(完整编码) |
Br(14) |
Sign_XingHao |
Bool |
型号刻印标记 |
Br(15) |
Sign_DN |
Bool |
口径刻印标记 |
Br(16) |
Sign_PN |
Bool |
压力刻印标记 |
Br(17) |
Sign_JieZhi |
Bool |
介质刻印标记 |
Br(18) |
Sign_WenDu |
Bool |
温度刻印标记 |
Br(19) |
Sign_Year |
Bool |
出厂年刻印标记 |
Br(20) |
Sign_Month |
Bool |
出厂月刻印标记 |
Br(21) |
Sign_SN |
Bool |
出厂编号刻印标记 |
Br(22) |
Sign_KKS |
Bool |
KKS刻印标记 |
Br(23) |
Sign_ALL |
Bool |
全部刻印完毕标记 |
Br(24) |
hgz_ShuLiang |
Int |
合格证数量 |
Br(25) |
hgz_YangShi |
Int |
合格证版型 |
Br(26) |
hgz_PdfPic |
Int |
合格证图片样式 |
Br(27) |
hgz_BianMaModel |
Int |
合格证编码模式 |
Br(28) |
hgz_xlMuBanName |
Text(Memo) |
合格证模板名称 |
Br(29) |
hgz_PrintTime |
Date |
合格证打印时间 |
Br(30) |
PrinterName |
Text |
合格证打印机名(存整数代码) |
Br(31) |
Sign_PrintTime |
Date |
铭牌打印时间(未使用,空值) |
Br(32) |
Sign_ModelFullName |
Text |
铭牌路径(或重复条目数) |
Br(33) |
Sign_PrintCount |
Int |
铭牌标记条目数 |
Br(34) |
不存在 |
— |
VBA 跳过 Br(34),INSERT SQL 中用 |
Br(35) |
FaTiCaiZhi |
Text |
阀体材质 |
Br(36) |
FaGanCaiZhi |
Text |
阀杆材质 |
Br(37) |
QiBiJianCaiZhi |
Text |
启闭件材质 |
Br(38) |
JiShuYaoQiu |
Text(Memo) |
技术要求 |
Br(39) |
SheBeiWeiHao |
Text |
设备位号 |
Br(40) |
ZiXiangMu |
Text |
子项目 |
Br(41) |
SNFromXSB |
Text |
销售产品编号 |
Br(42) |
ZhongLei |
Text |
销售种类 |
Br(43) |
ZhongLiang |
Text |
销售重量要求 |
Br(44) |
XuHao |
Text |
销售序号标识 |
Br(45) |
YaoHuoDanHaoFromXSB |
Text |
营销部要货单号 |
Br(46) |
Sign_FTCZ |
Bool |
阀体材质刻印标记 |
Br(47) |
Sign_FGCZ |
Bool |
阀杆材质刻印标记 |
Br(48) |
Sign_QBJCZ |
Bool |
启闭件材质刻印标记 |
Br(49) |
DcOrPlPrint |
Text |
打印模式 ("0"=单次, "1"=批量) |
Br(50) |
MaxJinShuiTou |
Text |
最大净水头 |
Br(51) |
MaxShengYaShuiTou |
Text |
最大升压水头 |
逐字段对照详情¶
Br(1) — JiHuaRiQi(计划日期)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
逻辑 |
|
直接取 cert_data["plan_date"] |
默认值 |
|
|
类型 |
Date |
DateTime (String → DateTime) |
状态 |
⚠️ 有差异 — VBA 空值默认 1899-12-30,Python 默认空字符串。但实际使用中 |
Br(2) — DingHuoDanWei(订货单位)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
逻辑 |
|
|
默认值 |
|
|
状态 |
✅ 逻辑一致 — 都有空值保护。默认值不同但不影响铭牌系统读取。 |
Br(3) — XiangMuMingCheng(项目名称)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
逻辑 |
先判断 Arr_All 是否为空,再判断 Trim 长度 |
|
默认值 |
|
|
状态 |
✅ 逻辑一致 — 都有空值保护。 |
Br(4) — ChanPinMingCheng(产品名称)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
逻辑 |
|
|
默认值 |
|
|
状态 |
✅ 逻辑一致。 |
Br(5) — ChanPinXingHao(产品型号)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
逻辑 |
|
|
默认值 |
|
|
状态 |
✅ 逻辑一致。 |
Br(6) — DN(公称通径)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
逻辑 |
|
|
额外处理 |
去掉末尾 "MM";如果型号含 "LB" 则保留英制格式 |
无 |
默认值 |
|
|
状态 |
⚠️ 有差异 — VBA 有英制/公制判断(优先 B6,空则取 C6),Python 直接取值。VBA 会去掉末尾 "MM"。如果铭牌系统用 LB 制阀门,DN 格式可能不一致。 |
Br(7) — PN(公称压力)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
逻辑 |
|
|
额外处理 |
去掉末尾 "MPA";如果型号含 "LB" 则追加 "Lb" 后缀 |
无 |
默认值 |
|
|
状态 |
⚠️ 有差异 — 同 DN,VBA 有英制/公制判断和单位后缀清理。 |
Br(8) — ShiYongJieZhi(适用介质)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
逻辑 |
|
|
状态 |
✅ 逻辑一致。 |
Br(9) — ShiYongWenDu(适用温度)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
逻辑 |
|
|
默认值 |
|
|
状态 |
⚠️ 有差异 — VBA 会清理 |
Br(10) — ChuChangRiQiYear(出厂日期年)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
逻辑 |
|
直接取 cert_data |
默认值 |
|
|
状态 |
⚠️ 有差异 — VBA 默认 1900,Python 默认 0。且 VBA 从 Excel 日期字段取前4位,Python 依赖调用方传入。当前 |
Br(11) — ChuChangRiQiMonth(出厂日期月)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
逻辑 |
|
直接取 cert_data |
默认值 |
|
|
状态 |
⚠️ 有差异 — 同 Br(10)。当前 |
Br(12) — SN(出厂编号,短编码)¶
这是最关键的字段之一,VBA 逻辑复杂。
属性 |
VBA |
Python |
|---|---|---|
来源 |
Excel B13 或 B12 单元格(取决于编码模式) |
|
逻辑 |
见下方详细分析 |
见下方 |
VBA 逻辑(按 hgz_BianMaModel 分支):
Select Case A_Byte_hgzBianMaModel:
Case 5, 6: # 双编码模式
Select Case ar(2, 8): # 判断 B12/B13 哪个是 KKS、哪个是 SN
"B12单元格为KKS编码,B13单元格为产品编号":
SN = ar(13, 2) # B13
"B12单元格为产品编号,B13单元格为KKS编码":
SN = ar(12, 2) # B12
Case 4: # 正则编码模式
SN = ar(12, 2) # 取 B12
如果以 V 开头: SN = V + Right(编码, Len-5) # 去掉中间4位年月
Case Else: # 普通模式 (0,1,2,3)
SN = ar(12, 2) # 取 B12
如果以 V 开头: SN = V + Right(编码, Len-5) # 去掉中间4位年月
Python 逻辑 (_derive_sn_and_kks):
def _derive_sn_and_kks(full_code: str) -> tuple[str, str]:
if not full_code or not full_code.startswith("V"):
return full_code or "", full_code or ""
if len(full_code) > 5:
sn = full_code[0] + full_code[5:] # V + 去掉年月的部分
else:
sn = full_code
kks = full_code
return sn, kks
状态: ⚠️ 有差异 — 两处差异:
Python 不处理编码模式 5/6 的 KKS/SN 互换:当前始终将
certificate_no按固定规则(SN=短编码, KKS=长编码)处理,不会根据number_model(即hgz_BianMaModel)做分支。CertificateController.batch_print_certificates中 SN 和 KKS 都直接设为certificate_no,完全没有调用_derive_sn_and_kks。
Br(13) — KKS(KKS编码,完整编码)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
Excel B12 或 B13(取决于编码模式) |
|
逻辑 |
取原始值,最多12位: |
直接取 |
截断 |
最多 12 位 |
无截断 |
状态 |
⚠️ 有差异 — Python 不截断 KKS 到 12 位,也不处理编码模式 5/6 的互换。 |
Br(14) ~ Br(23) — 刻印标记(10个 Boolean)¶
字段 |
VBA 值 |
Python 值 |
状态 |
|---|---|---|---|
Br(14) Sign_XingHao |
|
默认 |
✅ 一致 |
Br(15) Sign_DN |
|
默认 |
✅ 一致 |
Br(16) Sign_PN |
|
默认 |
✅ 一致 |
Br(17) Sign_JieZhi |
|
默认 |
✅ 一致 |
Br(18) Sign_WenDu |
|
默认 |
✅ 一致 |
Br(19) Sign_Year |
|
默认 |
✅ 一致 |
Br(20) Sign_Month |
|
默认 |
✅ 一致 |
Br(21) Sign_SN |
|
默认 |
✅ 一致 |
Br(22) Sign_KKS |
|
默认 |
✅ 一致 |
Br(23) Sign_ALL |
|
默认 |
✅ 一致 |
结论: 全部一致。这些字段在打印时初始化为 False,由铭牌刻印系统后续更新。
Br(24) — hgz_ShuLiang(合格证数量)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
逻辑 |
|
默认值 1 |
默认值 |
|
|
状态 |
⚠️ 有差异 — VBA 默认 0,Python 默认 1。实际使用中此值应为正整数,差异不大。 |
Br(25) — hgz_YangShi(合格证版型)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
子程序参数 |
|
含义 |
1=全中文, 2=中英文, 3=全英文 |
|
状态 |
✅ 基本一致 — 都是整数,但 VBA 从调用方传入,Python 默认 0 且 batch_print 中硬编码 1。 |
Br(26) — hgz_PdfPic(合格证图片样式)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
子程序参数 |
|
状态 |
✅ 一致 — 默认 0。 |
Br(27) — hgz_BianMaModel(合格证编码模式)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
子程序参数 |
|
含义 |
0=普通, 4=正则, 5/6=双编码模式 |
|
状态 |
⚠️ 潜在差异 — 此字段影响 Br(12) SN 和 Br(13) KKS 的赋值逻辑(见上方)。当前 Python 硬编码 0,如果实际使用模式 5/6,SN/KKS 会不正确。 |
Br(28) — hgz_xlMuBanName(合格证模板名称)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
处理 |
将换行符 |
无 |
默认值 |
|
|
状态 |
⚠️ 有差异 — Python 不替换换行符为 |
Br(29) — hgz_PrintTime(合格证打印时间)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
状态 |
✅ 一致 — 都取当前时间。 |
Br(30) — PrinterName(合格证打印机名)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
映射表 |
0=默认, 1=Foxit PDF, 2=EPSON LQ-635KII, 3=网络打印机, 4=HP LaserJet M225, 5=Microsoft XPS, 6=DocuCom PDF, 7=HP LaserJet M225(销售) |
直接存打印机名称字符串 |
状态 |
⚠️ 有差异 — VBA 存整数代码,Python 存字符串。如果铭牌系统根据此字段值做逻辑判断,可能不兼容。 需要确认铭牌系统是否依赖此字段。 |
Br(31) — Sign_PrintTime(铭牌打印时间)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
未赋值(注释写"未使用") |
ORM 未显式赋值,默认为 None |
状态 |
✅ 一致 — 都是空值。 |
Br(32) — Sign_ModelFullName(铭牌路径)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
如果为空则填入 |
ORM 未显式赋值,默认为 None |
逻辑 |
|
无 |
状态 |
⚠️ 有差异 — VBA 有特殊逻辑:当铭牌路径为空时,先查询 SN 重复数,然后填入重复条目数统计。Python 直接为 None。这个重复条目数对铭牌系统可能有意义(标识同编号重复打印次数)。 |
Br(33) — Sign_PrintCount(铭牌标记条目数)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
状态 |
✅ 一致。 |
⚠️ Br(34) — 不存在¶
VBA 中 Br(34) 没有赋值,INSERT SQL 中从 Case 34 开始用 Br(i+2) 做偏移(第 2537-2544 行)。
Python 模型中也正确跳过了 Br(34),字段从 Br(35) 开始。
Br(35) — FaTiCaiZhi(阀体材质)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
子程序参数 |
|
默认值 |
|
|
状态 |
✅ 逻辑一致 — 都有空值保护。 |
Br(36) — FaGanCaiZhi(阀杆材质)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
子程序参数 |
|
默认值 |
|
|
状态 |
✅ 逻辑一致。 |
Br(37) — QiBiJianCaiZhi(启闭件材质)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
子程序参数 |
|
默认值 |
|
|
状态 |
✅ 逻辑一致。 |
Br(38) — JiShuYaoQiu(技术要求)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
默认值 |
|
|
状态 |
✅ 逻辑一致。 |
Br(39) — SheBeiWeiHao(设备位号)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
默认值 |
|
|
状态 |
✅ 逻辑一致。 |
Br(40) — ZiXiangMu(子项目)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
默认值 |
|
|
状态 |
✅ 逻辑一致。 |
Br(41) — SNFromXSB(销售产品编号)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
默认值 |
|
|
状态 |
✅ 逻辑一致。 |
Br(42) — ZhongLei(销售种类)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
默认值 |
|
|
状态 |
✅ 逻辑一致。 |
Br(43) — ZhongLiang(销售重量要求)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
默认值 |
|
|
状态 |
✅ 逻辑一致。 |
Br(44) — XuHao(销售序号标识)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
默认值 |
|
|
状态 |
✅ 逻辑一致。 |
Br(45) — YaoHuoDanHaoFromXSB(营销部要货单号)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
|
|
默认值 |
|
|
状态 |
✅ 逻辑一致。 |
Br(46) — Sign_FTCZ(阀体材质刻印标记)¶
属性 |
VBA |
Python |
|---|---|---|
值 |
|
默认 |
状态 |
✅ 一致。 |
Br(47) — Sign_FGCZ(阀杆材质刻印标记)¶
属性 |
VBA |
Python |
|---|---|---|
值 |
|
默认 |
状态 |
✅ 一致。 |
Br(48) — Sign_QBJCZ(启闭件材质刻印标记)¶
属性 |
VBA |
Python |
|---|---|---|
值 |
|
默认 |
状态 |
✅ 一致。 |
Br(49) — DcOrPlPrint(打印模式)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
子程序参数 |
|
逻辑 |
|
直接取,默认 |
类型 |
字符串 ("0"/"1") |
字符串 ("0"/"1") |
状态 |
✅ 一致 — 都是字符串类型。 |
Br(50) — MaxJinShuiTou(最大净水头)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
子程序参数 |
|
默认值 |
|
|
状态 |
✅ 逻辑一致。 |
Br(51) — MaxShengYaShuiTou(最大升压水头)¶
属性 |
VBA |
Python |
|---|---|---|
来源 |
子程序参数 |
|
默认值 |
|
|
状态 |
✅ 逻辑一致。 |
差异汇总¶
🔴 关键差异(影响铭牌系统读取)¶
# |
字段 |
差异描述 |
建议 |
|---|---|---|---|
1 |
Br(12) SN |
Python 不处理编码模式 5/6 的 KKS/SN 互换 |
在 |
2 |
Br(13) KKS |
VBA 最多截断 12 位,Python 不截断 |
增加 |
3 |
Br(30) PrinterName |
VBA 存整数代码,Python 存字符串 |
确认铭牌系统是否依赖此字段做判断 |
🟡 中等差异(可能影响特定场景)¶
# |
字段 |
差异描述 |
建议 |
|---|---|---|---|
4 |
Br(9) ShiYongWenDu |
VBA 清理 |
在写入前做符号清理 |
5 |
Br(10) ChuChangRiQiYear |
当前硬编码 0,未从 Certificate 解析 |
从 |
6 |
Br(11) ChuChangRiQiMonth |
当前硬编码 0,未从 Certificate 解析 |
同上 |
7 |
Br(32) Sign_ModelFullName |
VBA 填入重复条目数,Python 为空 |
如果铭牌系统需要此数据则需补实现 |
8 |
Br(27) hgz_BianMaModel |
硬编码 0,未反映实际编码模式 |
从 Certificate 获取实际编码模式 |
🟢 轻微差异(不影响铭牌系统)¶
# |
字段 |
差异描述 |
|---|---|---|
9 |
Br(1) JiHuaRiQi |
VBA 空值默认 1899-12-30 |
10 |
Br(6) DN |
VBA 有英制/公制判断和 "MM" 后缀清理 |
11 |
Br(7) PN |
VBA 有英制/公制判断和 "MPA"/"Lb" 后缀处理 |
12 |
Br(24) hgz_ShuLiang |
VBA 默认 0,Python 默认 1 |
13 |
Br(28) hgz_xlMuBanName |
VBA 替换换行符为 |
14 |
Br(2,3,4,5,8,35-45) |
VBA 空值默认用 |
CertificateController.batch_print_certificates 额外问题¶
src/certflow/controllers/certificate_controller.py 中第 232-240 行直接创建 PrintLog 对象,完全绕过了 CertificatePrintService.record_print_log,导致:
SN/KKS 未推导:
SN和KKS都直接设为cert.certificate_no(长编码),没有短编码/长编码分离缺少 51 个兼容字段的完整赋值:只设置了 5 个字段(certificate_id, SN, KKS, printer_name, hgz_ShuLiang, status, content_summary)
缺少打印时间:没有设置
hgz_PrintTime
建议:将此处的直接创建 PrintLog 改为调用 CertificatePrintService.record_print_log。
扩展字段说明¶
以下 4 个字段是 SignTb 中不存在的扩展字段,仅存在于 Python SQLite print_logs 表:
字段 |
类型 |
用途 |
|---|---|---|
|
Integer |
关联回 Certificate 批次表 |
|
String(20) |
打印成功/失败状态 (success/failed) |
|
Text |
失败原因 |
|
Text |
可读摘要 |
注意:VBA 中还有
Br(32)的特殊逻辑(存入重复条目数),这是铭牌系统判断同编号重复打印的依据。如果铭牌系统切换到 SQLiteprint_logs表,需确认是否还需要此逻辑。
第二部分:VBA xlsx 回填子程序对照(含业务背景说明)¶
业务背景¶
VBA 时代的数据流经过多年演变,各子程序的定位如下:
子程序 |
原始用途 |
现状 |
|---|---|---|
① 保存到"打印历史" |
打印日志,方便后期点击某条记录按格式重新排版 |
后来改用 Access SignTb 作为铭牌数据源,此表可以停止维护 |
② 保存到"数据库" |
记录每个单元格的值和格式(对齐/字体/字号等),用于后期还原模板格式 |
VBA 通过复制整个单元格实现;Python PySide6 打印不需要格式信息,只需记录值 |
③ 保存到 Access SignTb |
将打印信息写入 Access 数据库,作为铭牌刻印系统的数据源 |
铭牌系统读的是 32 位 Access 2010,Python 64 位无法直连,需导出或链表 |
④ 保存到"合格证清单" |
将打印后的参数回填到合格证主表 |
Python 体系用 SQLite Certificate + SalePlan 替代,字段映射待确认 |
VBA 子程序总览(按调用顺序)¶
每次打印后,VBA 按顺序调用以下 4 个子程序:
打印完成
├── 1. 保存合格证内容到打印历史工作表 (→ "打印历史" 工作表) [已可废弃]
├── 2. 将打印内容添加到数据库 (→ "数据库" 工作表) [只需值,无需格式]
├── 3. 将打印内容添加到Access数据库 (→ SignDB.mdb SignTb) [铭牌数据源]
└── 4. 保存数据到合格证清单 (→ "合格证_2026" 工作表) [待确认映射]
2.1 ① Sub 保存合格证内容到打印历史工作表¶
定位: N 台打印为一条记录,工作日志性质。
VBA 源位置: print.vb 第 2754-2859 行
Python 对应: CertificatePrintService.record_print_log → SQLite print_logs 表
结论: ✅ Python 已覆盖核心功能 — SQLite print_logs 表替代了 xlsx "打印历史"。如果后期 SQLite 数据量偏大,可拆分为多个库(一库一表)。
VBA "打印历史" 工作表列结构(22列):
列 |
VBA 字段 |
来源 |
Python SQLite 对应 |
|---|---|---|---|
A (1) |
序号 |
上一行行号 |
✅ |
B (2) |
合格证编号 |
|
✅ |
C-D (3-4) |
产品名称/型号 |
|
✅ |
E (5) |
公称通径 |
|
✅ |
F (6) |
公称压力 |
|
✅ |
G-L (7-12) |
温度/介质/标准号/工号/日期/编号 |
B7-B12 |
✅ 分散在 print_logs 兼容字段 |
M-N (13-14) |
通径补充/压力补充 |
C5/C6 |
❌ 未实现 |
O (15) |
编号区间 |
参数 |
❌ 未实现 |
P (16) |
打印时间 |
参数 |
✅ |
Q (17) |
工作簿路径 |
|
❌ 未实现(无意义) |
R (18) |
打印机名称+类别 |
|
⚠️ 仅存打印机名 |
S (19) |
模板名称 |
|
✅ |
T (20) |
打印数量 |
|
✅ |
U (21) |
KKS 编码 |
B12/B13 |
✅ |
V (22) |
本厂编号 |
B12/B13 |
✅ |
2.2 ② Sub 将打印内容添加到数据库(写入 xlsx "数据库" 工作表)¶
定位: VBA 通过复制整个单元格实现,不仅记录打印值,还记录对齐、字体、字号等格式信息。Python PySide6 窗体打印不需要格式信息,只需记录值即可。
VBA 源位置: print.vb 第 2561-2724 行
Python 对应: TemplateManager.writeback_to_xlsx → templates.xlsx「数据库」表
结论: ✅ 仅需存值,格式信息可省略。Python writeback_to_xlsx 已覆盖核心业务字段(产品名/型号/DN/PN/温度/介质/标准号/工号/日期/编号)。
不需要实现的部分(VBA 特有的格式信息,PySide6 场景下无意义):
行高/列宽/合并标记 → PySide6 用 templates.xlsx 模板,不需要还原格式
工作簿路径 → 无意义
KKS 备注 → 已通过 print_logs 记录
2.3 ④ Sub 保存数据到合格证清单¶
VBA 源位置: print.vb 第 2985-3125 行
目标工作表: 合格证_2026(或 合格证_2022)
Python 对应: 无 — 完全未实现
VBA 逻辑: 每次打印后将温度/介质/标准号/材质等回写到"合格证_2026"主表。
Python 体系现状: ⚠️ 待确认 — 需要先搞清楚两个问题:
销售计划表 → 合格证表的字段映射关系:合格证表哪些字段来自 SalePlan 导入?哪些需要打印后回填?哪些字段空着没用?
Certificate 表的结构:Certificate 已有
working_temp、working_medium、test_standard、product_spec、print_time等字段,如果这些字段在 Certificate 创建时已从模板写入,则可能不需要额外回填。
目前已知的字段映射(CertificatePrintService.create_certificates):
SalePlan 字段 |
Certificate 字段 |
备注 |
|---|---|---|
|
|
FK |
|
|
唯一键 |
|
|
冗余 |
|
|
冗余 |
|
|
产品编号 |
|
|
优先 cert_ 前缀 |
|
|
优先 cert_ 前缀 |
|
|
优先 cert_ 前缀 |
|
|
数量 |
|
|
计划日期 |
|
|
订货单位 |
|
|
项目名称 |
|
|
试压标准 |
Certificate 表中可能缺少的字段(VBA 需要但 Certificate 未定义):
阀体材质 (
FaTiCaiZhi)阀杆材质 (
FaGanCaiZhi)启闭件材质 (
QiBiJianCaiZhi)口径/规格补充
下一步: 需确认 SalePlan 导入时哪些字段被填充到 Certificate,哪些字段是空的需要打印后回填。
第四部分:VBA 交互式参数补充对照¶
4.1 参数来源梳理¶
关键澄清:
参数 |
来源 |
说明 |
|---|---|---|
|
模板匹配 |
筛选同型号模板后选择某个模板,得到工作温度值。不来自 SalePlan。 |
|
模板匹配 |
同上,来自模板选择。不来自 SalePlan。 |
|
模板匹配 或 SalePlan |
|
|
模板匹配 |
模板的 |
|
模板匹配 |
模板的 |
阀体/阀杆/启闭件材质 |
VBA InputBox |
VBA 弹出输入框让用户填写,Python 完全未实现 |
4.2 VBA 的 InputBox 交互汇总¶
VBA 在打印主流程 Sub 批量打印流水合格证 中有大量交互式参数补充,共约 40+ 处 InputBox,按场景分类:
场景 A:英制压力模式(型号含 LB 或 2500)¶
InputBox |
触发条件 |
提示文本 |
|---|---|---|
口径 |
始终弹出 |
|
英制压力 |
始终弹出 |
|
适用温度 |
始终弹出 |
|
VBA 英制判断逻辑(第 634 行):
If (UCase(.Cells(iR, 14 + OfSet)) Like "*LB*") Or (UCase(.Cells(iR, 14 + OfSet)) Like "*2500*") Then
型号包含 LB 或 2500 → 英制。VBA 还会从型号中提取 LB 等级(150/300/600/1500/2500)作为 InputBox 默认值。
场景 B:公制压力模式(手动)¶
InputBox |
触发条件 |
提示文本 |
|---|---|---|
口径 |
始终弹出 |
|
压力 |
始终弹出 |
|
适用温度 |
始终弹出 |
|
场景 C:公制压力模式(自动)¶
InputBox |
触发条件 |
提示文本 |
|---|---|---|
口径 |
口径为空时 |
|
压力 |
压力为空时 |
|
适用温度 |
始终弹出 |
|
场景 D:通用参数(所有模式)¶
InputBox |
提示文本 |
用途 |
|---|---|---|
适用介质 |
|
补充适用介质 |
检验工号 |
|
中英文模板补充检验工号 |
出厂年月 |
|
修正出厂日期 |
阀体材质 |
|
每次打印前弹出 |
阀杆材质 |
|
每次打印前弹出 |
启闭件材质 |
|
每次打印前弹出 |
场景 E:编码相关交互¶
InputBox |
触发条件 |
提示文本 |
|---|---|---|
编码前缀 |
军工模式 |
|
起始编号 |
军工/line1 模式 |
|
份数 |
军工/line1 模式 |
|
编号后缀 |
军工/line1 模式 |
|
产品名称 |
新型号时 |
|
场景 F:行号回退(数据未找到时)¶
InputBox |
提示文本 |
|---|---|
行号 |
|
4.3 VBA 英制/公制口径和压力的处理细节¶
在「数据库」工作表中¶
VBA 只是原样复制单元格(mk.Range("B5").Copy),不做转换:
B5 单元格 → 数据库第 5 列(公称通径 DN)
C5 单元格 → 数据库第 13 列(备用口径)
B6 单元格 → 数据库第 6 列(公称压力 PN)
C6 单元格 → 数据库第 14 列(备用压力)
B5/B6 存公制数据(DN mm / PN MPa),C5/C6 存英制数据(inch / LB 磅级数值)。
在 Access SignTb 中(写入时转换)¶
' DN 口径:B5 优先,空则用 C5
A_Str_DN = Trim(IIf(Len(Trim(ar(5,2))) = 0, ar(5,3), ar(5,2)))
' PN 压力:B6 优先,空则用 C6 + "Lb" 后缀
A_Str_PN = Trim(IIf(Len(Trim(ar(6,2))) = 0, Trim(ar(6,3)) & "Lb", ar(6,2)))
' 清理单位后缀
If UCase(Right(A_Str_DN, 2)) = "MM" Then A_Str_DN = Left(A_Str_DN, Len(A_Str_DN) - 2)
If UCase(Right(A_Str_PN, 3)) = "MPA" Then A_Str_PN = Left(A_Str_PN, Len(A_Str_PN) - 3)
' 英制型号:确保压力以 "Lb" 结尾
If UCase(A_Str_CPXH) Like "*LB*" Then A_Str_PN = IIf(Right(A_Str_PN, 2) = "Lb", A_Str_PN, A_Str_PN & "Lb")
4.4 Python 现状 vs VBA 交互差距¶
VBA 功能 |
Python 现状 |
差距 |
|---|---|---|
英制 LB 判断 ( |
无 |
不会判断英制型号 |
英制 LB 等级提取 (150/300/600/1500/2500) |
无 |
不能从型号中提取 LB 等级 |
DN 口径 B5/C5 回退逻辑 |
|
没有 C5 备用列 |
PN 压力 B6/C6 回退 + Lb 后缀 |
|
完全丢失 |
DN 后缀清理 (去 |
无 |
不去掉单位后缀 |
PN 后缀清理 (去 |
无 |
不去掉单位后缀 |
型号含 LB 时自动加 Lb 后缀 |
无 |
压力值可能缺少单位 |
适用温度 InputBox |
仅从模板取 |
新型号时无法补充 |
适用介质 InputBox |
仅从模板取 |
新型号时无法补充 |
检验工号 InputBox |
仅从模板取 |
始终为空 |
阀体/阀杆/启闭件材质 InputBox |
无 |
材质数据完全丢失 |
出厂年月修正 InputBox |
无 |
无法修正 |
产品名称修正 InputBox |
无 |
新型号无法修正 |
行号回退(数据未找到) |
无 |
匹配失败时无回退方案 |
4.5 需要新增的参数对照表¶
根据你的说明,Python 后期应该增加以下几类参数对照表:
对照表 |
内容 |
用途 |
|---|---|---|
型号-压力对照 |
型号 → 默认压力等级 (MPa / LB) |
新型号时自动推荐压力值,减少 InputBox |
口径-字符串对照 |
口径值 → 显示文本(如 DN100 → "100" 或 "4inch") |
英制/公制自动转换和显示 |
材质牌号-元素对照 |
材质牌号 → 化学成分元素值 |
自动填充阀体/阀杆/启闭件材质 |
型号-温度对照 |
型号 → 默认适用温度 |
新型号时自动推荐温度 |
型号-介质对照 |
型号 → 默认适用介质 |
新型号时自动推荐介质 |
注意:VBA 中的
确认口径()和确认压力()是两个自定义函数,定义在function.vb中。核心逻辑:
从
CanShuSheet的命名范围(口径替换数据表/型号压力转换表)查对照表找到匹配 → 返回对照值;未找到 → 弹出 InputBox + 自动记录到对照表
新值自动写入对照表,下次同型号就能直接命中
第五部分:yaml 配置化重构方案¶
5.1 设计思路¶
VBA 中的对照表(口径替换、型号-压力、型号-标准号)和交互逻辑,非常适合用 yaml 配置化实现。参照项目已有的 config.yaml + ui.yaml 模式,新增 parameters.yaml。
核心原则:
数据驱动:对照表数据存 yaml,不写死在 Python 代码中
自学习:用户通过界面补充的新值,自动追加到 yaml(类似 VBA 的 CanShuSheet 自动记录)
分层设计:配置层(对照表)+ 规则层(处理逻辑)+ UI 层(交互界面)
5.2 建议的 yaml 结构¶
# config/parameters.yaml
# ============================================================
# 打印参数配置 — 对照表 + 处理规则
# ============================================================
# ---- 英制判断规则 ----
imperial_rules:
# 判断型号是否为英制的关键字
keywords:
- "LB"
- "2500" # 2500 本身也是 LB 级别
# LB 等级提取(从型号字符串中匹配)
lb_levels:
- "150LB": 150
- "300LB": 300
- "600LB": 600
- "800LB": 800
- "900LB": 900
- "1500LB": 1500
- "2500LB": 2500
# LB → MPa 转换(可选)
lb_to_mpa:
150: 2.0
300: 5.0
600: 10.0
800: 13.0
900: 15.0
1500: 25.0
2500: 42.0
# ---- DN/PN 单位清理规则 ----
unit_cleanup:
dn:
# 从口径字符串中移除的后缀
strip_suffixes:
- "MM"
- "mm"
- "mm"
pn:
strip_suffixes:
- "MPA"
- "MPa"
- "mpa"
# ---- 口径替换对照表(VBA: 口径替换数据表)----
caliber_mapping:
# 原始口径字符串 → 替换后的值
# VBA CanShuSheet 命名范围 "口径替换数据表"
mappings:
"DN50": 50
"DN65": 65
"DN80": 80
"DN100": 100
"DN125": 125
"DN150": 150
"DN200": 200
"DN250": 250
"DN300": 300
"DN350": 350
"DN400": 400
"DN450": 450
"DN500": 500
"DN600": 600
"DN700": 700
"DN800": 800
"DN900": 900
"DN1000": 1000
"DN1200": 1200
# 英制口径(从型号中提取的英寸值)
'2"': 50
'2-1/2"': 65
'3"': 80
'4"': 100
'5"': 125
'6"': 150
'8"': 200
'10"': 250
'12"': 300
'14"': 350
'16"': 400
'18"': 450
'20"': 500
'24"': 600
'28"': 700
'32"': 800
'36"': 900
'40"': 1000
'48"': 1200
# 特殊值
special_values:
- "-----" # 表示不适用
- "/" # 表示无
# ---- 型号-压力对照表(VBA: 型号压力转换表)----
model_pressure_mapping:
# 型号字符串 → 压力值
# VBA CanShuSheet 命名范围 "型号压力转换表",列1=型号,列2=压力
mappings:
"D942X-10Q": "1.0MPa"
"HH47X-25C": "2.5MPa"
"VSSJA-2-10": "1.0MPa"
"VSSJA-2-25": "2.5MPa"
"Z41H-25C": "2.5MPa"
"Z941H-25C": "2.5MPa"
# ... 更多型号-压力对照
# 英制压力特殊处理
imperial_pressure_handling:
# "150Lb" → 数值 2.0 (MPa)
# "300Lb" → 数值 5.0 (MPa)
# "600Lb" → 数值 10.0 (MPa)
enabled: true
# ---- 型号-标准号对照表(VBA: 型号压力转换表 列3)----
model_standard_mapping:
# 型号 → 试压标准号
# VBA CanShuSheet 命名范围 "型号压力转换表",列1=型号,列3=标准号
mappings:
"Z41H-25C": "GB/T 13927-2008"
"Z941H-25C": "GB/T 13927-2008"
"D942X-10Q": "GB/T 13927-2008"
# ... 更多型号-标准对照
# ---- 材质对照表 ----
material_mapping:
# 阀体材质常见牌号
body:
- "WCB"
- "CF8"
- "CF8M"
- "CF3"
- "CF3M"
- "LCB"
- "WC6"
- "WC9"
- "HT200"
- "QT450-10"
# 阀杆材质
stem:
- "2Cr13"
- "304"
- "316"
- "17-4PH"
- "F53"
# 启闭件材质
disc:
- "2Cr13"
- "304"
- "316"
- "WCB+13Cr"
- "CF8+STL"
# ---- 自动回填到 yaml 的配置(自学习)----
auto_learning:
# 启用自动学习(用户补充的新值自动追加到对应映射表)
enabled: true
# 追加时是否去重
deduplicate: true
# 是否保留注释标记(标记为自动学习的条目)
add_comment: true
comment_marker: "# auto-learned"
5.3 与现有 yaml 的关系¶
config/
├── config.yaml ← 主配置(include 其他 yaml)
│ !include ui.yaml
│ !include parameters.yaml ← 新增
├── ui.yaml ← UI 布局/样式
├── parameters.yaml ← 新增:对照表 + 处理规则
├── columns.yaml ← 列映射
├── query_fields.yaml ← 查询字段
└── userconfig.yaml ← 用户本地配置
5.4 Python 侧改造点¶
改造项 |
现状 |
yaml 配置化后 |
|---|---|---|
英制判断 |
无 |
读 |
LB 等级提取 |
无 |
读 |
DN 后缀清理 |
无 |
读 |
PN 后缀清理 |
无 |
读 |
口径转换 |
无 |
读 |
型号→压力 |
无 |
读 |
型号→标准号 |
无 |
读 |
材质选择 |
无 |
读 |
Certificate.pn 字段 |
不存在 |
模型需新增 |
C5/C6 英制列写入 |
不写 |
从对照表解析后写入 templates.xlsx |
5.5 自学习机制¶
对标 VBA 的 CanShuSheet 自动记录行为:
用户打印新型号
→ 对照表查不到型号
→ PySide6 弹出参数补充对话框(替代 InputBox)
→ 用户填写口径/压力/标准号/材质
→ Python 自动追加到 parameters.yaml
→ 下次同型号直接命中,无需再次输入
5.6 实施优先级¶
优先级 |
配置项 |
原因 |
|---|---|---|
P0 |
|
解决 DN/PN 最紧迫的处理差距 |
P0 |
Certificate 模型加 |
当前 PN 完全丢失 |
P1 |
|
口径替换对照,减少交互 |
P1 |
|
型号→压力对照,减少交互 |
P2 |
|
自学习机制,积累数据 |
P2 |
|
型号→标准号对照 |
P3 |
|
材质下拉选项 |
第六部分:SQLite 配置表方案(综合 TODO)¶
6.1 为什么用 SQLite 代替 yaml 配置对照表?¶
第五部分的 yaml 方案适合小量静态配置(如英制规则、单位清理规则),但对于大量动态数据有明显缺陷:
维度 |
yaml 配置 |
SQLite 配置表 |
|---|---|---|
数据规模 |
适合几十条,上千条会臃肿 |
天然支持百万级 |
编辑方式 |
文本编辑器 / 程序追加 |
SQL 查询 + 未来可做 UI 编辑界面 |
查询效率 |
加载到内存遍历 |
SQL 索引查询,毫秒级 |
并发写入 |
需要文件锁 |
SQLite WAL 模式支持并发读 |
数据关系 |
扁平键值对 |
支持外键关联、多表 JOIN |
模板规模 |
❌ 几千条模板不适合 |
✅ 建表 + 索引,秒查 |
材质牌号-化学成分 |
❌ 多对多关系无法表达 |
✅ 标准的多对多关联表 |
结论: 采用混合方案:
yaml:英制规则、单位清理规则、LB 等级表(几十条)
SQLite:模板对照表、材质牌号对照表、化学成分表、口径映射表、自学习记录(几百~几千条)
6.2 新增 SQLite 配置表设计¶
以下 5 张新表均建在现有 certflow.db 中,利用现有的 DatabaseManager._migrate_missing_columns() 机制自动创建。
表 A: model_param_mappings — 型号参数对照表¶
对标 VBA CanShuSheet 的 "型号压力转换表" 命名范围。
CREATE TABLE model_param_mappings (
id INTEGER PRIMARY KEY AUTOINCREMENT,
product_model VARCHAR(200) NOT NULL, -- 产品型号(如 Z41H-25C)
pressure_value VARCHAR(50), -- 公称压力(如 2.5MPa / 150Lb)
test_standard VARCHAR(200), -- 试压标准号(如 GB/T 13927-2008)
working_temp VARCHAR(50), -- 工作温度(如 ≤425℃)
working_medium VARCHAR(100), -- 适用介质(如水、蒸汽)
source VARCHAR(20) DEFAULT 'manual', -- 来源: manual / auto-learned / import
usage_count INTEGER DEFAULT 0, -- 使用次数(热门度)
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 索引:型号精确查询
CREATE UNIQUE INDEX idx_mapping_model ON model_param_mappings(product_model);
数据来源:
从 VBA
CanShuSheet的 "型号压力转换表" 导出(几百条现有数据)从现有
templates.xlsx「数据库」表导入运行时自学习追加
表 B: caliber_mappings — 口径字符串映射表¶
对标 VBA CanShuSheet 的 "口径替换数据表" 命名范围。
CREATE TABLE caliber_mappings (
id INTEGER PRIMARY KEY AUTOINCREMENT,
raw_text VARCHAR(50) NOT NULL UNIQUE, -- 原始口径字符串(如 DN100 / 2" / 2-1/2")
caliber_value VARCHAR(20) NOT NULL, -- 标准化口径值(如 100 / 50 / 65)
is_imperial BOOLEAN DEFAULT FALSE, -- 是否英制口径
source VARCHAR(20) DEFAULT 'manual',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_caliber_raw ON caliber_mappings(raw_text);
表 C: material_grades + material_compositions — 材质牌号与化学成分对照表¶
这是用户特别关注的:材质牌号与化学成分的对应关系。现有系统完全没有这个数据。
-- 材质牌号主表
CREATE TABLE material_grades (
id INTEGER PRIMARY KEY AUTOINCREMENT,
grade_code VARCHAR(50) NOT NULL UNIQUE, -- 牌号(如 WCB / CF8 / 2Cr13 / 304)
grade_name VARCHAR(100), -- 中文名称(如 碳素钢铸件)
category VARCHAR(20) NOT NULL, -- 分类: body(阀体) / stem(阀杆) / disc(启闭件) / common(通用)
standard_ref VARCHAR(100), -- 参考标准(如 ASTM A216 / GB/T 12229)
is_active BOOLEAN DEFAULT TRUE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_grade_code ON material_grades(grade_code);
CREATE INDEX idx_grade_category ON material_grades(category);
-- 化学成分表(每个牌号对应多条元素记录)
CREATE TABLE material_compositions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
grade_code VARCHAR(50) NOT NULL, -- 关联 material_grades.grade_code
element VARCHAR(20) NOT NULL, -- 元素符号(如 C / Mn / Si / Cr / Ni / Mo)
min_value FLOAT, -- 最小值(%)
max_value FLOAT, -- 最大值(%)
is_single_value BOOLEAN DEFAULT FALSE, -- TRUE 表示单一值而非范围
display_order INTEGER DEFAULT 0, -- 显示排序
FOREIGN KEY (grade_code) REFERENCES material_grades(grade_code)
);
CREATE INDEX idx_comp_grade ON material_compositions(grade_code);
CREATE INDEX idx_comp_element ON material_compositions(element);
示例数据:
-- 牌号
INSERT INTO material_grades VALUES (1, 'WCB', '碳素钢铸件', 'body', 'ASTM A216', TRUE, NOW());
INSERT INTO material_grades VALUES (2, 'CF8', '304不锈钢铸件', 'body', 'ASTM A351', TRUE, NOW());
INSERT INTO material_grades VALUES (3, '2Cr13', '马氏体不锈钢', 'stem', 'GB/T 1220', TRUE, NOW());
-- 化学成分(WCB)
INSERT INTO material_compositions VALUES (1, 'WCB', 'C', 0.18, 0.25, FALSE, 1);
INSERT INTO material_compositions VALUES (2, 'WCB', 'Mn', 0.50, 0.80, FALSE, 2);
INSERT INTO material_compositions VALUES (3, 'WCB', 'Si', 0.30, 0.60, FALSE, 3);
INSERT INTO material_compositions VALUES (4, 'WCB', 'P', NULL, 0.04, FALSE, 4);
INSERT INTO material_compositions VALUES (5, 'WCB', 'S', NULL, 0.045, FALSE, 5);
用途:
打印时材质报告自动填充化学成分
用户选择阀体/阀杆材质时提供下拉选项
未来可在 UI 中编辑、新增、修改牌号和化学成分
表 D: param_auto_learn_log — 自学习记录表¶
对标 VBA CanShuSheet 的自动追加机制,但用结构化方式记录。
CREATE TABLE param_auto_learn_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
table_name VARCHAR(50) NOT NULL, -- 目标表: model_param_mappings / caliber_mappings
field_name VARCHAR(50) NOT NULL, -- 字段名: pressure_value / caliber_value
lookup_key VARCHAR(200) NOT NULL, -- 查询键(型号 / 口径字符串)
user_value VARCHAR(200) NOT NULL, -- 用户输入的值
certificate_no VARCHAR(50), -- 关联的合格证编号
learned_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_learn_table_key ON param_auto_learn_log(table_name, lookup_key);
用途: 追踪每次自学习的记录,便于审计和回滚。
6.3 SQLite 模型定义位置¶
src/certflow/models/
├── sale_plan.py ← 现有
├── certificate.py ← 现有
├── print_log.py ← 现有
├── auto_number.py ← 现有
├── report_template.py ← 现有
├── sale_plan_change.py ← 现有
├── model_param_mapping.py ← 新增:型号参数对照表
├── caliber_mapping.py ← 新增:口径映射表
├── material_grade.py ← 新增:材质牌号表
├── material_composition.py ← 新增:化学成分表
└── param_auto_learn_log.py ← 新增:自学习记录表
6.4 Python 服务层设计¶
# src/certflow/services/param_lookup_service.py
class ParamLookupService:
"""参数查找服务 — 对标 VBA 确认口径() / 确认压力() / 确认标准号()"""
def lookup_caliber(self, raw_text: str) -> str | None:
"""从 caliber_mappings 表查找口径值"""
...
def lookup_model_params(self, model: str) -> dict | None:
"""从 model_param_mappings 表查找型号的压力/标准号/温度/介质"""
...
def save_or_update_mapping(self, table, lookup_key, field, value):
"""自学习:保存用户补充的新值到对应表"""
...
def get_material_grades(self, category: str = None) -> list:
"""获取材质牌号列表(可按阀体/阀杆/启闭件分类)"""
...
def get_material_composition(self, grade_code: str) -> list:
"""获取指定牌号的化学成分"""
...
6.5 交互流程¶
对标 VBA 的 InputBox 交互,Python 使用 PySide6 对话框:
打印服务调用 ParamLookupService.lookup_model_params("Z41H-25C")
├─ 命中 → 直接返回 {pressure: "2.5MPa", standard: "GB/T 13927-2008", temp: "≤425℃"}
└─ 未命中 → 弹出参数补充对话框
├─ 预填: 型号 Z41H-25C, DN 从模板提取, 温度/介质从模板提取
├─ 用户补充: 公称压力 [2.5MPa ▼] 标准号 [GB/T 13927-2008 ▼]
│ 阀体材质 [WCB ▼] 阀杆材质 [2Cr13 ▼] 启闭件材质 [2Cr13 ▼]
│ (下拉选项从 material_grades 表读取)
├─ 确认 → 自动写入 model_param_mappings + param_auto_learn_log
└─ 下次同型号直接命中
6.6 与现有数据库的关系¶
certflow.db (现有 3.29 MB)
├── sale_plans ← 现有 (53 字段)
├── certificates ← 现有 (47 字段)
├── print_logs ← 现有 (54 字段)
├── auto_number_rules ← 现有
├── auto_number_counters ← 现有
├── report_templates ← 现有
├── sale_plan_changes ← 现有
├── model_param_mappings ← 🆕 新增 (型号参数对照)
├── caliber_mappings ← 🆕 新增 (口径映射)
├── material_grades ← 🆕 新增 (材质牌号)
├── material_compositions ← 🆕 新增 (化学成分)
└── param_auto_learn_log ← 🆕 新增 (自学习记录)
6.7 数据初始化策略¶
数据源 |
表 |
导入方式 |
预估条数 |
|---|---|---|---|
VBA |
|
从 xlsx 导出 CSV → SQLite INSERT |
~200-500 |
VBA |
|
从 xlsx 导出 CSV → SQLite INSERT |
~50-100 |
标准材质牌号数据库 |
|
编写 seed 脚本批量导入 |
~50-100 |
运行时自学习 |
|
用户操作自动追加 |
逐步增长 |
6.8 yaml vs SQLite 分工(最终方案)¶
config/
├── config.yaml ← 主配置
├── ui.yaml ← UI 布局/样式
├── imperial_rules.yaml ← 🆕 英制规则(几十条,不常变)
│ ├── lb_keywords: [LB, 2500]
│ ├── lb_levels: {150LB: 150, 300LB: 300, ...}
│ ├── lb_to_mpa: {150: 2.0, 300: 5.0, ...}
│ └── unit_cleanup: {dn: [MM], pn: [MPA, Lb]}
├── columns.yaml ← 列映射
├── query_fields.yaml ← 查询字段
└── userconfig.yaml ← 用户本地配置
certflow.db (SQLite)
├── model_param_mappings ← 型号参数对照(几百条,频繁查询/更新)
├── caliber_mappings ← 口径映射(几十条)
├── material_grades ← 材质牌号(几十条)
├── material_compositions ← 化学成分(几百条,多对多)
└── param_auto_learn_log ← 自学习记录(逐步增长)
6.9 未来 UI 编辑界面(展望)¶
SQLite 配置表的一个重要优势是可以通过 UI 界面编辑,而无需手动写 SQL:
┌─────────────────────────────────────────────────────┐
│ 系统设置 → 参数对照表管理 │
│ │
│ ┌─ 标签页 ───────────────────────────────────────┐ │
│ │ [型号参数] [口径映射] [材质牌号] [化学成分] │ │
│ ├────────────────────────────────────────────────┤ │
│ │ 型号 │ 压力 │ 标准号 │ 操作 │ │
│ │ Z41H-25C │ 2.5MPa │ GB/T 13927 │ 编辑 │ │
│ │ Z941H-25C │ 2.5MPa │ GB/T 13927 │ 编辑 │ │
│ │ D942X-10Q │ 1.0MPa │ GB/T 13927 │ 编辑 │ │
│ │ ... │ ... │ ... │ ... │ │
│ ├────────────────────────────────────────────────┤ │
│ │ [+ 新增] [导入 CSV] [导出 CSV] [批量删除] │ │
│ └────────────────────────────────────────────────┘ │
│ │
│ ┌─ 材质化学成分编辑弹窗 ──────────────────────────┐│
│ │ 牌号: WCB 分类: 阀体 标准: ASTM A216 ││
│ │ ││
│ │ 元素 最小值(%) 最大值(%) ││
│ │ C 0.18 0.25 [删除] ││
│ │ Mn 0.50 0.80 [删除] ││
│ │ Si 0.30 0.60 [删除] ││
│ │ P - 0.04 [删除] ││
│ │ S - 0.045 [删除] ││
│ │ [+ 添加元素] ││
│ │ ││
│ │ [保存] [取消] ││
│ └─────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────┘
6.10 实施 TODO 清单¶
# |
任务 |
优先级 |
依赖 |
预估工时 |
|---|---|---|---|---|
1 |
创建 5 个 SQLAlchemy 模型文件 |
P0 |
无 |
2h |
2 |
创建 |
P0 |
任务 1 |
4h |
3 |
从 VBA xlsx 导出并导入 |
P0 |
任务 1 |
2h |
4 |
从 VBA xlsx 导出并导入 |
P0 |
任务 1 |
1h |
5 |
编写材质牌号 seed 脚本(50+ 牌号 + 化学成分) |
P1 |
任务 1 |
4h |
6 |
Certificate 模型添加 |
P0 |
无 |
0.5h |
7 |
打印服务集成 |
P0 |
任务 2 |
4h |
8 |
PySide6 参数补充对话框(替代 VBA InputBox) |
P0 |
任务 2 |
6h |
9 |
实现自学习自动写入机制 |
P1 |
任务 2 |
3h |
10 |
|
P0 |
无 |
3h |
11 |
UI 参数对照表管理界面 |
P2 |
任务 1 |
8h |
12 |
材质报告自动填充化学成分 |
P2 |
任务 5 |
4h |
13 |
C5/C6 英制列回填到 xlsx「数据库」表 |
P2 |
任务 10 |
3h |
总预估: P0(核心)= 22h, P1 = 7h, P2 = 15h, 合计约 44 小时。
第三部分:整体 VBA → Python 迁移状态¶
VBA 完整打印流程¶
用户操作 → 查找活动的工作表并指定相关参数
↓
批量打印流水合格证 (主流程, ~1800 行)
↓ 每次打印后
┌────┼────┬──────────────────────┐
↓ ↓ ↓ ↓
GDI ①保存到 ②保存到"数据库" ③保存到 Access
打印 "打印历史" (xlsx 内部表) SignDB.mdb
↓ (铭牌刻印数据源)
④保存到"合格证_2026"清单
↓
取消筛选 + 静默保存工作簿
Python 当前迁移覆盖度¶
VBA 子程序 |
VBA 行号 |
Python 对应 |
覆盖度 |
|---|---|---|---|
查找活动工作表 |
77-94 |
— |
❌ 不需要(PySide6 UI 替代) |
批量打印流水合格证 |
309-2150 |
|
⚠️ 60% — GDI 打印 + 编号展开已实现 |
① 保存到"打印历史" |
2754-2859 |
|
✅ 可废弃 — SQLite print_logs 已替代 |
② 保存到"数据库" |
2561-2724 |
|
⚠️ 值不完整 — DN/PN 处理粗糙,缺 C5/C6 英制列 |
③ 保存到 Access SignTb |
2211-2559 |
|
⚠️ 85% — 字段兼容但铭牌系统仍读 Access |
④ 保存到合格证清单 |
2985-3125 |
无 |
❌ 0% — 需先确认字段映射 |
VBA 交互式参数补充 |
~40处 InputBox |
无 |
❌ 0% — 完全缺失,见第四部分 |
Access 导出方案(铭牌刻印数据源)¶
现状: 铭牌刻印系统目前读取的是 32 位 Access 2010 的 SignDB.mdb → SignTb 表。Python 64 位环境下 pyodbc 无法连接 32 位 Access ODBC 驱动。
两种可行方案:
方案 |
描述 |
优点 |
缺点 |
|---|---|---|---|
A. SQLite 导出到 Access |
打印后从 SQLite |
铭牌系统无需改动 |
需要 32 位 Access 引擎(可用独立 32 位 Python 进程或 Access COM 自动化) |
B. SQLite 链表到 Access |
在 Access 2010 中创建 ODBC 链接表指向 SQLite |
数据实时同步,无需导出 |
需要 SQLite ODBC 驱动 + Access 中配置链接表 |
当前代码状态:
export_to_access方法已标注为废弃(certificate_print_service.py第 244 行),内部尝试 pyodbc 但 64 位无法连接certflow export-accessCLI 命令存在但底层已废弃pyproject.toml中无 pyodbc 依赖(仅在 try-except 中延迟导入)
建议: 方案 B(链表)更优,避免每次打印后手动导出。需要安装 SQLite ODBC 驱动并在 Access 中配置。如果不可行,可用方案 A 通过 32 位 Python 子进程或 COM 自动化写入 .mdb。
未实现的关键功能¶
# |
功能 |
重要性 |
说明 |
|---|---|---|---|
1 |
交互式参数补充 |
🔴 高 |
VBA 有 ~40 处 InputBox,新型号/未知参数时让用户补充口径/压力/温度/介质/材质。Python 完全缺失。 |
2 |
PN 公称压力字段 |
🔴 高 |
Certificate 模型缺少 |
3 |
DN/PN 英制处理 |
🔴 高 |
没有 LB 判断、LB 等级提取、C5/C6 回退、单位后缀清理( |
4 |
Access 导出/链表 |
🔴 高 |
铭牌刻印系统依赖 Access SignTb,必须解决 64/32 位兼容问题。 |
5 |
材质字段 |
🟡 中 |
VBA InputBox 填写的阀体/阀杆/启闭件材质,Python 完全缺失。 |
6 |
SN/KKS 互换逻辑 |
🟡 中 |
编码模式 5/6 下 KKS/SN 位置互换,当前 Python 未处理。 |
7 |
参数对照表 |
🟡 中 |
VBA 的 |
8 |
PrinterName 整数代码 |
🟢 低 |
VBA 存整数代码(0-7),Python 存字符串,铭牌系统可能依赖。 |
9 |
编号区间记录 |
🟢 低 |
VBA 写入范围(如 V2506121-140),Python print_logs 存逐台 SN。 |
迁移优先级建议¶
P0 Certificate 模型修复: 添加
pn字段(公称压力),确保模板的 PN 值能写入 CertificateP0 DN/PN 处理: 实现 LB 英制判断、等级提取、C5/C6 回退、单位后缀清理逻辑
P0 交互式参数补充: 在 PySide6 打印对话框中增加参数确认/补充界面(口径/压力/温度/介质/材质)
P1 Access 数据源: 确定方案 A(导出)或 B(链表),确保铭牌系统能读到打印数据
P1 参数对照表: 建立型号-压力、口径-字符串、材质-元素对照表,减少手动输入
P2 SN/KKS 修复: 编码模式 5/6 下的互换逻辑 + KKS 12 位截断
P2 ② xlsx 回填完善: 写入 C5/C6 英制列到 templates.xlsx「数据库」表
P3 ④ 合格证清单回填: 如果确认 Certificate 表已完整记录所有字段,则可省略
文档版本¶
创建日期: 2026-06-06
最后更新: 2026-06-06(v7:P0 实施 — DNService + ParamSupplementDialog + 打印流程集成)
VBA 源版本:
data/print.vb(3235 行)Python 版本: v2.0 重构后
本次修改记录 (v7)¶
# |
文件 |
变更 |
|---|---|---|
1 |
|
🆕 新建 — 对标 VBA 确认口径() 的完整 DN 处理服务 |
2 |
|
🆕 新建 — 对标 VBA InputBox 的 PySide6 参数补充对话框 |
3 |
|
🆕 新建 — 口径映射表 SQLAlchemy 模型 |
4 |
|
集成 DNService + 参数补充流程 + |
5 |
|
|
6 |
|
导出 CaliberMapping |
7 |
|
导出 ParamSupplementDialog |
本次修改记录 (v6)¶
# |
文件 |
变更 |
|---|---|---|
1 |
|
添加 |
2 |
|
🆕 新建 — 对标 VBA 确认压力() 的完整 PN 处理服务 |
3 |
|
集成 PNService,6 处硬编码 |
4 |
|
🆕 新建 — 型号参数对照表模型 |
5 |
|
🆕 新建 — 自学习记录表模型 |
6 |
|
导出新模型 |
7 |
|
🆕 新建 — 英制规则配置 |
关键结论¶
VBA 子程序 |
处理策略 |
|---|---|
① 保存到"打印历史" |
✅ 可废弃 — SQLite print_logs 已替代 |
② 保存到"数据库" |
⚠️ 需完善 — DN/PN 处理粗糙,需补充 C5/C6 英制列 + 单位清理 |
③ 保存到 Access SignTb |
⚠️ 需解决 — 字段兼容(85%),但需导出/链表到 Access 供铭牌系统读取 |
④ 保存到合格证清单 |
❌ 待确认 — 如果 Certificate 表完整记录了打印参数,可能不需要额外回填 |
VBA InputBox 交互 |
❌ 完全缺失 — ~40 处交互式参数补充在 Python 中完全未实现 |
VBA CanShuSheet 参数表 |
🆕 SQLite 化 — 用 5 张配置表替代 Excel 命名范围,支持 UI 编辑 |
配置方案最终选型¶
数据类型 |
存储方式 |
原因 |
|---|---|---|
英制规则 / 单位清理 |
yaml ( |
少量静态规则,几十条 |
型号-压力-标准对照 |
SQLite ( |
几百条,频繁查询/更新 |
口径字符串映射 |
SQLite ( |
几十条,自学习增长 |
材质牌号 + 化学成分 |
SQLite ( |
多对多关系,需 UI 编辑 |
核心数据流(已确认)¶
SalePlan 导入
├─ product_name / product_model / product_spec → Certificate
├─ customer / project_name / test_standard → Certificate
└─ quantity / plan_date / production_order_no → Certificate
模板匹配 (templates.xlsx「数据库」表)
├─ dn → Certificate.product_spec (覆盖)
├─ pn → Certificate.pn (❌ 丢失!Certificate 无 pn 字段)
├─ temperature → Certificate.working_temp (✅)
├─ medium → Certificate.working_medium (✅)
├─ check_standard → Certificate.test_standard (可能覆盖 SalePlan 值)
├─ inspector_id → Certificate.inspector_id (❌ 丢失!Certificate 无此字段)
└─ manufacture_date → Certificate.issue_date (✅)
打印后写入 SQLite print_logs
├─ 51 个兼容字段(对应 Access SignTb)
├─ DN/PN 未做英制处理(LB 判断/单位清理缺失)
└─ 阀体/阀杆/启闭件材质未写入(VBA 靠 InputBox 填写)