Word文档嵌入附件打不开问题

场景是这样的,根据模板文档生成目标文档,模板文档中会有一个附件,这个附件本身也是模板,我会根据模板附件生成一个新的附件,再调用InsertOleObjectAsIcon接口将新附件嵌入到目标文档中,同时也调用Save接口将新附件保存到本地,保存到本地的附件是能打开的且数据是正常的,但是双击目标文档中的附件总是报异常(Aspose.Words.dll为23.9版本,基于wps测试的,异常图片在附件中),打不开,这是什么原因呢?

@jumy 您能否附上您的输入和输出文档以及允许我们重现问题的代码? 我们会亲自检查问题并为您提供更多信息。 不幸的是,无法使用屏幕截图来分析问题。

我的测试场景相对复杂,还涉及到数据库的,我全部替换成用微软的office工具了,双击附件仍会报这种异常,大概会是什么原因呢?我是直接用附件模板的progId生成附件再嵌入到word中的,然后图标名字传的null,就使用默认图标生成了

@jumy 不幸的是,如果我们无法重现问题,就很难说出问题是什么。 如果可能,请提供我们这边重现问题所需的简单代码和文件。 我们将检查该问题并为您提供更多信息。

您好,我复现出来了,以下是demo,文件在附件中:

Aspose.Words.Document docTemplate = new Aspose.Words.Document("测试.docx");
Aspose.Words.Document doc = new Aspose.Words.Document();
DocumentBuilder documentbuilderDestination = new DocumentBuilder(doc);
MemoryStream memorystreamTemplate = null;
NodeCollection nodecollection = docTemplate.FirstSection.Body.GetChildNodes(NodeType.Shape, true);
try
{
    foreach (Node node in nodecollection)
    {
        memorystreamTemplate = new MemoryStream();
        ((Shape)node).OleFormat.Save(memorystreamTemplate);
        Aspose.Cells.Workbook workbookTemplate = new Aspose.Cells.Workbook(memorystreamTemplate);
        Aspose.Cells.Workbook workbookDestination = new Aspose.Cells.Workbook();
        workbookDestination.Copy(workbookTemplate);
        documentbuilderDestination.MoveToDocumentEnd();
        documentbuilderDestination.InsertOleObjectAsIcon(workbookDestination.SaveToStream(), ((Shape)node).OleFormat.ProgId, null, "用户工作流清单.xlsx");
    }
    doc.Save("目标.docx");
}
finally
{
    if (memorystreamTemplate != null)
        memorystreamTemplate.Close();
}

Demo.zip (75.6 KB)

运行结果现象:生成的目标文件中,双击用户工作流清单附件,报异常

@jumy 感谢您提供更多信息。 代码中有两个错误。 第一个 - workbookDestination.SaveToStream() 返回 MemoryStream,位置设置为末尾,因此零字节被写入 OLE 对象。 第二个 - workbookDestination.SaveToStream() 将工作簿保存为 XLS,但原始的 ProgId 设置为 XLSX 格式。 因此,要使其正常工作,您应该修改以下代码:

documentbuilderDestination.InsertOleObjectAsIcon(workbookDestination.SaveToStream(), ((Shape)node).OleFormat.ProgId, null, "用户工作流清单.xlsx");

像这样:

using (MemoryStream ms = new MemoryStream())
{
    workbookDestination.Save(ms, Aspose.Cells.SaveFormat.Xlsx);
    ms.Position = 0;
    documentbuilderDestination.InsertOleObjectAsIcon(ms, ((Shape)node).OleFormat.ProgId, null, "用户工作流清单.xlsx");
}

另外,还不太清楚为什么在这里使用 Aspose.Cells。 如果您的目标只是复制 OLE 对象,您可以修改代码,如下所示:

Document docTemplate = new Document(@"C:\Temp\in.docx");
Document doc = new Document();
DocumentBuilder documentbuilderDestination = new DocumentBuilder(doc);
NodeCollection nodecollection = docTemplate.FirstSection.Body.GetChildNodes(NodeType.Shape, true);
foreach (Node node in nodecollection)
{
    using (MemoryStream memorystreamTemplate = new MemoryStream())
    {
        ((Shape)node).OleFormat.Save(memorystreamTemplate);
        documentbuilderDestination.MoveToDocumentEnd();
        memorystreamTemplate.Position = 0;
        documentbuilderDestination.InsertOleObjectAsIcon(memorystreamTemplate, ((Shape)node).OleFormat.ProgId, null, "用户工作流清单.xlsx");
    }
}
doc.Save(@"C:\Temp\out.docx");

嗯,非常感谢,问题得到解决了。我的实际场景相对复杂,不是简单的复制OLE对象,要进行分析后再生成,所以要用到Aspose.Cells。

@jumy 您成功解决了问题,这真是太完美了。 如有任何问题,请随时询问,我们随时乐意为您提供帮助。