2012-08-04 68 views
35

對不起,我的英語請。 我是新的打開xml sdk。 我的程序能夠將一些數據和DataTable導出到Excel文件(模板) 在模板中,我將數據插入一些佔位符。它的作品非常好,但我需要插入一個DataTable太... 我的示例代碼:用c#中的Open Xml SDK導出DataTable到Excel#

using (Stream OutStream = new MemoryStream()) 
{ 
    // read teamplate 
    using (var fileStream = File.OpenRead(templatePath)) 
     fileStream.CopyTo(OutStream); 

    // exporting 
    Exporting(OutStream); 

    // to start 
    OutStream.Seek(0L, SeekOrigin.Begin); 

    // out 
    using (var resultFile = File.Create(resultPath)) 
     OutStream.CopyTo(resultFile); 

下一頁方法導出

private void Exporting(Stream template) 
{ 
    using (var workbook = SpreadsheetDocument.Open(template, true, new OpenSettings       { AutoSave = true })) 
    { 
     // Replace shared strings 
     SharedStringTablePart sharedStringsPart = workbook.WorkbookPart.SharedStringTablePart; 
     IEnumerable<Text> sharedStringTextElements = sharedStringsPart.SharedStringTable.Descendants<Text>(); 

     DoReplace(sharedStringTextElements); 
     // Replace inline strings 
     IEnumerable<WorksheetPart> worksheetParts = workbook.GetPartsOfType<WorksheetPart>(); 

     foreach (var worksheet in worksheetParts) 
     { 
      DoReplace(worksheet.Worksheet.Descendants<Text>()); 
     } 

     int z = 40; 
     foreach (System.Data.DataRow row in ExcelWorkXLSX.ToOut.Rows) 
     { 
      for (int i = 0; i < row.ItemArray.Count(); i++) 
      { 
       ExcelWorkXLSX.InsertText(workbook, row.ItemArray.ElementAt(i).ToString(), getColumnName(i), Convert.ToUInt32(z)); } 
       z++; 
      } 
     } 

    } 
} 

但這個片段輸出數據表slooooooooooooooooooooooowwwwwww ...

如何快速,真實地將DataTable導出到Excel?

+0

你需要使用開放XML SDK? – KLIM8D 2012-08-04 21:22:51

+0

嗯...不,但打開xml sdk快速讀取/寫入excel文件。在我的程序中,我讀取xlsx文件,將數據抓取到datagridview(使用DataTable),重新檢查數據。首先,我使用互操作,但它需要優秀且非常緩慢。我的問題只是出口。但是,此刻我不想重寫很多代碼:) – user1576474 2012-08-04 21:37:25

回答

73

我寫了這個簡單的例子。這個對我有用。我只用一個數據集對其中的一個表進行了測試,但我想這對您而言可能已足夠。

考慮到我將所有單元格視爲字符串(甚至不是SharedStrings)。如果你想使用SharedStrings,你可能需要調整一下我的示例。

編輯:爲了使這項工作有必要添加WindowsBase和DocumentFormat.OpenXml引用項目。

享受,

