ExportToExcel.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Windows.Forms;
  7. using NPOI.SS.UserModel;
  8. using NPOI.HSSF.UserModel;//导出xls格式用HSSF
  9. using NPOI.XSSF.UserModel;//导出xlsx格式用XSSF
  10. using System.IO;
  11. using System.Runtime.InteropServices;
  12. using System.Diagnostics;
  13. using NPOI.SS.Util;
  14. namespace ExportToExcel
  15. {
  16. public class ExportDgvToExcel
  17. {
  18. #region NPOI DataGridView 导出 EXCEL
  19. /// <summary>
  20. /// NPOI DataGridView 导出 EXCEL
  21. /// 03版Excel-xls最大行数是65536行,最大列数是256列
  22. /// 07版Excel-xlsx最大行数是1048576行,最大列数是16384列
  23. /// </summary>
  24. /// <param name="imagePath">图片路径</param>
  25. /// <param name="dgv">DataGridView</param>
  26. /// <param name="fontname">字体名称</param>
  27. /// <param name="fontsize">字体大小</param>
  28. public void ExportExcel(string imagePath, DataGridView dgv, string fontname, short fontsize)
  29. {
  30. IWorkbook workbook;
  31. ISheet sheet;
  32. Stopwatch sw = null;
  33. //判断datagridview中内容是否为空
  34. if (dgv.Rows.Count == 0)
  35. {
  36. MessageBox.Show("DataGridView中内容为空,请先导入数据!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  37. return;
  38. }
  39. //保存文件
  40. string saveFileName = "";
  41. SaveFileDialog saveFileDialog = new SaveFileDialog();
  42. saveFileDialog.DefaultExt = "xls";
  43. saveFileDialog.Filter = "Excel文件(*.xls)|*.xls|Excel文件(*.xlsx)|*.xlsx";
  44. saveFileDialog.RestoreDirectory = true;
  45. saveFileDialog.Title = "Excel文件保存路径";
  46. MemoryStream ms = new MemoryStream(); //MemoryStream
  47. if (saveFileDialog.ShowDialog() == DialogResult.OK)
  48. {
  49. //**程序开始计时**//
  50. sw = new Stopwatch();
  51. sw.Start();
  52. saveFileName = saveFileDialog.FileName;
  53. //检测文件是否被占用
  54. if (!CheckFiles(saveFileName))
  55. {
  56. MessageBox.Show("文件被占用,请关闭文件" + saveFileName);
  57. workbook = null;
  58. ms.Close();
  59. ms.Dispose();
  60. return;
  61. }
  62. }
  63. else
  64. {
  65. workbook = null;
  66. ms.Close();
  67. ms.Dispose();
  68. }
  69. //*** 根据扩展名xls和xlsx来创建对象
  70. string fileExt = Path.GetExtension(saveFileName).ToLower();
  71. if (fileExt == ".xlsx")
  72. {
  73. workbook = new XSSFWorkbook();
  74. }
  75. else if (fileExt == ".xls")
  76. {
  77. workbook = new HSSFWorkbook();
  78. }
  79. else
  80. {
  81. workbook = null;
  82. }
  83. //***
  84. //创建Sheet
  85. if (workbook != null)
  86. {
  87. sheet = workbook.CreateSheet("二次采集颗粒");//Sheet的名称
  88. }
  89. else
  90. {
  91. return;
  92. }
  93. //设置单元格样式
  94. ICellStyle cellStyle = workbook.CreateCellStyle();
  95. //水平居中对齐和垂直居中对齐
  96. cellStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
  97. cellStyle.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center;
  98. //设置字体
  99. IFont font = workbook.CreateFont();
  100. font.FontName = fontname;//字体名称
  101. font.FontHeightInPoints = fontsize;//字号
  102. font.Color = NPOI.HSSF.Util.HSSFColor.Black.Index;//字体颜色
  103. cellStyle.SetFont(font);
  104. //添加列名
  105. IRow headRow = sheet.CreateRow(0);
  106. for (int i = 0; i < dgv.Columns.Count; i++)
  107. {
  108. //隐藏行列不导出
  109. if (dgv.Columns[i].Visible == true)
  110. {
  111. headRow.CreateCell(i).SetCellValue(dgv.Columns[i].HeaderText);
  112. headRow.GetCell(i).CellStyle = cellStyle;
  113. }
  114. if (i == 4)
  115. {
  116. headRow.CreateCell(i).SetCellValue("图片");
  117. headRow.GetCell(i).CellStyle = cellStyle;
  118. }
  119. if (i == 6)
  120. {
  121. headRow.CreateCell(i).SetCellValue("谱图");
  122. headRow.GetCell(i).CellStyle = cellStyle;
  123. }
  124. }
  125. //根据类型写入内容
  126. for (int rowNum = 0; rowNum < dgv.Rows.Count; rowNum++)
  127. {
  128. ///跳过第一行,第一行为列名
  129. IRow dataRow = sheet.CreateRow(rowNum + 1);
  130. for (int columnNum = 0; columnNum < dgv.Columns.Count; columnNum++)
  131. {
  132. int columnWidth = sheet.GetColumnWidth(columnNum) / 256; //列宽
  133. //隐藏行列不导出
  134. if (dgv.Rows[rowNum].Visible == true && dgv.Columns[columnNum].Visible == true)
  135. {
  136. //防止行列超出Excel限制
  137. if (fileExt == ".xls")
  138. {
  139. //03版Excel最大行数是65536行,最大列数是256列
  140. if (rowNum > 65536)
  141. {
  142. MessageBox.Show("行数超过Excel限制!");
  143. return;
  144. }
  145. if (columnNum > 256)
  146. {
  147. MessageBox.Show("列数超过Excel限制!");
  148. return;
  149. }
  150. }
  151. else if (fileExt == ".xlsx")
  152. {
  153. //07版Excel最大行数是1048576行,最大列数是16384列
  154. if (rowNum > 1048576)
  155. {
  156. MessageBox.Show("行数超过Excel限制!");
  157. return;
  158. }
  159. if (columnNum > 16384)
  160. {
  161. MessageBox.Show("列数超过Excel限制!");
  162. return;
  163. }
  164. }
  165. ICell cell = dataRow.CreateCell(columnNum);
  166. if (dgv.Rows[rowNum].Cells[columnNum].Value == null)
  167. {
  168. cell.SetCellType(CellType.Blank);
  169. }
  170. else
  171. {
  172. if (dgv.Rows[rowNum].Cells[columnNum].ValueType.FullName.Contains("System.Int32"))
  173. {
  174. cell.SetCellValue(Convert.ToInt32(dgv.Rows[rowNum].Cells[columnNum].Value));
  175. }
  176. else if (dgv.Rows[rowNum].Cells[columnNum].ValueType.FullName.Contains("System.String"))
  177. {
  178. cell.SetCellValue(dgv.Rows[rowNum].Cells[columnNum].Value.ToString());
  179. }
  180. else if (dgv.Rows[rowNum].Cells[columnNum].ValueType.FullName.Contains("System.Single"))
  181. {
  182. cell.SetCellValue(Convert.ToSingle(dgv.Rows[rowNum].Cells[columnNum].Value));
  183. }
  184. else if (dgv.Rows[rowNum].Cells[columnNum].ValueType.FullName.Contains("System.Double"))
  185. {
  186. cell.SetCellValue(Convert.ToDouble(dgv.Rows[rowNum].Cells[columnNum].Value));
  187. }
  188. else if (dgv.Rows[rowNum].Cells[columnNum].ValueType.FullName.Contains("System.Decimal"))
  189. {
  190. cell.SetCellValue(Convert.ToDouble(dgv.Rows[rowNum].Cells[columnNum].Value));
  191. }
  192. else if (dgv.Rows[rowNum].Cells[columnNum].ValueType.FullName.Contains("System.DateTime"))
  193. {
  194. cell.SetCellValue(Convert.ToDateTime(dgv.Rows[rowNum].Cells[columnNum].Value).ToString("yyyy-MM-dd"));
  195. }
  196. else if (dgv.Rows[rowNum].Cells[columnNum].ValueType.FullName.Contains("System.DBNull"))
  197. {
  198. cell.SetCellValue("");
  199. }
  200. else
  201. {
  202. cell.SetCellValue(dgv.Rows[rowNum].Cells[columnNum].Value.ToString());
  203. }
  204. }
  205. //设置列宽
  206. IRow currentRow;
  207. if (sheet.GetRow(rowNum) == null)
  208. {
  209. currentRow = sheet.CreateRow(rowNum);
  210. }
  211. else
  212. {
  213. currentRow = sheet.GetRow(rowNum);
  214. }
  215. if (currentRow.GetCell(columnNum) != null)
  216. {
  217. ICell currentCell = currentRow.GetCell(columnNum);
  218. int length = Encoding.Default.GetBytes(currentCell.ToString()).Length;
  219. if (columnWidth < length)
  220. {
  221. columnWidth = length + 10; //设置列宽数值
  222. }
  223. }
  224. sheet.SetColumnWidth(columnNum, columnWidth * 256);
  225. //单元格样式
  226. dataRow.GetCell(columnNum).CellStyle = cellStyle;
  227. }
  228. }
  229. }
  230. //插入图片操作
  231. for (int i = 0; i < dgv.RowCount + 1; i++)
  232. {
  233. CellRangeAddress region = new CellRangeAddress(i, i, 1, 2);
  234. sheet.AddMergedRegion(region);
  235. region = new CellRangeAddress(i, i, 4, 5);
  236. sheet.AddMergedRegion(region);
  237. region = new CellRangeAddress(i, i, 6, 7);
  238. sheet.AddMergedRegion(region);
  239. }
  240. sheet.SetColumnWidth(4, 16 * 256);
  241. sheet.SetColumnWidth(6, 32 * 256);
  242. for (int i = 0; i < dgv.RowCount; i++)
  243. {
  244. string imgPath = imagePath + "\\image\\" + dgv.Rows[i].Cells["FieldID"].Value + "_" + dgv.Rows[i].Cells["particleid"].Value + ".bmp";
  245. //将图片文件读入一个字符串
  246. if (File.Exists(imgPath))
  247. {
  248. byte[] bytes = System.IO.File.ReadAllBytes(imgPath); //路径(加载图片完整路径)
  249. int pictureIdx = workbook.AddPicture(bytes, PictureType.JPEG);
  250. //把图片添加到相应的位置
  251. HSSFPatriarch patriarch = (HSSFPatriarch)sheet.CreateDrawingPatriarch();
  252. HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0, 4, i + 1, 6, i + 2);
  253. HSSFPicture pict = (HSSFPicture)patriarch.CreatePicture(anchor, pictureIdx);
  254. }
  255. string xrayPath = imagePath + "\\xray\\" + dgv.Rows[i].Cells["FieldID"].Value + "_" + dgv.Rows[i].Cells["particleid"].Value + ".bmp";
  256. if (File.Exists(xrayPath))
  257. {
  258. byte[] bytes = System.IO.File.ReadAllBytes(xrayPath); //路径(加载图片完整路径)
  259. int pictureIdx = workbook.AddPicture(bytes, PictureType.JPEG);
  260. //把图片添加到相应的位置
  261. HSSFPatriarch patriarch = (HSSFPatriarch)sheet.CreateDrawingPatriarch();
  262. HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0, 6, i + 1, 8, i + 2);
  263. HSSFPicture pict = (HSSFPicture)patriarch.CreatePicture(anchor, pictureIdx);
  264. }
  265. IRow row = sheet.GetRow(i + 1);
  266. row.Height = 80 * 20; //设置excel行高,像素点是1/20
  267. }
  268. //保存为Excel文件
  269. workbook.Write(ms);
  270. FileStream file = new FileStream(saveFileName, FileMode.Create);
  271. workbook.Write(file);
  272. file.Close();
  273. workbook = null;
  274. ms.Close();
  275. ms.Dispose();
  276. //**程序结束计时**//
  277. sw.Stop();
  278. double totalTime = sw.ElapsedMilliseconds / 1000.0;
  279. //MessageBox.Show(" 导出成功\n耗时" + totalTime + "s", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
  280. }
  281. #endregion
  282. #region 检测文件是否被占用
  283. /// <summary>
  284. /// 判定文件是否打开
  285. /// </summary>
  286. [DllImport("kernel32.dll")]
  287. public static extern IntPtr _lopen(string lpPathName, int iReadWrite);
  288. [DllImport("kernel32.dll")]
  289. public static extern bool CloseHandle(IntPtr hObject);
  290. public const int OF_READWRITE = 2;
  291. public const int OF_SHARE_DENY_NONE = 0x40;
  292. public readonly IntPtr HFILE_ERROR = new IntPtr(-1);
  293. /// <summary>
  294. /// 检测文件被占用
  295. /// </summary>
  296. /// <param name="FileNames">要检测的文件路径</param>
  297. /// <returns></returns>
  298. public bool CheckFiles(string FileNames)
  299. {
  300. if (!File.Exists(FileNames))
  301. {
  302. //文件不存在
  303. return true;
  304. }
  305. IntPtr vHandle = _lopen(FileNames, OF_READWRITE | OF_SHARE_DENY_NONE);
  306. if (vHandle == HFILE_ERROR)
  307. {
  308. //文件被占用
  309. return false;
  310. }
  311. //文件没被占用
  312. CloseHandle(vHandle);
  313. return true;
  314. }
  315. #endregion
  316. }
  317. }