【发布时间】:2017-08-26 12:54:07
【问题描述】:
我想使用 Python 从 Office/Excel 文档中添加和提取文件。到目前为止添加东西很容易,但对于提取我还没有找到一个干净的解决方案。
为了弄清楚我有什么,我写了下面的小例子 test.py 并进一步解释。
test.py
import win32com.client as win32
import os
from tkinter import messagebox
import win32clipboard
# (0) Setup
dir_path = os.path.dirname(os.path.realpath(__file__))
print(dir_path)
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Open(dir_path + "\\" + "test_excel.xlsx")
ws = wb.Worksheets.Item(1)
objs = ws.OLEObjects()
# (1) Embed file
f = dir_path + "\\" + "test_txt.txt"
name = "test_txt_ole.txt"
objs.Add( Filename=f, IconLabel=name )
# (2) Access embedded file
obj = objs.Item(1) # Get single OLE from OLE list
obj.Copy()
win32clipboard.OpenClipboard()
data = win32clipboard.GetClipboardData(0xC004) # Binary access
win32clipboard.EmptyClipboard()
win32clipboard.CloseClipboard()
messagebox.showinfo(title="test_txt_ole.txt", message=str(data))
# (3) Press don't save here to keep
# wb.Close() # Will close excel document and leave excel opened.
excel.Application.Quit() # Will close excel with all opened documents
为了准备(步骤 0),它会打开一个给定的 excel 文档,其中包含一个之前通过使用 excel 中的 new document 按钮创建的工作表。
在步骤 (1) 中,它使用 API 将给定的文本文件嵌入到 excel 文档中。该文本文件是之前使用文本编辑器创建的,内容为“TEST123”。
随后在步骤 (2) 中,它尝试使用剪贴板从嵌入的 OLE 读回内容,并打开一个消息框,显示剪贴板中 OLE 的内容。
最后(3)程序关闭打开的文档。要保持不变的设置,请在此处按“否”。
此解决方案的最大缺点是使用剪贴板会破坏剪贴板中的任何用户内容,这在生产环境中是不好的风格。此外,它使用了一个未记录的剪贴板选项。
更好的解决方案是将 OLE 或 OLE 嵌入文件安全到 python 数据容器或我选择的文件。在我的示例中,我使用了 TXT 文件来轻松识别文件数据。最后,我将使用 ZIP 作为一体式解决方案,但对于 base64 数据,TXT 文件解决方案就足够了。
0xC004 = 49156 的来源:https://danny.fyi/embedding-and-accessing-a-file-in-excel-with-vba-and-ole-objects-4d4e7863cfff
这个 VBA 示例看起来很有趣,但我对 VBA 一无所知:Saving embedded OLE Object (Excel workbook) to file in Excel 2010
【问题讨论】:
-
所以,我发现这个问题令人困惑。看起来您想从 excel 文件中提取某些内容,但我发现 something 有点含糊。
-
我不熟悉python,但其实你已经在做很多“VBA”了。
Workbooks.Open、Worksheets.Item等是一种 VBA 命令(从技术上讲,它们是 IDispatch 调用)。你为什么不直接从你的python代码中尝试在VBA示例中调用oEmbFile.Object.SaveAs fName之类的东西 -
@Simon: Pyhton 和 VBA 一样使用 COM 接口。我可以使用以下代码行来查看对象 API,但没有 SaveAs,只有诸如激活和复制之类的东西。 messagebox.showinfo(title="packBootstrap", message="Item obj:\n"+ str(type(obj)) + str(dir(obj))) messagebox.showinfo(title="packBootstrap", message="oleobj:\n"+ str(type(obj._oleobj_)) + str(dir(obj._oleobj_)) ) 但是没有什么让我更进一步“obj._oleobj_”是一个“PylDispatch " 对象。
-
@Stephen:我的问题故意含糊不清,因为我想在没有深度协议的情况下将二进制数据添加到 Excel。要求是: 使用 Python。使用类似 COM 的策略 (win32com)。要专业(=没有“黑客”)。我还考虑过 Excel 单元格中的 base64 数据,但这里的大小限制为 32k。分块多细胞解决方案并不专业,因为它需要自制协议。
-
什么是对象 CLSID?打印(obj.CLSID)
标签: python excel com ms-office ole