首页 > 解决方案 > OpenXML:如何将工作表复制到另一个工作簿?

问题描述

我需要将一些工作簿的工作表合并到一个新的工作簿中。我尝试的是这个,但我得到“无法插入 OpenXmlElement “newChild”,因为它是树的一部分。”。

using (var document = SpreadsheetDocument.Create(destinationFileName, SpreadsheetDocumentType.Workbook))
{
    // Add a WorkbookPart to the document
    var workbookPart = document.AddWorkbookPart();
    workbookPart.Workbook = new Workbook();

    // Add a WorksheetPart to the WorkbookPart
    var worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
    worksheetPart.Worksheet = new Worksheet(new SheetData());

    foreach (var sourceFileName in sourceFileNames)
    {
        using (var sourceDocument = SpreadsheetDocument.Open(sourceFileName, false))
        {
            var sheet = (Sheet)sourceDocument.WorkbookPart.Workbook.Sheets.FirstChild;
            workbookPart.Workbook.AppendChild(new Worksheet(sheet));
        }
    }
}

标签: c#excelopenxmlopenxml-sdk

解决方案


错误消息意味着您正在尝试将已经具有父级OpenXmlElement(本例中为对象)的(本例中为 a)作为新子级添加到另一个(本例中为 a)。SheetOpenXmlCompositeElementSheetsOpenXmlCompositeElementWorksheet

在以下行项目中,您正在获取对Sheet已具有父Sheets对象的对象的引用。

var sheet = (Sheet)sourceDocument.WorkbookPart.Workbook.Sheets.FirstChild;

使用new Worksheet(sheet),您正在尝试将其添加sheet到另一个父级,即Worksheet您正在创建的实例。那是行不通的。

Sheet假设将 a 添加到 a是有意义的Worksheet,您的第二行必须重写如下:

workbookPart.Workbook.AppendChild(new Worksheet(sheet.CloneNode(true)));

在上面的代码行中,sheet替换为,它会生成没有父对象sheet.CloneNode(true)的原始对象的深层副本。Sheet因此,可以将克隆作为新子代添加到另一个父代。

虽然上述解决方案是对您直接问题的回答(因为它避免了错误消息),但您的代码没有意义,因为它没有创建有效的 Open XML 标记。Worksheet实例不应该添加到Workbook实例中,Sheet实例也不应该添加到Worksheet实例中。这不是复制多个工作表的方式,这是一项非常复杂的任务,需要您创建多个工作表部件,将这些工作表部件链接到您的工作簿部件,并考虑共享字符串、样式和其他内容。


推荐阅读