使用OpenXML将Excel内容读取到DataTable中

本文介绍如何利用OpenXML库将Excel文件中的数据读取至DataTable中,包括加载Excel文件到流、解析流内容并组织成DataTable的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    前言:前面的几篇文章简单的介绍了如何使用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中有很多种方式,这里就不赘述,本文主要介绍第二步。

        /// <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);
                    }
                    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);
        }

使用:

 

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

 

 

 

via: http://www.cnblogs.com/tewuapple/archive/2012/09/03/2668725.html

### 使用 OpenXMLExcel 文件数据导入 DataSet 为了实现从 Excel 文件读取数据并将其加载到 `DataSet` 中的功能,可以利用 Microsoft 提供的 Open XML SDK。此工具包允许开发人员处理 Office 文档而无需依赖于特定的应用程序安装。 通过使用 Open XML SDK 可以解析 `.xlsx` 文件的内容,并提取其中存储的信息以便填充至 `DataTable` 或者进一步封装成 `DataSet` 对象[^1]。 下面展示一段 C# 实现代码来完成这一操作: ```csharp using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Spreadsheet; public static class ExcelReader { public static DataSet LoadFromExcel(string filePath) { var dataSet = new DataSet(); using (SpreadsheetDocument document = SpreadsheetDocument.Open(filePath, false)) { WorkbookPart workbookPart = document.WorkbookPart; Sheet sheet = workbookPart.Workbook.Descendants<Sheet>().FirstOrDefault(); if (sheet != null) { Worksheet worksheet = ((WorksheetPart)workbookPart.GetPartById(sheet.Id)).Worksheet; SheetData data = worksheet.Elements<SheetData>().First(); string[] headers = GetHeaders(data); foreach (var header in headers) { dataTable.Columns.Add(header); } AddRowsToTable(data, dataTable); dataSet.Tables.Add(dataTable); } } return dataSet; } private static void AddRowsToTable(SheetData data, DataTable table) { bool isFirstRow = true; foreach (Row row in data.Elements<Row>()) { DataRow newRow = table.NewRow(); int cellIndex = 0; foreach (Cell cell in row.Elements<Cell>()) { if (!isFirstRow || cell.CellValue != null) { // Skip empty cells on first row. newRow[cellIndex++] = GetValue(cell); } } if (!isFirstRow && !newRow.ItemArray.All(x => x == DBNull.Value)) table.Rows.Add(newRow); isFirstRow = false; } } private static string[] GetHeaders(SheetData data) { Row headerRow = data.Elements<Row>().First(); List<string> headers = new List<string>(); foreach (Cell cell in headerRow.Elements<Cell>()) { headers.Add(GetValue(cell)); } return headers.ToArray(); } private static string GetValue(Cell cell) { SharedStringTable sst = cell?.GetParent<DocumentFormat.OpenXml.Packaging.WorksheetPart>()? .WorkbookPart.SharedStringTablePart.SharedStringTable; if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString && sst != null && int.TryParse(cell.InnerText, out int index)) { return sst.ElementAt(index).InnerText; } return cell?.CellValue.Text ?? ""; } } ``` 上述代码片段展示了如何打开指定路径下的 Excel 文件,并从中获取工作表中的所有行和列信息。对于每一行的数据项会逐一遍历其单元格内容,最终形成完整的表格结构存放在内存中作为返回值的一部分[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值