2014-02-15 29 views
0

我有一個修改現有電子表格的程序。該程序的一部分創建特定工作表的副本。要創建一個副本,程序運行良好,生成的文件也很好,在Excel中打開時不會顯示錯誤。但是,在創建相同的工作表的兩個副本時,程序仍然運行得很好,但在Excel中打開時,出現以下錯誤就無法讀取內容:製作多個OpenXML工作表副本的錯誤

Repaired Records: Worksheet properties from /xl/workbook.xml part (Workbook)

這裏是用來執行復制的代碼:

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); 
    var sheetData = part.Worksheet.ChildElements[5].Clone() as SheetData; 
    var merge = part.Worksheet.ChildElements[6].Clone() as MergeCells; 
    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>(sheetData, 5); 
    //copy.Worksheet.RemoveChild<MergeCells>(copy.Worksheet.ChildElements[6] as MergeCells); 
    //copy.Worksheet.InsertAt<MergeCells>(merge, 6); 
    //copy.Worksheet.SheetProperties.CodeName.Value = "Phase" + pNum + type; 

    var sheets = Document.WorkbookPart.Workbook.Sheets; 
    var sheet = new Sheet(); 
    sheet.Id = Document.WorkbookPart.GetIdOfPart(copy); 
    sheet.Name = "Phase " + pNum + " " + type; 
    sheet.SheetId = (uint)sheets.ChildElements.Count; 
    sheets.Append(sheet); 
} 

該方法利用的是.AddPart<>()執行任何部位的深層副本(和任何它引用)的事實,已經不屬於該文件中,有一個臨時表的幫助下,創建WorkSheet的所有參考部分的深層副本。

如上所述,如果該函數僅針對給定工作表被調用一次,則該工作非常有效。但是,如果它被多次調用,則在Excel中打開文件時會出現無法讀取的內容。這就是說,文件本身似乎很好,沒有丟失數據或任何東西(這將有助於弄清楚究竟是什麼錯誤),只是錯誤說有什麼問題。

被註釋掉的行是我爲解決關於.AddPart<>()的問題所必須做的「破解」,但我不會在這裏詳細討論它們,因爲我已經發布了關於此here(但我還沒有得到答覆,所以一定要回答這個問題!)。話雖如此,這些線似乎與這個當前的問題沒有關係,因爲錯誤出現有或沒有這些代碼行。

回答

1

我注意到源文件的工作表沒有正確編號,所以他們的SheetID不是順序的(6,1,3)。因此,我的程序在使用代碼sheet.SheetID = sheets.ChildElements.Count + 1創建兩個文件副本時,將值設置爲4,5,6和7,這會導致與現有工作表發生衝突。因此,我已經修改的部分,從而該程序總是得到一個有效的ID:

// ... 
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; 
//... 

有了這個我sheetIDs成爲(6,1,3,2,4,5,7),並且因此不存在衝突,沒有更多的錯誤!

0
static WorksheetPart GetWorkSheetPart(WorkbookPart workbookPart, string sheetName) 
    { 
     //Get the relationship id of the sheetname 
     string relId = workbookPart.Workbook.Descendants<Sheet>() 
     .Where(s => s.Name.Value.Equals(sheetName)) 
     .First() 
     .Id; 
     return (WorksheetPart)workbookPart.GetPartById(relId); 
    } 

    static void FixupTableParts(WorksheetPart worksheetPart, int numTableDefParts) 
    { 
     //Every table needs a unique id and name 
     foreach (TableDefinitionPart tableDefPart in worksheetPart.TableDefinitionParts) 
     { 
      tableId++; 
      tableDefPart.Table.Id = (uint)tableId; 
      tableDefPart.Table.DisplayName = "CopiedTable" + tableId; 
      tableDefPart.Table.Name = "CopiedTable" + tableId; 
      tableDefPart.Table.Save(); 
     } 
    } 

    private void CopySheet(SpreadsheetDocument mySpreadsheet, string sheetName, string clonedSheetName) 
    { 
     WorkbookPart workbookPart = mySpreadsheet.WorkbookPart; 
     IEnumerable<Sheet> source = workbookPart.Workbook.Descendants<Sheet>(); 
     Sheet sheet = Enumerable.First<Sheet>(source, (Func<Sheet, bool>)(s => (string)s.Name == sheetName)); 
     string sheetWorkbookPartId = (string)sheet.Id; 
     WorksheetPart sourceSheetPart = (WorksheetPart)workbookPart.GetPartById(sheetWorkbookPartId); 
     SpreadsheetDocument tempSheet = SpreadsheetDocument.Create(new MemoryStream(), mySpreadsheet.DocumentType); 
     WorkbookPart tempWorkbookPart = tempSheet.AddWorkbookPart(); 
     WorksheetPart tempWorksheetPart = tempWorkbookPart.AddPart<WorksheetPart>(sourceSheetPart); 
     //Add cloned sheet and all associated parts to workbook 
     WorksheetPart clonedSheet = workbookPart.AddPart<WorksheetPart>(tempWorksheetPart); 

     int numTableDefParts = sourceSheetPart.GetPartsCountOfType<TableDefinitionPart>(); 
     tableId = numTableDefParts; 
     if (numTableDefParts != 0) 
      FixupTableParts(clonedSheet, numTableDefParts); 
     CleanView(clonedSheet); 

     //Add new sheet to main workbook part 
     Sheets sheets = workbookPart.Workbook.GetFirstChild<Sheets>(); 
     Sheet copiedSheet = new Sheet(); 
     copiedSheet.Name = clonedSheetName; 
     copiedSheet.Id = workbookPart.GetIdOfPart(clonedSheet); 
     copiedSheet.SheetId = (uint)sheets.ChildElements.Count + 1; 
     sheets.Append(copiedSheet); 
     workbookPart.Workbook.Save(); 
    } 

    static void CleanView(WorksheetPart worksheetPart) 
    { 
     SheetViews views = worksheetPart.Worksheet.GetFirstChild<SheetViews>(); 
     if (views != null) 
     { 
      views.Remove(); 
      worksheetPart.Worksheet.Save(); 
     } 
    } 
+0

Excel的表示錯誤,同時打開「修理記錄:從/xl/workbook.xml部分(工作簿)工作表屬性」和「刪除了記錄:從/xl/worksheets/sheet14.xml部分細胞信息」,可以你幫我解決? –