zoukankan      html  css  js  c++  java
  • .Net操作Excel —— NPOI

    近期的两个项目都有关于NPOI的功能,经过了一点学习,自己也摸索了一会,感觉还有点意思。现在将部分代码分享一下。一部分是C#代码,一部分是VB.Net的,懒得修改了,基本上都是从项目文件中copy出来的。如果错漏,请指教。

    概述:

    1、整个Excel表格:WorkBook(工作薄),包含的叫页(工作表):Sheet;行:Row;单元格Cell。

    2、NPOI是POI的C#版本,NPOI的行和列的index都是从0开始

    3、POI读取Excel有两种格式一个是HSSF,另一个是XSSF。 HSSF和XSSF的区别如下: 
    HSSF is the POI Project's pure Java implementation of the Excel '97(-2007) file format. 
    XSSF is the POI Project's pure Java implementation of the Excel 2007 OOXML (.xlsx) file format. 
    即:HSSF适用2007以前的版本,XSSF适用2007版本及其以上的。

    4、NPOI能够在没有安装微软Office的情况下读写Office文件,支持的文件格式包括xls, doc, ppt等。

    引用:

    Manage NuGet packages -> NPOI

    读取excel:

           1、Asp.Net使用FileUpload控件上传excel文件(VB.Net代码):

    Dim fileOriginalPath As String = excelUploader.PostedFile.FileName
    Dim fileName As String = excelUploader.FileName
    Dim extension = Path.GetExtension(fileOriginalPath).ToLower()
    
    Dim workbook As IWorkbook
    If (extension = ".xlsx") Then   'excel 2007
         workbook = New XSSFWorkbook(excelUploader.PostedFile.InputStream)
    Else                                  'excel 2003
         workbook = New HSSFWorkbook(excelUploader.PostedFile.InputStream)
    End If

      2、WPF读取本地excel文件:

    using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read))  
    {  
                hssfworkbook = new HSSFWorkbook(file);  
    }  
    
    //其实HSSFWorkbook/XSSFWorkbook的构造方法可以直接传入FileInfo做参数

      3、WPF读取嵌入在资源文件的excel表格

            public XSSFWorkbook ReadDemoExcel()
            {
                MemoryStream ms = new MemoryStream(Properties.Resources.QNetTimesheet);
                ms.Position = 0;
    
                XSSFWorkbook book = new XSSFWorkbook(ms);
                return book;
            }

    获取表(sheet)、行(row)、单元格(cell):

    ISheet sheet = book.GetSheetAt(0)  //除了根据index,还可以根据名字获取:book.GetSheet("da")
    
    IRow row = sheet.GetRow(0);
    
    ICell cell = row.GetCell(4);  //row.Cells(i)方法也可以获取单元格, 但是此方法会跳过null的单元格。譬如,如果cell0跟cell3之间有一个单元格是null,那么row.Cells(3)就不会是你想要的那个cell...Please use row.GetCell(i)!!!!!
    
    book.SetSheetName(1, "新名字");//修改sheet名字
    
    IRow newRow = sheet.CreateRow(i);//创建新行
    
     int rowIndex = sheet.LastRowNum;//最后一行的index

    单元格的相关操作:

    ICell dateCell = row.CreateCell(0);
    dateCell.SetCellValue(cardInfoList[i].Date);
    
    ICell dayCell = row.CreateCell(1);
    dayCell.CellFormula = string.Format("WEEKDAY(A{0})", row.RowNum + 1);//设置公式, 并不需要“=”号
    
    ICell totalHoursCell = row.CreateCell(6);
    totalHoursCell.CellFormula = string.Format("SUM(G{0}:G{1})", x, y);//设置公式

    设置单元格样式(CellStyle):

    private ICellStyle GetCellDataStyle(IWorkbook book)
            {
                ICellStyle cs = book.CreateCellStyle();
                cs.BorderBottom = BorderStyle.Thin;
                cs.BorderLeft = BorderStyle.Thin;
                cs.BorderRight = BorderStyle.Thin;
                cs.BorderTop = BorderStyle.Thin;
    
                cs.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.LightYellow.Index;//单元格背景色
                cs.FillPattern = FillPattern.SolidForeground;
    
                cs.DataFormat = 1;//在excel中可以Format Cells->Caregory->Custom设置Type使得单元格对数据显示不同的格式,比如可以设置显示成整形、金额、浮点数或者星期几等等等,可以看下面的“DataFormat”部分
                cs.Alignment = HorizontalAlignment.Center;//水平对齐
    
                return cs;
            }
    
    
    cell.CellStyle = GetCellDataStyle(book);//赋值

    单元格的DataFormat:

    可以看到,对同一个单元格,设置不同的DataFormat,最终显示的内容是不同的。在NPOI中,我们可以通过对单元格设置其DataFormat属性来达到我们的目的。

    此属性是int类型,网上的例子不齐全。现实中,我们可以先创建一个excel表并且在excel中操作单元格使得其达到我们的要求,然后用NPOI读取得知其DataFormat。

    嗯,第一张截图显示Wednesday是我用公式=WEEKDAY(A7)根据日期计算并显示的,DataFormat是185

    /*
                    0, "General"
                    1, "0"
                    2, "0.00"
                    3, "#,##0"
                    4, "#,##0.00"
                    5, "($#,##0_);($#,##0)"
                    6, "($#,##0_);[Red]($#,##0)"
                    7, "($#,##0.00);($#,##0.00)"
                    8, "($#,##0.00_);[Red]($#,##0.00)"
                    9, "0%"
                    0xa, "0.00%"
                    0xb, "0.00E+00"
                    0xc, "# ?/?"
                    0xd, "# ??/??"
                    0xe, "m/d/yy"
                    0xf, "d-mmm-yy"
                    0x10, "d-mmm"
                    0x11, "mmm-yy"
                    0x12, "h:mm AM/PM"
                    0x13, "h:mm:ss AM/PM"
                    0x14, "h:mm"
                    0x15, "h:mm:ss"
                    0x16, "m/d/yy h:mm"
                    // 0x17 - 0x24 reserved for international and undocumented 0x25, "(#,##0_);(#,##0)"
                    0x26, "(#,##0_);[Red](#,##0)"
                    0x27, "(#,##0.00_);(#,##0.00)"
                    0x28, "(#,##0.00_);[Red](#,##0.00)"
                    0x29, "_(*#,##0_);_(*(#,##0);_(* "-"_);_(@_)"
                    0x2a, "_($*#,##0_);_($*(#,##0);_($* "-"_);_(@_)"
                    0x2b, "_(*#,##0.00_);_(*(#,##0.00);_(*"-"??_);_(@_)"
                    0x2c, "_($*#,##0.00_);_($*(#,##0.00);_($*"-"??_);_(@_)"
                    0x2d, "mm:ss"
                    0x2e, "[h]:mm:ss"
                    0x2f, "mm:ss.0"
                    0x30, "##0.0E+0"
                    0x31, "@" - This is text format.
                    0x31 "text" - Alias for "@" 
                */

    将excel内容转换为DataTable(VB.Net代码):

        Private Function GetDataTableFromExcel(workbook As IWorkbook) As DataTable
            Dim sheet = workbook.GetSheetAt(0)
            Dim rows = sheet.GetRowEnumerator()
            Dim dt = New DataTable()
            Dim j As Int16
    
            Dim headerRow = sheet.GetRow(0)
            For j = 0 To headerRow.Cells.Count - 1 'headerRow.LastCellNum - 1
                Dim columnName As String = headerRow.Cells(j).ToString()
                If Not (j = headerRow.Cells.Count - 1 And String.IsNullOrEmpty(columnName)) Then
                    dt.Columns.Add(columnName)
                End If
            Next
    
            rows.MoveNext()
            While rows.MoveNext()
                Dim row As IRow
                row = rows.Current
                Dim isRowEmpty As Boolean = IsEmptyRow(row)
                If isRowEmpty Then
                    Continue While 'do not add empty row to data table
                End If
    
                Dim dr As DataRow
                dr = dt.NewRow()
                Dim i As Int16
                For i = 0 To dt.Columns.Count - 1
                    Dim cell As ICell
                    cell = row.GetCell(i) 'row.Cells(i), this method will ignore the null column automatically...Please use row.GetCell(i)!!!!!
                    If cell Is Nothing Then
                        dr(i) = ""
                    Else
                        Try
                            Select Case cell.CellType
                                Case CellType.Blank
                                    dr(i) = ""
                                Case CellType.String
                                    dr(i) = cell.StringCellValue
                                Case CellType.Numeric
                                    If DateUtil.IsCellDateFormatted(cell) Then
                                        dr(i) = cell.DateCellValue
                                    Else
                                        dr(i) = cell.NumericCellValue
                                    End If
                                Case Else
                                    dr(i) = cell.ToString()
                            End Select
                        Catch ex As Exception
                            dr(i) = ""
                        End Try
                    End If
                Next
                dt.Rows.Add(dr)
            End While
    
            Return dt
        End Function
    
        Private Function IsEmptyRow(row As IRow) As Boolean
            Dim isEmpty As Boolean = True
            Dim i As Int16
            For i = 0 To row.Cells.Count - 1
                Dim cell As ICell
                cell = row.GetCell(i)
                If cell IsNot Nothing Then
                    If cell.CellType <> CellType.Blank Then
                        isEmpty = False
                        Exit For
                    End If
                End If
            Next
            Return isEmpty
        End Function

    将NPOI生成的excel内容保存为文件:

      1、WPF程序将excel内容保存为本地文件:

    XSSFWorkbook excelBook = npoiHelper.CreateExcel();
    using (MemoryStream MS = new MemoryStream())
    {
        excelBook.Write(MS);
        byte[] excelBytes = MS.ToArray();
        string excelPath = "C:Users	est.xlsx";
        using (FileStream fs = new FileStream(excelPath, FileMode.Create, FileAccess.Write))
        {
             fs.Write(excelBytes, 0, excelBytes.Length);
        }
    }

      2、Asp.net服务器返回文件让用户保存(VB.Net代码):

    Dim response As HttpResponse = HttpContext.Current.Response
    
    response.Clear()
    response.ClearHeaders()
    response.ClearContent()
    response.Charset = ""
    
    response.ContentType = "application/vnd.ms-excel"
    response.AddHeader("Content-Disposition", String.Format("attachment; filename={0}.xls", HttpUtility.UrlEncode(title + "_" + DateTime.Now.ToString("yyyy-MM-dd HH-mm"), System.Text.Encoding.UTF8)))
    
    Dim MS = New MemoryStream()
    book.Write(MS)
    response.BinaryWrite(MS.ToArray())
    response.End()
    response.Flush()
    MS.Close()
    MS.Dispose()

    参考:

    Class HSSFDataFormat

    Net操作Excel(终极方法NPOI)

    NPOI读写Excel

  • 相关阅读:
    多台计算机之间数据同步——1.[转]网线制作图解教程
    离心泵的使用注意事项泄露或未排气造成扬程不够
    家庭上网用路由器和ADSL的连接
    专业FLV地址解析
    [求助]带程序访问控制的防火墙 eTrust Personal Firewall 和卡巴斯基2009引起冲突造成系统频繁死机
    DV录像带导出一定要用1394
    Cursor:url()的使用
    理解并解决JavaScript内存泄漏
    CodeIgniter的HMVC
    关于在IE下JavaScript的 Stack overflow at line 错误可能的原因
  • 原文地址:https://www.cnblogs.com/AlvinLiang/p/7568968.html
Copyright © 2011-2022 走看看