2013-04-04 29 views
3

我正在嘗試使用實體框架數據創建Excel 2010工作簿(EF不是問題)。我或多或少地遵循以下代碼:CodeProject link保存OpenXML文檔時操作共享字符串表

在上面的鏈接中創建文本單元格的代碼將所有文本創建爲內嵌字符串。爲了遵循最佳實踐(至少據我瞭解OpenXML),我想將其更改爲使用共享字符串表,因此我正在查找代碼here以提供幫助。

爲此,我從工作簿中抓取Shared strings表,添加我的字符​​串,然後保存表。我的代碼:

private static int InsertSharedStringItem(WorkbookPart wbPart, string value) 
{ 
    int index = 0; 
    bool found = false; 
    var stringTablePart = wbPart.GetPartsOfType<SharedStringTablePart>() 
         .FirstOrDefault(); 

    if (stringTablePart == null) 
    { 
    // Create it. 
    stringTablePart = wbPart.AddNewPart<SharedStringTablePart>(); 
    } 

    var stringTable = stringTablePart.SharedStringTable; 
    if (stringTable == null) 
    { 
    stringTable = new SharedStringTable(); 
    } 

    foreach (SharedStringItem item in stringTable.Elements<SharedStringItem>()) 
    { 
    if (item.InnerText == value) 
    { 
     found = true; 
     break; 
    } 
    index += 1; 
    } 

if (!found) 
    { 
    stringTable.AppendChild(new SharedStringItem(new Text(value))); 
    stringTable.Save(); 
    } 

return index; 
} 

我突出(顯然分離)的問題,區)

不幸的是我在得到一個InvalidOperationException: Cannot save DOM tree since this element is not associated with an OpenXmlPart stringTable.Save();線

我試圖通過改變來糾正這一點,如果(!找到)阻止到:

if (!found) 
{ 
    stringTable.AppendChild(new SharedStringItem(new Text(value))); 
    wbPart.SharedStringTablePart.SharedStringTable = stringTable; 
    stringtable.Save(); 
} 

當代碼擊中它返回一個UnhandledArgument Exception: Cannot set the given root element to this part. The given part root element has already been associated with another OpenXmlPart.

在這一點上新的生產線,我我不知道我的stringtable是否與OpenXmlPart相關聯。

有人可以看到我做錯了什麼,或者指出一個更好的方法來做到這一點?

回答

3

當您添加SharedStringTablePart時,立即初始化與該部件關聯的SharedStringTable。然後你不檢查SharedStringTable對象的無效性。試試這個:

if (stringTablePart == null) 
{ 
    // Create it. 
    stringTablePart = wbPart.AddNewPart<SharedStringTablePart>(); 
    stringTablePart.SharedStringTable = new SharedStringTable(); 
} 

var stringTable = stringTablePart.SharedStringTable; 
//if (stringTable == null) 
//{ 
// stringTable = new SharedStringTable(); 
//} 

我希望這個片段足以讓你識別你的函數中的部分。如果SharedStringTablePart不爲null,它將已經有一個SharedStringTable對象。如果它爲空,那麼......好吧,同時創建兩個。

2

可能對原始海報沒有用處,但是如果其他人絆倒了這一點。微軟的例子有一個模板excel文件,他們用來修改。這個答案是從頭開始創建一個excel文檔。希望這可以幫助某人。

創建並首次保存文檔時,請嘗試添加SharedStringTablePartSharedStringTable。我正在創建一個文件並將其放在臨時文件夾中,然後重新打開要修改的文件。

public string CreateSpreadsheet() 
{ 
    string filepath = Path.GetTempFileName(); 
    filepath = filepath.Replace(".tmp", ".xlsx"); 
    // Create a spreadsheet document by supplying the filepath. 
    // By default, AutoSave = true, Editable = true, and Type = xlsx. 
    SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument. 
    Create(filepath, SpreadsheetDocumentType.Workbook); 


    // Add a WorkbookPart to the document. 
    WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart(); 
    workbookpart.Workbook = new Workbook(); 
    workbookpart.Workbook.Save(); 


    **WorkbookPart wbPart = spreadsheetDocument.WorkbookPart; 
    var stringTablePart = wbPart.GetPartsOfType<SharedStringTablePart>().FirstOrDefault(); 
    if (stringTablePart == null) 
    { 
     // Create it. 
     stringTablePart = wbPart.AddNewPart<SharedStringTablePart>(); 
    } 
    stringTablePart.SharedStringTable = new SharedStringTable();** 

    // Close the document. 
    spreadsheetDocument.Close(); 
    return filepath; 
    }