使用OpenXML將Excel內容讀取到DataTable中


        /// <summary>
        /// 按照給定的Excel流組織成Datatable
        /// </summary>
        /// <param name="stream">Excel文件流</param>
        /// <param name="sheetName">須要讀取的Sheet</param>
        /// <returns>組織好的DataTable</returns>
        private DataTable ReadExcel(string sheetName, Stream stream)
        {
            using (SpreadsheetDocument document = SpreadsheetDocument.Open(stream, false))
            {//打開Stream
                IEnumerable<Sheet> sheets = document.WorkbookPart.Workbook.Descendants<Sheet>().Where(s => s.Name == sheetName);
                if (sheets.Count() == 0)
                {//找出合適前提的sheet,沒有則返回
                    return null;
                }
                WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(sheets.First().Id);
                //獲取Excel中共享數據
                SharedStringTable stringTable = document.WorkbookPart.SharedStringTablePart.SharedStringTable;
                IEnumerable<Row> rows = worksheetPart.Worksheet.Descendants<Row>();//獲得Excel中得數據行
                DataTable dt = new DataTable("Excel");
                //因為須要將數據導入到DataTable中,所以我們假定Excel的第一行是列名,從第二行開端是行數據
                foreach (Row row in rows)
                {
                    if (row.RowIndex == 1)
                    {//Excel第一行動列名
                        GetDataColumn(row, stringTable, ref dt);
                    }
                    else
                        GetDataRow(row, stringTable, ref dt);//Excel第二行同時為DataTable的第一行數據
                }
                return dt;
            }
        }
        /// <summary>
        /// 構建DataTable的列
        /// </summary>
        /// <param name="row">OpenXML定義的Row對象</param>
        /// <param name="stringTablePart"></param>
        /// <param name="dt">須要返回的DataTable對象</param>
        /// <returns></returns>
        public void GetDataColumn(Row row, SharedStringTable stringTable, ref DataTable dt)
        {
            DataColumn col = new DataColumn();
            Dictionary<string, int> columnCount = new Dictionary<string, int>();
            foreach (Cell cell in row)
            {
                string cellVal = GetValue(cell, stringTable);
                col = new DataColumn(cellVal);
                if (IsContainsColumn(dt, col.ColumnName))
                {
                    if(!columnCount.ContainsKey(col.ColumnName))
                        columnCount.Add(col.ColumnName, 0);
                    col.ColumnName = col.ColumnName + (columnCount[col.ColumnName]++);
                }
                dt.Columns.Add(col);
            }
        }
        /// <summary>
        /// 構建DataTable的每一行數據,並返回該Datatable
        /// </summary>
        /// <param name="row">OpenXML的行</param>
        /// <param name="stringTablePart"></param>
        /// <param name="dt">DataTable</param>
        private void GetDataRow(Row row, SharedStringTable stringTable, ref DataTable dt)
        {
            // 讀取算法:按行一一讀取單位格,若是整行均是空數據
            // 則忽視改行(因為本人的工作內容不須要空行)-_-
            DataRow dr = dt.NewRow();
            int i = 0;
            int nullRowCount = i;
            foreach (Cell cell in row)
            {
                string cellVal = GetValue(cell, stringTable);
                if (cellVal == string.Empty)
                {
                    nullRowCount++;
                }
                dr[i] = cellVal;
                i++;
            }
            if (nullRowCount != i)
            {
                dt.Rows.Add(dr);
            }
        }
        /// <summary>
        /// 獲取單位格的值
        /// </summary>
        /// <param name="cell"></param>
        /// <param name="stringTablePart"></param>
        /// <returns></returns>
        private string GetValue(Cell cell, SharedStringTable stringTable)
        {
            //因為Excel的數據存儲在SharedStringTable中,須要獲取數據在SharedStringTable 中的索引
            string value = string.Empty;
            try
            {
                if (cell.ChildElements.Count == 0)
                    return value;
                value = double.Parse(cell.CellValue.InnerText).ToString();
                if ((cell.DataType != null) && (cell.DataType == CellValues.SharedString))
                {
                    value = stringTable.ChildElements[Int32.Parse(value)].InnerText;
                }
            }
            catch (Exception)
            {
                value = "N/A";
            }
            return value;
        }
        /// <summary>
        /// 判斷網格是否存在列
        /// </summary>
        /// <param name="dt">網格</param>
        /// <param name="columnName">列名</param>
        /// <returns></returns>
        public bool IsContainsColumn(DataTable dt, string columnName)
        {
            if (dt == null || columnName == null)
            {
                return false;
            }
            return dt.Columns.Contains(columnName);
        }        

  

前言:前面的幾篇文章簡單的介紹了如何使用OpenXML創建Excel文檔。由於在平時的工作中需要經常使用到Excel的讀寫操作,簡單的介紹下使用OpenXML讀取Excel中得數據。當然使用OpenXML將數據讀取成什么格式並不重要,本文僅僅介紹如何讀取到DataTable中。

准備工作:

      1. Excel2007文檔一個;

      2. OpenXML庫:DocumentFormat.OpenXml.dll;

      3. Console項目一個,添加對OpenXML庫和WindowsBase.dll的引用。

廢話不多說,進入正題.

本文介紹的讀取Excel的思路如下:

1. 將Excel加載到流Stream;

2. 使用OpenXML操作Stream,並寫入DataTable中。

將文件加載到Stream中有很多種方式,這里就不贅述,本文主要介紹第二步。


使用:

 

 

View Code
1       FileStream fs =  new FileStream( @" D:\工作簿1.xlsx ", FileMode.Open, FileAccess.Read, FileShare.Read);
2         DataTable dt=ReadExcel( " Sheet1 ",fs);


免責聲明!

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



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