近日突发奇想,封装一个Excel的帮助类,好让日后做一些Excel操作时方便一点,至少导入导出会方便点吧。不过在封装过程中发现自己太差劲了,问题多多,搞这么百来行代码花了很长时间,于是写篇日志,记录一下这个ExcelHelper,也顺便记录一下封装过程中遇到的一些问题。

整个Helper中包括了读和写两部分,读是利用ADO.NET的OleDB进行读,与查询SQL Server很相像,查询语句是这种形式

SELECT * FROM [Sheet1$A1:A10]

“$”符号后面可以加一个范围,表明要读取哪一部分,如果不加的话就表明全表读取了。
下面则是读那部分的方法,一个是通用的查询,另一个则是导入

 1         /// <summary>
 2         /// 执行SQL查询一个Excel文档的内容
 3         /// </summary>
 4         /// <param name="fileName">Excel文件名</param>
 5         /// <param name="cmdText">要执行的SQL 区域选择用 [Sheet1$A1:C7]形式</param>
 6         /// <param name="paramters">查询参数</param>
 7         /// <returns>查询结果</returns>
 8         public static DataTable ExecuteReader(string fileName, string cmdText, params OleDbParameter[] paramters)
 9         {
10             string strCon = " Provider = Microsoft.Jet.OLEDB.4.0 ; Data Source = " + fileName + ";Extended Properties='Excel 8.0;HDR=NO;IMEX=1';";
11             OleDbConnection cn = null;
12             OleDbCommand cmd = new OleDbCommand();
13             OleDbDataReader reader = null;
14             DataTable table = new DataTable();
15             try
16             {
17                 cn = new OleDbConnection(strCon);
18                 PrepareCommand(cmd, cn, cmdText, paramters);
19                 reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
20                 table.Load(reader);
21                 cmd.Parameters.Clear();
22             }
23             finally
24             {
25                 if (reader != null)
26                 {
27                     reader.Close();
28                     reader.Dispose();
29                 }
30                 if (cn != null)
31                 {
32                     cn.Close();
33                     cn.Dispose();
34                 }
35             }
36             return table;
37         }

 1         /// <summary>
 2         /// 把Excel的某个工作表导入到DataTable中
 3         /// </summary>
 4         /// <param name="fileName">文件完整路径</param>
 5         /// <param name="sheetName">工作表名</param>
 6         /// <param name="HasHeader">是否存在表头。若是会把工作表第一行转成DataTable的列名</param>
 7         /// <returns>导入后的DataTable</returns>
 8         public static DataTable ImportExcel(string fileName, string sheetName, bool HasHeader)
 9         {
10             DataTable table = ExecuteReader(fileName, "select * from [" + sheetName + "]", null);
11
12             if (HasHeader)
13             {
14                 for (int i = 0; i < table.Columns.Count; i++)
15                     table.Columns[i].ColumnName = table.Rows[0][i].ToString();
16                 table.Rows.RemoveAt(0);
17             }
18
19             return table;
20         }

其实导入也是调用了通用查询的方法,不过加了一点表头的处理罢了。

写则是利用了一个COM组件,需要添加一个dll应用,Microsoft.Office.Interop.Excel.dll。原本也想用ADO.NET的,但是那写INSERT 和 UPDATE的SQL我确实写不好,老抛异常,于是放弃了,改用COM,不过用COM好像还挺直观的。

