在先前被修改的OpenXML中复制工作表

我已经按照这里使用的例程将工作簿中的工作表复制到相同的工作簿中,通过使用.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中的引用对象也被复制。

这个工作,就像我现在有一份原始文档中的工作表一样。 但是,在调用CopySheet()之前,由SetupPages()所做的所有修改不会出现在复制的工作表中。 所以我现在有原来的工作表(在这个例子中)11行和复制的工作表只有1行。

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

有没有我不知道的OpenXML技巧?

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

 public void SetupPages(int p, int nSections) { Regex rn = new Regex("[0-9]+"); Regex rs = new Regex("[AZ]+"); 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完成的修改)的克隆,并将其设置为复制工作SheetSheetData 。 我只是在这里发布信息的目的,但如果有人仍然可以请指出,我没有看到代码中的错误,我会非常感激。 如果有人感兴趣,这里是CopySheet()的“黑客”版本。

 private void CopySheet(int sNum) { var tempSheet = SpreadsheetDocument.Create(new MemoryStream(), SpreadsheetDocumentType.Workbook); WorkbookPart tempWBP = tempSheet.AddWorkbookPart(); var part = Document.XGetWorkSheetPart(sNum); var b = part.Worksheet.ChildElements[5].Clone() as SheetData; WorksheetPart tempWSP = tempWBP.AddPart<WorksheetPart>(part); var copy = Document.WorkbookPart.AddPart<WorksheetPart>(tempWSP); copy.Worksheet.RemoveChild<SheetData>(copy.Worksheet.ChildElements[5] as SheetData); copy.Worksheet.InsertAt<SheetData>(b, 5); 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); } 

我已经尽我所能地解决了这个问题(从我从其他论坛收集到的信息,最好的“他们”可以)通过在创build副本之前closures和打开文件来解决这个问题。 这使更改永久,然后,复制时,更改也被复制。 由此,上述的“黑客”变得不必要了。 代码的最终版本因此变成了(为避免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); }