zoukankan      html  css  js  c++  java
  • C# NPOI Excel应用

    参考链接

    https://www.cnblogs.com/tangpeng97/p/7839189.html
    https://www.cnblogs.com/chenyanbin/archive/2019/05/10/10832614.html
    https://www.cnblogs.com/dedeyi/p/3240592.html 解决单元格null的问题

    准备工作

    • 安装好插件后,需要重写方法 //年代有点久,忘记为什么要重写了
            /// <summary>
            /// 重写Npoi方法
            /// </summary>
            public class NpoiMemoryStream : MemoryStream
            {
                public NpoiMemoryStream()
                {
                    AllowClose = true;
                }
    
                public bool AllowClose { get; set; }
    
                public override void Close()
                {
                    if (AllowClose)
                        base.Close();
                }
            }
    

    Excel文件转DataTable

    注意点

    • xlsx和xls 需要分别对应两个类型,xlsx对应XSSFWorkbook,xls对应HSSFWorkbook

    根据文件路径得到Excel转Datatable

                    XSSFWorkbook workbook = new XSSFWorkbook("D:\test.xlsx");//这段没测试,应该可以用
                    NPOI.SS.UserModel.ISheet sheet = workbook.GetSheetAt(0);
                    DataTable dt = new DataTable(sheet.SheetName);
    
                    // write header row
                    IRow headerRow = sheet.GetRow(0);
                    foreach (ICell headerCell in headerRow)
                    {
                        dt.Columns.Add(headerCell.ToString());
                    }
    
                    // write the rest
                    int rowIndex = 0;
                    foreach (IRow row in sheet)
                    {
                        // skip header row
                        if (rowIndex++ == 0) continue;
                        DataRow dataRow = dt.NewRow();
                        dataRow.ItemArray = row.Cells.Select(c => c.ToString()).ToArray();
                        dt.Rows.Add(dataRow);
                    }
                    return dt;
    

    根据文件转换成字节流生成DataTable

            /// <summary>
            /// 根据Excel文件流和类型 得到对应IWorkbook
            /// </summary>
            /// <param name="stream"></param>
            /// <param name="type"></param>
            /// <returns></returns>
            private static IWorkbook GetIWorkbookByStream(Stream stream, string type) //将Excel格式判定抽象出来
            {
                IWorkbook workbook;
                if (type.Equals(".xlsx"))
                {
                    workbook = new XSSFWorkbook(stream);
                }
                else
                {
                    workbook = new HSSFWorkbook(stream);
                }
                return workbook;
            }
    
            public static DataTable GetDataTableByISheet(ISheet sheet)//根据抽象出来的工作簿返回表格
            {
                DataTable dt = new DataTable();
                IRow headerRow = sheet.GetRow(0);
                foreach (ICell headerCell in headerRow)
                {
                    dt.Columns.Add(headerCell.ToString());
                }
    
                // write the rest
                int rowIndex = 0;
              
                foreach (IRow row in sheet)
                {
                    // skip header row  去除首行标题
                    if (rowIndex++ == 0) continue; 
                    DataRow dataRow = dt.NewRow();
                    //dataRow.ItemArray = row.Cells.Select(c => c.ToString()).ToArray();这个会自动去除为null的单元格,导致错位问题
                    //遍历每一个单元格,防止单元格为null被自动去除
                    for (int i = 0, len = row.LastCellNum; i < len; i++)
                    {
                        ICell cell = row.GetCell(i);
    
                        if (cell != null)
                        {
                            switch (cell.CellType)
                            {
                                case CellType.String:
                                    dataRow[i] = cell.StringCellValue;
                                    break;
                                case CellType.Numeric:
                                    dataRow[i] = cell.NumericCellValue;
                                    break;
                                case CellType.Boolean:
                                    dataRow[i] = cell.BooleanCellValue;
                                    break;
                                default:
                                    dataRow[i] = "ERROR";
                                    break;
                            }
                        }
                    }
                   dt.Rows.Add(dataRow);
                }
                return dt;
            }
    
            public static DataSet GetDataSetByIWorkbook(IWorkbook workbook)//根据抽象出来的Excel文件返回DataSet
            {
                DataSet ds = new DataSet();
               // IWorkbook workbook = GetIWorkbookByStream(stream, type);
                var flag = workbook.ActiveSheetIndex;
               for(int i = 0; i <= flag; i++)
                {
                    ds.Tables.Add(GetDataTableByISheet(workbook.GetSheetAt(i)));
                }
                return ds;
            }
    
            /// <summary>
            /// 根据上传文件得到DataTable,只取第一张表
            /// </summary>
            /// <param name="file"></param>
            /// <returns></returns>
            public static DataTable GetDataTableByExcelFile(HttpPostedFileBase file)
            {
                DataTable result = new DataTable();
                IWorkbook workbook;
            
                if (file.FileName.EndsWith(".xlsx"))
                {
                    workbook = GetIWorkbookByStream(file.InputStream, ".xlsx");
                }
                else if (file.FileName.EndsWith(".xls"))
                {
                    workbook = GetIWorkbookByStream(file.InputStream, ".xls");
                }
                else
                    throw new Exception("文件格式不正确,只允许.xlsx或.xls");
                result = GetDataTableByISheet(workbook.GetSheetAt(0));
                return result;
            }
    
    
            public static DataSet GetDataSetByExcelFile(HttpPostedFileBase file)
            {
                DataSet ds = new DataSet();
                IWorkbook workbook;
                //GetDataSetByISheet(file.InputStream, ".xlsx");
                if (file.FileName.EndsWith(".xlsx"))
                {
                    workbook = GetIWorkbookByStream(file.InputStream, ".xlsx");
                }
                else if (file.FileName.EndsWith(".xls"))
                {
                    workbook = GetIWorkbookByStream(file.InputStream, ".xls");
                }
                else
                    throw new Exception("文件格式不正确,只允许.xlsx或.xls");
    
                ds = GetDataSetByIWorkbook(workbook);
                return ds;
            }
    
    
    

    调用方式

        DataTable dt =GetDataTableByExcelFile(file);//Excel第一张表
        DataSet ds =GetDataSetByExcelFile(file);//Excel表集合
    

    根据DataTable生成Excel文件

    • 可传入单个DataTable或者List
            /// <summary>
            /// 根据DataTable 生成Excel
            /// </summary>
            /// <param name="source"></param>
            /// <returns></returns>
            public static NpoiMemoryStream GetExcelFile( DataTable source)
            {
         
                //创建Excel文件的对象,XLSX 
                XSSFWorkbook book = new XSSFWorkbook();
                //添加一个sheet
                ISheet sheet = book.CreateSheet($"OA导出");
    
                //行下标记录
                int rowIndex = 0;
                //创建首行
                IRow row0 = sheet.CreateRow(rowIndex++);
                ////创建单元格
                //ICell cell0 = row0.CreateCell(0);
                ////设置单元格内容
    
    
                //cell0.CellStyle.Alignment = HorizontalAlignment.CenterSelection;
    
                //cell0.SetCellValue("料品情况查询");
                //sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, source.Columns.Count));
    
               // IRow row1 = sheet.CreateRow(rowIndex++);
                for (var i = 0; i < source.Columns.Count; i++)
                {
                    row0.CreateCell(i).SetCellValue(source.Columns[i].ToString());
                }
    
    
                for (var i = 0; i < source.Rows.Count; i++)
                {
    
                    IRow rowTemp = sheet.CreateRow(rowIndex++);
    
                    for (var j = 0; j < source.Columns.Count; j++)
                    {
    
                        if (source.Rows[i][j].GetType().Name == "Decimal")
                        {
                            rowTemp.CreateCell(j).SetCellValue(Convert.ToDouble(source.Rows[i][j]));
                        }
                        else
                        {
                            rowTemp.CreateCell(j).SetCellValue(source.Rows[i][j].ToString());
                        }
    
                    }
                }
    
    
    
                for (int columnNum = 0; columnNum < source.Columns.Count; columnNum++)
                {
                    int columnWidth = sheet.GetColumnWidth(columnNum) / 256;//获取当前列宽度  
                    for (int rowNum = 1; rowNum <= sheet.LastRowNum; rowNum++)//在这一列上循环行  
                    {
                        IRow currentRow = sheet.GetRow(rowNum);
                        ICell currentCell = currentRow.GetCell(columnNum);
                        int length = Encoding.UTF8.GetBytes(currentCell.ToString()).Length;//获取当前单元格的内容宽度  
                        if (columnWidth < length + 1)
                        {
                            columnWidth = length + 1;
                        }//若当前单元格内容宽度大于列宽,则调整列宽为当前单元格宽度,后面的+1是我人为的将宽度增加一个字符  
                    }
                    //sheet.SetColumnWidth(columnNum, columnWidth * 256);
                    if (columnWidth > 255)
                    {
                        columnWidth = 254;
                    }
                    else
                    {
                        sheet.SetColumnWidth(columnNum, columnWidth * 256);
                    }
       
                }
                var ms = new NpoiMemoryStream();
                ms.AllowClose = false;
                book.Write(ms);
                ms.Flush();
                ms.Seek(0, SeekOrigin.Begin);
                ms.AllowClose = true;
    
                return ms;
            }
    
            /// <summary>
            /// 根据多个DataTable 生成一个Excel多个表
            /// </summary>
            /// <param name="sources"></param>
            /// <returns></returns>
            public static NpoiMemoryStream GetExcelFile(List<DataTable> sources)
            {
    
                //创建Excel文件的对象,XLSX 
                XSSFWorkbook book = new XSSFWorkbook();
                int flag = 1;
                foreach(DataTable source in sources)
                {
                    //添加一个sheet
                    ISheet sheet = book.CreateSheet($"OA导出"+flag);
    
                    //行下标记录
                    int rowIndex = 0;
                    //创建首行
                    IRow row0 = sheet.CreateRow(rowIndex++);
                    ////创建单元格
                    //ICell cell0 = row0.CreateCell(0);
                    ////设置单元格内容
    
    
                    //cell0.CellStyle.Alignment = HorizontalAlignment.CenterSelection;
    
                    //cell0.SetCellValue("料品情况查询");
                    //sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, source.Columns.Count));
    
                    // IRow row1 = sheet.CreateRow(rowIndex++);
                    for (var i = 0; i < source.Columns.Count; i++)
                    {
                        row0.CreateCell(i).SetCellValue(source.Columns[i].ToString());
                    }
    
    
                    for (var i = 0; i < source.Rows.Count; i++)
                    {
    
                        IRow rowTemp = sheet.CreateRow(rowIndex++);
    
                        for (var j = 0; j < source.Columns.Count; j++)
                        {
    
                            if (source.Rows[i][j].GetType().Name == "Decimal")
                            {
                                rowTemp.CreateCell(j).SetCellValue(Convert.ToDouble(source.Rows[i][j]));
                            }
                            else
                            {
                                rowTemp.CreateCell(j).SetCellValue(source.Rows[i][j].ToString());
                            }
    
                        }
                    }
                    for (int columnNum = 0; columnNum < source.Columns.Count; columnNum++)
                    {
                        int columnWidth = sheet.GetColumnWidth(columnNum) / 256;//获取当前列宽度  
                        for (int rowNum = 1; rowNum <= sheet.LastRowNum; rowNum++)//在这一列上循环行  
                        {
                            IRow currentRow = sheet.GetRow(rowNum);
                            ICell currentCell = currentRow.GetCell(columnNum);
                            int length = Encoding.UTF8.GetBytes(currentCell.ToString()).Length;//获取当前单元格的内容宽度  
                            if (columnWidth < length + 1)
                            {
                                columnWidth = length + 1;
                            }//若当前单元格内容宽度大于列宽,则调整列宽为当前单元格宽度,后面的+1是我人为的将宽度增加一个字符  
                        }
                        //sheet.SetColumnWidth(columnNum, columnWidth * 256);
                        if (columnWidth > 255)
                        {
                            columnWidth = 254;
                        }
                        else
                        {
                            sheet.SetColumnWidth(columnNum, columnWidth * 256);
                        }
    
                    }
                    flag++;
                }
                var ms = new NpoiMemoryStream();
                ms.AllowClose = false;
                book.Write(ms);
                ms.Flush();
                ms.Seek(0, SeekOrigin.Begin);
                ms.AllowClose = true;
    
                return ms;
            }
    
    
  • 相关阅读:
    python自动化测试应用-番外篇--接口测试2
    python自动化测试应用-番外篇--接口测试1
    篇3 安卓app自动化测试-搞定界面元素
    selenium操作拖拽实现无效果的替代方案
    python自动化测试应用-第7篇(WEB测试)--Selenium进阶篇
    python自动化测试应用-第6篇(WEB测试)--Selenium元素篇
    篇4 安卓app自动化测试-Appium API进阶
    进程和应用程序生命周期
    任务和返回栈
    activity状态变化
  • 原文地址:https://www.cnblogs.com/Alex-Mercer/p/12102826.html
Copyright © 2011-2022 走看看