下面也粘两段代码,一个是编辑Excel文件的(其实就涵盖了原计划中的UPDATE和INSERT的操作而已,对于整行的删除,整列的删除,合并单元格等操作,鄙人还没做到。或许以后会补充上去。)另一个是导出到Excel文件。在这部分中重命名了Microsoft.Office.Interop.Excel这个明明空间,鄙人参考网友把它重命名为Excel了。

 1         /// <summary>
 2         /// 编辑一个Excel文档
 3         /// </summary>
 4         /// <param name="fileName">Excel文件名</param>
 5         /// <param name="table">要编辑的内容</param>
 6         /// <param name="startCell">目标单元格位置</param>
 7         public static void EditExcel(string fileName, DataTable table, string startCell)
 8         {
 9             Tuple<int, int> cell = ConvertCell(startCell);
10
11             object missing = System.Reflection.Missing.Value;
12             Excel.Application app = new Microsoft.Office.Interop.Excel.ApplicationClass();
13             app.Application.Workbooks.Add(true);
14
15             Excel.Workbook book = null;
16             Excel.Worksheet sheet = null;
17             bool existFile=IsExistFile(fileName);
18             if (existFile)
19             {
20                 book=app.Workbooks.Open(fileName, 0, false, 5, "", "", true, Excel.XlPlatform.xlWindows, "\t", false, false, 0, true);
21             }
22             else {
23                 book = (Excel.Workbook)app.ActiveWorkbook;
24             }
25             sheet = (Excel.Worksheet)book.ActiveSheet;
26
27             for (int i = 0,ei=cell.Item1; i < table.Rows.Count; i++,ei++)
28                 for (int j = 0, ej = cell.Item2; j < table.Columns.Count; j++, ej++)
29                     sheet.Cells[ei, ej] = table.Rows[i][j];
30
31
32             if(existFile) book.Save();
33             else book.SaveCopyAs(fileName);
34             //关闭文件
35             book.Close(false, missing, missing);
36             //退出excel
37             app.Quit();
38
39         }

 1         /// <summary>
 2         /// 把DataTable导出到一个Excel文件
 3         /// </summary>
 4         /// <param name="fileName">Excel文件名</param>
 5         /// <param name="table">要导出的DataTable</param>
 6         /// <param name="AddHeader">是否要增加表头</param>
 7         public static void ExportExcel(string fileName, DataTable table, bool AddHeader)
 8         {
 9
10             object missing = System.Reflection.Missing.Value;
11             Excel.Application app = new Microsoft.Office.Interop.Excel.ApplicationClass();
12             app.Application.Workbooks.Add(true);
13             Excel.Workbook book = (Excel.Workbook)app.ActiveWorkbook;
14             Excel.Worksheet sheet = (Excel.Worksheet)book.ActiveSheet;
15
16             if (AddHeader)
17                 for (int i = 0; i < table.Columns.Count; i++)
18                     sheet.Cells[1, i+1] = table.Columns[i].ColumnName;
19
20             for (int i = 0, ei = AddHeader ? 2 : 1; i < table.Rows.Count; i++, ei++)
21                 for (int j = 0; j < table.Columns.Count; j++)
22                     sheet.Cells[ei, j+1] = table.Rows[i][j];
23
24
25             string path = fileName.Substring(0, fileName.LastIndexOf('\\') + 1).Trim('\\');
26             if (!Directory.Exists(path))
27                 Directory.CreateDirectory(path);
28
29             book.SaveCopyAs(fileName);
30             //关闭文件
31             book.Close(false, missing, missing);
32             //退出excel
33             app.Quit();
34         }

在这部分中遇到两个问题:

第一个是调用ApplicationClass()这个构造函数时,编译会不同过,错误信息是“无法嵌入互操作类型”,只要把Microsoft.Office.Interop.Excel.dll的 嵌入互操作类型 属性设为False就行了。

第二是给交错数组sheet[,]赋值时,如果两个下标中任意一个用了0的话,运行时会抛出COMException的,异常信息是 Exception from HRESULT: 0x800A03EC 这是由于Excel的工作表第0行或第0列是Excel工作表的条标尺,如下图红框框住的两条。

因此不可赋值。在循环遍历时,循环变量则要从1开始。

