使用Open xml 操作Excel系列之二--從data table導出數據到Excel


由於Excel中提供了透視表PivotTable,許多項目都使用它來作為數據分析報表。 在有些情況下,我們需要在Excel中設計好模板,包括數據源表,透視表等, 當數據導入到數據源表時,自動更新透視表。本篇主要講述導出數據到Excel的過程。

假設我們需要從Sql Server 中讀取數據到DataTable中,然后把DataTable中的數據寫入到Excel.

那這個導入過程大致有如下邏輯步驟:

1. 讀取數據到DataTable中。

2. 讀取Excel指定Sheet中的數據字段名。 一般情況下,我們使用表格(Sheet)的第一行作為數據字段名,則如下代碼讀取WorkSheet中的字段定義. 以下示例代碼為實際應用中我使用自定義類來匹配相應字段

 1  public class Mapping
 2     {
 3         public string SourceField { get; set; }
 4         public string DestinationCellHeader { get; set; }
 5         public string DestinationReference { get; set; }
 6         public CellType CellType { get; set; }
 9     }
10 
11     public List<Mapping> GetRawMappings(string fileName,string sheetName)
12         {
13             List<Mapping> mappings = new List<Mapping>();
14             using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, true))
15             {
16                 WorkbookPart workbookPart = document.WorkbookPart;
17                 Sheet dataSheet = workbookPart.Workbook.Descendants<Sheet>().Where(s => string.Compare(s.Name, sheetName, true) == 0).FirstOrDefault();//sheetName為你要導入數據的工作表名稱
18                 if (dataSheet != null)
19                 {
20                     WorksheetPart worksheetPart = workbookPart.GetPartById(dataSheet.Id.Value) as WorksheetPart;
21                     var headerRow = worksheetPart.Worksheet.GetFirstChild<SheetData>().Elements<Row>().
22                                             FirstOrDefault(c => c.RowIndex == 1);//讀取首行
23                     mappings = headerRow.Elements<Cell>().Select(c => new Mapping()
24                     {
25                         DestinationReference = c.CellReference.Value.Replace("1", ""),
26                         DestinationCellHeader = ExcelHelper.GetCellValue(workbookPart, c)
27                     }).ToList();
28                 }
29             }
30         }

 

3. 讀取DataTable 中的數據字段名及數據類型。

4. 匹配DataTable中的數據字段名到Excel中的數據字段名。

 

   public enum CellType
    {
        Text,
        Number,
        Date,
        Boolean
    }

       private static CellType GetCellType(System.Data.DataColumn col)
        {
            if (col.DataType == typeof(System.Decimal))
            {
                return CellType.Number;
            }
            if (col.DataType == typeof(System.Boolean ))
            {
                return CellType.Boolean ;
            }
            if (col.DataType == typeof(System.DateTime) )
            {
                return CellType.Date ;
            }
            return CellType.Text;
        }
  
//data為從sqlserver中讀取得相應的數據表
 var cols = GetRawMappings("文件名","工作表名");
 List<Mapping> allColumnMappings = new List<Mapping>();
   var sourceDataColumns = data.Columns.Cast<System.Data.DataColumn>();
   //自動匹配的列
   var colsMapped = cols.Where(c => sourceDataColumns.
                        Any(cl => string.Compare(cl.ColumnName,c.DestinationCellHeader,true) == 0)).ToList();
   foreach (Mapping ma in colsMapped)
   {
       ma.SourceField = ma.DestinationCellHeader;
       System.Data.DataColumn col = sourceDataColumns.FirstOrDefault(c => string.Compare(c.ColumnName,ma.SourceField,true)==0);
                        ma.CellType = GetCellType(col);
   }

 

5. 循環讀取每個DataRow,並根據DataColumn的字段類型,循環寫入Excel中的相應字段,並設置字段類型。

 

 1         private static Row CreateContentRow(SpreadsheetDocument document, int index, System.Data.DataRow dr,List<Mapping> mappings,Nullable<uint> dateStyleID)
 2         {
 3             //Create the new row.
 4             Row row = new Row();
 5             row.RowIndex = (UInt32)index;
 6             //First cell is a text cell, so create it and append it.
 7             //Cell firstCell = CreateTextCell(referenceHeaders[0],index);
 8             //r.AppendChild(firstCell);
 9             //Create the cells that contain the data.
10             foreach(var mapping in mappings)
11             {
12                 Cell cell = null;
13                 string source = string.Empty;
14                 
15                 if (!string.IsNullOrEmpty(mapping.SourceField))
16                     source = dr[mapping.SourceField].ToString();
17                 
18                 cell = CreateCell(document, mapping.CellType, mapping.DestinationReference, index, source, dateStyleID);
19 
20                 row.AppendChild(cell);
21             }
22           
23             return row;
24         }
25 
26    
27         public static Cell CreateCell(SpreadsheetDocument document, CellType type, string header, int index, string text, Nullable<uint> dateStyleID)
28         {
29             Cell cell = new Cell();
30             cell.CellReference = header + index;
31 
32             CellValue value = null;
33             if (type == CellType.Text  )
34             {
35                 //int stringIndex = ExcelHelper.AppendOrGetSharedStringItem(text, document);
36                 //stringIndex.ToString()
37                 value = new CellValue(text);
38                 cell.DataType = new EnumValue<CellValues>(CellValues.String);
39             }
40             if (type == CellType.Date)
41             {
42                 if (!string.IsNullOrEmpty(text))
43                 {
44                     DateTime dt = DateTime.Parse(text);
45                     value = new CellValue(dt.ToOADate().ToString());
46                 }
47                 cell.StyleIndex = dateStyleID;
48                 cell.DataType = new EnumValue<CellValues>(CellValues.Number); //new EnumValue<CellValues>(CellValues.Date);
49             }
50             if (type == CellType.Number)
51             { 
52                  cell.DataType = new EnumValue<CellValues>(CellValues.Number);
53                  value = new CellValue(text);
54             }
55             
56             cell.CellValue = value;
57             //cell.AppendChild(value);
58             return cell;
59         }
60 
61  Stylesheet styleSheet = workbookPart.WorkbookStylesPart.Stylesheet;
62  var dateStyleId = ExcelHelper.CreateCellFormat(styleSheet, null, null, UInt32Value.FromUInt32(14));
63  //var  references = headerRow.Elements<Cell>().Select(c => c.CellReference.Value.Replace("1", "")).ToList();
64  var i = 1;
65  foreach (System.Data.DataRow row in data.Rows)
66  {
67     Row contentRow = CreateContentRow(document, ((int)maxRowIndex) + i++, row, cols, dateStyleId);
68     //Append new row to sheet data.
69     sheetData.AppendChild(contentRow);
70  }

下一篇,我將使用Open Xml修改Pivot table 數據源定義

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM