使用 win32com 和 comtypes 将字典传递给 Excel 宏
Pass dictionary to Excel macro using win32com and comtypes
我正在使用 Python 对 Excel 宏进行单元测试。在测试以下宏时,我需要将一个字典对象传递给它。
testDict.xlsm中的代码:
Function GetItemCount(dict As Variant) As Integer
GetItemCount = dict.Count
End Function
我的测试代码是这样的,它是基于comtypes项目中的test_dict.py:
test_comtypes_w_dict.py
from comtypes.client import CreateObject
import win32com.client as win32
d = CreateObject("Scripting.Dictionary", dynamic=True)
d.Add("Test", "An item")
filename = 'testDict.xlsm'
xl = win32.Dispatch("Excel.Application")
wb = xl.Workbooks.Open(filename)
count = xl.Application.Run(filename+'!Module1.GetItemCount', d)
assert count == 1
当运行测试时,引发TypeError。
Traceback (most recent call last):
File "C:\Users\[..]\test_comtypes_w_dict.py", line 11, in <module>
count = xl.Application.Run(filename+'!Module1.GetItemCount', d)
File "C:\Users\[..]\AppData\Local\Temp\gen_py.9[=13=]020813-0000-0000-C000-000000000046x0x1x9.py", line 44654, in Run
return self._ApplyTypes_(259, 1, (12, 0), ((12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17)), 'Run', None,Macro
File "C:\Users\[..]\venv\lib\site-packages\win32com\client\__init__.py", line 467, in _ApplyTypes_
self._oleobj_.InvokeTypes(dispid, 0, wFlags, retType, argTypes, *args), TypeError: Objects for SAFEARRAYS must be sequences (of sequences), or a buffer object.
我已尝试从对 CreateObject 的调用中删除 dynamic=True
。然后测试运行,但我在 Excel:
中遇到异常
Run-time error '424':
Object required
在ExcelVBAIDE和运行TypeName(dict)中调试时,结果为“Variant()”。
如何以正确识别的方式将字典传递给宏?
作为解决方法,我将尝试在宏中生成字典,return 将其传递给 Python 并将其传递给我要测试的宏。但是,如果可能的话,我想避免使用这种复杂的方法。
上面的代码混合了两个不同的库来创建 COM 对象。
替换
d = CreateObject("Scripting.Dictionary", dynamic=True)
和
d = win32.Dispatch('Scripting.Dictionary')
并免除 comtypes,除非某些其他功能需要它。
我正在使用 Python 对 Excel 宏进行单元测试。在测试以下宏时,我需要将一个字典对象传递给它。
testDict.xlsm中的代码:
Function GetItemCount(dict As Variant) As Integer
GetItemCount = dict.Count
End Function
我的测试代码是这样的,它是基于comtypes项目中的test_dict.py:
test_comtypes_w_dict.py
from comtypes.client import CreateObject
import win32com.client as win32
d = CreateObject("Scripting.Dictionary", dynamic=True)
d.Add("Test", "An item")
filename = 'testDict.xlsm'
xl = win32.Dispatch("Excel.Application")
wb = xl.Workbooks.Open(filename)
count = xl.Application.Run(filename+'!Module1.GetItemCount', d)
assert count == 1
当运行测试时,引发TypeError。
Traceback (most recent call last):
File "C:\Users\[..]\test_comtypes_w_dict.py", line 11, in <module>
count = xl.Application.Run(filename+'!Module1.GetItemCount', d)
File "C:\Users\[..]\AppData\Local\Temp\gen_py.9[=13=]020813-0000-0000-C000-000000000046x0x1x9.py", line 44654, in Run
return self._ApplyTypes_(259, 1, (12, 0), ((12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17), (12, 17)), 'Run', None,Macro
File "C:\Users\[..]\venv\lib\site-packages\win32com\client\__init__.py", line 467, in _ApplyTypes_
self._oleobj_.InvokeTypes(dispid, 0, wFlags, retType, argTypes, *args), TypeError: Objects for SAFEARRAYS must be sequences (of sequences), or a buffer object.
我已尝试从对 CreateObject 的调用中删除 dynamic=True
。然后测试运行,但我在 Excel:
Run-time error '424':
Object required
在ExcelVBAIDE和运行TypeName(dict)中调试时,结果为“Variant()”。
如何以正确识别的方式将字典传递给宏?
作为解决方法,我将尝试在宏中生成字典,return 将其传递给 Python 并将其传递给我要测试的宏。但是,如果可能的话,我想避免使用这种复杂的方法。
上面的代码混合了两个不同的库来创建 COM 对象。
替换
d = CreateObject("Scripting.Dictionary", dynamic=True)
和
d = win32.Dispatch('Scripting.Dictionary')
并免除 comtypes,除非某些其他功能需要它。