最近更新于 2025-03-24 22:30
前言
官方文档指定的开发方式是 BASIC,实际用什么语言可以自己选择。最终开发都是连接 PC-DMIS 的 COM 组件 INTEROP.PCDLRN.DLL,选择 Python 开发比较便利(三方库丰富,我也比较熟悉,而且相比于 C/C++ 等需要编译,Python 解释执行,用来写小工具非常适合)。
PC-DMIS 自带的 BASIC 编辑器非常难用,没有现代 IDE 的样子,我感觉甚至不如 Windows 的记事本。如果使用第三方 IDE 软件开发的话,我也不用 BASIC 了,我这里就选择了 Python。官方文档给的 BASIC 大概看一下还是知道在干嘛,毕竟关键字就那些,编程的操作逻辑都差不多,先用 Python 复现官方给的 BASIC 示例代码进行学习,后续查 API 文档就 OK 了。
另外想吐槽一下,PC-DMIS 本身的各种快捷键也独树一帜,只是不得不用,只能适应一下(虽然可以改,但是不用自己电脑的时候还是会不顺手,最好还是适应软件默认的)。如果搞过开发的,基本都熟悉调试运行用F5
(各种 IDE 默认都是这样),但 PC-DMIS 程序运行不是。更扯的是,撤销和反撤销也和 Windows 默认及各种软件不一致。
还有测量程序编辑部分和语言相关,我软件语言选择中文,编程也只能使用中文关键字。这就导致要频繁的中英文切换,经常要看语言状态栏确认当前语言,效率非常低下。既然要把关键字和语言关联,不如内部实现一个“输入法”,像搞中文编程的易语言,比如要输入“如果”,输入拼音首字母 rg 就可以候选出来,而不是要切换输入法再去输入。
这些都是其中一角,能吐槽的有一堆了。各种反直觉的设计,不知道是历史遗留,还是就喜欢标新立异?
软件版本
PC-DMIS CAD++ 2019 R2
PC-DMIS 对象库文档
2019 R2:
https://docs.hexagonmi.com/pcdmis/2019.2/en/helpcenter/mergedProjects/automationobjects/webframe.html#Introduction.html
2020 R2:
https://docs.hexagonmi.com/pcdmis/2020.2/en/helpcenter/mergedProjects/automationobjects/webframe.html
2021.1:
https://docs.hexagonmi.com/pcdmis/2021.1/en/helpcenter/mergedProjects/automationobjects/webframe.html
2022.2:
https://docs.hexagonmi.com/pcdmis/2022.2/en/helpcenter/mergedprojects/automationobjects/webframe.html#Introduction.html
2023.2:
https://docs.hexagonmi.com/pcdmis/2022.2/en/helpcenter/mergedprojects/automationobjects/webframe.html#Introduction.html
连接 PC-DMIS
我这里的开发环境:
- Python 3.13.1
- pywin32 308(Python 模块)
pip install pywin32==308
一个简单的示例代码,获取 PC-DMIS 版本
import win32com.client as wc
app = wc.Dispatch('PCDLRN.Application') # 创建 COM 对象实例
print(app.VersionString)
以管理员身份运行终端,再手动执行 Python 命令执行,或者使用 IDE 的话,以管理员身份运行 IDE,再执行代码。总之一定要以管理员身份运行代码,否者代码执行后可能一直阻塞,不会继续往下执行(必须保证和运行 PC-DMIS 的权限一致,PC-DMIS 因为一些操作需要,建议就是以管理员身份运行)。
如果上面代码运行报错,类似
发生异常: com_error
(-2147221005, '无效的类字符串', None, None)
pywintypes.com_error: (-2147221005, '无效的类字符串', None, None)
During handling of the above exception, another exception occurred:
File "I:\work\development\PC-DMIS\test1.py", line 3, in <module>
app = win32.Dispatch('PCDLRN.Application')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pywintypes.com_error: (-2147221005, '无效的类字符串', None, None)
一个可能的问题方向是 PC-DMIS 软件安装的问题,我用的 2019 R2 破解版没问题,但是用的 2023.2 破解版就有问题。试一下打开注册表,按 Ctrl
+F
搜索PCDLRN.Application,正常是可以查到存在这个值,如果查不到这个值,就可能出现上面的错误,说明 INTEROP.PCDLRN.DLL 没有正常注册到系统。
自动请求管理员身份执行方案
参考:https://blog.iyatt.com/?p=18238
如果是把程序添加到 PC-DMIS 的外部命令执行倒没什么问题,由 PC-DMIS 来执行我们自己写的外部程序,权限都是一致的。
如果是作为独立工具直接执行的,PC-DMIS 是管理员身份执行,但是我们写的工具默认没有管理员执行,就会一直阻塞,在不知情的用户看来,就会以为我们的程序有问题。直接在程序上检查是否有管理员权限,没有就自动请求了,也不需要用户来关心要不要管理员身份运行。
使用 COM 组件中的常量
方式一(打包可执行文件建议)
如果需要打包成可执行文件拷贝到别的电脑上执行就建议这种方式,方式二是动态加载,换电脑执行没有找到导出的文件就会报错,需要同样执行这里的操作。
PC-DMIS 的 COM 组件中定义了一些枚举(常量),在开发中经常会用到,直接用枚举的值的话,代码可读性很差,这里就用 pywin32 的模块导出这些常量到文件,再放置到开发目录下。
查看 pywin32 安装路径
pip show pywin32
根据查到的路径拼接上 \win32com\client\makepy.py 就是要用到的模块路径
然后 PC-DMIS 的类型定义文件位于软件安装目录下的 Pcdlrn.tlb 文件中
执行代码导出
python 【makepy.py路径】 -d 【Pcdlrn.tlb文件路径】
可以看到提示 “Generating to C:\Users\pc01\AppData\Local\Temp\gen_py\3.13\10C96EB9-ED97-492D-BC67-700C7F18E394x0x14x2__init__.py”,这就是生成文件的路径,这里就把 10C96EB9-ED97-492D-BC67-700C7F18E394x0x14x2 文件夹复制到项目目录下,改名为 pcdlrnconst(可以自己取名,导入包的时候名字跟随就行)
后面就可以通过这个模块访问常量
from pcdlrnconst import constants as pdconst
from win32com.client import constants as wcc
print('通过 win32com 访问,没有语法提示')
print(wcc.SET_COMMENT)
print(wcc.COMMENT_TYPE)
print(wcc.COMMENT_FIELD)
print('直接访问')
print(pdconst.SET_COMMENT)
print(pdconst.COMMENT_TYPE)
print(pdconst.COMMENT_FIELD)
方式二(代码通用)
方式一导出文件是手动移动到指定目录下使用,这种方式是导出文件后就不移动了,继续用 win32com 的机制,让它去动态加载,好在代码本身通用,坏在打包执行文件移动到没有导出文件的电脑上就找不到文件会报错,需要将导出文件一起复制过去,或者重新执行下面的操作。
# 导出
python [makepy.py路径] -d [tlb文件路径]
# 使用提示
python [makepy.py路径] -i [tlb文件路径]
会给你一段代码实现导入操作
from win32com.client import gencache
gencache.EnsureModule('{10C96EB9-ED97-492D-BC67-700C7F18E394}', 0, 14, 2)
下面提供一段示例
import win32com.client.gencache as wcg
from win32com.client import constants as wcc
wcg.EnsureModule('{10C96EB9-ED97-492D-BC67-700C7F18E394}', 0, 14, 2)
print(wcc.SET_COMMENT)
print(wcc.COMMENT_TYPE)
print(wcc.COMMENT_FIELD)
官方示例代码 Python 复现
示例 1
官方的示例是在 PC-DMIS 端让用户输入一个数,用一个变量存储这个数,接着执行 BASIC 去修改 PC-DMIS 中的这个变量,在 PC-DMIS 中查看这个结果。
下面是我复现的实现
PC-DMIS
C1 =注释/输入,否,全屏=否,
请输入一个整数
赋值/V1=INT(C1.INPUT)
注释/操作者,否,全屏=否,自动继续=否,
"用户输入值为:" + V1
注释/操作者,否,全屏=否,自动继续=否,
请执行 Python 代码后点确定
注释/操作者,否,全屏=否,自动继续=否,
"Python 修改后值为:" + V1
Python
import win32com.client as wc
app = wc.Dispatch('PCDLRN.Application')
part = app.ActivePartProgram # 获取当前 PC-DMIS 中激活状态的程序引用
v1obj = part.GetVariableValue('V1') # 获取 PC-DMIS 中变量 V1 对象
if v1obj.LongValue: # 如果成功获取 V1 变量
v1obj.LongValue += 1
part.SetVariableValue('V1', v1obj) # 将修改后的对象设置给 PC-DMIS 中的 V1 变量
print(f'自增后值为{v1obj.LongValue},请查看 PC-DMIS 端修改结果')
else:
print('V1 未定义')
运行 PC-DMIS 测量程序,输入一个整数
显示用户输入的值
弹框提醒的时候,去执行 Python 代码
Python 执行结束,显示修改后的值
回到 PC-DMIS 可以看到变量成功被修改
示例 2
用 Python 复现通过代码直接向 PC-DMIS 添加注释命令
Python
from pcdlrnconst import constants as pdconst
from win32com.client import constants as wcc
import win32com.client as wc
app = wc.Dispatch('PCDLRN.Application')
part = app.ActivePartProgram
cmds = part.Commands
noteContent = input('请输入要添加的注释内容:')
cmd = cmds.Add(pdconst.SET_COMMENT, True) # 添加命令
cmd.PutText('操作者', pdconst.COMMENT_TYPE, 0) # 设置注释类型
cmd.PutText(noteContent, pdconst.COMMENT_FIELD, 1) # 添加注释内容
cmd.ReDraw # 刷新
初始命令状态
执行 Python 代码
Python 代码执行后,添加上了注释命令
示例 3(暂停)
这个示例代码使用 BASIC 重新实现了添加注释命令的窗口
下面我使用 Python 复现
读写数据
获取特征
Python
from pcdlrnconst import constants as pdconst
import win32com.client as wc
from win32com.client import constants as wcc
app = wc.Dispatch('PCDLRN.Application')
part = app.ActivePartProgram
cmds = part.Commands
# 遍历当前 PC-DMIS 程序中的命令
for i in range(1, cmds.count):
# 判断当前命令是否为特征
if cmds[i].IsFeature:
# 用于存储特征坐标
x, y, z = 0, 0, 0
# 创建引用变量
xRef = wc.VARIANT(wc.pythoncom.VT_BYREF | wc.pythoncom.VT_R8, x)
yRef = wc.VARIANT(wc.pythoncom.VT_BYREF | wc.pythoncom.VT_R8, y)
zRef = wc.VARIANT(wc.pythoncom.VT_BYREF | wc.pythoncom.VT_R8, z)
print(f"命令 {i:<2} - 特征 {cmds[i]}")
cmds[i].FeatureCommand.GetPoint(pdconst.FPOINT_CENTROID, pdconst.FDATA_THEO, xRef, yRef, zRef)
print(f'\t理论值 X: {xRef.value}, Y: {yRef.value}, Z: {zRef.value}')
cmds[i].FeatureCommand.GetPoint(pdconst.FPOINT_CENTROID, pdconst.FDATA_MEAS, xRef, yRef, zRef)
print(f'\t实际值 X: {xRef.value}, Y: {yRef.value}, Z: {zRef.value}')
cmds[i].FeatureCommand.GetPoint(pdconst.FPOINT_CENTROID, pdconst.FDATA_TARG, xRef, yRef, zRef)
print(f'\t目标值 X: {xRef.value}, Y: {yRef.value}, Z: {zRef.value}')
读取尺寸
分析数据组织结构
先一个简单的,读取所有尺寸命令
from pcdlrnconst import constants as pdconst
import win32com.client as wc
app = wc.Dispatch('PCDLRN.Application')
part = app.ActivePartProgram
cmds = part.Commands
for i in range(cmds.count):
cmd = cmds[i]
if cmd.IsDimension:
dim = cmd.DimensionCommand
# 通过 DimensionCommand 对象属性读取
print(f'命令号:{i} 命令名:{dim.ID} 特征:{dim.Feat1} {dim.Feat2} {dim.Feat3} 单位:{dim.Units} 轴:{dim.AxisLetter} ' \
f'标称值:{dim.NOMINAL} 上公差:{dim.Plus} 下公差:{dim.Minus} 实测值:{dim.Measured} 偏差值:{dim.Deviation} 超差值:{dim.OutTol} 补偿值:{dim.Bonus}')
# 部分可以直接从命令读取
# 从命令读取单位可以直接得到字符串,从对象属性读取的是枚举值,1 为毫米,0 为英寸
# 另外使用 GetFieldValue 读取失败的值会返回 False,而如果从对象属性读取会得到 0(无法区分实际值为 0 还是失败了)
print(f'\t单位:{cmd.GetFieldValue(pdconst.UNIT_TYPE, 0)} 轴:{cmd.GetFieldValue(pdconst.AXIS, 0)} 标称值:{cmd.GetFieldValue(pdconst.NOMINAL, 0)} '\
f'上公差:{cmd.GetFieldValue(pdconst.F_PLUS_TOL, 0)} 下公差:{cmd.GetFieldValue(pdconst.F_MINUS_TOL, 0)} 实测值:{cmd.GetFieldValue(pdconst.DIM_MEASURED, 0)} '\
f'偏差值:{cmd.GetFieldValue(pdconst.DIM_DEVIATION, 0)} 超差值:{cmd.GetFieldValue(pdconst.DIM_OUTTOL, 0)} 补偿值:{cmd.GetFieldValue(pdconst.DIM_BONUS, 0)}')
print('-' * 200)
-
可以发现命令名为字母的,使用 GetFieldValue 读取全部是失败,这种命令就是基准,可以跳过这种值
-
下面两条是形位公差,但是又属于尺寸命令,可以发现公差、实测值等读取失败,那么这样就可以排除形位公差
-
可以发现“位置”这种命令是成对的,比如下面 256 和 257 一对,259 和 260 一对,一对命令最终在测量报告上只呈现一项。这对命令是相邻的,其中第一条命令的轴读取会失败,而第二条的命令的命令名为空,就可以用这种特点把它们组织在一起
公差下限符号问题
2024.2.7
最开始我都没发现这个问题,这几天写 PC-DMIS 数据导出工具,主体都写好了,今天测试验证才发觉 PC-DMIS 的公差下限不对劲。PC-DMIS 的默认设置下公差下限看着是正公差,实际内部是当作负公差的,要表示实际意义上的正公差,需要在前面添加一个负号,这个符号和内部默认的负号抵消才是正数,意义上是正公差,只是显示为负公差(挺反直觉的)。
要设置成负公差显示负号参考:https://blog.iyatt.com/?p=18778
这样设置以后,看到的公差下限是负数,实际意义表示的也是负数,和平时的使用习惯就一致了。
只是我们做开发就要注意,PC-DMIS 内部储存的数据中公差下限还是:正数表示负公差,负数表示正公差。最开始我就是因为这个现象意识到问题,我自己安装的 2019 R2、2023.2 都是默认状态,导出的数据和报告显示的是一致的,只是超差判定感觉不对劲,看着明明是超差的判定却是合格的。我把数据导出工具放到公司的三坐标电脑上使用,就发现导出的数据和报告上显示的公差下限不一致了,也验证了我的猜测,应该是有个什么设置控制显示,然后才发现设置里可以控制。
因此在做开发的时候,要知道内部存储数据的公差下限要取相反数才是意义上要表示的。
重新整理数据
从上面发现的规律,就可以这样处理:
基准和形位公差的实测值都会读取失败,那么就判断实测值读取失败的就忽略。对于位置命令,在前面的基础上,如果发现读取轴失败,下一条的命令名又为空,那么就读取这一对命令。
新的代码如下:
from pcdlrnconst import constants as pdconst
import win32com.client as wc
app = wc.Dispatch('PCDLRN.Application')
part = app.ActivePartProgram
cmds = part.Commands
datas = []
i = 0
data = {'命令号': None, '命令名': None, '特征': None, '单位': None, '轴': None, '标称值': None, '上公差': None, '下公差': None, '实测值': None, '偏差值': None, '超差值': None, '补偿值': None}
while i < cmds.Count:
cmd = cmds[i]
if cmd.IsDimension:
dim = cmd.DimensionCommand
measured = cmd.GetFieldValue(pdconst.DIM_MEASURED, 0)
if measured != False: # 排除形位公差和基准
data['命令号'] = i
data['命令名'] = dim.ID
data['特征'] = dim.Feat1 + ' ' + dim.Feat2 + ' ' + dim.Feat3
data['单位'] = cmd.GetFieldValue(pdconst.UNIT_TYPE, 0)
if cmd.GetFieldValue(pdconst.AXIS, 0) == False and cmds[i + 1].ID == '': # 这是一个位置命令,继续下一条命令
i += 1
cmd = cmds[i]
dim = cmd.DimensionCommand
data['轴'] = dim.AxisLetter
data['标称值'] = dim.NOMINAL
data['上公差'] = dim.Plus
# 注意公差下限要取相反数
data['下公差'] = -dim.Minus
data['实测值'] = dim.Measured
data['偏差值'] = dim.Deviation
data['超差值'] = dim.OutTol
data['补偿值'] = dim.Bonus
datas.append(data.copy())
i += 1
for data in datas:
print(data)
读取形位公差
Python
from pcdlrnconst import constants as pdconst
import win32com.client as wc
app = wc.Dispatch('PCDLRN.Application')
part = app.ActivePartProgram
cmds = part.Commands
datas = []
data = {'命令号': None, '命令名': None, '子命令号': None, '子命令': None, '特征': None, '单位': None, '形位公差类型': None, '形位公差': None, '跳动类型': None, '轴': None, '标称值': None, '上公差': None, '下公差': None, '实测值': None, '偏差值': None, '超差值': None, '补偿值': None}
for i in range(cmds.Count):
cmd = cmds[i]
if cmd.IsFcfCommand:
data['命令号'] = i
data['命令名'] = cmd.ID
data['单位'] = cmd.GetFieldValue(pdconst.UNIT_TYPE, 0)
# 形位公差评价对象自身的尺寸信息
for j in range(1, cmd.GetDataTypeCount(pdconst.LINE1_MEAS) + 1):
data['形位公差类型'] = None
data['形位公差'] = None
data['跳动类型'] = None
data['子命令号'] = j
data['子命令'] = cmd.GetFieldValue(pdconst.LINE1_TBLHDR, j)
data['特征'] = cmd.GetFieldValue(pdconst.LINE1_FEATNAME, j)
data['轴'] = None
data['标称值'] = cmd.GetFieldValue(pdconst.LINE1_NOMINAL, j)
data['上公差'] = cmd.GetFieldValue(pdconst.LINE1_PLUSTOL, j)
# 注意下公差要取相反数,后面一样
data['下公差'] = -cmd.GetFieldValue(pdconst.LINE1_MINUSTOL, j)
data['实测值'] = cmd.GetFieldValue(pdconst.LINE1_MEAS, j)
data['偏差值'] = cmd.GetFieldValue(pdconst.LINE1_DEV, j)
data['超差值'] = cmd.GetFieldValue(pdconst.LINE1_OUTTOL, j)
data['补偿值'] = cmd.GetFieldValue(pdconst.LINE1_BONUS, j)
datas.append(data.copy())
# 形位公差
for j in range(1, cmd.GetDataTypeCount(pdconst.LINE2_MEAS) + 1):
data['形位公差类型'] = cmd.GetFieldValue(pdconst.GDT_SYMBOL, 0)
data['形位公差'] = cmd.GetFieldValue(pdconst.LINE2_TOL, 0)
data['跳动类型'] = cmd.GetFieldValue(pdconst.FCF_RUNOUT_TYPE, 0)
data['子命令号'] = j
data['子命令'] = cmd.GetFieldValue(pdconst.LINE2_TBLHDR, j)
data['特征'] = cmd.GetFieldValue(pdconst.LINE2_FEATNAME, j)
data['轴'] = cmd.GetFieldValue(pdconst.LINE2_AXIS, j)
data['标称值'] = cmd.GetFieldValue(pdconst.LINE2_NOMINAL, j)
data['上公差'] = cmd.GetFieldValue(pdconst.LINE2_PLUSTOL, j)
data['下公差'] = -cmd.GetFieldValue(pdconst.LINE2_MINUSTOL, j)
data['实测值'] = cmd.GetFieldValue(pdconst.LINE2_MEAS, j)
data['偏差值'] = cmd.GetFieldValue(pdconst.LINE2_DEV, j)
data['超差值'] = cmd.GetFieldValue(pdconst.LINE2_OUTTOL, j)
data['补偿值'] = cmd.GetFieldValue(pdconst.LINE2_BONUS, j)
datas.append(data.copy())
for j in range(1, cmd.GetDataTypeCount(pdconst.LINE3_MEAS) + 1):
data['形位公差类型'] = None
data['形位公差'] = cmd.GetFieldValue(pdconst.LINE3_TOL, 0)
data['跳动类型'] = None
data['子命令号'] = j
data['子命令'] = cmd.GetFieldValue(pdconst.LINE3_TBLHDR, j)
data['特征'] = cmd.GetFieldValue(pdconst.LINE3_FEATNAME, j)
data['轴'] = None
data['标称值'] = cmd.GetFieldValue(pdconst.LINE3_NOMINAL, j)
data['上公差'] = cmd.GetFieldValue(pdconst.LINE3_PLUSTOL, j)
data['下公差'] = -cmd.GetFieldValue(pdconst.LINE3_MINUSTOL, j)
data['实测值'] = cmd.GetFieldValue(pdconst.LINE3_MEAS, j)
data['偏差值'] = cmd.GetFieldValue(pdconst.LINE3_DEV, j)
data['超差值'] = cmd.GetFieldValue(pdconst.LINE3_OUTTOL, j)
data['补偿值'] = cmd.GetFieldValue(pdconst.LINE3_BONUS, j)
datas.append(data.copy())
for data in datas:
print(data)
修改评价尺寸
Python
from pcdlrnconst import constants as pdconst
import win32com.client as wc
from win32com.client import constants as wcc
app = wc.Dispatch('PCDLRN.Application')
part = app.ActivePartProgram
cmds = part.Commands
# 精度
precision = 4
axisLetterWidth = 8
nominalWidth = 8
plusWidth = 8
minusWidth = 8
measuredWidth = 8
deviationWidth = 8
outTolWidth = 8
axisLetterString = '测量类型'
nominalString = '标称值'
plusString = '上偏差'
minusString = '下偏差'
measuredString = '测量值'
deviationString = '偏差值'
outTolString = '超差值'
# 遍历当前 PC-DMIS 程序中的命令
for i in range(1, cmds.count):
cmd = cmds[i]
# 判断当前命令是否为评价尺寸
if cmd.IsDimension:
dim = cmd.DimensionCommand
# 单位
units = cmd.GetFieldValue(pdconst.UNIT_TYPE, 0)
# 特征
feat1 = dim.Feat1
feat2 = dim.Feat2
feat3 = dim.Feat3
# 测量类型(D 直径,M 距离)
axisLetter = cmd.GetFieldValue(pdconst.AXIS, 0)
if axisLetter != False:
axisLetter = str(axisLetter)
else:
axisLetter = ''
# 标称值
nominal = cmd.GetFieldValue(pdconst.NOMINAL, 0)
nominal = float(nominal)
nominal = round(nominal, precision)
# 上偏差
plus = cmd.GetFieldValue(pdconst.F_PLUS_TOL, 0)
plus = float(plus)
plus = round(plus, precision)
if plus > 0:
plus = f'+{plus}'
# 下偏差
minus = cmd.GetFieldValue(pdconst.F_MINUS_TOL, 0)
minus = float(minus)
minus = round(minus, precision)
if minus > 0:
minus = f'+{minus}'
# 实际值
measured = cmd.GetFieldValue(pdconst.DIM_MEASURED, 0)
measured = float(measured)
measured = round(measured, precision)
# 偏差值
deviation = cmd.GetFieldValue(pdconst.DIM_DEVIATION, 0)
deviation = float(deviation)
deviation = round(deviation, precision)
# 超差值
outTol = cmd.GetFieldValue(pdconst.DIM_OUTTOL, 0)
outTol = float(outTol)
outTol = round(outTol, precision)
if len(cmd.ID) != 0 and cmd.GetFieldValue(pdconst.NOMINAL, 0) != False:
print(f'{i} {cmd.ID} {feat1} {feat2} {feat3},单位:{units}')
# 直接读取头部信息
dimHeading = cmd.GetFieldValue(pdconst.DIM_HEADING, 0)
print(dimHeading)
print('-' * 100)
if len(axisLetter) != 0:
print(f'\t{axisLetterString:<{axisLetterWidth}}\t{nominalString:<{nominalWidth}}\t{plusString:<{plusWidth}}\t{minusString:<{minusWidth}}\t{measuredString:<{measuredWidth}}\t{deviationString:<{deviationWidth}}\t{outTolString:<{outTolWidth}}')
print(f'\t{axisLetter:<{axisLetterWidth}}\t{nominal:<{nominalWidth}}\t{plus:<{plusWidth}}\t{minus:<{minusWidth}}\t{measured:<{measuredWidth}}\t{deviation:<{deviationWidth}}\t{outTol:<{outTolWidth}}')
print('-' * 100)
# 对所有测量值增加 100
measured += 100
ret = cmd.PutText(measured, pdconst.DIM_MEASURED, 0)
if ret:
print(f'修改成功,测量值修改为{measured}')
else:
print('修改失败')
print('=' * 100)
# 刷新报告
part.ReportWindow.RefreshReport
下面的报告是初始状态
执行代码对报告进行修改,所有测量值增加 100
刷新报告
PC-DMIS 的 COM 组件枚举常量使用帮助
PC-DMIS 的对象库文档就是个半截子,像在使用 GetText、GetFieldValue、PutText 的时候需要用到 ENUM_FIELD_TYPES 枚举,如果看文档就是下面的情况,Description 那列都是空着的,这一堆枚举成员只看名字也不一定知道是干啥的。
思路一
可以看到这些枚举成员实际都是映射一个数值的,那么就可以用附带测量数值的测量程序遍历匹配找到需要的枚举成员。
这里还是用上面的 PC-DMIS 测量程序,运行下面的 Python 代码
from pcdlrnconst import constants as pdconst
import win32com.client as wc
from win32com.client import constants as wcc
app = wc.Dispatch('PCDLRN.Application')
part = app.ActivePartProgram
cmds = part.Commands
for i in range(1, cmds.Count):
cmd = cmds[i]
if cmd.DimensionCommand:
dim = cmd.DimensionCommand
id = dim.ID
if len(id) != 0 and cmd.GetFieldValue(pdconst.NOMINAL, 0) != False:
print(f'{i} {id}')
下面有打印显示的命令索引就是评价尺寸(要获得形位公差的就判断是不是行为公差对象就行),从中任选一个,这里我就选第 207 个命令,对它进行枚举成员遍历
执行下面 Python 程序
import win32com.client as wc
app = wc.Dispatch('PCDLRN.Application')
part = app.ActivePartProgram
cmds = part.Commands
# 枚举最大遍历数值
enumMaxSize = 2000
# 使用的命令索引
cmdIdx = 207
for i in range(1, enumMaxSize):
val = cmds[cmdIdx].GetFieldValue(i, 0)
if val:
print(f'{i} {val}')
这个时候就对照检测报告看,48.000 这个值是标称值,其对应的枚举值是 166,然后查文档里的表,166 对应的枚举成员是 NOMINAL;
同样道理,报告上这个评价尺寸测量值是 48.017,这里对应的有 3 个枚举值:328、332、336,那么就去查表,这就知道这三个值分别对应DIM_MAX、DIM_MEASURED、DIM_MIN,即测量最大值,测量值(拟合结果),测量最小值。
思路二
PC-DMIS 的报告是使用模板插值的,查看模板就知道特定字段的名称了。
编辑标签模板,比如 Line2.lbl 模板文件
每个字段的名称一目了然
修改形位公差(可能无法实现)
我测试使用 PutText 修改,返回值是 True,但是在执行后再次读取测量值,结果不变,可能这个字段是只读的,无法修改。