之前我一直以为,python对OFFICE的自动化,相较VBA的话,是有限的,就像openpyxl那样,需要有人去不断地追加维护才行。
经过学习后,发现其实只要使用win32com这个库,就可以将VBA的代码直接移植到python上使用。功能上是和当前VBA的宿主相关,例如Excel版本越高,VBA的功能越多,相应的win32com这个库也可以自动增加这些功能,本质上win32com只是一个桥梁,使用python可以驱动COM组件,COM组件暴露多少功能,它就能实现多少。
不过按童大谦老师的【代替VBA!用python轻松实现Excel编程】一书里说的,极个别接口还是有些异常的。
我专门测试了一下,拿Excel比较新的接口如PowerQuery。实测还是正常可以获取的,代码如下(xlwings本质底层用的是win32com):
所以,如果python自动化的是COM组件,应该使用win32com,更科学。而不是使用pythonnet,后者是对.NET的非托管的dll起作用。如果硬着来,效果比较差,例如以下的代码,需要使用反映的方式才能操作COM组件。
那有哪些软件是COM组件暴露,哪些不是?这个可以用一段小命令,调出一个COM浏览器,不过更快的应该直接问GPT4,哈哈。
from win32com.client import combrowse
combrowse.main()
因为我本机是OFFICE365,所以这里就直接获取到最新COM组件Excel16。
当然如果要使用C#来实现这些新的接口,如果没有引用Excel16的dll,就没有智能提示,只能用动态类型来处理,也一样可以的。
static void Main(string[] args)
{
Excel.Application app = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
dynamic wkb = app.ActiveWorkbook;
Console.WriteLine(wkb.Queries.Item[1].Name);
}
除了OFFICE软件,笔者用到的还有sqlserver的对象模型自动化,它有两个模型SMO和AMO。其中SMO可能比较旧的技术,还是COM组件的,但AMO分析模型,就已经变成是.NET的托管模型了。
import win32com.client
# 创建 SQL Server 对象
smo = win32com.client.Dispatch('Microsoft.SqlServer.Management.Smo.Server')
# 连接到 SQL Server 实例
server = smo('localhost') # 替换为你的服务器名称
# 获取数据库列表
databases = server.Databases
for db in databases:
print(f'Database Name: {db.Name}')
所以后者需要用pythonnet的方案了。
import clr
from System import String
from System.Reflection import BindingFlags
# 添加对 Microsoft.AnalysisServices.Tabular 的引用
dll_path = r'C:\Path\To\Your\Microsoft.AnalysisServices.Tabular.dll'
clr.AddReference(dll_path)
# 导入 Microsoft.AnalysisServices.Tabular 命名空间
from Microsoft.AnalysisServices.Tabular import Server, Database
# 创建并连接到 Analysis Services 服务器实例
server = Server()
server.Connect('localhost') # 替换为你的服务器地址
# 获取数据库对象
database = server.Databases['YourDatabaseName'] # 替换为你的数据库名称
# 打印数据库信息
print(f'Database Name: {database.Name}')
print(f'Database Compatibility Level: {database.CompatibilityLevel}')
# 列出所有表
for table in database.Model.Tables:
print(f'Table: {table.Name}')