using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.IO; using System.Windows.Forms; using OfficeOpenXml; using OfficeOpenXml.Style; using CK.SCP.Utils; namespace ChangkeTec.Utils { public class EpPlusHelper { private DataSet _dsExcel; private DataTable _dtExcel; private string _excelFileName; private List _readSheetNames; private BackgroundWorker _bgw; private string _pasword = string.Empty; public Action ReadCompleted; readonly SaveFileDialog _sfd = new SaveFileDialog { Filter = "Excel 工作簿 (*.xlsx)|*.xlsx", CheckFileExists = false, CheckPathExists = false, FilterIndex = 0, RestoreDirectory = true, CreatePrompt = false, Title = "保存为Excel文件" }; public EpPlusHelper() { _bgw = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true }; } #region Read public void ReadExcelToDt(string fileName, string password = "") { _excelFileName = fileName; _pasword = password; var excelFileExt = GetFileExt(fileName); switch (excelFileExt) { case ".XLSX": var poDv = new ProcessOperator { BackgroundWork = ReadExcelToDataTable }; poDv.BackgroundWorkerCompleted += ReadExcel_Completed; poDv.Start(); break; case ".XLS": throw new Exception($"需要使用NPOI解析后缀名为{excelFileExt}的文件!"); default: throw new Exception($"无法解析后缀名为{excelFileExt}的文件!"); } //return _dtExcel; } private DataTable ReadData(ExcelWorksheet sheet) { var dt = new DataTable(sheet.Name); int colStart = sheet.Dimension.Start.Column; int colEnd = sheet.Dimension.End.Column; int rowStart = sheet.Dimension.Start.Row; int rowEnd = sheet.Dimension.End.Row; for (var i = colStart; i < colEnd + 1; i++)//从1开始计数 { var columnName = sheet.Cells[rowStart, i].Value?.ToString(); dt.Columns.Add(columnName); } for (var row = rowStart + 1; row < rowEnd + 1; row++)//从1开始计数,跳过第一行 { var dr = dt.NewRow(); for (var col = colStart; col < colEnd + 1; col++)//从1开始计数 { dr[col - 1] = sheet.Cells[row, col]?.Value?.ToString(); } dt.Rows.Add(dr); } RemoveEmptyRow(dt); return dt; } private void ReadExcelToDataTable() { _readSheetNames = new List(); _dsExcel = new DataSet(); var fs = new FileStream(_excelFileName, FileMode.Open); try { using ( var package = string.IsNullOrEmpty(_pasword) ? new ExcelPackage(fs) : new ExcelPackage(fs, _pasword) ) { var validSheetList = GetValidSheetList(package); if (validSheetList.Count == 0) throw new Exception("未找到有效的Excel表单"); var sheet = validSheetList[0]; _readSheetNames.Add(sheet.Name); _dtExcel = ReadData(sheet); } } finally { fs.Close(); fs.Dispose(); } } private void ReadExcel_Completed(object sender, BackgroundWorkerEventArgs e) { if (e.BackGroundException == null) { if (_readSheetNames == null || _readSheetNames.Count == 0) { throw new Exception("文件读失败,未找到符合的系统要求的工作表!"); } else if (ReadCompleted != null) { ReadCompleted(_dtExcel); } } else { throw new Exception("文件读取失败,请联系管理员!"); } } private List GetValidSheetList(ExcelPackage package) { var list = new List(); for (var i = 1; i <= package.Workbook.Worksheets.Count; i++) { var sheet = package.Workbook.Worksheets[i]; var tableName = sheet.Name; if (!tableName.Equals("_xlnm#_FilterDatabase") && tableName.IndexOf("_", StringComparison.Ordinal) != tableName.Length - 1 && tableName.IndexOf("FilterDatabase", StringComparison.Ordinal) == -1) { list.Add(sheet); } } return list; } private void GetFileName(string fileName) { _excelFileName = fileName; } private string GetFileExt(string fileName) { return Path.GetExtension(fileName)?.ToUpper(); } #endregion #region Write public void WriteDsToExcel(DataSet ds, string password = "") { if (_sfd.ShowDialog() != DialogResult.OK) return; var fileName = _sfd.FileName; WriteDsToExcel(ds, fileName, password); } public void WriteDsToExcel(DataSet ds, string excelFileName, string password) { if (ds == null || ds.Tables.Count == 0) throw new Exception("当前表单没有任何数据"); var poDv = new ProcessOperator { BackgroundWork = () => WriteDataSetToExcel(ds, excelFileName, password) }; poDv.BackgroundWorkerCompleted += WriteExcel_Completed; poDv.Start(); } private void WriteDataSetToExcel(DataSet ds, string excelFileName, string password) { var newFile = GetNewFile(excelFileName); _excelFileName = excelFileName; using (var package = string.IsNullOrEmpty(password) ? new ExcelPackage(newFile) : new ExcelPackage(newFile, password)) { foreach (DataTable dt in ds.Tables) { if (string.IsNullOrEmpty(dt?.TableName) || dt.Rows.Count == 0) continue; EpPlusHelper.RemoveEmptyRow(dt); var sheetName = "sheet1"; if (!string.IsNullOrEmpty(dt.TableName)) sheetName = dt.TableName; var worksheet = package.Workbook.Worksheets.Add(sheetName); //表头 SetTitle(dt, worksheet); //各行数据 SetData(dt, worksheet); //设置单元格格式 SetFormat(worksheet); } if (package.Workbook.Worksheets.Count <= 0) return; if (string.IsNullOrEmpty(password)) package.Save(); else package.Save(password); } } public void WriteDtToExcel(DataTable dt, string password = "") { if (_sfd.ShowDialog() != DialogResult.OK) return; var fileName = _sfd.FileName; WriteDtToExcel(dt, fileName, password); } public void WriteDtToExcel(DataTable dt, string excelFileName, string password) { var excelFileExt = GetFileExt(excelFileName); switch (excelFileExt) { case ".XLSX": if (dt == null || dt.Rows.Count <= 0) throw new Exception("当前表单没有任何数据"); var poDv = new ProcessOperator { BackgroundWork = () => WriteDataTableToExcel(dt, excelFileName, password) }; poDv.BackgroundWorkerCompleted += WriteExcel_Completed; poDv.Start(); break; case ".XLS": throw new Exception($"需要使用NPOI解析后缀名为{excelFileExt}的文件!"); default: throw new Exception($"无法解析后缀名为{excelFileExt}的文件!"); } } private static FileInfo GetNewFile(string excelFileName) { var newFile = new FileInfo(excelFileName); if (newFile.Exists) { newFile.Delete(); // ensures we create a new workbook newFile = new FileInfo(excelFileName); } return newFile; } private void WriteDataTableToExcel(DataTable dt, string excelFileName, string password) { var newFile = GetNewFile(excelFileName); _excelFileName = excelFileName; using (var package = string.IsNullOrEmpty(password) ? new ExcelPackage(newFile) : new ExcelPackage(newFile, password)) { var sheetName = "sheet1"; if (!string.IsNullOrEmpty(dt.TableName)) sheetName = dt.TableName; using (var worksheet = package.Workbook.Worksheets.Add(sheetName)) { //表头 SetTitle(dt, worksheet); //各行数据 SetData(dt, worksheet); //设置单元格格式 SetFormat(worksheet); if (string.IsNullOrEmpty(password)) package.Save(); else package.Save(password); } } } private void WriteExcel_Completed(object sender, BackgroundWorkerEventArgs e) { var newFile = new FileInfo(_excelFileName); if (newFile.Exists) Process.Start(_excelFileName); } private static void SetFormat(ExcelWorksheet worksheet) { if (worksheet.Dimension == null) return; int colStart = worksheet.Dimension.Start.Column; int colEnd = worksheet.Dimension.End.Column; int rowStart = worksheet.Dimension.Start.Row; int rowEnd = worksheet.Dimension.End.Row; // using (var range = worksheet.Cells[1, 1, 1, dt.Columns.Count]) using (var range = worksheet.Cells[rowStart, colStart, rowStart, colEnd]) { range.Style.Fill.PatternType = ExcelFillStyle.LightGrid; range.Style.Fill.BackgroundColor.SetColor(Color.LightYellow); range.Style.HorizontalAlignment = ExcelHorizontalAlignment.CenterContinuous; } // using (var range = worksheet.Cells[1, 1, dt.Rows.Count + 1, dt.Columns.Count]) using (var range = worksheet.Cells[rowStart, colStart, rowEnd, colEnd]) { range.Style.Border.BorderAround(ExcelBorderStyle.Thin); range.Style.Font.Name = "微软雅黑"; range.Style.Font.Size = 12; range.AutoFitColumns(); } } private static void SetData(DataTable dt, ExcelWorksheet worksheet) { for (int i = 0; i < dt.Rows.Count; i++) { var row = i + 2; for (int j = 0; j < dt.Columns.Count; j++) { var col = j + 1; var s = dt.Rows[i][j]; ////////////////// //格式化日期字段 var dc = dt.Columns[j]; if (dc.DataType.FullName == "System.DateTime") { DateTime time; DateTime.TryParse(s.ToString(), out time); s = time.ToString("yyyy-MM-dd HH:mm:ss"); } //使用EPPLUS貌似不需要做这个转换了? // if (dc.DataType.FullName == "System.String") // { // s = "'" + s; // } decimal d; if (decimal.TryParse(s.ToString(), out d)) { if (Math.Round(d, 5) == 0) { s = 0; } } worksheet.Cells[row, col].Value = s; } } } private static void SetTitle(DataTable dt, ExcelWorksheet worksheet) { int row = 1; for (int i = 0; i < dt.Columns.Count; i++) { var dc = dt.Columns[i]; row = 1; var col = i + 1; worksheet.Cells[row, col].Value = dc.ColumnName; } worksheet.View.FreezePanes(row + 1, 1); //冻结表头 } #endregion public static void RemoveEmptyRow(DataTable dt) { if (dt == null || dt.Rows.Count == 0) return; var isEmpty = true; for (var idx = dt.Rows.Count - 1; idx >= 0; idx--) { var dr = dt.Rows[idx]; for (var i = 0; i < dt.Columns.Count; i++) { if (dr[i].ToString().Trim() != string.Empty) { isEmpty = false; } } if (isEmpty) dt.Rows.Remove(dr); } } } }