我已使用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 = 15
(SetupPages
之后的预期行数)。但是,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()
答案 0 :(得分:1)
我已经尽我所能解决了这个问题(并且我从其他论坛收集的内容中,通过关闭和打开,我已经问过,最好的&#34;他们可以#34;)创建副本之前的文件。这会使更改成为永久更改,然后在复制时也会复制更改。有了这个,&#34; hack&#34;如上所述变得不必要。因此,代码的最终版本变为(通过更改以避免SheetID
和Sheet.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);
}