在以前修改过的OpenXML中复制工作表

时间:2014-02-14 22:53:51

标签: c# excel openxml

我已使用here例程将工作簿中的工作表复制到同一工作簿中,使用.AddPart<>()和临时工作簿作为中间人,但提出了一些问题。在复制工作表之前,我已对其进行了修改。但是,工作表的复制版本保留原始工作表,而不是修改后的工作表。这是代码:

Document = SpreadsheetDocument.Open(filename, true);
SetupPages(0, nSections);
CopySheet(1);

SetupPages()只需获取一个工作表,该工作表只有一行表,然后将该行复制nSections - 1次,以便该表以nSections行结束。这很有效。

CopySheet()包含以下代码:

private void CopySheet(int sNum)
{
    var tempSheet = SpreadsheetDocument.Create(new MemoryStream(), SpreadsheetDocumentType.Workbook);
    WorkbookPart tempWBP = tempSheet.AddWorkbookPart();
    var part = Document.XGetWorkSheetPart(sNum);
    WorksheetPart tempWSP = tempWBP.AddPart<WorksheetPart>(part);
    var copy = Document.WorkbookPart.AddPart<WorksheetPart>(tempWSP);

    var sheets = Document.WorkbookPart.Workbook.GetFirstChild<Sheets>();
    var sheet = new Sheet();
    sheet.Id = Document.WorkbookPart.GetIdOfPart(copy);
    sheet.Name = "AAA";
    sheet.SheetId = (uint)sheets.ChildElements.Count + 1;
    sheets.Append(sheet);
}

此方法获取所需的workSheetPart并使用tempSheet.AddPart<>()执行所需部分的深层副本,然后再次使用它将其深层复制回原始文档。这样,所有workSheetPart中包含的所有引用对象也将被复制。

这很有用,因为我现在在原始文档中有一份workSheet副本。但是,SetupPages()在调用CopySheet()之前所做的所有修改都不会出现在复制的工作表中。所以我现在有原始的Sheet(在这个例子中)有11行,复制的Sheet只有1行。

我尝试在Document.WorkBookPart.WorkBook.Save()SetupPages()之间放置一个CopySheet(),看看“保存更改”是否也可以复制它们,但无济于事。< / p>

是否有任何我不知道的OpenXML技巧?

编辑:使用调试器我刚刚注意到part.WorkSheet.ChildElements.Count = 15SetupPages之后的预期行数)。但是,tempWBP.WorkSheet.ChildElements.Count = 5(修改SetupPages之前原始工作表中的行数)。无论出于何种原因,我的程序添加的新Rows都没有被深层复制。现在我只是不明白。 如果它与我的部分或某些行的不正确绑定有关,这里是SetupPages()的定义:

public void SetupPages(int p, int nSections)
{
    Regex rn = new Regex("[0-9]+");
    Regex rs = new Regex("[A-Z]+");
    SheetData sData = Document.XGet<SheetData>(2 * p + 1);
    for (uint i = 1; i < nSections; i++)
    {
        var r = sData.ChildElements.GetItem(4).Clone() as Row;
        r.RowIndex.Value += i;
        foreach (OpenXmlElement _c in r.ChildElements)
        {
            var c = _c as Cell;
            Match mn = rn.Match(c.CellReference.Value);
            Match ms = rs.Match(c.CellReference.Value);
            string str = (int.Parse(mn.Value) + i).ToString();
            c.CellReference.Value = ms.Value + str;
        }
        (r.FirstChild as Cell).CellValue = new CellValue((i + 1).ToString());
        sData.Append(r);
    }
}

编辑2:我已经能够完全复制,但它非常不优雅并且不能解决代码中明显错误的问题,而只是一种假装的紧急措施没有问题。我基本上得到原始SheetData的克隆(其中包含SetupPages中完成的修改),并将其设置为复制的SheetData的{​​{1}}。我只是在这里发布信息用于提供信息,但如果有人仍然可以指出我没有看到的代码中有什么问题,我会非常感激。如果有人感兴趣的话,这是Sheet的“黑客”版本。

CopySheet()

1 个答案:

答案 0 :(得分:1)

我已经尽我所能解决了这个问题(并且我从其他论坛收集的内容中,通过关闭和打开,我已经问过,最好的&#34;他们可以#34;)创建副本之前的文件。这会使更改成为永久更改,然后在复制时也会复制更改。有了这个,&#34; hack&#34;如上所述变得不必要。因此,代码的最终版本变为(通过更改以避免SheetIDSheet.Name冲突):

private void CopySheet(int sNum, int pNum, string type)
{
    var tempSheet = SpreadsheetDocument.Create(new MemoryStream(), SpreadsheetDocumentType.Workbook);
    WorkbookPart tempWBP = tempSheet.AddWorkbookPart();
    var part = Document.XGetWorkSheetPart(sNum);
    WorksheetPart tempWSP = tempWBP.AddPart<WorksheetPart>(part);
    var copy = Document.WorkbookPart.AddPart<WorksheetPart>(tempWSP);
    var sheets = Document.WorkbookPart.Workbook.GetFirstChild<Sheets>();
    var sheet = new Sheet();
    sheet.Id = Document.WorkbookPart.GetIdOfPart(copy);
    sheet.Name = "Phase " + pNum + " " + type;
    uint id = 1;
    bool valid = false;
    while (!valid)
    {
        uint temp = id;
        foreach (OpenXmlElement e in sheets.ChildElements)
        {
            var s = e as Sheet;
            if (id == s.SheetId.Value)
            {
                id++;
                break;
            }
        }
        if (temp == id)
            valid = true;
    }
    sheet.SheetId = id;
    sheets.Append(sheet);
}