// ================================================================================ // File: ExcelFile.cs // Desc: Excel操作类。 // 主要功能是用于Excel数据的导入导出。 // // Called by: // // Auth: 汪洋 // Date: 2010年8月20日 // ================================================================================ // Change History // ================================================================================ // Date: Author: Description: // -------- -------- ------------------- // // ================================================================================ // Copyright (C) 2010-2012 // ================================================================================ using System; using System.Data; using System.Data.OleDb; using System.IO; using System.Collections.Generic; using System.Collections.Specialized; using System.Text; namespace xiaoy.Excel { /// /// Excel文件操作类。 /// public class ExcelFile { #region 私有变量 //excel版本,默认为98-2003版Excel。 string m_version=string.Empty; //连接串中的HDR属性,用于标识第一行是列名。默认是。 string m_hdr = string.Empty; //excel文件路径 string m_filePath = string.Empty; DataTable m_dataSource = null; //缓存静态变量 static NameValueCollection m_excelVersion = null; static NameValueCollection m_excelTypeMap = null; static int m_maxSheelSize = 0; #endregion #region 构造函数 /// /// 静态构造函数 /// static ExcelFile() { m_excelVersion = AppConfig.GetConfig(AppConfigKey.ExcelVersionKey); m_excelTypeMap = AppConfig.GetConfig(AppConfigKey.ExcelTypeKey); m_maxSheelSize = int.Parse(AppConfig.AppSettings[AppConfigKey.MaxSheelSize]); ////将m_excelVersion值中的'替换成" //foreach (string key in m_excelVersion.Keys) //{ // m_excelVersion[key] = m_excelVersion[key].Replace("'","\""); //} } /// /// 无参构造函数 /// public ExcelFile():this(null) { } /// /// 构造函数 /// /// Excel文档版本,使用ExcelVersion类型。 public ExcelFile(string excelVersion) { //设置默认值 m_version = ExcelVersion.Excel8; m_hdr = HDRType.Yes; //覆盖默认值 if (!string.IsNullOrEmpty(excelVersion)) { m_version = excelVersion; } } #endregion #region 公用属性 /// /// 获取或设置Excel文档版本号。 /// 为ExcelVersion类型的值。 /// public string Version { get { return m_version; } set { m_version = value; } } /// /// 获取或设置HDR类型。 /// public string HDR { get { return HDR; } set { HDR = value; } } /// /// 获取或设置Excel文件路径。 /// public string FilePath { get { return m_filePath; } set { m_filePath = value; } } /// /// 获取或设置数据源。 /// public DataTable DataSource { get { return m_dataSource; } set { m_dataSource = value; } } #endregion #region 公用方法 /// /// 导入DataSource到Excel中 /// public void Import() { SetData(DataSource, FilePath, Version, HDR); } /// /// 获取Excel中的数据 /// /// 多表数据是否合并 /// DataTable集合 public DataTable[] GetData(bool bMerge) { return GetData(FilePath, Version, HDR, bMerge); } #endregion #region 公用静态方法 /// /// 写数据到Excel。 /// /// 数据源 /// Excel导出路径 /// excel版本,为ExcelVersion类型 /// 第一行是否标题,为HDRType类型 public static void SetData(DataTable dtSource, string filePath, string excelVersion, string pHDR) { //数据源为空 if (dtSource == null) { throw new Exception("无数据可导"); } //保存路径为空 if(string.IsNullOrEmpty(filePath)) { throw new Exception("未设置Excel保存路径"); } //删除文件 if (File.Exists(filePath)) { File.Delete(filePath); } string connectionString = string.Format(m_excelVersion[excelVersion], filePath,pHDR); // 连接Excel using(OleDbConnection Connection = new OleDbConnection(connectionString)) { Connection.Open(); //导入数据 using(OleDbCommand command = new OleDbCommand()) { command.Connection = Connection; //构建列 格式如:Name VarChar,CreateDate Date string colList = CreateExcelColums(dtSource); //构建插入SQL语句 //格式如 "INSERT INTO TABLE [tablename](col1,col2,col3) VALUES(@col1,@col2,@col3)"; StringBuilder sbColumNames = new StringBuilder(); StringBuilder sbColumValues = new StringBuilder(); int c = 0; foreach (DataColumn dc in dtSource.Columns) { sbColumNames.AppendFormat(",[{0}]", dc.ColumnName); sbColumValues.AppendFormat(",@{0}", "c_"+c.ToString()); c++; } //去掉多余的逗号 sbColumNames.Remove(0, 1); sbColumValues.Remove(0, 1); //当数据量超过每页最大数据量时,自动分页 int totalRows = dtSource.Rows.Count;//总数据量 int pageIndex = 0; //开始插入数据 do...while循环是为了处理分页逻辑 do { //计算此轮插入的数据量 int insertRows = m_maxSheelSize - 1; //如果总数据量没有达到容量 if (totalRows < insertRows) { insertRows = totalRows; } string tableName = dtSource.TableName + pageIndex; if (pageIndex == 0) { tableName = "Sheet1"; } //创建表框架 StringBuilder sbCom = new StringBuilder(); sbCom.Append("CREATE TABLE ["); sbCom.Append(tableName); sbCom.Append("]("); sbCom.Append(colList); sbCom.Append(")"); command.CommandText = sbCom.ToString(); try { command.ExecuteNonQuery(); } catch(Exception ex) { //如果使用Create语句创建失败则直接创建Excel文件 CreateExcelFile(filePath, excelVersion, command.CommandText); } //插入数据 sbCom = new StringBuilder(); sbCom.AppendFormat("INSERT INTO [{0}]({1}) VALUES({2})", tableName, sbColumNames.ToString(), sbColumValues.ToString()); int startIndex = pageIndex * (m_maxSheelSize-1); int endIndex = pageIndex * (m_maxSheelSize-1) + insertRows; for (int i = startIndex; i < endIndex; i++) { DataRow drData = dtSource.Rows[i]; OleDbParameterCollection dbParam = command.Parameters; dbParam.Clear(); c = 0; foreach (DataColumn dc in dtSource.Columns) { dbParam.Add(new OleDbParameter("@" + "c_"+c.ToString(), GetOleDbTypeByDataColumn(dc))); dbParam["@" + "c_" + c.ToString()].Value = drData[dc.ColumnName]; c++; } command.CommandText = sbCom.ToString(); command.ExecuteNonQuery(); } //计算剩余数据量 totalRows = totalRows - insertRows; pageIndex++; }while(totalRows > 0); }//end of using OleDbCommand }// end of using OleDbConnection } /// /// 从Excel读数据 /// /// excel文档路径 /// 文档版本 /// 第一行是否标题 /// /// 如果有多页,是否合并数据,合并时必须保证多页的表结构一致 /// /// DataTable集 public static DataTable[] GetData(string filePath, string excelVersion, string pHDR,bool bMerge) { List dtResult = new List(); string connectionString = string.Format(m_excelVersion[excelVersion], filePath,pHDR); using (OleDbConnection con = new OleDbConnection(connectionString)) { con.Open(); string[] sheels = GetExcelWorkSheets(filePath, excelVersion); foreach (string sheelName in sheels) { try { DataTable dtExcel = new DataTable(); OleDbDataAdapter adapter = new OleDbDataAdapter("Select * from [" + sheelName + "$]", con); adapter.FillSchema(dtExcel, SchemaType.Mapped); adapter.Fill(dtExcel); dtExcel.TableName = sheelName; dtResult.Add(dtExcel); } catch { //容错处理:取不到时,不报错,结果集为空即可。 } } //如果需要合并数据,则合并到第一张表 if (bMerge) { for (int i = 1; i < dtResult.Count; i++) { //如果不为空才合并 if (dtResult[0].Columns.Count==dtResult[i].Columns.Count && dtResult[i].Rows.Count > 0) { dtResult[0].Load(dtResult[i].CreateDataReader()); } } } } return dtResult.ToArray(); } #endregion #region 私有静态变量 /// /// 返回指定文件所包含的工作簿列表;如果有WorkSheet,就返回以工作簿名字命名的ArrayList,否则返回空 /// /// 要获取的Excel /// 文档版本 /// 如果有WorkSheet,就返回以工作簿名字命名的string[],否则返回空 private static string[] GetExcelWorkSheets(string filePath, string excelVersion) { List alTables = new List(); string connectionString = string.Format(m_excelVersion[excelVersion], filePath, "Yes"); using (OleDbConnection connection = new OleDbConnection(connectionString)) { connection.Open(); DataTable dt = new DataTable(); dt = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null); if (dt == null) { throw new Exception("无法获取指定Excel的架构。"); } foreach (DataRow dr in dt.Rows) { string tempName = dr["Table_Name"].ToString(); int iDolarIndex = tempName.IndexOf('$'); if (iDolarIndex > 0) { tempName = tempName.Substring(0, iDolarIndex); } //修正Excel2003中某些工作薄名称为汉字的表无法正确识别的BUG。 if (tempName[0] == '\'') { if (tempName[tempName.Length - 1] == '\'') { tempName = tempName.Substring(1, tempName.Length - 2); } else { tempName = tempName.Substring(1, tempName.Length - 1); } } if (!alTables.Contains(tempName)) { alTables.Add(tempName); } } } if (alTables.Count == 0) { return null; } return alTables.ToArray(); } /// /// 创建Excel文件 /// /// 文件路径 /// excel版本 /// 创建sheet的脚本 private static void CreateExcelFile(string filePath, string excelVersion,string createSql) { string outputDir = Path.GetDirectoryName(filePath); //导出路径不存在则创建 if (!Directory.Exists(outputDir)) { Directory.CreateDirectory(outputDir); } //导出文件不存在则创建,存在则重写 using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write)) { if (excelVersion == ExcelVersion.Excel12) { //创建2007Excel fs.Write(Properties.Resources._2007, 0, Properties.Resources._2007.Length); } else { //其他默认创建2003Excel fs.Write(Properties.Resources._2003, 0, Properties.Resources._2003.Length); } //插入Sheet表。 string connectionString = string.Format(m_excelVersion[excelVersion], filePath, "Yes"); using (OleDbConnection connection = new OleDbConnection(connectionString)) { connection.Open(); using (OleDbCommand command = new OleDbCommand()) { command.CommandText = createSql; command.ExecuteNonQuery(); } } } } /// /// 构建Excel列脚本。 /// 格式如:Name VarChar,CreateDate Date /// /// /// private static string CreateExcelColums(DataTable dtSource) { //检查列数 if (dtSource.Columns.Count == 0) { throw new Exception("数据源列数为0"); } //构建列 StringBuilder sbColums = new StringBuilder(); foreach (DataColumn dc in dtSource.Columns) { sbColums.AppendFormat(",[{0}] {1}", dc.ColumnName, GetExcelTypeByDataColumn(dc)); } //去掉多余的逗号 sbColums.Remove(0, 1); return sbColums.ToString(); } /// /// 获取DataColumn对应的Excel列类型 /// /// 源数据的列 /// Excel列类型名称 private static string GetExcelTypeByDataColumn(DataColumn dc) { foreach (string key in m_excelTypeMap.Keys) { if (key == dc.DataType.Name) { return m_excelTypeMap[dc.DataType.Name]; } } return m_excelTypeMap[AppConfigKey.DefaultTypeKey]; } /// /// 获取DataColumn对应的Excel列类型 /// /// 源数据的列 /// Excel列类型名称 private static OleDbType GetOleDbTypeByDataColumn(DataColumn dc) { switch (dc.DataType.Name) { case "String"://字符串 return OleDbType.VarChar; case "Double"://数字 return OleDbType.Double; case "Decimal"://数字 return OleDbType.Decimal; case "DateTime"://时间 return OleDbType.Date; default: return OleDbType.VarChar; } } #endregion } }