日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

POI 導(dǎo)出 Excel:字體顏色、行列自適應(yīng)、鎖住、合并單元格、一文搞定……

 昵稱10087950 2022-06-16 發(fā)布于江蘇

圖片

來(lái)源:zzzgd.blog.csdn.net/article/details/80627175

  • 前言
  • 鎖住單元格
  • 設(shè)置列寬
  • 設(shè)置行高
  • 設(shè)置字體,顏色
  • 合并單元格

1. 前言

poi框架可以支持我們?cè)趈ava代碼中, 將數(shù)據(jù)導(dǎo)出成excel,但是實(shí)際開(kāi)發(fā)中, 往往還需要設(shè)置excel字體,顏色,行高,列寬等屬性, 有時(shí)候還需要鎖住單元格, 防止別人講數(shù)據(jù)隨意篡改.

廢話不多說(shuō), 直接上代碼

2. 鎖住單元格

導(dǎo)出excel , 自然就有導(dǎo)入excel 了, 比如導(dǎo)出一些數(shù)據(jù)出來(lái), 修改一些再導(dǎo)入進(jìn)去, 但是這時(shí), 一些基本信息我們不希望用戶隨意去修改, 這里就用到了excel的鎖

圖片
圖片

sheet.protectSheet(密碼)

代碼:

// 創(chuàng)建Excel文件
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet(DateUtils.getDate("yyyyMMdd"));
//鎖定sheet
sheet.protectSheet("zgd");

這樣的話, 這個(gè)sheet都會(huì)被鎖定

但是我們又希望開(kāi)放一些單元格可以修改 , 這個(gè)時(shí)候就要細(xì)粒度的進(jìn)行設(shè)置了

創(chuàng)建一個(gè)cellStyle:

 CellStyle unlockCell = workbook.createCellStyle();
 unlockCell.setLocked(false);

然后在我們不需要鎖定的單元格上, 給它這個(gè) cellStyle

 // 設(shè)置dataRow這一行的第i個(gè)單元格不鎖定
 dataRow.getCell(i).setCellStyle(unlockCell);

3. 設(shè)置列寬

在鎖定了sheet之后, 會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題, 就是列寬都不能改變了

這個(gè)時(shí)候沒(méi)辦法, 只能自己設(shè)置列寬了, 現(xiàn)在網(wǎng)上找到的設(shè)置列寬的方法有以下幾個(gè):

1.自適應(yīng)列寬度:

sheet.autoSizeColumn(1);
sheet.autoSizeColumn(1, true);

這兩種方式都是自適應(yīng)列寬度,但是注意這個(gè)方法在后邊的版本才提供,poi的版本不要太老。

注意:第一個(gè)方法在合并單元格的的單元格并不好使,必須用第二個(gè)方法。

經(jīng)過(guò)測(cè)試,這種自適應(yīng)的api在遇到行數(shù)多一點(diǎn)的數(shù)據(jù)的時(shí)候,就會(huì)耗費(fèi)大量的時(shí)間,1000行花了2分鐘!!!所以盡量不要用

sheet.trackAllColumnsForAutoSizing();
sheet.autoSizeColumn(i);

而且這兩個(gè)方法對(duì)英文數(shù)字還好, 對(duì)中文支持的并不好:

圖片
圖片

2.用數(shù)組將大概的寬度設(shè)置好,手動(dòng)set寬度

int[] width = {xxx,xxx};
for循環(huán)
sheet.setColumnWidth(i,width[i]);

3.自己根據(jù)一列數(shù)據(jù)中的最長(zhǎng)的字符串長(zhǎng)度設(shè)置寬度

所以還是得自己費(fèi)心費(fèi)力去diy :

判斷這一列的最長(zhǎng)字符串,然后

int length = str.getBytes().length;
sheet.setColumnWidth((short)列數(shù),(short)(length*256));

這里經(jīng)過(guò)我反復(fù)嘗試,我個(gè)人覺(jué)得把最大寬度限制在10000到15000左右是比較合適的, 然后剩下的就交給excel的自動(dòng)換行

像我這里有很多行的數(shù)據(jù), 不知道哪一行的內(nèi)容最長(zhǎng), 這里簡(jiǎn)單提供兩種思路(方法是很多的, 能達(dá)到目的就行):

  1. 用一個(gè)Map<Integer, List>, key是指具體哪一列, List中放的是每行的這一列的內(nèi)容的長(zhǎng)度 , 每遍歷一行的一列, 就map.put(i, list.add(length)), 然后用Collections.max(map.get(i))來(lái)獲取第i列的最長(zhǎng)的長(zhǎng)度
  2. 還是一樣,用一個(gè)map: Map<Integer, Integer>,key是指具體哪一列,value是每行的這一列的內(nèi)容的長(zhǎng)度, map.put(i,Math.max(length,map.get(i))),來(lái)確保map中的key對(duì)應(yīng)的value永遠(yuǎn)是目前的最大的長(zhǎng)度.

