.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\test.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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM