查看: 1358|回复: 3

Python操作Excel OLE对象插入提取与管理实战教程

[复制链接]
发表于 昨天 14:00 | 显示全部楼层 |阅读模式
OLE(Object Linking and Embedding)对象让 Excel 不再只是表格工具,它可以把 Word、PDF、PPT、音频等外部文件直接嵌入工作表,成为集中管理文档的容器。在自动生成报表、批量归档或数据追溯时,用 Python 脚本管理这些 OLE 对象,能省去大量手动操作。本文基于 Spire.XLS for Python,演示如何在工作表中插入、提取与管理 OLE 对象。

环境准备

先安装依赖库:
  1. pip install Spire.XLS
复制代码

安装后,在脚本中导入 spire.xls 和 spire.xls.common 即可开始。

把已有 Excel 文件作为 OLE 对象插入

核心思路是:先给源文件生成一张预览图,然后调用 OleObjects.Add() 将文件嵌入当前工作表。下面代码把一个 Excel 文件作为 OLE 对象插入,并放到 B4 单元格位置。
  1. from spire.xls import *
  2. from spire.xls.common import *
  3. def GenerateImage(fileName):
  4.     book = Workbook()
  5.     book.LoadFromFile(fileName)
  6.     book.Worksheets[0].PageSetup.LeftMargin = 0
  7.     book.Worksheets[0].PageSetup.RightMargin = 0
  8.     book.Worksheets[0].PageSetup.TopMargin = 0
  9.     book.Worksheets[0].PageSetup.BottomMargin = 0
  10.     return book.Worksheets[0].ToImage(1, 1, 19, 5)
  11. inputFile = "./Data/InsertOLEObjects.xls"
  12. outputFile = "InsertOLEObjects.xlsx"
  13. workbook = Workbook()
  14. ws = workbook.Worksheets[0]
  15. ws.Range["A1"].Text = "Here is an OLE Object."
  16. image = GenerateImage(inputFile)
  17. oleObject = ws.OleObjects.Add(inputFile, image, OleLinkType.Embed)
  18. oleObject.Location = ws.Range["B4"]
  19. oleObject.ObjectType = OleObjectType.ExcelWorksheet
  20. workbook.SaveToFile(outputFile, ExcelVersion.Version2010)
  21. workbook.Dispose()
复制代码

关键点说明:
GenerateImage() 先用零边距加载源文件,再把第一页(区域 1,1 到 19,5)转成图片,作为 OLE 对象在工作表上显示的缩略图。OleObjects.Add() 第二参数就是这张预览图,第三个参数 OleLinkType.Embed 表示对象以嵌入方式存储,不是外部链接。Location 控制对象锚定在哪个单元格,ObjectType 指定 OLE 对象的展现类型,这里声明为 ExcelWorksheet。

插入音频文件作为 OLE 对象

音频、视频这类非文档文件,可以统一作为 Package 对象嵌入。预览图可以直接用一张自定义图片文件,而不是从源文件生成。
  1. from spire.xls import *
  2. from spire.xls.common import *
  3. inputFile = "./Data/WAVFileSample.wav"
  4. inputimg = "./Data/SpireXls.png"
  5. outputFile = "InsertWavFileOLEObject.xlsx"
  6. workbook = Workbook()
  7. sheet = workbook.Worksheets[0]
  8. with Stream(inputimg) as fs:
  9.     oleObject = sheet.OleObjects.Add(inputFile, fs, OleLinkType.Embed)
  10. oleObject.Location = sheet.Range["B4"]
  11. oleObject.ObjectType = OleObjectType.Package
  12. workbook.SaveToFile(outputFile, ExcelVersion.Version2010)
  13. workbook.Dispose()
复制代码

和插入文档对象相比,这里用 Stream 包装外部图片作为预览图,ObjectType 使用 Package,表示把音频文件当作一个通用包来嵌入。

从工作表提取 OLE 对象

提取的常用做法是:检查工作表是否含 OLE 对象,遍历每个对象,根据 ObjectType 判断类型,最后把 OleData 里的二进制内容写回文件。下面是一个从 Excel 中分别提取 Word、PDF、PPT 的示例:
  1. from spire.xls import *
  2. from spire.xls.common import *
  3. def WriteAllBytes(fname: str, data):
  4.     fp = open(fname, "wb")
  5.     for d in data:
  6.         fp.write(d)
  7.     fp.close()
  8. inputFile = "./Data/ExtractOle2.xlsx"
  9. workbook = Workbook()
  10. workbook.LoadFromFile(inputFile)
  11. sheet = workbook.Worksheets[0]
  12. if sheet.HasOleObjects:
  13.     for obj in sheet.OleObjects:
  14.         type = obj.ObjectType
  15.         if type is OleObjectType.WordDocument:
  16.             WriteAllBytes("ExtractedWord.docx", obj.OleData)
  17.         elif type is OleObjectType.AdobeAcrobatDocument:
  18.             WriteAllBytes("ExtractedPDF.pdf", obj.OleData)
  19.         elif type is OleObjectType.PowerPointSlide:
  20.             WriteAllBytes("ExtractedPPT.pptx", obj.OleData)
  21. workbook.Dispose()
复制代码

HasOleObjects 用于快速判断,避免没有对象时空跑循环。OleData 返回的是嵌入对象的原始字节,WriteAllBytes 按写入字节的方式落盘。需要注意,OleData 可能不是完整的文件格式流,实际开发时应先验证输出文件能否正常打开。