我這里使用的第二種:

設(shè)置自動(dòng)換行后,不要設(shè)置固定的行高,否則超出的部分也會(huì)被遮住不顯示

// 創(chuàng)建Excel文件
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("sheet");
//設(shè)置樣式
 CellStyle blackStyle = workbook.createCellStyle();
//自動(dòng)換行*重要*
 blackStyle.setWrapText(true);

//存儲(chǔ)最大列寬
Map<Integer,Integer> maxWidth = new HashMap<>();
// 標(biāo)題行
HSSFRow titleRow = sheet.createRow(0);
titleRow.setHeightInPoints(20);//目的是想把行高設(shè)置成20px
titleRow.createCell(0).setCellValue("sku編號(hào)");
titleRow.createCell(1).setCellValue("商品標(biāo)題");
titleRow.createCell(2).setCellValue("商品名");
// 初始化標(biāo)題的列寬,字體
for (int i= 0; i<=3;i++){
    maxWidth.put(i,titleRow.getCell(i).getStringCellValue().getBytes().length  * 256 + 200);
    titleRow.getCell(i).setCellStyle(blackStyle);//設(shè)置自動(dòng)換行
}

for (Map<String, Object> map : list) {
    int currentRowNum = sheet.getLastRowNum() + 1;
    //數(shù)據(jù)行
    HSSFRow dataRow = sheet.createRow(currentRowNum);
    // 記錄這一行的每列的長(zhǎng)度
    List<Object> valueList = new ArrayList<Object>();

    String val0 = map.get("skuId") == null ? "—" : ((Double) (map.get("skuId"))).intValue()+"";
    valueList.add(val0);
    dataRow.createCell(0).setCellValue(val0);
    String val1 = map.get("title") == null ? "" : map.get("title").toString();
    valueList.add(val1);
    dataRow.createCell(1).setCellValue(val1);
    String val2 = map.get("goodsName") == null ? "" : map.get("goodsName").toString();
    valueList.add(val2);
    dataRow.createCell(2).setCellValue(val2);
    String val3 = map.get("catName") == null ? "" : map.get("catName").toString();
    valueList.add(val3);
    dataRow.createCell(3).setCellValue(val3);
    String val4 = map.get("brandName") == null ? "" : map.get("brandName").toString();

     for(int i = 0;i<=3;i++){
         int length = valueList.get(i).toString().getBytes().length  * 256 + 200;
         //這里把寬度最大限制到15000
         if (length>15000){
             length = 15000;
         }
         maxWidth.put(i,Math.max(length,maxWidth.get(i)));
          dataRow.getCell(i).setCellStyle(blackStyle);//設(shè)置自動(dòng)換行
    }
}


for (int i= 0; i<=3;i++){
      //設(shè)置列寬
     sheet.setColumnWidth(i,maxWidth.get(i));
 }

現(xiàn)在的話, 列寬雖然是比較生硬的套用內(nèi)容長(zhǎng)度來(lái)設(shè)置, 不過(guò)也比之前好多了, 列寬是不能超過(guò)256*256的,否則會(huì)報(bào)錯(cuò),所以我這里設(shè)置的最大列寬為15000,超出的部分會(huì)自動(dòng)換行

圖片
圖片

4. 設(shè)置行高

行高就很簡(jiǎn)單了,

titleRow.setHeightInPoints(20);//目的是想把行高設(shè)置成20px

注意,設(shè)置了固定行高,自動(dòng)換行就不會(huì)自適應(yīng)行高了

5. 設(shè)置字體,顏色

創(chuàng)建CellStyle , 然后創(chuàng)建HSSFFont , 再把HSSFFont注入給CellStyle , 在把CellStyle給cell設(shè)置

// 設(shè)置字體
CellStyle redStyle = workbook.createCellStyle();
HSSFFont redFont = workbook.createFont();
//顏色
redFont.setColor(Font.COLOR_RED);
//設(shè)置字體大小
redFont.setFontHeightInPoints((short) 10);
//字體
//redFont.setFontName("宋體");
redStyle.setFont(redFont);

HSSFCell cell13 = titleRow.createCell(13);
cell13.setCellStyle(redStyle);
cell13.setCellValue("注意:只允許修改銷售價(jià),供應(yīng)價(jià),市場(chǎng)價(jià)和庫(kù)存");
圖片
圖片

6. 合并單元格

合并單元格的話,建議先合并,合并之后,在合并的第一行第一列set值就可以了

//這里代表在第0行開(kāi)始,到0行結(jié)束,從0列開(kāi)始,到10列結(jié)束,進(jìn)行合并,也就是合并第0行的0-10個(gè)單元格
CellRangeAddress cellRange1 = new CellRangeAddress(0, 0, (short) 0, (short) 10);
            sheet.addMergedRegion(cellRange1);
            CellRangeAddress

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多