代码改变世界

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

2011-11-22 23:32  ps_zw  阅读(1402)  评论(0编辑  收藏  举报

      前言:前面的几篇文章简单的介绍了如何使用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)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();
    foreach (Cell cell in row)
    {
       string cellVal = GetValue(cell, stringTable);

       col = new DataColumn(cellVal);         

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