获取 OLE 对象的原始文档名

嵌入时保留的原始文件名,可以通过 OriginName 属性读取。这在生成文档清单时很有用:
  1. from spire.xls.common import *
  2. from spire.xls import *
  3. inputFile = "Data/ExtractOleObjectName.xlsx"
  4. workbook = Workbook()
  5. workbook.LoadFromFile(inputFile)
  6. sheet = workbook.Worksheets[0]
  7. information = ""
  8. for ole in sheet.OleObjects:
  9.     ole_name = ole.OriginName
  10.     information += ole_name + "\r\n"
  11. print(information)
  12. workbook.Dispose()
复制代码

批量提取并按类型分类保存

实际业务中一个工作表可能混有多种类型的 OLE 对象。可以建立一个类型到扩展名的映射关系,提取时自动分类:
  1. type_mapping = {
  2.     OleObjectType.WordDocument: ".docx",
  3.     OleObjectType.AdobeAcrobatDocument: ".pdf",
  4.     OleObjectType.PowerPointSlide: ".pptx",
  5.     OleObjectType.ExcelWorksheet: ".xlsx"
  6. }
  7. if sheet.HasOleObjects:
  8.     for index, obj in enumerate(sheet.OleObjects):
  9.         ext = type_mapping.get(obj.ObjectType, ".bin")
  10.         filename = f"ole_object_{index}{ext}"
  11.         WriteAllBytes(filename, obj.OleData)
  12.         print(f"已提取: {filename} (类型: {obj.ObjectType})")
复制代码

这段代码配合前面已经加载好的 workbook 和 sheet 变量使用。映射不到的类型会保存为 .bin 文件,避免程序中断。

遍历多个工作表提取 OLE 对象

如果 OLE 对象分布在不同工作表中,需要遍历整个工作簿:
  1. for sheet_index in range(workbook.Worksheets.Count):
  2.     sheet = workbook.Worksheets[sheet_index]
  3.     if sheet.HasOleObjects:
  4.         for obj in sheet.OleObjects:
  5.             print(f"工作表 {sheet_index + 1}: {obj.OriginName} - {obj.ObjectType}")
复制代码

这种方式适合做文档盘点或合规审计,能快速列出每个工作表里嵌入了什么文件、放在哪个位置。

总结

本文围绕 Spire.XLS for Python 提供的 OLE 对象接口,给出了插入文档、插入音频、按类型提取、读取原始文件名、批量提取和跨工作表遍历的方法。核心 API 可以归纳为:OleObjects.Add() 负责插入,需要提供源文件、预览图和嵌入方式;ObjectType 控制对象展示类型;HasOleObjects 和 OleData 负责检测和提取;OriginName 用来追溯来源。把这些步骤整合到自动化管道中,外部文档的嵌入、提取和归档就能实现脚本化处理,节省大量重复劳动。
回复

使用道具 举报

发表于 昨天 19:00 | 显示全部楼层

Re: Python操作Excel OLE对象插入提取与管理实战教程

楼主这个教程太及时了,正在做电子档案管理,正好需要把 PDF 和工程图嵌到 Excel 里统一归档。按你的代码跑通了文档和音频的插入,但提取那段有个小疑问:`WriteAllBytes` 函数里 `for d in data: fp.write(d)`,如果 `obj.OleData` 是 bytes 类型,这样遍历会把每个字节当成整数写入,应该会报错吧?我改成 `fp.write(obj.OleData)` 或者先转换成 bytes 再写就正常了。不知道是不是 Spire.XLS 返回的 OleData 是别的类型(比如列表)?要是楼主能顺便验证下就好了。顺带问一下,除了 Word/PDF/PPT,其他常见 OLE 类型(比如 Visio 绘图或者 CAD)在 ObjectType 枚举里怎么判断?期待后续更新,感谢分享!
回复 支持 反对

使用道具 举报

发表于 昨天 19:00 | 显示全部楼层

Re: Python操作Excel OLE对象插入提取与管理实战教程

感谢楼主分享,写得很清楚。正好最近在批量归档文件,之前都是手工往Excel里嵌对象,麻烦得要命。看了这教程,那个用Python插入OLE和提取的思路很实用,尤其是用Spire.XLS把源文件转成预览图再嵌入,省了不少事。 有个小问题想请教:如果插入的是PDF或Word,预览图是不是也必须提前准备好?能不能像第一个例子那样自动从源文件生成?还有,提取出来的OleData写回文件时,是不是所有类型都能直接还原成原格式,还是有的会变成流文件需要特殊处理?期待楼主后续能补充一下这块。
回复 支持 反对

使用道具 举报

发表于 昨天 19:00 | 显示全部楼层

Re: Python操作Excel OLE对象插入提取与管理实战教程

学到了,正好最近在搞报表归档,手动插 OLE 对象插到怀疑人生。这个用 Python 批量处理确实方便,特别是预览图那一步,用源文件第一页生成缩略图很实用,不然嵌入的图标千篇一律,找起来费劲。 想追问一下:提取出来的 Word 对象,如果原来是 .doc 格式,写成 .docx 后缀会不会有问题?还是说要根据原始文件名来判断扩展名?希望楼主能再补充点细节,感谢!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-1 02:37 , Processed in 0.023172 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部