private void ExportDataSet(DataSet ds, string destination) 
     { 
      using (var workbook = SpreadsheetDocument.Create(destination, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook)) 
      { 
       var workbookPart = workbook.AddWorkbookPart(); 

       workbook.WorkbookPart.Workbook = new DocumentFormat.OpenXml.Spreadsheet.Workbook(); 

       workbook.WorkbookPart.Workbook.Sheets = new DocumentFormat.OpenXml.Spreadsheet.Sheets(); 

       foreach (System.Data.DataTable table in ds.Tables) { 

        var sheetPart = workbook.WorkbookPart.AddNewPart<WorksheetPart>(); 
        var sheetData = new DocumentFormat.OpenXml.Spreadsheet.SheetData(); 
        sheetPart.Worksheet = new DocumentFormat.OpenXml.Spreadsheet.Worksheet(sheetData); 

        DocumentFormat.OpenXml.Spreadsheet.Sheets sheets = workbook.WorkbookPart.Workbook.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Sheets>(); 
        string relationshipId = workbook.WorkbookPart.GetIdOfPart(sheetPart); 

        uint sheetId = 1; 
        if (sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Count() > 0) 
        { 
         sheetId = 
          sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Select(s => s.SheetId.Value).Max() + 1; 
        } 

        DocumentFormat.OpenXml.Spreadsheet.Sheet sheet = new DocumentFormat.OpenXml.Spreadsheet.Sheet() { Id = relationshipId, SheetId = sheetId, Name = table.TableName }; 
        sheets.Append(sheet); 

        DocumentFormat.OpenXml.Spreadsheet.Row headerRow = new DocumentFormat.OpenXml.Spreadsheet.Row(); 

        List<String> columns = new List<string>(); 
        foreach (System.Data.DataColumn column in table.Columns) { 
         columns.Add(column.ColumnName); 

         DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell(); 
         cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String; 
         cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(column.ColumnName); 
         headerRow.AppendChild(cell); 
        } 


        sheetData.AppendChild(headerRow); 

        foreach (System.Data.DataRow dsrow in table.Rows) 
        { 
         DocumentFormat.OpenXml.Spreadsheet.Row newRow = new DocumentFormat.OpenXml.Spreadsheet.Row(); 
         foreach (String col in columns) 
         { 
          DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell(); 
          cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String; 
          cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(dsrow[col].ToString()); // 
          newRow.AppendChild(cell); 
         } 

         sheetData.AppendChild(newRow); 
        } 

       } 
      } 
     } 
+4

我認爲'workbook.WorkbookPart.Workbook = new ...'和'workbook.WorkbookPart.Workbook.Sheets = new'應該移到foreach循環之外。否則,循環的每次迭代都會替換工作表,導致excel文件僅包含最終的'DataTable'。 – Brian 2013-03-13 18:16:13

+0

@布萊恩,謝謝你指出。它最初的工作原因是我只用一個表進行測試。我只是修好了,現在看起來好嗎? – eburgos 2013-03-13 21:05:37

+2

是的,它看起來很好。作爲一個不重要的地方,調用'.Max(s => s.SheetId.Value)'比調用'.Select(s => s.SheetId.Value).Max()'更清潔。同樣,由於'DataRow'具有'DataColumn'索引器,因此不需要'列表列';第二個'foreach'也可以遍歷'table.Columns'。 – Brian 2013-03-13 21:25:32

0

你可以試試看看這個庫。我已經將它用於我的一個項目,並且發現使用起來非常簡單,可靠且快速(我只用它來導出數據)。

http://epplus.codeplex.com/

+0

謝謝!這是一個主意!我會嘗試只出口。 – user1576474 2012-08-04 22:00:38

11

eburgos,我已經修改了你的代碼稍微因爲當你在你的數據集的數據表的多個它只是覆蓋它們在電子表格中,所以你只用在一張紙上留下工作簿。我基本上只是將創建工作簿的部分移出循環。這是更新的代碼。

