OLE(Object Linking and Embedding)对象让 Excel 不再只是表格工具,它可以把 Word、PDF、PPT、音频等外部文件直接嵌入工作表,成为集中管理文档的容器。在自动生成报表、批量归档或数据追溯时,用 Python 脚本管理这些 OLE 对象,能省去大量手动操作。本文基于 Spire.XLS for Python,演示如何在工作表中插入、提取与管理 OLE 对象。
环境准备
先安装依赖库:
安装后,在脚本中导入 spire.xls 和 spire.xls.common 即可开始。
把已有 Excel 文件作为 OLE 对象插入
核心思路是:先给源文件生成一张预览图,然后调用 OleObjects.Add() 将文件嵌入当前工作表。下面代码把一个 Excel 文件作为 OLE 对象插入,并放到 B4 单元格位置。
- from spire.xls import *
- from spire.xls.common import *
- def GenerateImage(fileName):
- book = Workbook()
- book.LoadFromFile(fileName)
- book.Worksheets[0].PageSetup.LeftMargin = 0
- book.Worksheets[0].PageSetup.RightMargin = 0
- book.Worksheets[0].PageSetup.TopMargin = 0
- book.Worksheets[0].PageSetup.BottomMargin = 0
- return book.Worksheets[0].ToImage(1, 1, 19, 5)
- inputFile = "./Data/InsertOLEObjects.xls"
- outputFile = "InsertOLEObjects.xlsx"
- workbook = Workbook()
- ws = workbook.Worksheets[0]
- ws.Range["A1"].Text = "Here is an OLE Object."
- image = GenerateImage(inputFile)
- oleObject = ws.OleObjects.Add(inputFile, image, OleLinkType.Embed)
- oleObject.Location = ws.Range["B4"]
- oleObject.ObjectType = OleObjectType.ExcelWorksheet
- workbook.SaveToFile(outputFile, ExcelVersion.Version2010)
- workbook.Dispose()
复制代码
关键点说明:
GenerateImage() 先用零边距加载源文件,再把第一页(区域 1,1 到 19,5)转成图片,作为 OLE 对象在工作表上显示的缩略图。OleObjects.Add() 第二参数就是这张预览图,第三个参数 OleLinkType.Embed 表示对象以嵌入方式存储,不是外部链接。Location 控制对象锚定在哪个单元格,ObjectType 指定 OLE 对象的展现类型,这里声明为 ExcelWorksheet。
插入音频文件作为 OLE 对象
音频、视频这类非文档文件,可以统一作为 Package 对象嵌入。预览图可以直接用一张自定义图片文件,而不是从源文件生成。
- from spire.xls import *
- from spire.xls.common import *
- inputFile = "./Data/WAVFileSample.wav"
- inputimg = "./Data/SpireXls.png"
- outputFile = "InsertWavFileOLEObject.xlsx"
- workbook = Workbook()
- sheet = workbook.Worksheets[0]
- with Stream(inputimg) as fs:
- oleObject = sheet.OleObjects.Add(inputFile, fs, OleLinkType.Embed)
- oleObject.Location = sheet.Range["B4"]
- oleObject.ObjectType = OleObjectType.Package
- workbook.SaveToFile(outputFile, ExcelVersion.Version2010)
- workbook.Dispose()
复制代码
和插入文档对象相比,这里用 Stream 包装外部图片作为预览图,ObjectType 使用 Package,表示把音频文件当作一个通用包来嵌入。
从工作表提取 OLE 对象
提取的常用做法是:检查工作表是否含 OLE 对象,遍历每个对象,根据 ObjectType 判断类型,最后把 OleData 里的二进制内容写回文件。下面是一个从 Excel 中分别提取 Word、PDF、PPT 的示例:
- from spire.xls import *
- from spire.xls.common import *
- def WriteAllBytes(fname: str, data):
- fp = open(fname, "wb")
- for d in data:
- fp.write(d)
- fp.close()
- inputFile = "./Data/ExtractOle2.xlsx"
- workbook = Workbook()
- workbook.LoadFromFile(inputFile)
- sheet = workbook.Worksheets[0]
- if sheet.HasOleObjects:
- for obj in sheet.OleObjects:
- type = obj.ObjectType
- if type is OleObjectType.WordDocument:
- WriteAllBytes("ExtractedWord.docx", obj.OleData)
- elif type is OleObjectType.AdobeAcrobatDocument:
- WriteAllBytes("ExtractedPDF.pdf", obj.OleData)
- elif type is OleObjectType.PowerPointSlide:
- WriteAllBytes("ExtractedPPT.pptx", obj.OleData)
- workbook.Dispose()
复制代码
HasOleObjects 用于快速判断,避免没有对象时空跑循环。OleData 返回的是嵌入对象的原始字节,WriteAllBytes 按写入字节的方式落盘。需要注意,OleData 可能不是完整的文件格式流,实际开发时应先验证输出文件能否正常打开。
获取 OLE 对象的原始文档名
嵌入时保留的原始文件名,可以通过 OriginName 属性读取。这在生成文档清单时很有用:
- from spire.xls.common import *
- from spire.xls import *
- inputFile = "Data/ExtractOleObjectName.xlsx"
- workbook = Workbook()
- workbook.LoadFromFile(inputFile)
- sheet = workbook.Worksheets[0]
- information = ""
- for ole in sheet.OleObjects:
- ole_name = ole.OriginName
- information += ole_name + "\r\n"
- print(information)
- workbook.Dispose()
复制代码
批量提取并按类型分类保存
实际业务中一个工作表可能混有多种类型的 OLE 对象。可以建立一个类型到扩展名的映射关系,提取时自动分类:
- type_mapping = {
- OleObjectType.WordDocument: ".docx",
- OleObjectType.AdobeAcrobatDocument: ".pdf",
- OleObjectType.PowerPointSlide: ".pptx",
- OleObjectType.ExcelWorksheet: ".xlsx"
- }
- if sheet.HasOleObjects:
- for index, obj in enumerate(sheet.OleObjects):
- ext = type_mapping.get(obj.ObjectType, ".bin")
- filename = f"ole_object_{index}{ext}"
- WriteAllBytes(filename, obj.OleData)
- print(f"已提取: {filename} (类型: {obj.ObjectType})")
复制代码
这段代码配合前面已经加载好的 workbook 和 sheet 变量使用。映射不到的类型会保存为 .bin 文件,避免程序中断。
遍历多个工作表提取 OLE 对象
如果 OLE 对象分布在不同工作表中,需要遍历整个工作簿:
- for sheet_index in range(workbook.Worksheets.Count):
- sheet = workbook.Worksheets[sheet_index]
- if sheet.HasOleObjects:
- for obj in sheet.OleObjects:
- print(f"工作表 {sheet_index + 1}: {obj.OriginName} - {obj.ObjectType}")
复制代码
这种方式适合做文档盘点或合规审计,能快速列出每个工作表里嵌入了什么文件、放在哪个位置。
总结
本文围绕 Spire.XLS for Python 提供的 OLE 对象接口,给出了插入文档、插入音频、按类型提取、读取原始文件名、批量提取和跨工作表遍历的方法。核心 API 可以归纳为:OleObjects.Add() 负责插入,需要提供源文件、预览图和嵌入方式;ObjectType 控制对象展示类型;HasOleObjects 和 OleData 负责检测和提取;OriginName 用来追溯来源。把这些步骤整合到自动化管道中,外部文档的嵌入、提取和归档就能实现脚本化处理,节省大量重复劳动。 |