下面则把整个ExcelHelper的代码粘出来,欢迎大家批评指正。

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Data.OleDb;
  6 using System.Data;
  7 using System.IO;
  8 using Microsoft.Office.Interop;
  9 using Excel = Microsoft.Office.Interop.Excel;
 10 using System.Text.RegularExpressions;
 11
 12 namespace MyHelpers.Helpers
 13 {
 14     public class ExcelHelper
 15     {
 16         #region 公共方法
 17
 18         #region 导入
 19
 20         /// <summary>
 21         /// 把Excel的某个工作表导入到DataTable中
 22         /// </summary>
 23         /// <param name="fileName">文件完整路径</param>
 24         /// <param name="sheetName">工作表名</param>
 25         /// <param name="HasHeader">是否存在表头。若是会把工作表第一行转成DataTable的列名</param>
 26         /// <returns>导入后的DataTable</returns>
 27         public static DataTable ImportExcel(string fileName, string sheetName, bool HasHeader)
 28         {
 29             DataTable table = ExecuteReader(fileName, "select * from [" + sheetName + "]", null);
 30
 31             if (HasHeader)
 32             {
 33                 for (int i = 0; i < table.Columns.Count; i++)
 34                     table.Columns[i].ColumnName = table.Rows[0][i].ToString();
 35                 table.Rows.RemoveAt(0);
 36             }
 37
 38             return table;
 39         }
 40
 41         /// <summary>
 42         /// 把Excel的Sheet工作表导入到DataTable中
 43         /// </summary>
 44         /// <param name="fileName">文件完整路径</param>
 45         /// <param name="HasHeader">是否存在表头。若是会把工作表第一行转成DataTable的列名</param>
 46         /// <returns>导入后的DataTable</returns>
 47         public static DataTable ImportExcel(string fileName, bool HasHeader)
 48         {
 49             return ImportExcel(fileName, "sheet1$", HasHeader);
 50         }
 51
 52         /// <summary>
 53         /// 把Excel的某个工作表导入到DataTable中
 54         /// </summary>
 55         /// <param name="fileName">文件完整路径</param>
 56         /// <returns></returns>
 57         public static DataTable ImportExcel(string fileName)
 58         {
 59             return ImportExcel(fileName, true);
 60         }
 61
 62         #endregion
 63
 64         #region 导出
 65
 66         /// <summary>
 67         /// 把DataTable导出到一个Excel文件,并增加表头
 68         /// </summary>
 69         /// <param name="fileName">Excel文件名</param>
 70         /// <param name="table">要导出的DataTable</param>
 71         public static void ExportExcel(string fileName, DataTable table)
 72         {
 73             ExportExcel(fileName, table, true);
 74         }
 75
 76         /// <summary>
 77         /// 把DataTable导出到一个Excel文件
 78         /// </summary>
 79         /// <param name="fileName">Excel文件名</param>
 80         /// <param name="table">要导出的DataTable</param>
 81         /// <param name="AddHeader">是否要增加表头</param>
 82         public static void ExportExcel(string fileName, DataTable table, bool AddHeader)
 83         {
 84
 85             object missing = System.Reflection.Missing.Value;
 86             Excel.Application app = new Microsoft.Office.Interop.Excel.ApplicationClass();
 87             app.Application.Workbooks.Add(true);
 88             Excel.Workbook book = (Excel.Workbook)app.ActiveWorkbook;
 89             Excel.Worksheet sheet = (Excel.Worksheet)book.ActiveSheet;
 90
 91             if (AddHeader)
 92                 for (int i = 0; i < table.Columns.Count; i++)
 93                     sheet.Cells[1, i+1] = table.Columns[i].ColumnName;
 94
 95             for (int i = 0, ei = AddHeader ? 2 : 1; i < table.Rows.Count; i++, ei++)
 96                 for (int j = 0; j < table.Columns.Count; j++)
 97                     sheet.Cells[ei, j+1] = table.Rows[i][j];
 98
 99
100             string path = fileName.Substring(0, fileName.LastIndexOf('\\') + 1).Trim('\\');
101             if (!Directory.Exists(path))
102                 Directory.CreateDirectory(path);
103
104             book.SaveCopyAs(fileName);
105             //关闭文件
106             book.Close(false, missing, missing);
107             //退出excel
108             app.Quit();
109         }
110
111         #endregion
112
113         #region 通用读取
114
115         /// <summary>
116         /// 执行SQL查询一个Excel文档的内容
117         /// </summary>
118         /// <param name="fileName">Excel文件名</param>
119         /// <param name="cmdText">要执行的SQL 区域选择用 [Sheet1$A1:C7]形式</param>
120         /// <param name="paramters">查询参数</param>
121         /// <returns>查询结果</returns>
122         public static DataTable ExecuteReader(string fileName, string cmdText, params OleDbParameter[] paramters)
123         {
124             string strCon = " Provider = Microsoft.Jet.OLEDB.4.0 ; Data Source = " + fileName + ";Extended Properties='Excel 8.0;HDR=NO;IMEX=1';";
125             OleDbConnection cn = null;
126             OleDbCommand cmd = new OleDbCommand();
127             OleDbDataReader reader = null;
128             DataTable table = new DataTable();
129             try
130             {
131                 cn = new OleDbConnection(strCon);
132                 PrepareCommand(cmd, cn, cmdText, paramters);
133                 reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
134                 table.Load(reader);
135                 cmd.Parameters.Clear();
136             }
137             finally
138             {
139                 if (reader != null)
140                 {
141                     reader.Close();
142                     reader.Dispose();
143                 }
144                 if (cn != null)
145                 {
146                     cn.Close();
147                     cn.Dispose();
148                 }
149             }
150             return table;
151         }
152
153         /// <summary>
154         /// 执行SQL查询一个Excel文档默认工作表Sheet1的内容
155         /// </summary>
156         /// <param name="fileName">Excel文件名</param>
157         /// <param name="cmdText">查询参数</param>
158         /// <returns>查询结果</returns>
159         public static DataTable ExecuteReader(string fileName, string cmdText)
160         {
161             return ExecuteReader(fileName, cmdText, null);
162         }
163
164         #endregion
165
166         #region 通用编辑
167
168         /// <summary>
169         /// 编辑一个Excel文档
170         /// </summary>
171         /// <param name="fileName">Excel文件名</param>
172         /// <param name="table">要编辑的内容</param>
173         /// <param name="startCell">目标单元格位置</param>
174         public static void EditExcel(string fileName, DataTable table, string startCell)
175         {
176             Tuple<int, int> cell = ConvertCell(startCell);
177
178             object missing = System.Reflection.Missing.Value;
179             Excel.Application app = new Microsoft.Office.Interop.Excel.ApplicationClass();
180             app.Application.Workbooks.Add(true);
181
182             Excel.Workbook book = null;
183             Excel.Worksheet sheet = null;
184             bool existFile=IsExistFile(fileName);
185             if (existFile)
186             {
187                 book=app.Workbooks.Open(fileName, 0, false, 5, "", "", true, Excel.XlPlatform.xlWindows, "\t", false, false, 0, true);
188             }
189             else {
190                 book = (Excel.Workbook)app.ActiveWorkbook;
191             }
192             sheet = (Excel.Worksheet)book.ActiveSheet;
193
194             for (int i = 0,ei=cell.Item1; i < table.Rows.Count; i++,ei++)
195                 for (int j = 0, ej = cell.Item2; j < table.Columns.Count; j++, ej++)
196                     sheet.Cells[ei, ej] = table.Rows[i][j];
197
198
199             if(existFile) book.Save();
200             else book.SaveCopyAs(fileName);
201             //关闭文件
202             book.Close(false, missing, missing);
203             //退出excel
204             app.Quit();
205
206         }
207
208         /// <summary>
209         /// 编辑一个Excel文档
210         /// </summary>
211         /// <param name="fileName">Excel文件名</param>
212         /// <param name="table">要编辑的内容</param>
213         public static void EditExcel(string fileName, DataTable table)
214         {
215             EditExcel(fileName, table, "A1");
216         }
217
218         #endregion
219
220         #endregion
221
222         #region 私有方法
223
224         /// <summary>
225         /// 检查文件是否存在,若不存在则会先确保文件所在的目录存在
226         /// </summary>
227         /// <param name="fileName">文件名</param>
228         /// <returns>检查结果</returns>
229         private static bool IsExistFile(string fileName)
230         {
231             if(File.Exists(fileName))return true;
232             string path = fileName.Substring(0, fileName.LastIndexOf('\\') + 1).Trim('\\');
233             if (!Directory.Exists(path))
234                 Directory.CreateDirectory(path);
235             return false;
236         }
237
238         /// <summary>
239         /// 转换单元格位置
240         /// </summary>
241         /// <param name="cell">单元格位置</param>
242         /// <returns>int二元组</returns>
243         private static Tuple<int, int> ConvertCell(string cell)
244         {
245             Match colM=Regex.Match(cell,@"[a-zA-Z]+");
246             if (string.IsNullOrEmpty(colM.Value))
247                 throw new Exception("单元格格式有误!");
248             string colStr = colM.Value.ToUpper();
249             int colIndex = 0;
250             foreach (char ci in colStr)
251                 colIndex += 1+(ci - 'A');
252
253             Match rowM = Regex.Match(cell, @"\d+");
254             if(string.IsNullOrEmpty(rowM.Value))
255                 throw new Exception("单元格格式有误!");
256             int rowIndex =Convert.ToInt32( rowM.Value);
257
258             Tuple<int, int> result = new Tuple<int, int>(rowIndex,colIndex);
259             return result;
260         }
261
262         /// <summary>
263         /// 准备OleDbCommand
264         /// </summary>
265         /// <param name="command">查询命令</param>
266         /// <param name="connection">连接类</param>
267         /// <param name="cmdText">命令内容</param>
268         /// <param name="paramters">查询参数</param>
269         private static void PrepareCommand(OleDbCommand command, OleDbConnection connection, string cmdText, params OleDbParameter[] paramters)
270         {
271             command.CommandText = cmdText;
272             command.Connection = connection;
273
274             if (paramters != null)
275                 foreach (OleDbParameter item in paramters)
276                     command.Parameters.Add(item);
277
278             if (connection.State !=  ConnectionState.Open)
279                 connection.Open();
280         }
281
282         #endregion
283     }
284 }

