根据配置文件 将EXCEL中数据读入目标结构的DATASET,并对合并单元格作处理
1、类设计,EXCEL要据配置读入DATASET
using System;using System.Data;using System.Collections;using System.Data.OleDb;
namespace HKH.Common{ /// <summary> /// 从Excel导入数据到DataSet,带有虚函数的基类 /// </summary> /// <remarks>Create By Liwt on 2006 - 09 - 15 /// </remarks> public class clsImportExcel { #region 变量
protected String m_MappingFile; //映射配置文件路径 protected String m_ExcelSheetName; //Excel中要导入数据的表名 protected String m_SqlTableName; //要导入的Sql表名,也可为其它类型的,如Oracle protected ArrayList[] m_ColumnMapping; //列映射配置列表,包括3部分 0--Sql列名,1--Excel列索引 //2-- 如当前Excel行为空,是否赋值为上一行的值 private bool isLoadMapping;
#endregion
#region 构造函数
/// <summary> /// 无参构造 /// </summary> public clsImportExcel() { m_MappingFile = ""; m_ExcelSheetName = ""; isLoadMapping = false; m_ColumnMapping = new ArrayList[3]; m_ColumnMapping[0] = new ArrayList(); m_ColumnMapping[1] = new ArrayList(); m_ColumnMapping[2] = new ArrayList(); }
/// <summary> /// 构造函数重载 /// </summary> /// <param name="mappingFilePath">映射配置文件路径</param> /// <param name="excelSheetName">Excel中要导入数据的表名</param> public clsImportExcel(String mappingFilePath, String excelSheetName) { m_MappingFile = mappingFilePath; m_ExcelSheetName = excelSheetName; isLoadMapping = false; m_ColumnMapping = new ArrayList[3];
m_ColumnMapping[0] = new ArrayList(); m_ColumnMapping[1] = new ArrayList(); m_ColumnMapping[2] = new ArrayList(); }
#endregion
#region 属性
/// <summary> /// 读取或设置 映射配置文件路径 /// </summary> public String MappingFilePath { get { return m_MappingFile; } set { m_MappingFile = value; isLoadMapping = false; } }
/// <summary> /// 读取或设置 Excel中要导入数据的表名 /// </summary> public String ExcelSheetName { get { return m_ExcelSheetName; } set { m_ExcelSheetName = value; isLoadMapping = false; } }
#endregion
#region 公共方法
/// <summary> /// 导入数据 /// </summary> /// <param name="excelFilePath">要导入的Excel文件路径</param> /// <param name="dsTarget">目标DataSet</param> /// <returns>ture -- 成功, false -- 失败 /// </returns> public bool Import(String excelFilePath,ref DataSet dsTarget) { try { if (!isLoadMapping) { if (!LoadMapping()) { return false; } }
//利用Ole读取Excel数据 OleDbConnection oleConn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=Excel 8.0;Data Source=" + excelFilePath + ";"); OleDbDataAdapter oleDA = new OleDbDataAdapter("SELECT * FROM [" + m_ExcelSheetName + "$]",oleConn);
DataSet dsExcel = new DataSet(); oleDA.Fill(dsExcel,m_ExcelSheetName);
oleDA.Dispose(); oleConn.Dispose();
//对建立数据行缓存,以备填充对空单元格进行处理 DataRow tempRow = dsExcel.Tables[m_ExcelSheetName].Rows[0];
for ( int i = 0 ;i<dsExcel.Tables[m_ExcelSheetName].Rows.Count; i ++ ) { DataRow excelRow = dsExcel.Tables[m_ExcelSheetName].Rows[i];
//调用导入前数据处理函数,并根据返回值确定下一步处理 if (!ImportingBefore(ref excelRow)) { continue; }
DataRow sqlNewRow = dsTarget.Tables[0].NewRow();
for ( int j = 0 ;j<m_ColumnMapping[0].Count; j ++ ) { String sqlColName = m_ColumnMapping[0][j].ToString(); int excelColindex = (int)m_ColumnMapping[1][j]; bool inherit = Convert.ToBoolean(m_ColumnMapping[2][j]);
//如果当前行当前列为空 if (Convert.IsDBNull(excelRow[excelColindex])) { //如果允许以临时值填充 if (inherit) { sqlNewRow[sqlColName] = tempRow[excelColindex]; } } else { //填充数据,更新缓存行数据 sqlNewRow[sqlColName] = excelRow[excelColindex]; tempRow[excelColindex] = excelRow[excelColindex]; }
}
//调用导入后数据处理,并根据返回值决定下一步处理 if (ImportingAfter(ref sqlNewRow)) { dsTarget.Tables[0].Rows.Add(sqlNewRow); } }
return true; } catch(Exception ex) { throw ex; } }
#endregion
#region 受保护的虚函数,子类须重写
/// <summary> /// 在导入前对Excel行数据进行处理 /// </summary> /// <param name="drExcelRow">正在读取的当前Excel行</param> /// <returns>true -- 继续处理,false -- 跳过当前行 /// </returns> protected virtual bool ImportingBefore(ref DataRow drExcelRow) { return true; }
/// <summary> /// 在数据转存后对当前行进行处理 /// </summary> /// <param name="drSqlRow">已经转存数据的当前Sql行</param> /// <returns>true -- 继续处理,false -- 跳过当前行 /// </returns> protected virtual bool ImportingAfter(ref DataRow drSqlRow) { return true; }
#endregion
#region 私有方法
/// <summary> /// 加载配置文件,取得表和列的映射 /// </summary> /// <returns></returns> private bool LoadMapping() { try { //清除已过时的配置 m_ColumnMapping[0].Clear(); m_ColumnMapping[1].Clear(); m_ColumnMapping[2].Clear();
if ( null == m_MappingFile || "" == m_MappingFile ) { throw new Exception("找不到配置文件"); }
//读入配置文件 DataSet dsMaping = new DataSet(); dsMaping.ReadXml(m_MappingFile);
if (dsMaping.Tables.Count == 0) { throw new Exception("读取配置文件失败"); }
//读取表映射 DataRow[] tableMap = dsMaping.Tables["TableMapping"].Select("excelSheet='" + m_ExcelSheetName + "'");
if (tableMap.Length != 1) { throw new Exception("该Sheet不存在或多次配置"); }
//读取列映射 DataRow[] colMap = dsMaping.Tables["ColumnMapping"].Select("TableMapping_id="+tableMap[0]["TableMapping_id"].ToString());
if ( colMap.Length <= 0) { throw new Exception("没有为该表配置列映射"); }
for (int i = 0; i < colMap.Length; i ++) { m_ColumnMapping[0].Add(colMap[i]["sqlCol"]); m_ColumnMapping[1].Add(ExecColumnIndex(colMap[i]["excelCol"].ToString())); m_ColumnMapping[2].Add(colMap[i]["inherit"]); }
//设置为已加载配置 isLoadMapping = true;
return true; } catch { return false; } }
/// <summary> /// 计算EXCEL中列标题对应的索引 (A = 0 ) /// </summary> /// <param name="strColumnTitle"></param> /// <returns></returns> private int ExecColumnIndex( string strColumnTitle ) { if ( null == strColumnTitle || "" == strColumnTitle.Trim() ) return -1;
string temp = strColumnTitle.Trim().ToUpper();
if( 2 == temp.Length ) {// return temp[0] - 65 + 26 + temp[1] - 65; return temp[0] - 104 + temp[1]; } else { return temp[0] - 65; } }
#endregion }}
2、配置文件XSD
3、 配置文件样例
excelSheet ----要导入数据库的EXCEL文件中的工作薄名
SQLTABLE---要导入的数据库表名
EXCELCOL--EXCEL表中列标头
SQLCOL--SQL数据库中列名
inherit---当EXCEL中有表格合并时,是否继续上面的单元格值,此处用于拆解单元格,本处指合并行,TRUE为拆解,即所有单元格都以合并值填充,为FALSE则第一行为填充值,其它各行以空填充
<ImportConfiguration> <TableMapping excelSheet="Sheet1" sqlTable="CNKI_illegalIPInfo"> <ColumnMapping excelCol="A" sqlCol="UnitName" inherit="false"/> <ColumnMapping excelCol="B" sqlCol="StartIP" inherit="false"/> <ColumnMapping excelCol="C" sqlCol="EndIP" inherit="false"/> </TableMapping></ImportConfiguration>