Excel操作輔助類ExcelHelper

實現效果

  • 本輔助類主要是用來方便實現對Excel的相關操作,不需要調用Office的VBA相關類。 該導出操作是基於XML文件和OleDB格式的,因此導出Excel文件不需要客戶端安裝Excel軟件,因此非常方便易用。
  • 輔助類可以列出Excel的所有表、列出指定表的所有列、從Excel轉換爲DataSet對象集合、把DataSet轉換保存爲Excel文件等操作。

實現步驟

在代碼引用相關的代碼實現動態調用。

實現代碼

  • 輔助類提供的方法接口如下所示:
 #region 獲取Excel連接字符串    
/// 返回Excel 連接字符串   [IMEX=1]  
public static string GetExcelConnectstring(string excelPath, bool header, ExcelType eType)   
/// 返回Excel 連接字符串   
public static string GetExcelConnectstring(string excelPath, bool header, ExcelType eType, IMEXType imex)   
#endregion   
#region 獲取Excel工作表名    
/// 返回Excel工作表名    
public static List<string> GetExcelTablesName(string excelPath, ExcelType eType)    
/// 返回Excel工作表名   
public static List<string> GetExcelTablesName(string connectstring)    
/// 返回Excel工作表名    
public static List<string> GetExcelTablesName(OleDbConnection connection)    
/// 返回Excel第一個工作表表名  
public static string GetExcelFirstTableName(string excelPath, ExcelType eType)    
/// 返回Excel第一個工作表表名 
public static string GetExcelFirstTableName(string connectstring)    
/// 返回Excel第一個工作表表名    
public static string GetExcelFirstTableName(OleDbConnection connection)    
/// 獲取Excel文件中指定工作表的列     
public static List<string> GetColumnsList(string excelPath, ExcelType eType, string table)   
#endregion   

#region EXCEL導入DataSet    
/// EXCEL導入DataSet    
public static DataSet ExcelToDataSet(string excelPath, string table, bool header, ExcelType eType)    
/// 判斷工作表名是否存在  
private static bool isExistExcelTableName(OleDbConnection connection, string table)    
/// EXCEL導入DataSet  
public static DataSet ExcelToDataSet(string connectstring, string table)    
/// EXCEL所有工作表導入DataSet 
public static DataSet ExcelToDataSet(string excelPath, bool header, ExcelType eType)
/// EXCEL所有工作表導入DataSet 
public static DataSet ExcelToDataSet(string connectstring) 
#endregion 
/// 把一個數據集中的數據導出到Excel文件中(XML格式操作)    
public static void DataSetToExcel(DataSet source, string fileName) 
/// 將DataTable到處爲Excel(OleDb 方式操作)   
public static void DataSetToExcel(DataTable dataTable, string fileName)   

  • 輔助類ExcelHeper的使用例子代碼如下所示:
string filePath = @"C:\test.xls";    
//獲取第一個表名    
string sheetname = ExcelHelper.GetExcelFirstTableName(filePath, ExcelHelper.ExcelType.Excel2003);//Sheet1$      
//列出所有表名稱    
List<string> tableList = ExcelHelper.GetExcelTablesName(filePath, ExcelHelper.ExcelType.Excel2003);
//從Excel轉換爲DataSet對象集合    
DataSet ds =  ExcelHelper.ExcelToDataSet(filePath, true, ExcelHelper.ExcelType.Excel2003); 
//列出指定表的列名稱    
List<string> columnList = ExcelHelper.GetColumnsList(filePath, ExcelHelper.ExcelType.Excel2003, "Sheet1$"); 
//綁定數據顯示    
this.dataGridView1.DataSource = ds.Tables[0].DefaultView;
//導出DataSet到Excel文件中    
filePath = FileDialogHelper.SaveExcel();
ExcelHelper.DataSetToExcel(ds, filePath);    
Process.Start(filePath);  

附上源碼