这里有个连接通向用NPOI封装的ExcelHelper类:  另一个ExcelHelper

一个Excel的帮助类——ExcelHelper相关推荐

  1. 一个Excel导出类的实现过程(二):显示定制

    导出操作中,我们常常不需要显示所有属性,比如Person类加入Guid属性: public class Person {public Int32 ID { get; set; }public Guid ...

  2. DataGrid 导出到 Excel 的帮助类

    DataGrid 导出到 Excel 的帮助类 //========================================================================== ...

  3. .net excel循环插数据_Python实战: 如何将数据从一个Excel文件移动到另一个?

    使用Python中的Pandas库,我们可以从源Excel文件中获取数据并将其插入到新的Excel文件中,然后命名并保存该文件.当您需要深入到特定数据和/或重新格式化报表的数据时,这很有用. 作为一个 ...

  4. python获取excel数据进行判断输出结果到excel,如何使用python xlrd/xlwt从一个excel工作簿提取数据并输出到另一个excel工作簿?...

    我正在为xlutils.xlrd和xlwt创建一个名为excel functions的类,最终我可能会创建一个库.如果你有兴趣帮我做一个删除工作表的功能. 您可能希望转向openpyxl和/或pyex ...

  5. java读写excel文件poi_Java利用POI读写Excel文件工具类

    本文实例为大家分享了Java读写Excel文件工具类的具体代码,供大家参考,具体内容如下 package com.test.app.utils; import java.io.File; import ...

  6. php中访问excel文件,PHP中常用的Excel文件访问类及修改 | 学步园

    近日,由于手头项目需要解析web提交的excel文件,不得不看看这个在php中使用比较广泛的excel访问类了.之所以说它使用广泛,是后来在网上查找问题解决方法时才知道它的使用面的. 首先说遇到的问题 ...

  7. excel每行按模板导出为一个excel文件,可以指定列文本生成二维码或者条形码

    程序修改了bug,增加了功能.(20220825) 该程序可以把一个excel文件中每行数据按指定模板生成一个单独excel文件. 1. 模板文件为tpl\template.xlsx. 2. 从左侧数 ...

  8. java复制sheet_java-poi 复制Sheet到另一个excel的sheet中

    原题链接在这里:https://leetcode.com/problems/excel-sheet-column-number/ 这道题与Excel Sheet Column Title相呼应.Tim ...

  9. java Excel导出工具类

    Excel工具类 一.开发原因 最近工作的时候,正在写关于Excel导出功能,由于当前使用的工具类不太灵活和不易看懂,自己从头写又很浪费时间等原因,我决定自己写一款很简单的Excel导出的工具类,仅仅 ...

最新文章

  1. html 字母列表通讯录,仿微信通讯录字母排序列表
  2. fragment中的onCreateView和onViewCreated的区别和
  3. 20162329 2017-2018-1 《程序设计与数据结构》第九周学习总结
  4. 将DataTable的内容以EXCEl的形式导出到本地
  5. python的标准库学习之__buitin__
  6. 巧设IP路由 实现不同网段互通
  7. CentOS 7使用通过二进制包安装MySQL 5.7.18
  8. Identity of indiscernibles(不可分与同一性)
  9. Docker 如何支持多种日志方案?- 每天5分钟玩转 Docker 容器技术(88)
  10. 报数(约瑟夫环问题)
  11. 重学Es6 Promise
  12. 还在肝阴阳师?别错过千年一遇的高冷妹纸
  13. 电脑安装linux点歌系统,如何组装单机版电脑点歌系统
  14. 漫游测试之性能测试(5.4-执行计划)
  15. mac 远程桌面连接工具 Microsoft Remote Desktop for Mac 的安装与使用
  16. 【矩阵论】02——线性空间——基、维数与坐标
  17. 【云杂谈】之二《AT&T发布基于云存储的物联网产品》
  18. 人脸表情识别 实战项目
  19. H.264压缩技术之总览(Overview)——Matlab源码解析
  20. 质量保证漫漫谈之QA、QC、QM的关系与区别

热门文章

  1. Java系列之:Collections实现斗地主游戏
  2. train_test_split的用法(机器学习)
  3. 2023计算机毕业设计SSM最新选题之java交通违章举报平台lxsqm
  4. Springboot毕设项目个性相册网站52jtb(java+VUE+Mybatis+Maven+Mysql)
  5. 网络超火的音效素材、BGM,全在这里了。
  6. 计算机网络实验仿真系统设计,计算机网络安全实验仿真系统
  7. 通过java获取手机信息_android获取手机信息
  8. Ubuntu20.10命令行运行纸牌游戏AisleRiot
  9. AutoHotKey (AHK) 自定义快捷键
  10. 共享单车神经网络预测(pytorch )每行代码详细解释