• .netcore导入导出Excel


    使用NPOI包2.5.4版

    思路:简单的导入导出,就是一表、一行、一单元格读写的过程

    读取分三种常见情况,1.一次读取全部表的全部数据2.读取单表的所有数据3.按指定数量读取

    写入分两种情况,1.一次写入全部数据2.按指定数量写入

    使用的时候只需要继承导入或者导出类,并实现数据转换方法,简单的导入导出就OK了

    导出的时候用了新版NPOI缓存新方法,不用在怕海量导出时候内存爆炸,新问题是.....C盘要大不然临时缓存会让C盘爆炸

    PS:如果是用EF读取数据库的朋友,建议引用Microsoft.EntityFrameworkCore然后再查询的时候调用一下AsNoTracking()方法取消追踪,减少内存占用.

      1     /// <summary>
      2     /// 需要处理Excel数据导入,继承本类并实现方法
      3     /// </summary>
      4     public abstract class ExcelImport
      5     {
      6         ISheet _sheet = null;
      7         IWorkbook _workbook = null;
      8         int _numberOfSheets = 0;
      9         int _sheetsIndexByCount = 0;
     10         int _sheetsIndex = 0;
     11         int _rowIndex = 0;
     12         bool _skipFirst = false;
     13         public ExcelImport(string filePath, bool skipFirst = false)
     14         {
     15             var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
     16             if (filePath.IndexOf(".xlsx") > 0) // 2007版本
     17                 _workbook = new XSSFWorkbook(fs);
     18             else if (filePath.IndexOf(".xls") > 0) // 2003版本
     19                 _workbook = new HSSFWorkbook(fs);
     20             _numberOfSheets = _workbook.NumberOfSheets;
     21             _skipFirst = skipFirst;
     22         }
     23         /// <summary>
     24         /// 处理一行转成string集合的数据
     25         ///     原始表格数据,需要重写处理方法
     26         ///     返回数据类型必须和读取方法传参的T类型一致
     27         ///     可以用{ typeof(T) == typeof(模型类) }判断,用于分别处理不同模型的数据
     28         /// </summary>
     29         protected abstract Object AnalysisData<T>(List<string> origin) where T : new();
     30         /// <summary>
     31         /// 读取自定义数量数据
     32         ///     单表数量不足,会读取下一张表
     33         /// </summary>
     34         public virtual List<T> ReadSheetByCount<T>(int readCount) where T : new()
     35         {
     36             List<T> data = new();
     37             if (_rowIndex == 0) _rowIndex = Convert.ToInt32(_skipFirst);
     38             IRow dataRow;
     39             int rowCount = 0;//最后一行的标号(标号从0开始)
     40             if (_sheet != null) rowCount = _sheet.LastRowNum + 1;
     41             do
     42             {
     43                 if (_sheet == null || rowCount == _rowIndex)
     44                 {
     45                     if (_sheetsIndexByCount == _numberOfSheets) break;
     46                     _sheet = _workbook.GetSheetAt(_sheetsIndexByCount);
     47                     _sheetsIndexByCount++;
     48                     _rowIndex = Convert.ToInt32(_skipFirst);
     49                     rowCount = _sheet.LastRowNum + 1;
     50                 }
     51 
     52                 dataRow = _sheet.GetRow(_rowIndex);
     53                 _rowIndex++;
     54                 if (dataRow == null) continue; //没有数据的行默认是null
     55                 var origin = dataRow.Cells.Select(m => m.StringCellValue.ToTrim()).ToList();
     56                 if (origin.Where(m => string.IsNullOrEmpty(m)).Count() == origin.Count) continue; //整行数据都为空
     57                 data.Add((T)AnalysisData<T>(origin));
     58             } while (readCount > data.Count);
     59 
     60             return data;
     61         }
     62         /// <summary>
     63         /// 处理单表数据
     64         ///     return null表示没有更多sheet可以读取了
     65         /// </summary>
     66         public virtual List<T> ReadNextSheet<T>() where T : new()
     67         {
     68             List<T> data = new();
     69             if (_sheetsIndex < _numberOfSheets)
     70             {
     71                 _sheet = _workbook.GetSheetAt(_sheetsIndex);
     72                 _sheetsIndex++;
     73             }
     74             else { return null; }
     75 
     76             int rowIndex = Convert.ToInt32(_skipFirst);
     77             IRow dataRow;
     78             int rowCount = _sheet.LastRowNum + 1;//最后一行的标号(标号从0开始)
     79             do
     80             {
     81                 dataRow = _sheet.GetRow(rowIndex);
     82                 rowIndex++;
     83                 if (dataRow == null) continue; //没有数据的行默认是null
     84                 var origin = dataRow.Cells.Select(m => m.StringCellValue.ToTrim()).ToList();
     85                 if (origin.Where(m => string.IsNullOrEmpty(m)).Count() == origin.Count) continue; //整行数据都为空
     86                 data.Add((T)AnalysisData<T>(origin));
     87             } while (rowIndex < rowCount);
     88             return data;
     89         }
     90         /// <summary>
     91         /// 一次性处理全部sheet数据
     92         ///     *不建议,过量数据可能导致内存溢出
     93         /// </summary>
     94         public virtual List<T> ReadAllSheet<T>() where T : new()
     95         {
     96             List<T> data = new();
     97             do
     98             {
     99                 data.AddRange(ReadNextSheet<T>());
    100             } while (_sheetsIndex < _numberOfSheets);
    101             return data;
    102         }
    103     }
    104     /// <summary>
    105     /// 需要处理Excel数据导出,继承本类并实现方法
    106     /// </summary>
    107     public abstract class ExcelExport
    108     {
    109         SXSSFWorkbook _workbook;// 虚拟工作薄
    110         SXSSFSheet _sheet;// 虚拟工作表
    111         IRow _row;
    112         ICell _newCell;
    113         int _rowIndex = 0;
    114         int _rowMax = 1024 * 1024;//默认单表最大行数
    115         string _filePath;
    116 
    117         ICellStyle Title { get; set; }
    118         ICellStyle Cell { get; set; }
    119 
    120         /// <summary>
    121         /// 导出Excel
    122         /// </summary>
    123         /// <param name="filePath">保存文件路径(不带文件名)</param>
    124         /// <param name="maxRowCount">单表最大数据行,默认1W条</param>
    125         public ExcelExport(string directory, int maxRowCount = 10000)
    126         {
    127             _filePath = directory + "\" + Guid.NewGuid().ToString("N").ToLower() + ".xlsx";
    128             if (!Directory.Exists(directory)) Directory.CreateDirectory(directory);
    129             if (System.IO.File.Exists(_filePath)) System.IO.File.Delete(_filePath);
    130        // 需要先创建一个xlsx文件不然后面会报格式错误
    131             using (FileStream fs = new FileStream(_filePath, FileMode.Create, FileAccess.ReadWrite))
    132             {
    133                 var wb = new XSSFWorkbook();
    134                 wb.Write(fs);
    135                 wb.Close();
    136             }
    137 
    138             _workbook = new SXSSFWorkbook(new XSSFWorkbook(), 500);// 创建一个xlsx格式的虚拟表,500表示每500条数据写入硬盘缓存,释放内存
    139 
    140             if (maxRowCount <= _rowMax) _rowMax = maxRowCount;
    141 
    142             Title = _workbook.CreateCellStyle();
    143             Title.Alignment = HorizontalAlignment.Center;
    144             Title.VerticalAlignment = VerticalAlignment.Center;
    145             IFont font = _workbook.CreateFont();
    146             font.Color = IndexedColors.Red.Index;
    147             Title.SetFont(font);
    148 
    149             Cell = _workbook.CreateCellStyle();
    150             Cell.Alignment = HorizontalAlignment.Justify;//两端自动对齐(自动换行)
    151             Cell.VerticalAlignment = VerticalAlignment.Center;
    152         }
    153         /// <summary>
    154         /// 处理一个实体对象
    155         ///     将实体对象数据转换成导入Excel用得数据结构
    156         ///     可以用{ typeof(T) == typeof(模型类) }判断
    157         /// </summary>
    158         protected abstract List<ExcelCell> ConvertData<T>(T origin) where T : new();
    159         /// <summary>
    160         /// 写入数据(在虚拟工作薄中操作)
    161         ///     单表写满,会创建新表
    162         ///     如果出现转换失败的数据会出现在返回的List<T>集合中
    163         /// </summary>
    164         public virtual List<T> WriteByCount<T>(List<T> data, List<string> title = null) where T : new()
    165         {
    166             if (data == null && data.Count == 0)
    167                 return default;
    168 
    169             List<T> error = new();
    170             int columnNum = 0, dataIndex = 0;
    171             if (title == null) columnNum = ConvertData<T>(data[0]).Count;
    172             else columnNum = title.Count;
    173 
    174             do
    175             {
    176                 if (_rowIndex == 0 || _rowIndex == _rowMax)
    177                 {
    178                     _sheet = _workbook.CreateSheetByAutoWidth(columnNum);
    179                     _rowIndex = 0;
    180                     if (title != null)
    181                     {
    182                         _row = _sheet.CreateRowByHeight(_rowIndex);
    183                         _rowIndex++;
    184                         for (int j = 0; j < title.Count; j++)
    185                         {
    186                             _newCell = _row.CreateCell(j);
    187                             _newCell.SetCellValue(title[j]);
    188                             _newCell.CellStyle = Title;
    189                         }
    190                     }
    191                 }
    192 
    193                 _row = _sheet.CreateRowByHeight(_rowIndex);
    194                 try
    195                 {
    196                     var cellData = ConvertData<T>(data[dataIndex]);
    197                     for (int i = 0; i < cellData.Count; i++)
    198                     {
    199                         _newCell = _row.CreateCell(i);
    200                         _newCell.CellStyle = Cell;
    201                         switch (cellData[i].CellType)
    202                         {
    203                             case ExcelCellType.Boolean:
    204                                 _newCell.SetCellValue(bool.Parse(cellData[i].Value));
    205                                 break;
    206                             case ExcelCellType.DateTime:
    207                                 _newCell.SetCellValue(DateTime.Parse(cellData[i].Value));
    208                                 break;
    209                             case ExcelCellType.Number:
    210                                 _newCell.SetCellValue(double.Parse(cellData[i].Value));
    211                                 break;
    212                             case ExcelCellType.String:
    213                                 _newCell.SetCellValue(cellData[i].Value);
    214                                 break;
    215                             default:
    216                                 _newCell.SetCellValue(cellData[i].Value);
    217                                 break;
    218                         }
    219                     }
    220                     _rowIndex++;
    221                 }
    222                 catch
    223                 {
    224                     error.Add(data[dataIndex]);
    225                 }
    226                 finally
    227                 {
    228                     dataIndex++;
    229                 }
    230             } while (data.Count > dataIndex);
    231             return error;
    232         }
    233         /// <summary>
    234         /// 单表写入数据(在虚拟工作薄中操作)
    235         ///     数据总数超过单表最大的行数剩下部分不会写入
    236         ///     如果出现转换失败的数据会出现在返回的List<T>集合中
    237         /// </summary>
    238         public virtual List<T> WriteBySheet<T>(List<T> data, List<string> title = null) where T : new()
    239         {
    240             if (data == null && data.Count == 0)
    241                 return default;
    242 
    243             List<T> error = new();
    244             int columnNum = 0, dataIndex = 0, rowIndex = 0;
    245 
    246             if (title == null) columnNum = ConvertData<T>(data[0]).Count;
    247             else columnNum = title.Count;
    248 
    249             _sheet = _workbook.CreateSheetByAutoWidth(columnNum);
    250             if (title != null)
    251             {
    252                 _row = _sheet.CreateRowByHeight(rowIndex);
    253                 rowIndex++;
    254                 for (int i = 0; i < title.Count; i++)
    255                 {
    256                     _newCell = _row.CreateCell(i);
    257                     _newCell.SetCellValue(title[i]);
    258                     _newCell.CellStyle = Title;
    259                 }
    260             }
    261 
    262             do
    263             {
    264                 if (rowIndex == 1024 * 1024) break;//   超出单表最大行数
    265                 _row = _sheet.CreateRowByHeight(rowIndex);
    266                 try
    267                 {
    268                     var cellData = ConvertData<T>(data[dataIndex]);
    269                     for (int i = 0; i < cellData.Count; i++)
    270                     {
    271                         _newCell = _row.CreateCell(i);
    272                         _newCell.CellStyle = Cell;
    273                         switch (cellData[i].CellType)
    274                         {
    275                             case ExcelCellType.Boolean:
    276                                 _newCell.SetCellValue(bool.Parse(cellData[i].Value));
    277                                 break;
    278                             case ExcelCellType.DateTime:
    279                                 _newCell.SetCellValue(DateTime.Parse(cellData[i].Value));
    280                                 break;
    281                             case ExcelCellType.Number:
    282                                 _newCell.SetCellValue(double.Parse(cellData[i].Value));
    283                                 break;
    284                             case ExcelCellType.String:
    285                                 _newCell.SetCellValue(cellData[i].Value);
    286                                 break;
    287                             default:
    288                                 _newCell.SetCellValue(cellData[i].Value);
    289                                 break;
    290                         }
    291                     }
    292                     rowIndex++;
    293                 }
    294                 catch { error.Add(data[dataIndex]); }
    295                 finally { dataIndex++; }
    296             } while (data.Count > dataIndex);
    297             return error;
    298         }
    299         /// <summary>
    300         /// 完成写入获取导出文件路径,把硬盘上的临时文件数据打包成xlsx文件
    301         /// </summary>
    302         public virtual string WriteEnd()
    303         {
    304             using (FileStream fs = File.Open(_filePath, FileMode.Open))
    305             {
    306                 _workbook.Write(fs);
    307                 _workbook.Dispose();
    308                 return _filePath;
    309             }
    310         }
    311     }
    312     /// <summary>
    313     /// 扩展
    314     /// </summary>
    315     public static class ISheetExt
    316     {
    317         public static IRow CreateRowByHeight(this ISheet sheet, int rownum)
    318         {
    319             var row = sheet.CreateRow(rownum);
    320             row.HeightInPoints = 30;
    321             return row;
    322         }
    323         public static SXSSFSheet CreateSheetByWidth(this IWorkbook workbook, int columnnum, int width)
    324         {
    325             width = width * 256;//  Excel表格宽度单位跟像素不一样
    326             var sheet = (SXSSFSheet)workbook.CreateSheet();
    327             for (int i = 0; i < columnnum; i++)
    328                 sheet.SetColumnWidth(i, width);
    329             return sheet;
    330         }
    331         public static SXSSFSheet CreateSheetByAutoWidth(this IWorkbook workbook, int columnnum)
    332         {
    333             var sheet = (SXSSFSheet)workbook.CreateSheet();
    334             for (int i = 0; i < columnnum; i++)
    335             {
    336                 sheet.TrackColumnForAutoSizing(i);
    337                 sheet.AutoSizeColumn(i);
    338             }
    339             return sheet;
    340         }
    341     }
    342     public class ExcelCell
    343     {
    344         public ExcelCellType CellType { get; set; }
    345         public string Value { get; set; }
    346     }
    347     public enum ExcelCellType
    348     {
    349         Boolean,
    350         DateTime,
    351         Number,
    352         String
    353     }
  • 相关阅读:
    kafka源码学习笔记
    spring学习笔记
    logback pattern配置详解
    hive笔记
    hbase笔记
    打监控的坑
    Consul1 在window7安装
    springboot1.4下hystrix dashboard Unable to connect to Command Metric Stream解决办法
    com.netflix.hystrix.contrib.javanica.exception.FallbackDefinitionException: fallback method wasn't found: serviceError([class java.lang.String]) 异常
    Keepalived 集群在Linux下的搭建
  • 原文地址:https://www.cnblogs.com/carlows/p/15138421.html
Copyright © 2020-2023  润新知