1 using NPOI.HSSF.UserModel; 2 using NPOI.HSSF.Util; 3 using NPOI.SS.UserModel; 4 using NPOI.XSSF.UserModel; 5 using System; 6 using System.Collections.Generic; 7 using System.ComponentModel; 8 using System.Data; 9 using System.Globalization; 10 using System.IO; 11 using System.Linq; 12 using System.Text; 13 using System.Threading.Tasks; 14 using NPOI.SS.Util; 15 16 namespace POICommen 17 { 18 public class NpoiHelper 19 { 20 #region 属性 21 22 private readonly int _perSheetCount = 40000; //每个sheet要保存的条数 23 24 public NpoiHelper() 25 { 26 } 27 28 /// <summary> 29 /// 最大接收5万条每页,大于5万时,使用系统默认的值(4万) 30 /// </summary> 31 /// <param name="perSheetCounts"></param> 32 public NpoiHelper(int perSheetCounts) 33 { 34 if (_perSheetCount <= 50000) 35 _perSheetCount = perSheetCounts; 36 } 37 38 #endregion 39 40 #region IExcelProvider 成员 41 42 public DataTable Import(Stream fs, string ext, out string msg, List<string> validates = null) 43 { 44 msg = string.Empty; 45 var dt = new DataTable(); 46 try 47 { 48 IWorkbook workbook; 49 if (ext == ".xls") 50 workbook = new HSSFWorkbook(fs); 51 else 52 workbook = new XSSFWorkbook(fs); 53 const int num = 0; 54 var sheet = workbook.GetSheetAt(num); 55 dt.TableName = sheet.SheetName; 56 var rowCount = sheet.LastRowNum; 57 const int firstNum = 0; 58 var headerRow = sheet.GetRow(0); 59 int cellCount = headerRow.LastCellNum; 60 if (validates != null) 61 { 62 var validateCount = validates.Count; 63 if (validateCount > cellCount) 64 { 65 msg = "上传EXCEL文件格式不正确"; 66 return null; 67 } 68 for (var i = 0; i < validateCount; i++) 69 { 70 var columnName = headerRow.GetCell(i).StringCellValue; 71 if (validates[i] == columnName) continue; 72 msg = "上传EXCEL文件格式不正确"; 73 return null; 74 } 75 } 76 for (int i = headerRow.FirstCellNum; i < cellCount; i++) 77 { 78 var column = new DataColumn(headerRow.GetCell(i).StringCellValue); 79 dt.Columns.Add(column); 80 } 81 for (var i = firstNum + 1; i <= rowCount; i++) 82 { 83 var row = sheet.GetRow(i); 84 var dataRow = dt.NewRow(); 85 if (row != null) 86 for (int j = row.FirstCellNum; j < cellCount; j++) 87 if (row.GetCell(j) != null) 88 dataRow[j] = GetCellValue(row.GetCell(j), ext); 89 dt.Rows.Add(dataRow); 90 } 91 return dt; 92 } 93 catch (Exception ex) 94 { 95 throw new Exception(ex.Message); 96 } 97 } 98 99 private static IFont GetFont(IWorkbook workbook, HSSFColor color) 100 { 101 var font = workbook.CreateFont(); 102 font.Color = color.Indexed; 103 font.FontHeightInPoints = 10; 104 font.Boldweight = 700; 105 //font.FontName = "楷体"; 106 font.IsItalic = true; 107 return font; 108 } 109 110 public static void SetCellValues(ICell cell, string cellType, string cellValue) 111 { 112 switch (cellType) 113 { 114 case "System.String": //字符串类型 115 double result; 116 if (double.TryParse(cellValue, out result)) 117 cell.SetCellValue(result); 118 else 119 cell.SetCellValue(cellValue); 120 break; 121 case "System.DateTime": //日期类型 122 DateTime dateV; 123 DateTime.TryParse(cellValue, out dateV); 124 cell.SetCellValue(dateV); 125 break; 126 case "System.Boolean": //布尔型 127 bool boolV; 128 bool.TryParse(cellValue, out boolV); 129 cell.SetCellValue(boolV); 130 break; 131 case "System.Int16": //整型 132 case "System.Int32": 133 case "System.Int64": 134 case "System.Byte": 135 int intV; 136 int.TryParse(cellValue, out intV); 137 cell.SetCellValue(intV); 138 break; 139 case "System.Decimal": //浮点型 140 case "System.Double": 141 double doubV; 142 double.TryParse(cellValue, out doubV); 143 cell.SetCellValue(doubV); 144 break; 145 case "System.DBNull": //空值处理 146 cell.SetCellValue(""); 147 break; 148 default: 149 cell.SetCellValue(""); 150 break; 151 } 152 } 153 154 public string Export(string excelFileName, DataTable dtIn) 155 { 156 var workbook = new HSSFWorkbook(); 157 ICell cell; 158 var sheetCount = 1; //当前的sheet数量 159 var currentSheetCount = 0; //循环时当前保存的条数,每页都会清零 160 161 //表头样式 162 var style = workbook.CreateCellStyle(); 163 style.Alignment = HorizontalAlignment.Center; 164 var green = new HSSFColor.Green(); 165 style.SetFont(GetFont(workbook, green)); 166 167 //内容样式 168 style = workbook.CreateCellStyle(); 169 style.Alignment = HorizontalAlignment.Center; 170 var blue = new HSSFColor.Blue(); 171 style.SetFont(GetFont(workbook, blue)); 172 173 var sheet = workbook.CreateSheet("Sheet" + sheetCount); 174 //填充表头 175 var row = sheet.CreateRow(0); 176 for (var i = 0; i < dtIn.Columns.Count; i++) 177 { 178 cell = row.CreateCell(i); 179 cell.SetCellValue(dtIn.Columns[i].ColumnName); 180 cell.CellStyle = style; 181 } 182 //填充内容 183 for (var i = 0; i < dtIn.Rows.Count; i++) 184 { 185 if (currentSheetCount >= _perSheetCount) 186 { 187 sheetCount++; 188 currentSheetCount = 0; 189 sheet = workbook.CreateSheet("Sheet" + sheetCount); 190 } 191 row = sheetCount == 1 ? sheet.CreateRow(currentSheetCount + 1) : sheet.CreateRow(currentSheetCount); 192 currentSheetCount++; 193 for (var j = 0; j < dtIn.Columns.Count; j++) 194 { 195 cell = row.CreateCell(j); 196 cell.CellStyle = style; 197 SetCellValues(cell, dtIn.Columns[j].DataType.ToString(), dtIn.Rows[i][j].ToString()); 198 } 199 } 200 var fs = new FileStream(excelFileName, FileMode.CreateNew, FileAccess.Write); 201 workbook.Write(fs); 202 fs.Close(); 203 return excelFileName; 204 } 205 206 public DataTable Import(string filepath, string key, string sheetName, string endKey) 207 { 208 var table = new DataTable(); 209 try 210 { 211 using (var excelFileStream = new FileStream(filepath, FileMode.Open, FileAccess.Read)) 212 { 213 var file = Path.GetExtension(filepath); 214 if (file != null) 215 { 216 var type = file.Replace(".", ""); 217 IWorkbook workbook; 218 if (type == "xls") 219 workbook = new HSSFWorkbook(excelFileStream); 220 else 221 workbook = new XSSFWorkbook(excelFileStream); 222 223 for (var num = 0; num < workbook.NumberOfSheets; num++) 224 { 225 var sheet = workbook.GetSheetAt(num); 226 if (sheet.SheetName != sheetName) 227 continue; 228 table.TableName = sheet.SheetName; 229 var rowCount = sheet.LastRowNum; 230 IRow headerRow = null; 231 var cellCount = 0; 232 var firstNum = 0; 233 234 for (var i = 0; i <= rowCount; i++) 235 { 236 if (sheet.GetRow(i).GetCell(0).StringCellValue != key) continue; 237 headerRow = sheet.GetRow(i); 238 cellCount = headerRow.LastCellNum; 239 firstNum = i; 240 break; 241 } 242 243 //列名 244 245 //handling header. 246 if (headerRow != null) 247 for (int i = headerRow.FirstCellNum; i < cellCount; i++) 248 { 249 var column = new DataColumn(headerRow.GetCell(i).StringCellValue); 250 table.Columns.Add(column); 251 } 252 253 for (var i = firstNum + 1; i <= rowCount; i++) 254 { 255 var row = sheet.GetRow(i); 256 var dataRow = table.NewRow(); 257 var isEnd = false; 258 if (row != null) 259 for (int j = row.FirstCellNum; j < cellCount; j++) 260 { 261 if (row.GetCell(j) != null) 262 dataRow[j] = GetCellValue(row.GetCell(j), type); 263 if (dataRow[j].ToString() != endKey) continue; 264 isEnd = true; 265 break; 266 } 267 if (isEnd) 268 break; 269 table.Rows.Add(dataRow); 270 } 271 return table; 272 } 273 } 274 } 275 } 276 catch (Exception) 277 { 278 return null; 279 } 280 return table; 281 } 282 283 private static string GetCellValue(ICell cell, string type) 284 { 285 if (cell == null) 286 return string.Empty; 287 switch (cell.CellType) 288 { 289 case CellType.Blank: 290 return string.Empty; 291 case CellType.Boolean: 292 return cell.BooleanCellValue.ToString(); 293 case CellType.Error: 294 return cell.ErrorCellValue.ToString(); 295 case CellType.Numeric: 296 var format = cell.CellStyle.DataFormat; 297 if (format == 14 || format == 31 || format == 57 || format == 58) 298 { 299 var date = cell.DateCellValue; 300 var re = date.ToString("yyy-MM-dd"); 301 return re; 302 } 303 return cell.ToString(); 304 305 case CellType.String: 306 return cell.StringCellValue; 307 308 case CellType.Formula: 309 try 310 { 311 if (type == "xls") 312 { 313 var e = new HSSFFormulaEvaluator(cell.Sheet.Workbook); 314 e.EvaluateInCell(cell); 315 return cell.ToString(); 316 } 317 else 318 { 319 var e = new XSSFFormulaEvaluator(cell.Sheet.Workbook); 320 e.EvaluateInCell(cell); 321 return cell.ToString(); 322 } 323 } 324 catch 325 { 326 return cell.NumericCellValue.ToString(CultureInfo.InvariantCulture); 327 } 328 case CellType.Unknown: 329 return cell.ToString(); 330 default: 331 return cell.ToString(); 332 } 333 } 334 335 #endregion 336 337 #region 辅助导入 338 339 /// <summary> 340 /// </summary> 341 /// <typeparam name="T"></typeparam> 342 /// <param name="datatable"></param> 343 /// <returns></returns> 344 public IEnumerable<T> ConvertTo<T>(DataTable datatable) where T : new() 345 { 346 var temp = new List<T>(); 347 try 348 { 349 var columnsNames = 350 (from DataColumn dataColumn in datatable.Columns select dataColumn.ColumnName).ToList(); 351 temp = datatable.AsEnumerable().ToList().ConvertAll(row => GetObject<T>(row, columnsNames)); 352 return temp; 353 } 354 catch 355 { 356 return temp; 357 } 358 } 359 360 /// <summary> 361 /// 根据DataTable生成对象,对象的属性与列同名 362 /// </summary> 363 /// <typeparam name="T"></typeparam> 364 /// <param name="row"></param> 365 /// <param name="columnsName"></param> 366 /// <returns></returns> 367 public T GetObject<T>(DataRow row, List<string> columnsName) where T : new() 368 { 369 var obj = new T(); 370 try 371 { 372 var properties = typeof(T).GetProperties(); 373 foreach (var objProperty in properties) 374 { 375 var attrs = objProperty.GetCustomAttributes(typeof(DisplayNameAttribute), false); 376 if (!attrs.Any()) continue; 377 var displayName = ((DisplayNameAttribute)attrs.First()).DisplayName; 378 379 var columnname = columnsName.Find(s => s == displayName); 380 if (string.IsNullOrEmpty(columnname)) continue; 381 var value = row[columnname].ToString(); 382 if (string.IsNullOrEmpty(value)) continue; 383 if (Nullable.GetUnderlyingType(objProperty.PropertyType) != null) 384 { 385 value = row[columnname].ToString().Replace("$", "").Replace(",", ""); 386 objProperty.SetValue(obj, 387 Convert.ChangeType(value, 388 Type.GetType(Nullable.GetUnderlyingType(objProperty.PropertyType).ToString())), null); 389 } 390 else 391 { 392 value = row[columnname].ToString().Replace("%", ""); 393 objProperty.SetValue(obj, 394 Convert.ChangeType(value, Type.GetType(objProperty.PropertyType.ToString())), null); 395 } 396 } 397 return obj; 398 } 399 catch 400 { 401 return obj; 402 } 403 } 404 405 public static void CopyRow(int startRow, int endRow, int pPosition, ISheet sheet) 406 { 407 int pStartRow = startRow - 1; 408 int pEndRow = endRow - 1; 409 int targetRowFrom; 410 int targetRowTo; 411 int cloumnCount; 412 413 CellRangeAddress region = null; 414 415 416 if (pStartRow==-1||pEndRow==-1) 417 { 418 return; 419 } 420 421 422 //拷贝合并的单元格 423 for (int k = 0; k < sheet.NumMergedRegions; k++) 424 { 425 region = sheet.GetMergedRegion(k); 426 if (region.FirstRow>=pStartRow&®ion.LastRow<=pEndRow) 427 { 428 targetRowFrom = region.FirstRow - pStartRow + pPosition; 429 targetRowTo = region.LastRow - pStartRow + pPosition; 430 CellRangeAddress newRegion = region.Copy(); 431 newRegion.FirstRow = targetRowFrom; 432 newRegion.FirstColumn = region.FirstColumn; 433 newRegion.LastRow = targetRowTo; 434 newRegion.LastColumn = region.LastColumn; 435 sheet.AddMergedRegion(newRegion); 436 } 437 438 } 439 440 //设置列宽 441 for (int k = pStartRow; k <=pEndRow; k++) 442 { 443 IRow sourceRow = sheet.GetRow(k); 444 cloumnCount = sourceRow.LastCellNum; 445 if (sourceRow!=null) 446 { 447 IRow newRow = sheet.CreateRow(pPosition - pStartRow + k); 448 newRow.Height = sourceRow.Height; 449 for (int l = 0; l < cloumnCount; l++) 450 { 451 ICell templateCell = sourceRow.GetCell(l); 452 if (templateCell!=null) 453 { 454 ICell newCell = newRow.CreateCell(l); 455 CopyCell(templateCell,newCell); 456 } 457 } 458 } 459 460 } 461 462 463 } 464 465 private static void CopyCell(ICell srcCell, ICell distCell) 466 { 467 distCell.CellStyle=srcCell.CellStyle; 468 if (srcCell.CellComment!= null) 469 { 470 distCell.CellComment=srcCell.CellComment; 471 } 472 473 CellType srcCellType = srcCell.CellType; 474 distCell.SetCellType(srcCellType); 475 476 string cellValue = GetCellValue(srcCell, "xlsx"); 477 SetCellValues(distCell, "System.String", cellValue); 478 } 479 480 #endregion 481 } 482 }