private void ExportDSToExcel(DataSet ds, string destination) 
{ 
    using (var workbook = SpreadsheetDocument.Create(destination, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook)) 
    { 
     var workbookPart = workbook.AddWorkbookPart(); 
     workbook.WorkbookPart.Workbook = new DocumentFormat.OpenXml.Spreadsheet.Workbook(); 
     workbook.WorkbookPart.Workbook.Sheets = new DocumentFormat.OpenXml.Spreadsheet.Sheets(); 

     uint sheetId = 1; 

     foreach (DataTable table in ds.Tables) 
     { 
      var sheetPart = workbook.WorkbookPart.AddNewPart<WorksheetPart>(); 
      var sheetData = new DocumentFormat.OpenXml.Spreadsheet.SheetData(); 
      sheetPart.Worksheet = new DocumentFormat.OpenXml.Spreadsheet.Worksheet(sheetData);     

      DocumentFormat.OpenXml.Spreadsheet.Sheets sheets = workbook.WorkbookPart.Workbook.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Sheets>(); 
      string relationshipId = workbook.WorkbookPart.GetIdOfPart(sheetPart); 

      if (sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Count() > 0) 
      { 
       sheetId = 
        sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Select(s => s.SheetId.Value).Max() + 1; 
      } 

      DocumentFormat.OpenXml.Spreadsheet.Sheet sheet = new DocumentFormat.OpenXml.Spreadsheet.Sheet() { Id = relationshipId, SheetId = sheetId, Name = table.TableName }; 
      sheets.Append(sheet); 

      DocumentFormat.OpenXml.Spreadsheet.Row headerRow = new DocumentFormat.OpenXml.Spreadsheet.Row(); 

      List<String> columns = new List<string>(); 
      foreach (DataColumn column in table.Columns) 
      { 
       columns.Add(column.ColumnName); 

       DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell(); 
       cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String; 
       cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(column.ColumnName); 
       headerRow.AppendChild(cell); 
      } 

      sheetData.AppendChild(headerRow); 

      foreach (DataRow dsrow in table.Rows) 
      { 
       DocumentFormat.OpenXml.Spreadsheet.Row newRow = new DocumentFormat.OpenXml.Spreadsheet.Row(); 
       foreach (String col in columns) 
       { 
        DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell(); 
        cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String; 
        cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(dsrow[col].ToString()); // 
        newRow.AppendChild(cell); 
       } 

       sheetData.AppendChild(newRow); 
      } 
     } 
    } 
} 
+0

謝謝,剛剛看到Brian的評論,我也對我做了同樣的評論。 – eburgos 2013-03-13 21:06:28

0

你可以看看我的圖書館here。在文檔部分下,您將找到如何導入數據表。

你只需要編寫

using (var doc = new SpreadsheetDocument(@"C:\OpenXmlPackaging.xlsx")) { 
    Worksheet sheet1 = doc.Worksheets.Add("My Sheet"); 
    sheet1.ImportDataTable(ds.Tables[0], "A1", true); 
} 

希望它能幫助!

1

我寫了我自己的出口到Excel作家,因爲沒有別的完全滿足我的需求。它速度很快,並允許大量格式的單元格。您可以在

https://openxmlexporttoexcel.codeplex.com/

審查,我希望它能幫助。

7

我還寫了一個C#/ VB.Net「導出到Excel」庫,使用OpenXML和(更重要的是)也使用OpenXmlWriter,因此在寫入大文件時不會耗盡內存。

完整的源代碼和演示,可以在這裏下載:

Export to Excel

它的死很容易使用。 只需將它傳遞給您要寫入的文件名即可,並且可以使用DataTable,DataSetList<>

CreateExcelFile.CreateExcelDocument(myDataSet, "MyFilename.xlsx"); 

而且如果你從一個ASP.Net應用程序中調用它,它傳遞的HttpResponse到文件寫出來。

CreateExcelFile.CreateExcelDocument(myDataSet, "MyFilename.xlsx", Response); 
+0

鏈接已經死了... – Arwin 2016-06-21 07:31:21

+1

對不起...!它現在還活着,踢起來。 – 2016-06-21 08:01:07

+0

@MikeGledhill任何解決方法異步執行它?當我嘗試寫入一個巨大的文件時,出現內存異常,我讀過所有相關的帖子,看起來似乎只限於可用內存? – afr0 2018-01-10 01:24:43

0

我試着接受答案,並得到消息說生成的excel文件在試圖打開時被破壞。我可以通過做一些修改來修復它,比如在代碼的下面添加代碼。

workbookPart.Workbook.Save();

我已經發布完整的代碼@Export DataTable to Excel with Open XML in c#