zoukankan      html  css  js  c++  java
  • 读取Excel文件的两种方法比较 以及用NPOI写入Excel

    1. 采用NPOI方式,只需引用NPOI.dll,但目前最高只能到2.4.0版。

    缺点:只支持.xls,不支持.xlsx格式。github上的2.4.1版支持.xlsx,但总提示缺ICSharpCode.SharpZipLib.dll,但找不到合适版本,暂时不能用。

    优点:读取excel文件极快,1万行*9列的excel文件0.5秒就能读完,比下面的传统Office方法快将近1000倍!首选此方法。

    using NPOI.HSSF.UserModel;
    using NPOI.SS.UserModel;

    DataSet ds = null;

                try

                { 

                    FileStream fileStream = new FileStream(tbFilePath.Text, FileMode.Open);

                    HSSFWorkbook workbook = new HSSFWorkbook(fileStream); 

                    ISheet sheet = null;

                    IRow row = null; 

                    ds = new DataSet();

                    DataTable dt = null; 

                    for (int i = 0; i < workbook.Count; i++)

                    {

                        dt = new DataTable();

                        dt.TableName = "table" + i.ToString(); 

                        //获取 sheet 表

                        sheet = workbook.GetSheetAt(i); 

                        //起始行索引

                        int rowIndex = sheet.FirstRowNum; 

                        //获取行数

                        int rowCount = sheet.LastRowNum; 

                        //获取第一行

                        IRow firstRow = sheet.GetRow(rowIndex); 

                        //起始列索引

                        int colIndex = firstRow.FirstCellNum; 

                        //获取列数

                        int colCount = firstRow.LastCellNum; 

                        DataColumn dc = null; 

                        //获取列名

                        for (int j = colIndex; j < colCount; j++)

                        {

                            dc = new DataColumn(firstRow.GetCell(j).StringCellValue);

                            dt.Columns.Add(dc);

                        } 

                        //跳过第一行列名

                        rowIndex++; 

                        for (int k = rowIndex; k <= rowCount; k++)

                        {

                            DataRow dr = dt.NewRow();

                            row = sheet.GetRow(k); 

                            for (int l = colIndex; l < colCount; l++)

                            {

                                if (row.GetCell(l) == null)

                                {

                                    continue;

                                }

                                if (row.GetCell(l).CellType == CellType.Numeric)

                                    dr[l] = row.GetCell(l).NumericCellValue.ToString();

                                else

                                    dr[l] = row.GetCell(l).StringCellValue;

                            } 

                            dt.Rows.Add(dr);

                        } 

                        ds.Tables.Add(dt);

                    } 

                    sheet = null;

                    workbook = null; 

                    fileStream.Close();

                    fileStream.Dispose();

                }

                catch (Exception ex)

                {

                    throw;

                }

    方法二、传统的通过引用Office Excel dll读取

    缺点:速度极慢,1万行*9列的excel文件要6.5分钟才能读完,比上面的方法一慢1000倍

    DataSet ds = null;

                DataTable dt = null;

     

                Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();

                Microsoft.Office.Interop.Excel.Workbook workbook = null;

                Microsoft.Office.Interop.Excel.Worksheet worksheet = null;

                Microsoft.Office.Interop.Excel.Sheets sheets = null;

                Microsoft.Office.Interop.Excel.Range range = null;

                object missing = System.Reflection.Missing.Value;

     

                try

                {

                    if (excel == null)

                    {

                        return null;

                    }

     

                    //打开 Excel 文件

                    workbook = excel.Workbooks.Open(filePath, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing);

     

                    //获取所有的 sheet 表

                    sheets = workbook.Worksheets;

     

                    ds = new DataSet();

     

                    for (int i = 1; i <= sheets.Count; i++)

                    {

                        //获取第一个表

                        worksheet = (Microsoft.Office.Interop.Excel.Worksheet)sheets.get_Item(i);

     

                        int rowCount = worksheet.UsedRange.Rows.Count;

                        int colCount = worksheet.UsedRange.Columns.Count;

     

                        int rowIndex = 1;   //起始行为 1

                        int colIndex = 1;   //起始列为 1

     

                        DataColumn dc;

                        dt = new DataTable();

                        dt.TableName = "table" + i.ToString();

     

                        //读取列名

                        for (int j = 0; j < colCount; j++)

                        {

                            range = worksheet.Cells[rowIndex, colIndex + j];

     

                            dc = new DataColumn();

                            dc.DataType = Type.GetType("System.String");

                            dc.ColumnName = range.Text.ToString().Trim();

     

                            //添加列

                            dt.Columns.Add(dc);

                        }

     

                        //读取行数据

                        for (int k = 1; k < rowCount; k++)

                        {

                            DataRow dr = dt.NewRow();

                            for (int l = 0; l < colCount; l++)

                            {

                                range = worksheet.Cells[rowIndex + k, colIndex + l];

     

                                //使用 range.Value.ToString(); 或 range.Value2.ToString(); 或 range.Text.ToString(); 都可以获取单元格的值

                                dr[l] = range.Text.ToString();

                            }

                            dt.Rows.Add(dr.ItemArray);

                        }

     

                        ds.Tables.Add(dt);

                    }

                }

                catch

                {

                    throw;

                }

                finally

                {

                    workbook.Close();

     

                    //关闭退出

                    excel.Quit();

     

                    //释放 COM 对象

                    Marshal.ReleaseComObject(worksheet);

                    Marshal.ReleaseComObject(workbook);

                    Marshal.ReleaseComObject(excel);

     

                    worksheet = null;

                    workbook = null;

                    excel = null;

     

                    GC.Collect();

                }

                return ds;

     ///NPOI写入大内容Excel,效率也是惊人的高,而且设置样式很方便/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    private static void DataWrite2Sheet(DataTable dt, int startRow, int endRow, IWorkbook book, string sheetName)

            {

                //创建标题行字体

                IFont titleFont = (HSSFFont)book.CreateFont();

                titleFont.IsBold = true; //字体加粗

                titleFont.FontHeightInPoints = 13; //字体大小

                titleFont.FontName = "仿宋";

     

                //创建列头样式

                ICellStyle titleStyle = (HSSFCellStyle)book.CreateCellStyle();

                titleStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left; //居左

                titleStyle.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center; //垂直居中           

                titleStyle.SetFont(titleFont); //将字体绑定到样式 

     

                //创建内容样式           

                ICellStyle cellStyle = (HSSFCellStyle)book.CreateCellStyle();

                cellStyle.WrapText = true; //自动换行,也使内容中的换行符生效

     

                ISheet sheet = book.CreateSheet(sheetName);

                sheet.CreateFreezePane(1,1); //冻结列头行

     

     

                //设置标题行

                IRow header = sheet.CreateRow(0);//创建标题行

                for (int i = 0; i < dt.Columns.Count; i++)

                {

                    ICell cell = header.CreateCell(i);

                    string val = dt.Columns[i].Caption ?? dt.Columns[i].ColumnName;

                    cell.SetCellValue(val);

                    cell.CellStyle = titleStyle;

                }

     

                //设置每行、每列内容

                int rowIndex = 1;

                for (int i = startRow; i <= endRow; i++)

                {

                    DataRow dtRow = dt.Rows[i];

                    IRow excelRow = sheet.CreateRow(rowIndex++);

                    for (int j = 0; j < dtRow.ItemArray.Length; j++)

                    {

                        ICell cell_Conent = excelRow.CreateCell(j);

                        cell_Conent.SetCellValue(dtRow[j].ToString());

                        cell_Conent.CellStyle = cellStyle;

     

                    }

                } 

                //列宽自适应,只对英文和数字有效

                for (int i = 0; i <= dt.Rows.Count; i++)

                {

                    sheet.AutoSizeColumn(i);

                }

            }

    //此外关于计算中文内容自动计算列宽的方法

    //先设置自动列宽

    for (int i = 0; i <= dt.Rows.Count; i++)

                {

                    sheet.AutoSizeColumn(i);

                }

    //再根据中文列宽计算,注意,该方法无法区分有换行符的内容,都按单行计算长度,而且也未考虑字体大小的影响,不准确

      for (int columnNum = 0; columnNum <= 26; columnNum++)

                {

                    int columnWidth = ffSheet.GetColumnWidth(columnNum) / 256;//获取当前列宽度

                    for (int rowNum = 1; rowNum <= ffSheet.LastRowNum; rowNum++)//在这一列上循环行

                    {

                        IRow currentRow = ffSheet.GetRow(rowNum);

                        ICell currentCell = currentRow.GetCell(columnNum);

                        int length = Encoding.UTF8.GetBytes(currentCell.ToString()).Length;//获取当前单元格的内容宽度

                        if (columnWidth < length + 1)

                        {

                            columnWidth = length + 1;

                        }//若当前单元格内容宽度大于列宽,则调整列宽为当前单元格宽度,后面的+1是我人为的将宽度增加一个字符

                    }

                    ffSheet.SetColumnWidth(columnNum, columnWidth * 256);

                }</span>

        columnNum是列号,从0开始循环到表格最后一列,循环的范围可以自己指定,原理很简单,就是在先循环列,在列上循环行,比对行内容宽度与列宽度,若行内容宽度大于列宽则增大列宽,循环以后,每列宽度等于该列中最宽的那一行的宽度。

         值得注意的是使用UTF8编码来计算的,在UTF8编码中数字和英文字母宽度为2,汉字宽度为3。而且字号越小,其效果就越好。在实际使用中内容为10磅的时候,其效果就相当不错。

  • 相关阅读:
    apt常用命令(安装,更新,删除)
    记录一次坑爹的VM连接主机的路程
    VM安装centos
    初窥DB2之insert语句
    关于虚拟机的linux不能使用shell连接时的处理方法
    linux命令之查看字符集
    趣图:学JavaScript
    PHP搭建大文件切割分块上传功能示例
    判断变量是否不为空,函数isset()、!empty()与!is_null()的比较
    Javascript 中 null、NaN和undefined的区别
  • 原文地址:https://www.cnblogs.com/mol1995/p/11382744.html
Copyright © 2011-2022 走看看