1. 程式人生 > >【POI框架實戰】——POI匯出Excel時設定單元格型別為數值型別

【POI框架實戰】——POI匯出Excel時設定單元格型別為數值型別



背 景

  最近做的一個ITFIN的專案中,後臺需要用POI實現匯出功能,匯出的資料中有文字格式,也有貨幣格式,所以為了方便在將來匯出的表格中做計算,存放貨幣的單元格需要設定為數值型別。

  匯出的Excel的單元格都是文字格式(單元格左上角有個小三角):

這裡寫圖片描述

  費了不少功夫,終於把“小三角”去掉了,這裡總結並分享一下問題的解決方法。

  通過poi匯出excel的過程大致是這樣的:

     規定單元格的格式
        ↓
      建立單元格
        ↓
     設定單元格的格式
        ↓
     設定資料的格式
        ↓
    把資料存放到單元格中


        ↓
      通過IO流輸出


背景POI匯出Excel時設定單元格型別為數值型別

  要想存放數值的單元格以數值型別匯出,其中最關鍵的步驟就是上面加粗的兩步,設定單元格的格式和向單元格中存放資料。

  核心程式碼如下:

    /**
     * 匯出Excel-胡玉洋-2015年11月11日
     * 
     *@param outPutParam Excel資料實體,包括要匯出的excel標頭、列標題、資料等
     * */
    private void createContentRows(ExcelParam outPutParam) {
        HSSFWorkbook workbook=new
HSSFWorkbook(); //建立一個Excel檔案 // 遍歷集合資料,產生資料行 for (int i = 0; i < outPutParam.getContent().size(); i++) { int rowIndex = i + 2; HSSFRow contentRow = sheet.createRow(rowIndex); Map<String, Object> rowDate = outPutParam.getContent().get(i); //遍歷列
for (int j = 0; j < outPutParam.getTitleList().size(); j++) { Title headTitle = outPutParam.getTitleList().get(j);//獲取第i行第j列列標題 String headerName = headTitle.getName();//獲取第j列列標識 Object data = rowDate.get(headerName);//獲取第i行第j列所放資料 HSSFCellStyle contextstyle =workbook.createCellStyle(); HSSFCell contentCell = contentRow.createCell(j); Boolean isNum = false;//data是否為數值型 Boolean isInteger=false;//data是否為整數 Boolean isPercent=false;//data是否為百分數 if (data != null || "".equals(data)) { //判斷data是否為數值型 isNum = data.toString().matches("^(-?\\d+)(\\.\\d+)?$"); //判斷data是否為整數(小數部分是否為0) isInteger=data.toString().matches("^[-\\+]?[\\d]*$"); //判斷data是否為百分數(是否包含“%”) isPercent=data.toString().contains("%"); } //如果單元格內容是數值型別,涉及到金錢(金額、本、利),則設定cell的型別為數值型,設定data的型別為數值型別 if (isNum && !isPercent) { HSSFDataFormat df = workbook.createDataFormat(); // 此處設定資料格式 if (isInteger) { contextstyle.setDataFormat(df.getBuiltinFormat("#,#0"));//資料格式只顯示整數 }else{ contextstyle.setDataFormat(df.getBuiltinFormat("#,##0.00"));//保留兩位小數點 } // 設定單元格格式 contentCell.setCellStyle(contextstyle); // 設定單元格內容為double型別 contentCell.setCellValue(Double.parseDouble(data.toString())); } else { contentCell.setCellStyle(contextstyle); // 設定單元格內容為字元型 contentCell.setCellValue(data.toString()); } } } }

  如上,有兩個比較重要的點:
  1、先用正則表示式判斷資料是否為數值型,如果為數值型,則設定單元格格式為整數或者小數;
  2、然後往單元格中存放資料的時候要設定資料的格式為double型別,如果檢視poi的原始碼HSSFCell.java會發現設定資料的方法如下,所以用setCellValue(double)方法即可。

   這裡寫圖片描述


優化

  到了這裡,您可能以為萬事大吉啊了,其實上面的程式碼有個陷阱,如果不經過大資料量的測試是發覺不出來的哦~~

  如果資料量大的話,系統可能會報錯“The maximum number of cell styles was exceeded. You can define up to 4000 styles in a .xls workbook”,原因是style建立的次數太多了,解決這個問題的方法很簡單,在迴圈體外面建立單元格格式contextstyle(即把它當成一個“全域性”變數),不要在迴圈內部建立。

  正確的程式碼如下:

    /**
     * 匯出Excel-胡玉洋-2015年11月11日
     * 
     *@param outPutParam Excel資料實體,包括要匯出的excel標頭、列標題、資料等
     * */
    private void createContentRows(ExcelParam outPutParam) {
        HSSFWorkbook workbook=new HSSFWorkbook(); //建立一個Excel檔案
        HSSFCellStyle contextstyle =workbook.createCellStyle();
        // 遍歷集合資料,產生資料行
        for (int i = 0; i < outPutParam.getContent().size(); i++) {
            int rowIndex = i + 2;
            HSSFRow contentRow = sheet.createRow(rowIndex);
            Map<String, Object> rowDate = outPutParam.getContent().get(i);
            //遍歷列
            for (int j = 0; j < outPutParam.getTitleList().size(); j++) {       
                Title headTitle = outPutParam.getTitleList().get(j);//獲取第i行第j列列標題
                String headerName = headTitle.getName();//獲取第j列列標識
                Object data = rowDate.get(headerName);//獲取第i行第j列所放資料
                HSSFCell contentCell = contentRow.createCell(j);                
                Boolean isNum = false;//data是否為數值型
                Boolean isInteger=false;//data是否為整數
                Boolean isPercent=false;//data是否為百分數
                if (data != null || "".equals(data)) {
                    //判斷data是否為數值型
                    isNum = data.toString().matches("^(-?\\d+)(\\.\\d+)?$");
                    //判斷data是否為整數(小數部分是否為0)
                    isInteger=data.toString().matches("^[-\\+]?[\\d]*$");
                    //判斷data是否為百分數(是否包含“%”)
                    isPercent=data.toString().contains("%");
                }

                //如果單元格內容是數值型別,涉及到金錢(金額、本、利),則設定cell的型別為數值型,設定data的型別為數值型別
                if (isNum && !isPercent) {
                    HSSFDataFormat df = workbook.createDataFormat(); // 此處設定資料格式
                    if (isInteger) {
                        contextstyle.setDataFormat(df.getBuiltinFormat("#,#0"));//資料格式只顯示整數
                    }else{
                        contextstyle.setDataFormat(df.getBuiltinFormat("#,##0.00"));//保留兩位小數點
                    }                   
                    // 設定單元格格式
                    contentCell.setCellStyle(contextstyle);
                    // 設定單元格內容為double型別
                    contentCell.setCellValue(Double.parseDouble(data.toString()));
                } else {
                    contentCell.setCellStyle(contextstyle);
                    // 設定單元格內容為字元型
                    contentCell.setCellValue(data.toString());
                }
            }
        }
    }

  最後匯出的正確格式:

這裡寫圖片描述

相關推薦

POI框架實戰——POI匯出Excel設定單元型別數值型別

背 景   最近做的一個ITFIN的專案中,後臺需要用POI實現匯出功能,匯出的資料中有文字格式,也有貨幣格式,所以為了方便在將來匯出的表格中做計算,存放貨幣的單元格需要設定為數值型別。   匯出的Excel的單元格都是文字格式(單元格左上角有個小三

laravel匯出excel設定單元格式

$list = $this->recommend($request); $data = array(); foreach($list as $k=>$v){ $data[] = array_values($v); $len = count($v); } $header =

C# DataGridView匯出Excel設定單元合併,隱藏行

不得不承認,做程式需要研究。 DataGridView匯出Excel的原始碼 using System.Windows.Forms;using System.Collections.Generic;using System;using Microsoft.Office.In

poi匯出Excel設定某個單元顏色

需求:    查詢資料庫表資料然後到另一個表找錯誤的對應欄位(就是找到需要填充的單元格所在行的列),對這個單元格進行設定背景色,然後匯出資料。 具體的工具類如下   import cn.afterturn.easypoi.excel.annotatio

POI 匯出Excel實現合併單元以及列自適應寬度

目錄 參考推薦: POI 匯出Excel 1. 合併單元格 POI是apache提供的一個讀寫Excel文件的開源元件,在操作excel時常要合併單元格,合併單元格的方法是: public CellRang

apache POI匯出excel檔案 及單元合併 、樣式的設定

客戶需要從完單物料資訊中到處excel 大概思路: 單擊某一按鈕,觸發請求至後臺,建立輸出流,匯出excel ^_^ 前臺程式碼: (此段程式碼 註釋部分存在一個問題,註釋部分的請求無效,後臺無法響應前臺請求, 引數傳過去了,後臺也接受了,但輸出流沒有輸出,木雞wh

java poi 匯入excel 讀取單元內容的方法 ,其中包含excel中有函式的讀法

public static String getExcelCellValue(Cell cell) { String ret = ""; try { if (cell == null) { ret = ""; } else if (cell.get

C#實戰016:Excel操作-設定單元屬性

 獲取單元格之後我們需要對單元格進行操作,比如過單元格寬、單元格高、單元格背景色、單元格邊框等等。 App = new Application(); //建立 Excel物件 object missing = Missing.Value; //獲取缺少

ios學習記錄-如何定製UITableView的圓角單元

     自從ios7更新以來,UITableView控制元件的邊角style由預設圓角變成了直角,更加適應UI扁平化設計的效果了。但對於某種情況來說,如果tableview寬度不是拉伸到與父檢視等寬,那麼使用直角的tableview則會顯得不好看。如下圖分組列

jxl匯出excel(合併單元

Demo import java.io.*;   import jxl.*;   import jxl.format.UnderlineStyle;  import jxl.write.*;   publicclass CreateXLS {       public

C#匯出Excel,某單元內容長度超過255 的解決方法

只需要將該列首個單元格指定為memo型別就可以了! C# code publicstaticvoid ToExcel(DataTable dtSource, string strPath, string strSheetName) { System.Data.OleD

解決Java POI 匯出Excel檔名中文亂碼,相容瀏覽器

     String agent = request.getHeader("USER-AGENT").toLowerCase();   response.setContentType("application/vnd.ms-excel");&

POI匯出excel,當有大量超連結存在,匯出速度慢

    最近修改專案,發現用SXSSF匯出的excel有大量超連結的時候,寫檔案的速度會非常慢     後來查了谷歌,發現是jar包的BUG,不要使用3.10以下的jar包,我用的3.12的jar包就不存在這個問題了

SpringMVC+POI下載檔案模板和匯出Excel

如果檔案模板是固定的,直接放到服務目錄下,然後可以用下面的程式碼下載 <a target="_self" href="/template/template.xlsx" >下載office模版</a>       如果是需要從資料庫查詢出來匯出

POI匯出Excel設定單元格式2--建立與設定Excel合併單元

POI建立與設定Excel合併單元格 話不多說上栗子 //準備工作 XSSFWorkbook wb = new XSSFWorkbook(); Sheet sheet = wb.createSheet("sheet1"); XSSFCreationHelper creationHel

POI匯出Excel設定單元格式

使用Apache的POI相關API匯出Excel設定單元格格式 栗子,一下各個程式碼之間的變數是通用的,要是在某個程式碼塊中找不到某個變數,則可以向上找尋 準備工作 InputStream = template//檔案輸入流 XSSFWorkbook wb = new XSSFW

[置頂]POI操作EXCEL匯出Excel設定有效性,下拉列表引用)

//write 2003Excel public static void write2003Excel(String filePath,List list,String[][] data,String str) { try { if

poi匯出excel,合併單元後,求和不正確,即“假”合併

excel中所謂“真假”合併單元格 真合併:我們選擇一段連續的單元格,點選合併,這時候,EXCEL會提示如果合併只會顯示第一個單元格的資料,而且其他單元的的資料也會沒掉. 假合併:如果我們用一個已經合併的單元格,格式刷要合併的單元格,這時候沒有提示資料丟失的.事實上,這時候

慕課實戰Android高階面試 10大開源框架原始碼解析

程式設計最好的學習方法是閱讀頂尖工程師的原始碼!本課程將帶你深度剖析Android主流開源框架的原始碼,讓你全面掌握框架的使用場景、內部機制、構造原理、核心類、架構與設計思想等,提升你的程式碼閱讀與分析能力、提高程式碼設計能力及改造能力,快速突破技術瓶頸,輕鬆應對Androi

推薦系統實戰:C++實現基於用戶的協同過濾(UserCollaborativeFilter)

color style popu ted std 相似度 abi ear result 好早的時候就打算寫這篇文章,可是還是參加阿裏大數據競賽的第一季三月份的時候實驗就完畢了。硬生生是拖到了十一假期。自己也是醉了。。。找工作不是非常順利,希望寫點東西回想一下知識。然後再