/// <summary>
/// Excel操作輔助類(無需VBA引用)
/// </summary>
public class ExcelHelper
{
        /// <summary>
        /// Excel 版本
        /// </summary>
        public enum ExcelType
        {
            Excel2003, Excel2007
        }

        /// <summary>
        /// IMEX 三種模式。
        /// IMEX是用來告訴驅動程序使用Excel文件的模式,其值有0、1、2三種,分別代表導出、導入、混合模式。
        /// </summary>
        public enum IMEXType
        {
            ExportMode = 0, ImportMode = 1, LinkedMode = 2
        }

        #region 獲取Excel連接字符串

        /// <summary>
        /// 返回Excel 連接字符串   [IMEX=1]
        /// </summary>
        /// <param name="excelPath">Excel文件 絕對路徑</param>
        /// <param name="header">是否把第一行作爲列名</param>
        /// <param name="eType">Excel 版本 </param>
        /// <returns></returns>
        public static string GetExcelConnectstring(string excelPath, bool header, ExcelType eType)
        {
            return GetExcelConnectstring(excelPath, header, eType, IMEXType.ImportMode);
        }

        /// <summary>
        /// 返回Excel 連接字符串
        /// </summary>
        /// <param name="excelPath">Excel文件 絕對路徑</param>
        /// <param name="header">是否把第一行作爲列名</param>
        /// <param name="eType">Excel 版本 </param>
        /// <param name="imex">IMEX模式</param>
        /// <returns></returns>
        public static string GetExcelConnectstring(string excelPath, bool header, ExcelType eType, IMEXType imex)
        {
            if (!FileUtil.IsExistFile(excelPath))
                throw new FileNotFoundException("Excel路徑不存在!");

            string connectstring = string.Empty;

            string hdr = "NO";
            if (header)
                hdr = "YES";

            if (eType == ExcelType.Excel2003)
                connectstring = "Provider=Microsoft.Jet.OleDb.4.0; data source=" + excelPath + ";Extended Properties='Excel 8.0; HDR=" + hdr + "; IMEX=" + imex.GetHashCode() + "'";
            else
                connectstring = "Provider=Microsoft.ACE.OLEDB.12.0; data source=" + excelPath + ";Extended Properties='Excel 12.0 Xml; HDR=" + hdr + "; IMEX=" + imex.GetHashCode() + "'";

            return connectstring;
        }

        #endregion

        #region 獲取Excel工作表名

        /// <summary>
        /// 返回Excel工作表名
        /// </summary>
        /// <param name="excelPath">Excel文件 絕對路徑</param>
        /// <param name="eType">Excel 版本 </param>
        /// <returns></returns>
        public static List<string> GetExcelTablesName(string excelPath, ExcelType eType)
        {
            string connectstring = GetExcelConnectstring(excelPath, true, eType);
            return GetExcelTablesName(connectstring);
        }

        /// <summary>
        /// 返回Excel工作表名
        /// </summary>
        /// <param name="connectstring">excel連接字符串</param>
        /// <returns></returns>
        public static List<string> GetExcelTablesName(string connectstring)
        {
            using (OleDbConnection conn = new OleDbConnection(connectstring))
            {
                return GetExcelTablesName(conn);
            }
        }

        /// <summary>
        /// 返回Excel工作表名
        /// </summary>
        /// <param name="connection">excel連接</param>
        /// <returns></returns>
        public static List<string> GetExcelTablesName(OleDbConnection connection)
        {
            List<string> list = new List<string>();

            if (connection.State == ConnectionState.Closed)
                connection.Open();

            DataTable dt = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
            if (dt != null && dt.Rows.Count > 0)
            {
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    list.Add(ConvertHelper.ConvertTo<string>(dt.Rows[i][2]));
                }
            }

