MYExcelHelper.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Data;
  6. using System.Data.OleDb;
  7. using System.IO;
  8. namespace LYFZ.WinAPI
  9. {
  10. /// <summary>
  11. /// 描述:对Excel文件的创建表、读取、写入數据操作.
  12. /// </summary>
  13. public static class MYExcelHelper
  14. {
  15. #region 取文件的擴展名
  16. /// <summary>
  17. /// 取文件的扩展名
  18. /// </summary>
  19. /// <param name="FileName">文件名称</param>
  20. /// <returns>string</returns>
  21. public static string GetExtFileTypeName(string FileName)
  22. {
  23. return System.IO.Path.GetExtension(FileName).ToLower();
  24. }
  25. #endregion
  26. #region 检查一个文件是不是2007版本的Excel文件
  27. /// <summary>
  28. /// 检查一个文件是不是2007版本的Excel文件
  29. /// </summary>
  30. /// <param name="FileName">文件名称</param>
  31. /// <returns>bool</returns>
  32. public static bool IsExcel2007(string FileName)
  33. {
  34. bool r;
  35. switch (GetExtFileTypeName(FileName))
  36. {
  37. case ".xls":
  38. r = false;
  39. break;
  40. case ".xlsx":
  41. r = true;
  42. break;
  43. default:
  44. throw new Exception("你要检查" + FileName + "是2007版本的Excel文件还是之前版本的Excel文件,但是這个文件不是一个有效的Excel文件。");
  45. }
  46. return r;
  47. }
  48. #endregion
  49. #region Excel的连接串
  50. //Excel的连接串
  51. //2007和之前的版本是有区別的,但是新的可以读取旧的
  52. /// <summary>
  53. /// Excel文件在服务器上的OLE连接字符串
  54. /// </summary>
  55. /// <param name="excelFile">Excel文件在服务器上的路径</param>
  56. /// <param name="eHDR">第一行不是否标题</param>
  57. /// <param name="eIMEX">连接模式</param>
  58. /// <returns>String</returns>
  59. public static string GetExcelConnectionString(string excelFile, ExHDR eHDR,ExIMEX eIMEX)
  60. {
  61. try
  62. {
  63. if (IsExcel2007(excelFile))
  64. {
  65. return "Provider=Microsoft.Ace.OleDb.12.0;" + "data source=" + excelFile + ";Extended Properties='Excel 12.0; HDR=" + eHDR.ToString() + "; IMEX="+((int)eIMEX).ToString()+"'"; //此连接可以操作.xls与.xlsx文件
  66. }
  67. else
  68. {
  69. return "Provider=Microsoft.Jet.OleDb.4.0;" + "data source=" + excelFile + ";Extended Properties='Excel 8.0; HDR=" + eHDR.ToString() + "; IMEX=" + ((int)eIMEX).ToString() + "'"; //此连接只能操作Excel2007之前(.xls)文件
  70. }
  71. }
  72. catch (Exception ee)
  73. {
  74. throw new Exception(ee.Message);
  75. }
  76. }
  77. #endregion
  78. #region 读取Excel中的所有表名
  79. //读取Excel中的所有表名
  80. //读取Excel文件时,可能一个文件中会有多个Sheet,因此获取Sheet的名称是非常有用的
  81. /// <summary>
  82. /// 根据Excel物理路径获取Excel文件中所有表名,列名是TABLE_NAME
  83. /// </summary>
  84. /// <param name="excelFile">Excel物理路径</param>
  85. /// <returns>DataTable</returns>
  86. public static System.Data.DataTable GetExcelSheetNames2DataTable(string excelFile)
  87. {
  88. OleDbConnection objConn = null;
  89. System.Data.DataTable dt = null;
  90. try
  91. {
  92. string strConn = GetExcelConnectionString(excelFile,ExHDR.NO,ExIMEX.ImportMode);
  93. objConn = new OleDbConnection(strConn);
  94. objConn.Open();
  95. dt = objConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
  96. if (dt == null)
  97. {
  98. return null;
  99. }
  100. return dt;
  101. }
  102. catch (Exception ee)
  103. {
  104. throw new Exception(ee.Message);
  105. }
  106. finally
  107. {
  108. if (objConn != null)
  109. {
  110. objConn.Close();
  111. objConn.Dispose();
  112. }
  113. if (dt != null)
  114. {
  115. dt.Dispose();
  116. }
  117. }
  118. }
  119. /// <summary>
  120. /// 根据Excel物理路径获取Excel文件中所有表名
  121. /// </summary>
  122. /// <param name="excelFile">Excel物理路径</param>
  123. /// <returns>String[]</returns>
  124. public static string[] GetExcelSheetNames(string excelFile)
  125. {
  126. System.Data.DataTable dt = null;
  127. try
  128. {
  129. dt = GetExcelSheetNames2DataTable(excelFile);
  130. if (dt == null)
  131. {
  132. return null;
  133. }
  134. string[] excelSheets = new string[dt.Rows.Count];
  135. int i = 0;
  136. foreach (DataRow row in dt.Rows)
  137. {
  138. excelSheets[i] = row["TABLE_NAME"].ToString();
  139. i++;
  140. }
  141. return excelSheets;
  142. }
  143. catch (Exception ee)
  144. {
  145. throw new Exception(ee.Message);
  146. }
  147. finally
  148. {
  149. if (dt != null)
  150. {
  151. dt.Dispose();
  152. }
  153. }
  154. }
  155. /// <summary>
  156. /// 根据Excel物理路径获取Excel文件中所有表名
  157. /// </summary>
  158. /// <param name="excelFile">Excel物理路径</param>
  159. /// <returns>String[]</returns>
  160. public static List<string> GetExcelSheetNames2List(string excelFile)
  161. {
  162. List<string> l = new List<string>();
  163. try
  164. {
  165. if (File.Exists(excelFile))//如果文件不存在,就不用检查了,一定是0个表的
  166. {
  167. string[] t = GetExcelSheetNames(excelFile);
  168. foreach (string s in t)
  169. {
  170. string ss = s;
  171. if (ss.LastIndexOf('$') > 0)
  172. {
  173. ss = ss.Substring(0, ss.Length - 1);
  174. }
  175. l.Add(ss);
  176. }
  177. }
  178. return l;
  179. }
  180. catch (Exception ee)
  181. {
  182. throw ee;
  183. }
  184. }
  185. #endregion
  186. #region Sheet2DataTable
  187. /// <summary>
  188. /// 获取Excel文件中指定SheetName的內容到DataTable
  189. /// </summary>
  190. /// <param name="FileFullPath">Excel物理路径</param>
  191. /// <param name="SheetName">SheetName</param>
  192. /// <param name="no_HDR">第一行不是题題:true;第一行是题題:false;</param>
  193. /// <returns>DataTable</returns>
  194. public static DataTable GetExcelToDataTableBySheet(string FileFullPath, string SheetName, bool no_HDR)
  195. {
  196. try
  197. {
  198. return GetExcelToDataSet(FileFullPath, no_HDR, SheetName).Tables[SheetName];
  199. }
  200. catch (Exception ee)
  201. {
  202. throw new Exception(ee.Message);
  203. }
  204. }
  205. /// <summary>
  206. /// 获取Excel文件中指定SheetName的內容到DataTable
  207. /// </summary>
  208. /// <param name="FileFullPath">Excel物理路径</param>
  209. /// <param name="SheetName">SheetName</param>
  210. /// <returns>DataTable</returns>
  211. public static DataTable GetExcelToDataTableBySheet(string FileFullPath, string SheetName)
  212. {
  213. try
  214. {
  215. return GetExcelToDataTableBySheet(FileFullPath, SheetName, false);
  216. }
  217. catch (Exception ee)
  218. {
  219. throw new Exception(ee.Message);
  220. }
  221. }
  222. #endregion
  223. #region Excel2DataSet
  224. /// <summary>
  225. /// 获取Excel文件中所有Sheet的內容到DataSet,以Sheet名做DataTable名
  226. /// </summary>
  227. /// <param name="FileFullPath">Excel物理路径</param>
  228. /// <param name="no_HDR">第一行不是题題:true;第一行是题題:false;</param>
  229. /// <returns>DataSet</returns>
  230. public static DataSet GetExcelToDataSet(string FileFullPath, bool no_HDR)
  231. {
  232. try
  233. {
  234. ExHDR cEHDR = ExHDR.NO;
  235. if (no_HDR)
  236. {
  237. cEHDR = ExHDR.YES;
  238. }
  239. string strConn = GetExcelConnectionString(FileFullPath, cEHDR, ExIMEX.ImportMode);
  240. OleDbConnection conn = new OleDbConnection(strConn);
  241. conn.Open();
  242. DataSet ds = new DataSet();
  243. foreach (string colName in GetExcelSheetNames(FileFullPath))
  244. {
  245. OleDbDataAdapter odda = new OleDbDataAdapter(string.Format("SELECT * FROM [{0}]", colName), conn); //("select * from [Sheet1$]", conn);
  246. odda.Fill(ds, colName);
  247. }
  248. conn.Close();
  249. return ds;
  250. }
  251. catch (Exception ee)
  252. {
  253. throw new Exception(ee.Message);
  254. }
  255. }
  256. /// <summary>
  257. /// 获取Excel文件中指定Sheet的內容到DataSet,以Sheet名做DataTable名
  258. /// </summary>
  259. /// <param name="FileFullPath">Excel物理路径</param>
  260. /// <param name="no_HDR">第一行不是题題:true;第一行是题題:false;</param>
  261. /// <param name="SheetName">第一行不是题題:true;第一行是题題:false;</param>
  262. /// <returns>DataSet</returns>
  263. public static DataSet GetExcelToDataSet(string FileFullPath, bool no_HDR, string SheetName)
  264. {
  265. try
  266. {
  267. ExHDR cEHDR = ExHDR.NO;
  268. if (no_HDR)
  269. {
  270. cEHDR = ExHDR.YES;
  271. }
  272. string strConn = GetExcelConnectionString(FileFullPath, cEHDR, ExIMEX.ImportMode);
  273. OleDbConnection conn = new OleDbConnection(strConn);
  274. conn.Open();
  275. DataSet ds = new DataSet();
  276. OleDbDataAdapter odda = new OleDbDataAdapter(string.Format("SELECT * FROM [{0}]", SheetName), conn); //("select * from [Sheet1$]", conn);
  277. odda.Fill(ds, SheetName);
  278. conn.Close();
  279. return ds;
  280. }
  281. catch (Exception ee)
  282. {
  283. throw new Exception(ee.Message);
  284. }
  285. }
  286. #endregion
  287. #region 刪除過時文件
  288. //刪除過時文件
  289. public static bool DeleteOldFile(string servepath)
  290. {
  291. try
  292. {
  293. FileInfo F = new FileInfo(servepath);
  294. F.Delete();
  295. return true;
  296. }
  297. catch (Exception ee)
  298. {
  299. throw new Exception(ee.Message + "刪除" + servepath + "出錯.");
  300. }
  301. }
  302. #endregion
  303. #region 在Excel文件中创建表,Excel物理路径如果文件不是一个已存在的文件,会自动创建文件
  304. /// <summary>
  305. /// 在一个Excel文件中创建Sheet
  306. /// </summary>
  307. /// <param name="servepath">Excel物理路径,如果文件不是一个已存在的文件,会自动创建文件</param>
  308. /// <param name="sheetName">Sheet Name</param>
  309. /// <param name="cols">表头列表</param>
  310. /// <returns>bool</returns>
  311. public static bool CreateSheet(string servepath, string sheetName, string[] cols)
  312. {
  313. try
  314. {
  315. if (sheetName.Trim() == "")
  316. {
  317. throw new Exception("需要提供表名。");
  318. }
  319. //if (!File.Exists(servepath))
  320. //{
  321. // throw new Exception(servepath+"不是一个有效的文件路径。");
  322. //}
  323. if (cols.Equals(null))
  324. {
  325. throw new Exception("创建表需要提供字段列表。");
  326. }
  327. using (OleDbConnection conn = new OleDbConnection(GetExcelConnectionString(servepath, ExHDR.YES, ExIMEX.LinkedMode)))
  328. {
  329. conn.Open();
  330. OleDbCommand cmd = new OleDbCommand();
  331. cmd.Connection = conn;
  332. if (sheetName.LastIndexOf('$') > 0)
  333. {
  334. sheetName = sheetName.Substring(sheetName.Length - 1);
  335. }
  336. cmd.CommandType = CommandType.Text;
  337. cmd.CommandTimeout = 3600;
  338. StringBuilder sql = new StringBuilder();
  339. sql.Append("CREATE TABLE [" + sheetName + "](");
  340. foreach (string s in cols)
  341. {
  342. sql.Append("[" + s + "] text,");
  343. }
  344. sql = sql.Remove(sql.Length - 1, 1);
  345. sql.Append(")");
  346. cmd.CommandText = sql.ToString();
  347. cmd.ExecuteNonQuery();
  348. return true;
  349. }
  350. }
  351. catch (Exception ee)
  352. {
  353. throw ee;
  354. }
  355. }
  356. #endregion
  357. #region DataTable2Sheet,把一个DataTable写入Excel中的表,Excel物理路径,如果文件不是一个已存在的文件,会自动创建文件
  358. /// <summary>
  359. /// 把一个DataTable写入到一个或多个Sheet中
  360. /// </summary>
  361. /// <param name="servepath">Excel物理路径,如果文件不是一个已存在的文件,会自动创建文件</param>
  362. /// <param name="dt">DataTable</param>
  363. /// <returns>bool</returns>
  364. public static bool DataTable2Sheet(string servepath, DataTable dt)
  365. {
  366. try
  367. {
  368. return DataTable2Sheet(servepath, dt, dt.TableName);
  369. }
  370. catch (Exception ee)
  371. {
  372. throw ee;
  373. }
  374. }
  375. /// <summary>
  376. /// 把一个DataTable写入到一个或多个Sheet中
  377. /// </summary>
  378. /// <param name="servepath">Excel物理路径,如果文件不是一个已存在的文件,会自动创建文件</param>
  379. /// <param name="dt">DataTable</param>
  380. /// <param name="maxrow">一个Sheet的行數</param>
  381. /// <returns>bool</returns>
  382. public static bool DataTable2Sheet(string servepath, DataTable dt, int maxrow)
  383. {
  384. try
  385. {
  386. return DataTable2Sheet(servepath, dt, dt.TableName, maxrow);
  387. }
  388. catch (Exception ee)
  389. {
  390. throw ee;
  391. }
  392. }
  393. /// <summary>
  394. /// 把一个DataTable写入到一个或多个Sheet中
  395. /// </summary>
  396. /// <param name="servepath">Excel物理路径,如果文件不是一个已存在的文件,会自动创建文件</param>
  397. /// <param name="dt">DataTable</param>
  398. /// <param name="sheetName">Sheet Name</param>
  399. /// <returns>bool</returns>
  400. public static bool DataTable2Sheet(string servepath, DataTable dt, string sheetName)
  401. {
  402. try
  403. {
  404. return DataTable2Sheet(servepath, dt, sheetName, 0);
  405. }
  406. catch (Exception ee)
  407. {
  408. throw ee;
  409. }
  410. }
  411. /// <summary>
  412. /// 把一个DataTable写入到一个或多个Sheet中
  413. /// </summary>
  414. /// <param name="servepath">Excel物理路径,如果文件不是一个已存在的文件,会自动创建文件</param>
  415. /// <param name="dt">DataTable</param>
  416. /// <param name="sheetName">Sheet Name</param>
  417. /// <param name="maxrow">一个Sheet的行數</param>
  418. /// <returns>bool</returns>
  419. public static bool DataTable2Sheet(string servepath, DataTable dt, string sheetName, int maxrow)
  420. {
  421. try
  422. {
  423. if (sheetName.Trim() == "")
  424. {
  425. throw new Exception("需要提供表名。");
  426. }
  427. StringBuilder strSQL = new StringBuilder();
  428. //看看目题表是否已存在
  429. List<string> tables = GetExcelSheetNames2List(servepath);
  430. if (tables.Contains(sheetName))
  431. {
  432. //存在,直接写入
  433. using (OleDbConnection conn = new OleDbConnection(GetExcelConnectionString(servepath, ExHDR.YES, ExIMEX.LinkedMode)))
  434. {
  435. conn.Open();
  436. OleDbCommand cmd = new OleDbCommand();
  437. cmd.Connection = conn;
  438. for (int i = 0; i < dt.Rows.Count; i++)
  439. {
  440. StringBuilder strfield = new StringBuilder();
  441. StringBuilder strvalue = new StringBuilder();
  442. for (int j = 0; j < dt.Columns.Count; j++)
  443. {
  444. strfield.Append("[" + dt.Columns[j].ColumnName + "]");
  445. strvalue.Append("'" + dt.Rows[i][j].ToString().Replace(",", ",").Replace("'", "’").Replace(";", ";") + "'");
  446. if (j != dt.Columns.Count - 1)
  447. {
  448. strfield.Append(",");
  449. strvalue.Append(",");
  450. }
  451. }
  452. if (maxrow == 0)//不需要限制一个表的行數
  453. {
  454. cmd.CommandText = strSQL.Append(" insert into [" + sheetName + "]( ")
  455. .Append(strfield.ToString()).Append(") values (").Append(strvalue).Append(")").ToString();
  456. }
  457. else
  458. {
  459. //加1才可才防止i=0的情況只写入一行
  460. string sheetNameT = sheetName + ((i + 1) / maxrow + (Math.IEEERemainder(i + 1, maxrow) == 0 ? 0 : 1)).ToString();
  461. if (!tables.Contains(sheetNameT))
  462. {
  463. tables = GetExcelSheetNames2List(servepath);
  464. string[] cols = new string[dt.Columns.Count];
  465. for (int ii = 0; ii < dt.Columns.Count; ii++)
  466. {
  467. cols[ii] = dt.Columns[ii].ColumnName;
  468. }
  469. if (!(CreateSheet(servepath, sheetNameT, cols)))
  470. {
  471. throw new Exception("在" + servepath + "上创建表" + sheetName + "失敗.");
  472. }
  473. else
  474. {
  475. tables = GetExcelSheetNames2List(servepath);
  476. }
  477. }
  478. cmd.CommandText = strSQL.Append(" insert into [" + sheetNameT + "]( ")
  479. .Append(strfield.ToString()).Append(") values (").Append(strvalue).Append(")").ToString();
  480. }
  481. cmd.ExecuteNonQuery();
  482. strSQL.Remove(0, strSQL.Length);
  483. }
  484. conn.Close();
  485. }
  486. }
  487. else
  488. {
  489. //不存在,需要先创建
  490. using (OleDbConnection conn = new OleDbConnection(GetExcelConnectionString(servepath, ExHDR.YES, ExIMEX.LinkedMode)))
  491. {
  492. conn.Open();
  493. OleDbCommand cmd = new OleDbCommand();
  494. cmd.Connection = conn;
  495. //创建表
  496. string[] cols = new string[dt.Columns.Count];
  497. for (int i = 0; i < dt.Columns.Count; i++)
  498. {
  499. cols[i] = dt.Columns[i].ColumnName;
  500. }
  501. //产生写數据的语句
  502. for (int i = 0; i < dt.Rows.Count; i++)
  503. {
  504. StringBuilder strfield = new StringBuilder();
  505. StringBuilder strvalue = new StringBuilder();
  506. for (int j = 0; j < dt.Columns.Count; j++)
  507. {
  508. strfield.Append("[" + dt.Columns[j].ColumnName + "]");
  509. strvalue.Append("'" + dt.Rows[i][j].ToString().Replace(",", ",").Replace("'", "’").Replace(";", ";") + "'");
  510. if (j != dt.Columns.Count - 1)
  511. {
  512. strfield.Append(",");
  513. strvalue.Append(",");
  514. }
  515. }
  516. if (maxrow == 0)//不需要限制一个表的行數
  517. {
  518. if (!tables.Contains(sheetName))
  519. {
  520. if (!(CreateSheet(servepath, sheetName, cols)))
  521. {
  522. throw new Exception("在" + servepath + "上创建表" + sheetName + "失敗.");
  523. }
  524. else
  525. {
  526. tables = GetExcelSheetNames2List(servepath);
  527. }
  528. }
  529. cmd.CommandText = strSQL.Append(" insert into [" + sheetName + "]( ")
  530. .Append(strfield.ToString()).Append(") values (").Append(strvalue).Append(")").ToString();
  531. }
  532. else
  533. {
  534. //加1才可才防止i=0的情況只写入一行
  535. string sheetNameT = sheetName + ((i + 1) / maxrow + (Math.IEEERemainder(i + 1, maxrow) == 0 ? 0 : 1)).ToString();
  536. if (!tables.Contains(sheetNameT))
  537. {
  538. for (int ii = 0; ii < dt.Columns.Count; ii++)
  539. {
  540. cols[ii] = dt.Columns[ii].ColumnName;
  541. }
  542. if (!(CreateSheet(servepath, sheetNameT, cols)))
  543. {
  544. throw new Exception("在" + servepath + "上创建表" + sheetName + "失敗.");
  545. }
  546. else
  547. {
  548. tables = GetExcelSheetNames2List(servepath);
  549. }
  550. }
  551. cmd.CommandText = strSQL.Append(" insert into [" + sheetNameT + "]( ")
  552. .Append(strfield.ToString()).Append(") values (").Append(strvalue).Append(")").ToString();
  553. //
  554. }
  555. cmd.ExecuteNonQuery();
  556. strSQL.Remove(0, strSQL.Length);
  557. }
  558. conn.Close();
  559. }
  560. }
  561. return true;
  562. }
  563. catch (Exception ee)
  564. {
  565. throw ee;
  566. }
  567. }
  568. #endregion
  569. /// <summary>
  570. /// 参数HDR的值:HDR=Yes,这代表第一行是标题,不做为数据使用 ,如果用HDR=NO,则表示第一行不是标题,做为数据来使用。系统默认的是YES
  571. /// </summary>
  572. public enum ExHDR
  573. {
  574. YES,
  575. NO,
  576. }
  577. /// <summary>
  578. /// 我这里特别要说明的就是 IMEX 参数了,因为不同的模式代表著不同的读写行为:
  579. ///当 IMEX=0 时为“输出模式”,这个模式开启的 Excel 档案只能用来做“写入”用途。
  580. ///当 IMEX=1 时为“输入模式”,这个模式开启的 Excel 档案只能用来做“读取”用途。
  581.    ///当 IMEX=2 时为“连結模式”,这个模式开启的 Excel 档案可同时支援“读取”与“写入”用途。
  582. /// </summary>
  583. public enum ExIMEX
  584. {
  585. /// <summary>
  586. /// IMEX=0 时为“输出模式”
  587. /// </summary>
  588. ExportMode=0,
  589. /// <summary>
  590. /// IMEX=1 时为“输入模式”
  591. /// </summary>
  592. ImportMode=1,
  593. /// <summary>
  594. /// IMEX=2 时为“连結模式”
  595. /// </summary>
  596. LinkedMode=2,
  597. }
  598. }
  599. }