來源:zzzgd.blog.csdn.net/article/details/80627175
1. 前言
poi框架可以支持我們在java代碼中, 將資料匯出成excel,但是實際開發中, 往往還需要設定excel字體,顏色,行高,列寬等屬性, 有時候還需要鎖住單元格, 防止別人講資料隨意篡改.
廢話不多說, 直接上代碼
2. 鎖住單元格
匯出excel , 自然就有匯入excel 了, 比如匯出一些資料出來, 修改一些再匯入進去, 但是這時, 一些基本資訊我們不希望用戶隨意去修改, 這里就用到了excel的鎖

sheet.protectSheet(密碼)
代碼:
// 創建Excel檔案
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet(DateUtils.getDate("yyyyMMdd"));
//鎖定sheet
sheet.protectSheet("zgd");
這樣的話, 這個sheet都會被鎖定
但是我們又希望開放一些單元格可以修改 , 這個時候就要細粒度的進行設定了
創建一個cellStyle:
CellStyle unlockCell = workbook.createCellStyle();
unlockCell.setLocked(false);
然后在我們不需要鎖定的單元格上, 給它這個 cellStyle
// 設定dataRow這一行的第i個單元格不鎖定
dataRow.getCell(i).setCellStyle(unlockCell);
3. 設定列寬
在鎖定了sheet之后, 會發現一個問題, 就是列寬都不能改變了
這個時候沒辦法, 只能自己設定列寬了, 現在網上找到的設定列寬的方法有以下幾個:
1.自適應列寬度:
sheet.autoSizeColumn(1);
sheet.autoSizeColumn(1, true);
這兩種方式都是自適應列寬度,但是注意這個方法在后邊的版本才提供,poi的版本不要太老,
注意:第一個方法在合并單元格的的單元格并不好使,必須用第二個方法,
經過測驗,這種自適應的api在遇到行數多一點的資料的時候,就會耗費大量的時間,1000行花了2分鐘!!!所以盡量不要用
sheet.trackAllColumnsForAutoSizing();
sheet.autoSizeColumn(i);
而且這兩個方法對英文數字還好, 對中文支持的并不好:

2.用陣列將大概的寬度設定好,手動set寬度
int[] width = {xxx,xxx};
for回圈
sheet.setColumnWidth(i,width[i]);
3.自己根據一列資料中的最長的字串長度設定寬度
所以還是得自己費心費力去diy :
判斷這一列的最長字串,然后
int length = str.getBytes().length;
sheet.setColumnWidth((short)列數,(short)(length*256));
這里經過我反復嘗試,我個人覺得把最大寬度限制在10000到15000左右是比較合適的, 然后剩下的就交給excel的自動換行
像我這里有很多行的資料, 不知道哪一行的內容最長, 這里簡單提供兩種思路(方法是很多的, 能達到目的就行):
- 用一個
Map<Integer, List>, key是指具體哪一列, List中放的是每行的這一列的內容的長度 , 每遍歷一行的一列, 就map.put(i, list.add(length)), 然后用Collections.max(map.get(i))來獲取第i列的最長的長度 - 還是一樣,用一個map:
Map<Integer, Integer>,key是指具體哪一列,value是每行的這一列的內容的長度,map.put(i,Math.max(length,map.get(i))),來確保map中的key對應的value永遠是目前的最大的長度.
我這里使用的第二種:
設定自動換行后,不要設定固定的行高,否則超出的部分也會被遮住不顯示
// 創建Excel檔案
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("sheet");
//設定樣式
CellStyle blackStyle = workbook.createCellStyle();
//自動換行*重要*
blackStyle.setWrapText(true);
//存盤最大列寬
Map<Integer,Integer> maxWidth = new HashMap<>();
// 標題行
HSSFRow titleRow = sheet.createRow(0);
titleRow.setHeightInPoints(20);//目的是想把行高設定成20px
titleRow.createCell(0).setCellValue("sku編號");
titleRow.createCell(1).setCellValue("商品標題");
titleRow.createCell(2).setCellValue("商品名");
// 初始化標題的列寬,字體
for (int i= 0; i<=3;i++){
maxWidth.put(i,titleRow.getCell(i).getStringCellValue().getBytes().length * 256 + 200);
titleRow.getCell(i).setCellStyle(blackStyle);//設定自動換行
}
for (Map<String, Object> map : list) {
int currentRowNum = sheet.getLastRowNum() + 1;
//資料行
HSSFRow dataRow = sheet.createRow(currentRowNum);
// 記錄這一行的每列的長度
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);//設定自動換行
}
}
for (int i= 0; i<=3;i++){
//設定列寬
sheet.setColumnWidth(i,maxWidth.get(i));
}
現在的話, 列寬雖然是比較生硬的套用內容長度來設定, 不過也比之前好多了, 列寬是不能超過256*256的,否則會報錯,所以我這里設定的最大列寬為15000,超出的部分會自動換行

4. 設定行高
行高就很簡單了,
titleRow.setHeightInPoints(20);//目的是想把行高設定成20px
注意,設定了固定行高,自動換行就不會自適應行高了
5. 設定字體,顏色
創建CellStyle , 然后創建HSSFFont , 再把HSSFFont注入給CellStyle , 在把CellStyle給cell設定
// 設定字體
CellStyle redStyle = workbook.createCellStyle();
HSSFFont redFont = workbook.createFont();
//顏色
redFont.setColor(Font.COLOR_RED);
//設定字體大小
redFont.setFontHeightInPoints((short) 10);
//字體
//redFont.setFontName("宋體");
redStyle.setFont(redFont);
HSSFCell cell13 = titleRow.createCell(13);
cell13.setCellStyle(redStyle);
cell13.setCellValue("注意:只允許修改銷售價,供應價,市場價和庫存");

6. 合并單元格
合并單元格的話,建議先合并,合并之后,在合并的第一行第一列set值就可以了
//這里代表在第0行開始,到0行結束,從0列開始,到10列結束,進行合并,也就是合并第0行的0-10個單元格
CellRangeAddress cellRange1 = new CellRangeAddress(0, 0, (short) 0, (short) 10);
sheet.addMergedRegion(cellRange1);
CellRangeAddress
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2022最新版)
2.勁爆!Java 協程要來了,,,
3.Spring Boot 2.x 教程,太全了!
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!
5.《Java開發手冊(嵩山版)》最新發布,速速下載!
覺得不錯,別忘了隨手點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/458277.html
標籤:其他
上一篇:Java的原始碼執行(建議結合Javase語法學習來加深印象)
下一篇:JavaSE前期準備1
