Apache POI 组件,导出Excel表格的时候,默认情况下是不会自动调整列宽、行高的,如果需要根据内容自动调整宽度和高度,可以用下面的代码:
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
public class POIExcelUtil {
private POIExcelUtil() {
throw new IllegalStateException("Utility class");
}
private static final Float POINT_TO_TWIPS = 20.0F;
private static final Float DEFAULT_EXCEL_ROW_HEIGHT = (float) 24;
private static final int UPPER_AND_LOWER_WHITE_SPACE = 8;
private static final int MAX_CHARACTER_FOR_COLUMN_WIDTH = 256;
private static final String LINE_BREAKS_STR = "\\r?\\n";
public static void adjustRowHeights(XSSFRow sourceRow) {
if(sourceRow == null) return ;
double maxCellHeight = 0;
for (int cellIndex = sourceRow.getFirstCellNum(); cellIndex <= sourceRow.getPhysicalNumberOfCells(); cellIndex++) {
if (cellIndex < 0 || sourceRow.getCell(cellIndex) == null || StringUtils.isBlank(getCellContentAsString(sourceRow.getCell(cellIndex)))){
continue;
}
XSSFCell sourceCell = sourceRow.getCell(cellIndex);
String cellContent = getCellContentAsString(sourceCell);
Map<String, Object> cellInfoMap = getCellInfo(sourceCell);
Integer cellWidth = (Integer) cellInfoMap.get("width");
Integer cellHeight = (Integer) cellInfoMap.get("height");
XSSFCellStyle cellStyle = sourceCell.getCellStyle();
XSSFFont font = cellStyle.getFont();
short fontHeight = font.getFontHeight();
if(cellIndex > 0){
cellStyle.setFillPattern(FillPatternType.NO_FILL);
sourceCell.setCellStyle(cellStyle);
}
double stringNeedsLines = getStringNeedsLines(cellContent,cellWidth);
double stringNeedsHeight = setStringNeedsHeight(stringNeedsLines,fontHeight);
if(maxCellHeight > stringNeedsHeight && Boolean.TRUE.equals(getPartOfRowsRegion(cellInfoMap))){
stringNeedsHeight = maxCellHeight;
}
setRowHeight(stringNeedsHeight,cellHeight,cellInfoMap,sourceCell,sourceRow);
maxCellHeight = stringNeedsHeight;
}
setDefaultRowHeight(sourceRow,sourceRow.getHeight());
}
private static double setStringNeedsHeight(double stringNeedsLines,short fontHeight){
double totalFontHeight = (fontHeight * stringNeedsLines );
double stringNeedsHeight = totalFontHeight ;
if(stringNeedsLines > 1.0 ){
stringNeedsHeight = totalFontHeight + (POINT_TO_TWIPS * 2 * UPPER_AND_LOWER_WHITE_SPACE );
}
return stringNeedsHeight;
}
private static double getStringNeedsLines(String cellContent, Integer cellWidth) {
double cellContentWidth = getCellContentWidth(cellContent);
double stringNeedsLines = getStringLineCount(cellContent,cellWidth) > 0 ? getStringLineCount(cellContent,cellWidth) : Math.round(cellContentWidth / cellWidth);
if (stringNeedsLines < 1.0) {
stringNeedsLines = 1.0;
}
return stringNeedsLines;
}
private static void setRowHeight(double stringNeedsHeight,Integer cellHeight,Map<String, Object> cellInfoMap,XSSFCell sourceCell, XSSFRow sourceRow) {
Boolean isPartOfRowsRegion = getPartOfRowsRegion(cellInfoMap);
if (Boolean.TRUE.equals(isPartOfRowsRegion)) {
int firstRow = (Integer)cellInfoMap.get("firstRow");
int lastRow = (Integer)cellInfoMap.get("lastRow");
double addHeight = (stringNeedsHeight - cellHeight) / (lastRow - firstRow + 1);
for (int i = firstRow; i <= lastRow; i++) {
double rowsRegionHeight = sourceRow.getSheet().getRow(i).getHeight() + addHeight;
setDefaultRowHeight(sourceRow.getSheet().getRow(i),rowsRegionHeight);
}
}else{
if(stringNeedsHeight > sourceCell.getRow().getHeight()){
sourceRow.setHeight((short)stringNeedsHeight);
}
}
}
private static int getStringLineCount(String cellValue,Integer cellWidth) {
int stringLineCount= 0;
if(StringUtils.isNotBlank(cellValue)){
String[] linesStr = cellValue.split(LINE_BREAKS_STR);
for (String cellContent : linesStr) {
if(!(LINE_BREAKS_STR).equals(cellContent) && StringUtils.isNotBlank(cellContent)){
double cellContentWidth = getCellContentWidth(cellContent);
double stringNeedsLines = Math.round(cellContentWidth / cellWidth) < 1.0 ? 1.0 : Math.round(cellContentWidth / cellWidth);
stringLineCount = (int) (stringLineCount + stringNeedsLines);
}
}
stringLineCount = stringLineCount + getLineBreaksCount(cellValue);
}
return stringLineCount;
}
private static int getLineBreaksCount(String cellValue) {
int stringLineCount= 0;
if(StringUtils.isNotBlank(cellValue)){
for (int i = 0; i < cellValue.length(); i++) {
if(cellValue.charAt(i) == '\n' || cellValue.charAt(i) == '\r') {
stringLineCount ++;
}
}
}
return stringLineCount;
}
private static double getCellContentWidth(String cellContent){
return StringUtils.isNotBlank(cellContent) ? cellContent.getBytes().length * MAX_CHARACTER_FOR_COLUMN_WIDTH : 0;
}
private static String getCellContentAsString(XSSFCell cell) {
if (cell == null ) {
return StringUtils.EMPTY;
}
String result = StringUtils.EMPTY;
switch (cell.getCellType()) {
case NUMERIC:
result = String.valueOf(cell.getNumericCellValue());
break;
case STRING:
result = String.valueOf(cell.getRichStringCellValue());
break;
case BLANK:
break;
case BOOLEAN:
result = String.valueOf(cell.getBooleanCellValue());
break;
case ERROR:
break;
default:
break;
}
return result;
}
private static Map<String, Object> getCellInfo(XSSFCell cell) {
Map<String, Object> map = new HashMap<>();
XSSFSheet sheet = cell.getSheet();
int rowIndex = cell.getRowIndex();
int columnIndex = cell.getColumnIndex();
boolean isPartOfRegion = false;
int firstColumn = 0;
int lastColumn = 0;
int firstRow = 0;
int lastRow = 0;
int sheetMergeCount = sheet.getNumMergedRegions();
for (int i = 0; i < sheetMergeCount; i++) {
CellRangeAddress c = sheet.getMergedRegion(i);
firstColumn = c.getFirstColumn();
lastColumn = c.getLastColumn();
firstRow = c.getFirstRow();
lastRow = c.getLastRow();
if (rowIndex >= firstRow && rowIndex <= lastRow && columnIndex >= firstColumn && columnIndex <= lastColumn) {
isPartOfRegion = true;
break;
}
}
Integer width = 0;
Integer height = 0;
boolean isPartOfRowsRegion = false;
if (isPartOfRegion) {
for (int i = firstColumn; i <= lastColumn; i++) {
width = width + sheet.getColumnWidth(i);
}
for (int i = firstRow; i <= lastRow; i++) {
if (sheet.getRow(i) == null) {
height += sheet.createRow(i).getHeight();
} else {
height += sheet.getRow(i).getHeight();
}
}
isPartOfRowsRegion = isPartOfRowsRegion(lastRow, firstRow,isPartOfRowsRegion);
} else {
width = sheet.getColumnWidth(columnIndex);
height = height + cell.getRow().getHeight();
}
map.put("isPartOfRowsRegion", isPartOfRowsRegion);
map.put("firstRow", firstRow);
map.put("lastRow", lastRow);
map.put("width", width);
map.put("height", height);
return map;
}
private static boolean getPartOfRowsRegion(Map<String, Object> cellInfoMap){
return (Boolean) cellInfoMap.get("isPartOfRowsRegion");
}
private static boolean isPartOfRowsRegion(int lastRow, int firstRow,boolean isPartOfRowsRegion) {
if (lastRow > firstRow) {
isPartOfRowsRegion = true;
}
return isPartOfRowsRegion;
}
private static void setDefaultRowHeight(XSSFRow sourceRow,double rowHeight) {
sourceRow.setHeight((short) (Float.compare((float) rowHeight, (DEFAULT_EXCEL_ROW_HEIGHT * POINT_TO_TWIPS)) == -1 ? (DEFAULT_EXCEL_ROW_HEIGHT * POINT_TO_TWIPS) : rowHeight));
}
}