使用 C++ 在演示文稿中管理 OLE
简介
Note
OLE(Object Linking & Embedding)是 Microsoft 的一项技术,允许在一个应用程序中创建的数据和对象通过链接或嵌入的方式放置到另一个应用程序中。考虑在 MS Excel 中创建的图表。该图表随后放置在 PowerPoint 幻灯片中。该 Excel 图表被视为 OLE 对象。
- OLE 对象可能显示为图标。在这种情况下,双击图标时,图表将在其关联的应用程序(Excel)中打开,或系统会要求您选择用于打开或编辑对象的应用程序。
- OLE 对象可能显示其实际内容,例如图表的内容。在这种情况下,图表在 PowerPoint 中被激活,图表界面加载,您可以在 PowerPoint 中修改图表的数据。
Aspose.Slides for C++ 允许您将 OLE 对象作为 OLE 对象框(OleObjectFrame)插入到幻灯片中。
向幻灯片添加 OLE 对象框
假设您已经在 Microsoft Excel 中创建了图表,并希望使用 Aspose.Slides for C++ 将其嵌入到幻灯片中作为 OLE 对象框,您可以按以下方式进行:
- 创建一个 Presentation 类的实例。
- 通过索引获取幻灯片的引用。
- 将 Excel 文件读取为字节数组。
- 将 OleObjectFrame 添加到幻灯片中,并包含字节数组以及 OLE 对象的其他信息。
- 将修改后的演示文稿写入为 PPTX 文件。
在下面的示例中,我们使用 Aspose.Slides for C++ 将来自 Excel 文件的图表作为 OleObjectFrame 添加到幻灯片中。注意,OleEmbeddedDataInfo 构造函数将可嵌入对象的扩展名作为第二个参数。此扩展名使 PowerPoint 能够正确解释文件类型并选择正确的应用程序打开此 OLE 对象。
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/ISlideSize.h>
#include <DOM/Presentation.h>
#include <Export/SaveFormat.h>
#include <Ole/OleEmbeddedDataInfo.h>
#include <drawing/size_f.h>
#include <system/io/file.h>
#include <system/smart_ptr.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::DOM::Ole;
using namespace Aspose::Slides::Export;
using namespace System;
using namespace System::IO;
auto presentation = MakeObject<Presentation>();
auto slideSize = presentation->get_SlideSize()->get_Size();
auto slide = presentation->get_Slide(0);
// Prepare data for the OLE object.
auto fileData = File::ReadAllBytes(u"book.xlsx");
auto dataInfo = MakeObject<OleEmbeddedDataInfo>(fileData, u"xlsx");
// Add the OLE object frame to the slide.
slide->get_Shapes()->AddOleObjectFrame(0, 0, slideSize.get_Width(), slideSize.get_Height(), dataInfo);
presentation->Save(u"output.pptx", SaveFormat::Pptx);
presentation->Dispose();
添加链接的 OLE 对象框
Aspose.Slides for C++ 允许您添加一个不嵌入数据、仅通过链接指向文件的 OleObjectFrame。
下面的 C++ 代码演示了如何将带有链接的 Excel 文件的 OleObjectFrame 添加到幻灯片:
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/Presentation.h>
#include <Export/SaveFormat.h>
#include <system/smart_ptr.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::Export;
using namespace System;
auto presentation = MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
// 添加一个带有链接的 Excel 文件的 OLE 对象框.
slide->get_Shapes()->AddOleObjectFrame(20, 20, 200, 150, u"Excel.Sheet.12", u"book.xlsx");
presentation->Save(u"output.pptx", SaveFormat::Pptx);
presentation->Dispose();
访问 OLE 对象框
如果 OLE 对象已经嵌入到幻灯片中,您可以通过以下方式轻松查找或访问它:
- 通过创建 Presentation 类的实例,加载包含嵌入 OLE 对象的演示文稿。
- 使用其索引获取幻灯片的引用。
- 访问 OleObjectFrame 形状。在我们的示例中,我们使用了先前创建的 PPTX,该 PPTX 的第一张幻灯片上只有一个形状。然后我们将该对象 cast 为 IOleObjectFrame。这就是要访问的目标 OLE 对象框。
- 一旦访问到 OLE 对象框,您就可以对其执行任何操作。
下面的示例中,访问了 OLE 对象框(嵌入到幻灯片中的 Excel 图表对象)及其文件数据。
#include <DOM/IOleEmbeddedDataInfo.h>
#include <DOM/IOleObjectFrame.h>
#include <DOM/ISlide.h>
#include <DOM/Presentation.h>
#include <system/object_ext.h>
using namespace Aspose::Slides;
using namespace System;
auto presentation = MakeObject<Presentation>(u"sample.pptx");
auto slide = presentation->get_Slide(0);
auto shape = slide->get_Shape(0);
if (ObjectExt::Is<IOleObjectFrame>(shape))
{
auto oleFrame = ExplicitCast<IOleObjectFrame>(shape);
// 获取嵌入的文件数据。
auto fileData = oleFrame->get_EmbeddedData()->get_EmbeddedFileData();
// 获取嵌入文件的扩展名。
auto fileExtension = oleFrame->get_EmbeddedData()->get_EmbeddedFileExtension();
// ...
}
访问链接的 OLE 对象框属性
Aspose.Slides 允许您访问链接的 OLE 对象框属性。
下面的 C++ 代码演示了如何检查 OLE 对象是否为链接的以及获取链接文件的路径:
#include <DOM/IOleObjectFrame.h>
#include <DOM/ISlide.h>
#include <DOM/Presentation.h>
#include <system/object_ext.h>
#include <system/string.h>
using namespace Aspose::Slides;
using namespace System;
auto presentation = MakeObject<Presentation>(u"sample.ppt");
auto slide = presentation->get_Slide(0);
auto shape = slide->get_Shape(0);
if (ObjectExt::Is<IOleObjectFrame>(shape))
{
auto oleFrame = ExplicitCast<IOleObjectFrame>(shape);
// 检查 OLE 对象是否为链接。
if (oleFrame->get_IsObjectLink())
{
// 打印链接文件的完整路径。
std::wcout << L"OLE object frame is linked to: " << oleFrame->get_LinkPathLong() << std::endl;
// 如有,请打印链接文件的相对路径。
// 仅 PPT 演示文稿可以包含相对路径。
if (!String::IsNullOrEmpty(oleFrame->get_LinkPathRelative()))
{
std::wcout << L"OLE object frame relative path: " << oleFrame->get_LinkPathRelative() << std::endl;
}
}
}
更改 OLE 对象数据
Note
在本节中,下面的代码示例使用了 Aspose.Cells for C++。如果 OLE 对象已经嵌入到幻灯片中,您可以通过以下方式轻松访问该对象并修改其数据:
- 通过创建 Presentation 类的实例,加载包含嵌入 OLE 对象的演示文稿。
- 使用其索引获取幻灯片的引用。
- 访问 OLEObjectFrame 形状。在我们的示例中,我们使用了先前创建的 PPTX,该 PPTX 的第一张幻灯片上只有一个形状。然后我们将该对象 cast 为 IOleObjectFrame。这就是要访问的目标 OLE 对象框。
- 一旦访问到 OLE 对象框,您就可以对其执行任何操作。
- 创建一个
Workbook对象并访问 OLE 数据。 - 访问所需的
Worksheet并修改数据。 - 将更新后的
Workbook保存到流中。 - 从流中更改 OLE 对象数据。
下面的示例中,访问了 OLE 对象框(嵌入到幻灯片中的 Excel 图表对象),并修改其文件数据以更新图表数据。
#include <DOM/IOleObjectFrame.h>
#include <DOM/ISlide.h>
#include <DOM/Presentation.h>
#include <Export/SaveFormat.h>
#include <Ole/OleEmbeddedDataInfo.h>
#include <system/io/memory_stream.h>
#include <system/smart_ptr.h>
#include "Aspose.Cells/Cell.h"
#include "Aspose.Cells/Cells.h"
#include "Aspose.Cells/Initializer.h"
#include "Aspose.Cells/OoxmlSaveOptions.h"
#include "Aspose.Cells/SaveFormat.h"
#include "Aspose.Cells/U16String.h"
#include "Aspose.Cells/Vector.h"
#include "Aspose.Cells/Workbook.h"
#include "Aspose.Cells/Worksheet.h"
#include "Aspose.Cells/WorksheetCollection.h"
using namespace Aspose::Slides;
using namespace Aspose::Slides::DOM::Ole;
using namespace Aspose::Slides::Export;
using namespace System;
using namespace System::IO;
// 在使用任何 Aspose.Cells 类型之前必须先启动 Aspose.Cells for C++。
Aspose::Cells::Startup();
auto presentation = MakeObject<Presentation>(u"sample.pptx");
auto slide = presentation->get_Slide(0);
// 获取第一个形状作为 OLE 对象框。
auto oleFrame = AsCast<IOleObjectFrame>(slide->get_Shape(0));
if (oleFrame != nullptr)
{
auto oleStream = MakeObject<MemoryStream>(oleFrame->get_EmbeddedData()->get_EmbeddedFileData());
// 将 OLE 对象数据读取为 Workbook 对象。
auto oleArray = oleStream->ToArray();
std::vector<uint8_t> workbookData(oleArray->data().begin(), oleArray->data().end());
Aspose::Cells::Workbook workbook(Aspose::Cells::Vector<uint8_t>(workbookData.data(), workbookData.size()));
// 修改工作簿数据。
auto worksheet = workbook.GetWorksheets().Get(0);
worksheet.GetCells().Get(0, 4).PutValue(Aspose::Cells::U16String("E"));
worksheet.GetCells().Get(1, 4).PutValue(12);
worksheet.GetCells().Get(2, 4).PutValue(14);
worksheet.GetCells().Get(3, 4).PutValue(15);
Aspose::Cells::OoxmlSaveOptions fileOptions(Aspose::Cells::SaveFormat::Xlsx);
auto newWorkbookData = workbook.Save(fileOptions);
auto newOleStream = MakeObject<MemoryStream>();
newOleStream->Write(
MakeArray<uint8_t>(std::vector<uint8_t>(newWorkbookData.GetData(), newWorkbookData.GetData() + newWorkbookData.GetLength())),
0, newWorkbookData.GetLength());
// 更改 OLE 框对象的数据。
auto newData = MakeObject<OleEmbeddedDataInfo>(newOleStream->ToArray(), oleFrame->get_EmbeddedData()->get_EmbeddedFileExtension());
oleFrame->SetEmbeddedData(newData);
}
presentation->Save(u"output.pptx", SaveFormat::Pptx);
Aspose::Cells::Cleanup();
在幻灯片中嵌入其他文件类型
除了 Excel 图表,Aspose.Slides for C++ 还允许您将其他类型的文件嵌入到幻灯片中。例如,您可以将 HTML、PDF 和 ZIP 文件插入为对象。当用户双击插入的对象时,它会自动在相应程序中打开,或提示用户选择合适的程序来打开它。
下面的 C++ 代码演示了如何将 HTML 和 ZIP 嵌入到幻灯片中:
#include <DOM/IOleObjectFrame.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/Presentation.h>
#include <Export/SaveFormat.h>
#include <Ole/OleEmbeddedDataInfo.h>
#include <system/io/file.h>
#include <system/smart_ptr.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::DOM::Ole;
using namespace Aspose::Slides::Export;
using namespace System;
using namespace System::IO;
auto presentation = MakeObject<Presentation>();
auto slide = presentation->get_Slide(0);
auto htmlData = File::ReadAllBytes(u"sample.html");
auto htmlDataInfo = MakeObject<OleEmbeddedDataInfo>(htmlData, u"html");
auto htmlOleFrame = slide->get_Shapes()->AddOleObjectFrame(150, 120, 50, 50, htmlDataInfo);
htmlOleFrame->set_IsObjectIcon(true);
auto zipData = File::ReadAllBytes(u"sample.zip");
auto zipDataInfo = MakeObject<OleEmbeddedDataInfo>(zipData, u"zip");
auto zipOleFrame = slide->get_Shapes()->AddOleObjectFrame(150, 220, 50, 50, zipDataInfo);
zipOleFrame->set_IsObjectIcon(true);
presentation->Save(u"output.pptx", SaveFormat::Pptx);
presentation->Dispose();
设置嵌入对象的文件类型
在处理演示文稿时,您可能需要将旧的 OLE 对象替换为新的,或将不受支持的 OLE 对象替换为受支持的。Aspose.Slides for C++ 允许您设置嵌入对象的文件类型,从而更新 OLE 框数据或其扩展名。
下面的 C++ 代码演示了如何将嵌入的 OLE 对象的文件类型设置为 zip:
#include <DOM/IOleObjectFrame.h>
#include <DOM/ISlide.h>
#include <DOM/Presentation.h>
#include <Export/SaveFormat.h>
#include <Ole/OleEmbeddedDataInfo.h>
#include <system/smart_ptr.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::DOM::Ole;
using namespace Aspose::Slides::Export;
using namespace System;
auto presentation = MakeObject<Presentation>(u"sample.pptx");
auto slide = presentation->get_Slide(0);
auto oleFrame = ExplicitCast<IOleObjectFrame>(slide->get_Shape(0));
auto fileExtension = oleFrame->get_EmbeddedData()->get_EmbeddedFileExtension();
auto fileData = oleFrame->get_EmbeddedData()->get_EmbeddedFileData();
std::wcout << L"Current embedded file extension is: " << fileExtension << std::endl;
// Change the file type to ZIP.
oleFrame->SetEmbeddedData(MakeObject<OleEmbeddedDataInfo>(fileData, u"zip"));
presentation->Save(u"output.pptx", SaveFormat::Pptx);
presentation->Dispose();
为嵌入对象设置图标图像和标题
嵌入 OLE 对象后,会自动添加由图标图像组成的预览。该预览是用户在访问或打开 OLE 对象之前看到的内容。如果您想在预览中使用特定的图像和文本作为元素,可以使用 Aspose.Slides for C++ 设置图标图像和标题。
下面的 C++ 代码演示了如何为嵌入对象设置图标图像和标题:
#include <DOM/IImageCollection.h>
#include <DOM/IOleObjectFrame.h>
#include <DOM/IPictureFillFormat.h>
#include <DOM/ISlide.h>
#include <DOM/ISlidesPicture.h>
#include <DOM/Presentation.h>
#include <Export/SaveFormat.h>
#include <system/io/file.h>
#include <system/smart_ptr.h>
using namespace Aspose::Slides;
using namespace Aspose::Slides::Export;
using namespace System;
using namespace System::IO;
auto presentation = MakeObject<Presentation>(u"sample.pptx");
auto slide = presentation->get_Slide(0);
auto oleFrame = ExplicitCast<IOleObjectFrame>(slide->get_Shape(0));
// 向演示文稿资源添加图像。
auto imageData = File::ReadAllBytes(u"image.png");
auto oleImage = presentation->get_Images()->AddImage(imageData);
// Set a title and the image for the OLE preview.
oleFrame->set_SubstitutePictureTitle(u"My title");
oleFrame->get_SubstitutePictureFormat()->get_Picture()->set_Image(oleImage);
oleFrame->set_IsObjectIcon(true);
presentation->Save(u"output.pptx", SaveFormat::Pptx);
presentation->Dispose();
防止 OLE 对象框被重新调整大小和重新定位
在向演示文稿幻灯片添加链接的 OLE 对象后,打开 PowerPoint 时,可能会看到提示更新链接的消息。单击 “Update Links” 按钮可能会改变 OLE 对象框的大小和位置,因为 PowerPoint 会从链接的 OLE 对象更新数据并刷新对象预览。为防止 PowerPoint 提示更新对象数据,请使用 false 调用 IOleObjectFrame 接口的 set_UpdateAutomatic 方法:
#include <DOM/IOleObjectFrame.h>
#include <DOM/ISlide.h>
#include <DOM/Presentation.h>
#include <system/smart_ptr.h>
using namespace Aspose::Slides;
using namespace System;
auto presentation = MakeObject<Presentation>(u"sample.pptx");
auto slide = presentation->get_Slide(0);
auto oleFrame = ExplicitCast<IOleObjectFrame>(slide->get_Shape(0));
oleFrame->set_UpdateAutomatic(false);
提取嵌入文件
您可以通过以下方式使用 Aspose.Slides for C++ 提取幻灯片中嵌入的文件作为 OLE 对象:
- 创建一个包含您要提取的 OLE 对象的 Presentation 类的实例。
- 遍历演示文稿中的所有形状并访问 OLEObjectFrame 形状。
- 从 OLE 对象框获取嵌入文件的数据并写入磁盘。
下面的 C++ 代码演示了如何提取嵌入到幻灯片中的文件作为 OLE 对象:
#include <DOM/IOleEmbeddedDataInfo.h>
#include <DOM/IOleObjectFrame.h>
#include <DOM/IShapeCollection.h>
#include <DOM/ISlide.h>
#include <DOM/Presentation.h>
#include <system/io/file.h>
#include <system/object_ext.h>
#include <system/string.h>
using namespace Aspose::Slides;
using namespace System;
using namespace System::IO;
auto presentation = MakeObject<Presentation>(u"sample.pptx");
auto slide = presentation->get_Slide(0);
for (int index = 0; index < slide->get_Shapes()->get_Count(); index++)
{
auto shape = slide->get_Shape(index);
if (ObjectExt::Is<IOleObjectFrame>(shape))
{
auto oleFrame = ExplicitCast<IOleObjectFrame>(shape);
auto fileData = oleFrame->get_EmbeddedData()->get_EmbeddedFileData();
auto fileExtension = oleFrame->get_EmbeddedData()->get_EmbeddedFileExtension();
auto fileName = String::Format(u"OLE_object_{0}{1}", index, fileExtension);
File::WriteAllBytes(fileName, fileData);
}
}
presentation->Dispose();
常见问题
导出幻灯片为 PDF/图像时会渲染 OLE 内容吗?
幻灯片上可见的内容会被渲染——图标/替代图像(预览)。在渲染过程中不会执行 “实时” OLE 内容。如有需要,可设置自己的预览图像,以确保导出的 PDF 中出现预期的外观。
要同时将嵌入的文件作为 PDF 附件保留,请使用 true 调用 PdfOptions::set_IncludeOleData。此选项默认是禁用的。有关示例和检查附件的说明,请参阅 Preserve Embedded OLE Files as PDF Attachments。
如何锁定幻灯片上的 OLE 对象,使用户在 PowerPoint 中无法移动/编辑?
锁定形状:Aspose.Slides 提供了 shape-level locks。这不是加密,但能够有效防止意外的编辑和移动。
为什么在打开演示文稿时,链接的 Excel 对象会“跳动”或改变大小?
PowerPoint 可能会刷新链接 OLE 的预览。为保持稳定的外观,请遵循 Working Solution for Worksheet Resizing 的做法——要么将框适配到范围,要么将范围缩放到固定框并设置合适的替代图像。
PPTX 格式会保留链接 OLE 对象的相对路径吗?
在 PPTX 中,不提供 “相对路径” 信息——仅有完整路径。相对路径仅在旧的 PPT 格式中存在。为实现可移植性,建议使用可靠的绝对路径/可访问的 URI 或进行嵌入。