            return list;
        }

        /// <summary>
        /// 返回Excel第一個工作表表名
        /// </summary>
        /// <param name="excelPath">Excel文件 絕對路徑</param>
        /// <param name="eType">Excel 版本 </param>
        /// <returns></returns>
        public static string GetExcelFirstTableName(string excelPath, ExcelType eType)
        {
            string connectstring = GetExcelConnectstring(excelPath, true, eType);
            return GetExcelFirstTableName(connectstring);
        }

        /// <summary>
        /// 返回Excel第一個工作表表名
        /// </summary>
        /// <param name="connectstring">excel連接字符串</param>
        /// <returns></returns>
        public static string GetExcelFirstTableName(string connectstring)
        {
            using (OleDbConnection conn = new OleDbConnection(connectstring))
            {
                return GetExcelFirstTableName(conn);
            }
        }

        /// <summary>
        /// 返回Excel第一個工作表表名
        /// </summary>
        /// <param name="connection">excel連接</param>
        /// <returns></returns>
        public static string GetExcelFirstTableName(OleDbConnection connection)
        {
            string tableName = string.Empty;

            if (connection.State == ConnectionState.Closed)
                connection.Open();

            DataTable dt = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
            if (dt != null && dt.Rows.Count > 0)
            {
                tableName = ConvertHelper.ConvertTo<string>(dt.Rows[0][2]);
            }

            return tableName;
        }

        /// <summary>
        /// 獲取Excel文件中指定工作表的列
        /// </summary>
        /// <param name="excelPath">Excel文件 絕對路徑</param>
        /// <param name="eType">Excel版本</param>
        /// <param name="table">名稱 excel table  例如:Sheet1$</param>
        /// <returns></returns>
        public static List<string> GetColumnsList(string excelPath, ExcelType eType, string table)
        {
            List<string> list = new List<string>();
            DataTable tableColumns = null;
            string connectstring = GetExcelConnectstring(excelPath, true, eType);
            using (OleDbConnection conn = new OleDbConnection(connectstring))
            {
                conn.Open();
                tableColumns = GetReaderSchema(table, conn);
            }
            foreach (DataRow dr in tableColumns.Rows)
            {
                string columnName = dr["ColumnName"].ToString();
                string datatype = ((OleDbType)dr["ProviderType"]).ToString();//對應數據庫類型
                string netType = dr["DataType"].ToString();//對應的.NET類型,如System.String
                list.Add(columnName);
            }         

            return list;
        }

        private static DataTable GetReaderSchema(string tableName, OleDbConnection connection)
        {
            DataTable schemaTable = null;
            IDbCommand cmd = new OleDbCommand();
            cmd.CommandText = string.Format("select * from [{0}]", tableName);
            cmd.Connection = connection;

            using (IDataReader reader = cmd.ExecuteReader(CommandBehavior.KeyInfo | CommandBehavior.SchemaOnly))
            {
                schemaTable = reader.GetSchemaTable();
            }
            return schemaTable;
        }

        #endregion

        #region EXCEL導入DataSet

        /// <summary>
        /// EXCEL導入DataSet
        /// </summary>
        /// <param name="excelPath">Excel文件 絕對路徑</param>
        /// <param name="table">名稱 excel table  例如:Sheet1$ </param>
        /// <param name="header">是否把第一行作爲列名</param>
        /// <param name="eType">Excel 版本 </param>
        /// <returns>返回Excel相應工作表中的數據 DataSet   [table不存在時返回空的DataSet]</returns>
        public static DataSet ExcelToDataSet(string excelPath, string table, bool header, ExcelType eType)
        {
            string connectstring = GetExcelConnectstring(excelPath, header, eType);
            return ExcelToDataSet(connectstring, table);
        }

        /// <summary>
        /// 判斷工作表名是否存在
        /// </summary>
        /// <param name="connection">excel連接</param>
        /// <param name="table">名稱 excel table  例如:Sheet1$</param>
        /// <returns></returns>
        private static bool isExistExcelTableName(OleDbConnection connection, string table)
        {
            List<string> list = GetExcelTablesName(connection);
            foreach (string tName in list)
            {
                if (tName.ToLower() == table.ToLower())
                    return true;
            }

            return false;
        }

        /// <summary>
        /// EXCEL導入DataSet
        /// </summary>
        /// <param name="connectstring">excel連接字符串</param>
        /// <param name="table">名稱 excel table  例如:Sheet1$ </param>
        /// <returns>返回Excel相應工作表中的數據 DataSet   [table不存在時返回空的DataSet]</returns>
        public static DataSet ExcelToDataSet(string connectstring, string table)
        {
            using (OleDbConnection conn = new OleDbConnection(connectstring))
            {
                DataSet ds = new DataSet();

                //判斷該工作表在Excel中是否存在
                if (isExistExcelTableName(conn, table))
                {
                    OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM [" + table + "]", conn);
                    adapter.Fill(ds, table);
                }

                return ds;
            }
        }

        /// <summary>
        /// EXCEL所有工作表導入DataSet
        /// </summary>
        /// <param name="excelPath">Excel文件 絕對路徑</param>
        /// <param name="header">是否把第一行作爲列名</param>
        /// <param name="eType">Excel 版本 </param>
        /// <returns>返回Excel第一個工作表中的數據 DataSet </returns>
        public static DataSet ExcelToDataSet(string excelPath, bool header, ExcelType eType)
        {
            string connectstring = GetExcelConnectstring(excelPath, header, eType);
            return ExcelToDataSet(connectstring);
        }

        /// <summary>
        /// EXCEL所有工作表導入DataSet
        /// </summary>
        /// <param name="connectstring">excel連接字符串</param>
        /// <returns>返回Excel第一個工作表中的數據 DataSet </returns>
        public static DataSet ExcelToDataSet(string connectstring)
        {
            using (OleDbConnection conn = new OleDbConnection(connectstring))
            {
                DataSet ds = new DataSet();
                List<string> tableNames = GetExcelTablesName(conn);

                foreach (string tableName in tableNames)
                {
                    OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM [" + tableName + "]", conn);
                    adapter.Fill(ds, tableName);
                }
                return ds;
            }
        }

        #endregion

        /// <summary>
        /// 把一個數據集中的數據導出到Excel文件中(XML格式操作)
        /// </summary>
        /// <param name="source">DataSet數據</param>
        /// <param name="fileName">保存的Excel文件名</param>
        public static void DataSetToExcel(DataSet source, string fileName)
        {
            #region Excel格式內容
            var excelDoc = new StreamWriter(fileName);
            const string startExcelXML = "<xml version>\r\n<Workbook " +
                  "xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\r\n" +
                  " xmlns:o=\"urn:schemas-microsoft-com:office:office\"\r\n " +
                  "xmlns:x=\"urn:schemas-    microsoft-com:office:" +
                  "excel\"\r\n xmlns:ss=\"urn:schemas-microsoft-com:" +
                  "office:spreadsheet\">\r\n <Styles>\r\n " +
                  "<Style ss:ID=\"Default\" ss:Name=\"Normal\">\r\n " +
                  "<Alignment ss:Vertical=\"Bottom\"/>\r\n <Borders/>" +
                  "\r\n <Font/>\r\n <Interior/>\r\n <NumberFormat/>" +
                  "\r\n <Protection/>\r\n </Style>\r\n " +
                  "<Style ss:ID=\"BoldColumn\">\r\n <Font " +
                  "x:Family=\"Swiss\" ss:Bold=\"1\"/>\r\n </Style>\r\n " +
                  "<Style     ss:ID=\"StringLiteral\">\r\n <NumberFormat" +
                  " ss:Format=\"@\"/>\r\n </Style>\r\n <Style " +
                  "ss:ID=\"Decimal\">\r\n <NumberFormat " +
                  "ss:Format=\"#,##0.###\"/>\r\n </Style>\r\n " +
                  "<Style ss:ID=\"Integer\">\r\n <NumberFormat " +
                  "ss:Format=\"0\"/>\r\n </Style>\r\n <Style " +
                  "ss:ID=\"DateLiteral\">\r\n <NumberFormat " +
                  "ss:Format=\"yyyy-mm-dd;@\"/>\r\n </Style>\r\n " +
                  "</Styles>\r\n ";
            const string endExcelXML = "</Workbook>"; 
            #endregion

            int sheetCount = 1;
            excelDoc.Write(startExcelXML);
            for (int i = 0; i < source.Tables.Count; i++)
            {
                int rowCount = 0;
                DataTable dt = source.Tables[i];

                excelDoc.Write("<Worksheet ss:Name=\"Sheet" + sheetCount + "\">");
                excelDoc.Write("<Table>");
                excelDoc.Write("<Row>");
                for (int x = 0; x < dt.Columns.Count; x++)
                {
                    excelDoc.Write("<Cell ss:StyleID=\"BoldColumn\"><Data ss:Type=\"String\">");
                    excelDoc.Write(source.Tables[0].Columns[x].ColumnName);
                    excelDoc.Write("</Data></Cell>");
                }
                excelDoc.Write("</Row>");
                foreach (DataRow x in dt.Rows)
                {
                    rowCount++;
                    //if the number of rows is > 64000 create a new page to continue output

                    if (rowCount == 64000)
                    {
                        rowCount = 0;
                        sheetCount++;
                        excelDoc.Write("</Table>");
                        excelDoc.Write(" </Worksheet>");
                        excelDoc.Write("<Worksheet ss:Name=\"Sheet" + sheetCount + "\">");
                        excelDoc.Write("<Table>");
                    }
                    excelDoc.Write("<Row>"); //ID=" + rowCount + "

                    for (int y = 0; y < source.Tables[0].Columns.Count; y++)
                    {
                        Type rowType = x[y].GetType();
                        #region 根據不同數據類型生成內容
                        switch (rowType.ToString())
                        {
                            case "System.String":
                                string XMLstring = x[y].ToString();
                                XMLstring = XMLstring.Trim();
                                XMLstring = XMLstring.Replace("&", "&");
                                XMLstring = XMLstring.Replace(">", ">");
                                XMLstring = XMLstring.Replace("<", "<");
                                excelDoc.Write("<Cell ss:StyleID=\"StringLiteral\">" +
                                               "<Data ss:Type=\"String\">");
                                excelDoc.Write(XMLstring);
                                excelDoc.Write("</Data></Cell>");
                                break;
                            case "System.DateTime":
                                //Excel has a specific Date Format of YYYY-MM-DD followed by
                                //the letter 'T' then hh:mm:sss.lll Example 2005-01-31T24:01:21.000
                                //The Following Code puts the date stored in XMLDate
                                //to the format above

                                var XMLDate = (DateTime)x[y];

                                string XMLDatetoString = XMLDate.Year +
                                                         "-" +
                                                         (XMLDate.Month < 10
                                                              ? "0" +
                                                                XMLDate.Month
                                                              : XMLDate.Month.ToString()) +
                                                         "-" +
                                                         (XMLDate.Day < 10
                                                              ? "0" +
                                                                XMLDate.Day
                                                              : XMLDate.Day.ToString()) +
                                                         "T" +
                                                         (XMLDate.Hour < 10
                                                              ? "0" +
                                                                XMLDate.Hour
                                                              : XMLDate.Hour.ToString()) +
                                                         ":" +
                                                         (XMLDate.Minute < 10
                                                              ? "0" +
                                                                XMLDate.Minute
                                                              : XMLDate.Minute.ToString()) +
                                                         ":" +
                                                         (XMLDate.Second < 10
                                                              ? "0" +
                                                                XMLDate.Second
                                                              : XMLDate.Second.ToString()) +
                                                         ".000";
                                excelDoc.Write("<Cell ss:StyleID=\"DateLiteral\">" +
                                             "<Data ss:Type=\"DateTime\">");
                                excelDoc.Write(XMLDatetoString);
                                excelDoc.Write("</Data></Cell>");
                                break;
                            case "System.Boolean":
                                excelDoc.Write("<Cell ss:StyleID=\"StringLiteral\">" +
                                            "<Data ss:Type=\"String\">");
                                excelDoc.Write(x[y].ToString());
                                excelDoc.Write("</Data></Cell>");
                                break;
                            case "System.Int16":
                            case "System.Int32":
                            case "System.Int64":
                            case "System.Byte":
                                excelDoc.Write("<Cell ss:StyleID=\"Integer\">" +
                                        "<Data ss:Type=\"Number\">");
                                excelDoc.Write(x[y].ToString());
                                excelDoc.Write("</Data></Cell>");
                                break;
                            case "System.Decimal":
                            case "System.Double":
                                excelDoc.Write("<Cell ss:StyleID=\"Decimal\">" +
                                      "<Data ss:Type=\"Number\">");
                                excelDoc.Write(x[y].ToString());
                                excelDoc.Write("</Data></Cell>");
                                break;
                            case "System.DBNull":
                                excelDoc.Write("<Cell ss:StyleID=\"StringLiteral\">" +
                                      "<Data ss:Type=\"String\">");
                                excelDoc.Write("");
                                excelDoc.Write("</Data></Cell>");
                                break;
                            default:
                                throw (new Exception(rowType.ToString() + " not handled."));
                        }
                        #endregion
                    }
                    excelDoc.Write("</Row>");
                }
                excelDoc.Write("</Table>");
                excelDoc.Write(" </Worksheet>");

                sheetCount++;
            }

            excelDoc.Write(endExcelXML);
            excelDoc.Close();
        }

        /// <summary>
        /// 將DataTable導出爲Excel(OleDb 方式操作)
        /// </summary>
        /// <param name="dataTable">表</param>
        /// <param name="fileName">導出默認文件名</param>
        public static void DataSetToExcel(DataTable dataTable, string fileName)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "xls files (*.xls)|*.xls";
            saveFileDialog.FileName = fileName;
            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                fileName = saveFileDialog.FileName;
                if (File.Exists(fileName))
                {
                    try
                    {
                        File.Delete(fileName);
                    }
                    catch
                    {
                        MessageBox.Show("該文件正在使用中,關閉文件或重新命名導出文件再試!");
                        return;
                    }
                }
                OleDbConnection oleDbConn = new OleDbConnection();
                OleDbCommand oleDbCmd = new OleDbCommand();
                string sSql = "";
                try
                {
                    oleDbConn.ConnectionString = "Provider=Microsoft.Jet.OleDb.4.0;Data Source=" + fileName + @";Extended ProPerties=""Excel 8.0;HDR=Yes;""";
                    oleDbConn.Open();
                    oleDbCmd.CommandType = CommandType.Text;
                    oleDbCmd.Connection = oleDbConn;
                    sSql = "CREATE TABLE sheet1 (";
                    for (int i = 0; i < dataTable.Columns.Count; i++)
                    {
                        // 字段名稱出現關鍵字會導致錯誤。
                        if (i < dataTable.Columns.Count - 1)
                            sSql += "[" + dataTable.Columns[i].Caption + "] TEXT(100) ,";
                        else
                            sSql += "[" + dataTable.Columns[i].Caption + "] TEXT(200) )";
                    }
                    oleDbCmd.CommandText = sSql;
                    oleDbCmd.ExecuteNonQuery();
                    for (int j = 0; j < dataTable.Rows.Count; j++)
                    {
                        sSql = "INSERT INTO sheet1 VALUES('";
                        for (int i = 0; i < dataTable.Columns.Count; i++)
                        {
                            if (i < dataTable.Columns.Count - 1)
                                sSql += dataTable.Rows[j][i].ToString() + " ','";
                            else
                                sSql += dataTable.Rows[j][i].ToString() + " ')";
                        }
                        oleDbCmd.CommandText = sSql;
                        oleDbCmd.ExecuteNonQuery();
                    }
                    MessageBox.Show("導出EXCEL成功");
                }
                catch (Exception ex)
                {
                    MessageBox.Show("導出EXCEL失敗:" + ex.Message);
                }
                finally
                {
                    oleDbCmd.Dispose();
                    oleDbConn.Close();
                    oleDbConn.Dispose();
                }
            }
        }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章