合并策略
public class ExcelMergeStrategy extends AbstractMergeStrategy {
/**
* 合并的列编号,从0开始,指定的index或自己按字段顺序数
*/
private Set<Integer> mergeCellIndex = new HashSet<>();
/**
* 数据集大小,用于区别结束行位置
*/
private Integer maxRow = 0;
/**
* 禁止无参声明
*/
private ExcelMergeStrategy() {
}
public ExcelMergeStrategy(Integer maxRow, int... mergeCellIndex) {
Arrays.stream(mergeCellIndex).forEach(item -> {
this.mergeCellIndex.add(item);
});
this.maxRow = maxRow;
}
/**
* 记录上一次合并的信息
*/
private Map<Integer, MergeRange> lastRow = new HashedMap();
/**
* 每行每列都会进入,绝对不要在这写循环
*
* @param sheet
* @param cell
* @param head
* @param relativeRowIndex
*/
@Override
protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
int currentCellIndex = cell.getColumnIndex();
String prefix = "";
if (mergeCellIndex.contains(currentCellIndex)) {
if(currentCellIndex> 0){
Row row = cell.getRow();
List<String> prefixList = new CopyOnWriteArrayList<>();
for (int cellIndex = currentCellIndex -1; cellIndex >= 0; cellIndex--) {
prefixList.add(row.getCell(cellIndex).getStringCellValue());
}
Collections.reverse(prefixList);
prefix = String.join("", prefixList);
}
// 判断该行是否需要合并
String currentCellValue = prefix + cell.getStringCellValue();
int currentRowIndex = cell.getRowIndex();
if (!lastRow.containsKey(currentCellIndex)) {
// 记录首行起始位置
lastRow.put(currentCellIndex, new MergeRange(currentCellValue, currentRowIndex, currentRowIndex, currentCellIndex, currentCellIndex));
return;
}
//有上行这列的值了,拿来对比.
MergeRange mergeRange = lastRow.get(currentCellIndex);
if (!(mergeRange.lastValue != null && (mergeRange.lastValue).equals(currentCellValue))) {
// 结束的位置触发下合并.
// 同行同列不能合并,会抛异常
if (mergeRange.startRow != mergeRange.endRow || mergeRange.startCell != mergeRange.endCell) {
sheet.addMergedRegionUnsafe(new CellRangeAddress(mergeRange.startRow, mergeRange.endRow, mergeRange.startCell, mergeRange.endCell));
}
// 更新当前列起始位置
lastRow.put(currentCellIndex, new MergeRange(currentCellValue, currentRowIndex, currentRowIndex, currentCellIndex, currentCellIndex));
}
// 合并行 + 1
mergeRange.endRow += 1;
// 结束的位置触发下最后一次没完成的合并
if (relativeRowIndex.equals(maxRow - 1)) {
MergeRange lastMergeRange = lastRow.get(currentCellIndex);
// 同行同列不能合并,会抛异常
if (lastMergeRange.startRow != lastMergeRange.endRow || lastMergeRange.startCell != lastMergeRange.endCell) {
sheet.addMergedRegionUnsafe(new CellRangeAddress(lastMergeRange.startRow, lastMergeRange.endRow, lastMergeRange.startCell, lastMergeRange.endCell));
}
}
}
}
public class MergeRange {
public int startRow;
public int endRow;
public int startCell;
public int endCell;
public String lastValue;
public MergeRange(String lastValue, int startRow, int endRow, int startCell, int endCell) {
this.startRow = startRow;
this.endRow = endRow;
this.startCell = startCell;
this.endCell = endCell;
this.lastValue = lastValue;
}
}
}
表头颜色策略
public class HeadTwoColorStyleWriteStrategy extends AbstractCellStyleStrategy {
private Workbook workbook;
/**
* 颜色分割点
*/
private Integer pointIndex;
private Integer pointIndex2;
/**
* 头的高度
*/
private Integer headHeight;
@Override
protected void initCellStyle(Workbook workbook) {
this.workbook=workbook;
}
public HeadTwoColorStyleWriteStrategy(Integer pointIndex, Integer pointIndex2){
//设置投高度默认
this.headHeight = 2;
this.pointIndex = pointIndex;
this.pointIndex2 = pointIndex2;
}
public HeadTwoColorStyleWriteStrategy(Integer headHeight,Integer pointIndex, Integer pointIndex2){
this.headHeight = headHeight;
this.pointIndex = pointIndex;
this.pointIndex2 = pointIndex2;
}
/**
* 设置表格头样式
* @param cell
* @param head
* @param relativeRowIndex
*/
@Override
protected void setHeadCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
if ( relativeRowIndex < headHeight) {
int columnIndex = cell.getColumnIndex();
WriteCellStyle writeCellStyle=new WriteCellStyle();
WriteFont headWriteFont = new WriteFont();
headWriteFont.setColor(IndexedColors.WHITE.getIndex());
writeCellStyle.setWriteFont(headWriteFont);
// WriteCellStyle转换为CellStyle
CellStyle headCellStyle = StyleUtil.buildHeadCellStyle(workbook, writeCellStyle);
XSSFCellStyle cellStyle = (XSSFCellStyle)headCellStyle;
if(columnIndex < pointIndex){
cellStyle.setFillForegroundColor(getRGBColor(0, 51, 102));
}else if (columnIndex < pointIndex2){
cellStyle.setFillForegroundColor(getRGBColor(0, 112, 192));
}else {
cellStyle.setFillForegroundColor(getRGBColor(146, 208, 80));
}
cell.setCellStyle(cellStyle);
}
}
@Override
protected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) {
}
/**
* 得到RBG自定义颜色
*
* @param redNum 红色数值
* @param greenNum 绿色数值
* @param blueNum 蓝色数值
* @return
*/
public static XSSFColor getRGBColor(int redNum, int greenNum, int blueNum) {
XSSFColor color = new XSSFColor(new byte[]{(byte) redNum, (byte) greenNum, (byte) blueNum}, new DefaultIndexedColorMap());
return color;
}
}
链接转跳和文本转跳策略
public class HyperlinkExcelStrategy implements CellWriteHandler {
/**
* 行
*/
private Integer row;
/**
* 列
*/
private Integer col;
/**
* type 类型 HyperlinkType 参考该枚举
*/
private HyperlinkType type;
/**
* 要替换成该 链接
*/
private String link;
/**
* 第几列添加链接
* @param col
* @param link
* @param type 类型 HyperlinkType.DOCUMENT
*/
public HyperlinkExcelStrategy(Integer col,String link,HyperlinkType type){
this.col = col;
this.link = link;
this.type = type;
}
@Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
}
@Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
if (!isHead){
int columnIndex = cell.getColumnIndex();
//等于当前列是添加链接 或链接文档
if (columnIndex== this.col){
CreationHelper helper=writeSheetHolder.getSheet().getWorkbook().getCreationHelper();
Hyperlink hyperlink=helper.createHyperlink(type);
hyperlink.setAddress(this.link);
cell.setHyperlink(hyperlink);
}
}
}
}
自定义表头宽度策略策略
public class CustomCellWriteHandler extends AbstractColumnWidthStyleStrategy {
private Map<Integer, Map<Integer, Integer>> CACHE = new HashMap<>(64);
private Integer dataLength(List<CellData> cellDataList, Cell cell, Boolean isHead) {
if (Boolean.TRUE.equals(isHead)) {
return cell.getStringCellValue().getBytes().length;
} else {
CellData cellData = cellDataList.get(0);
CellDataTypeEnum type = cellData.getType();
if (type == null) {
return -1;
} else {
switch (type) {
case STRING:
return cellData.getStringValue().getBytes().length;
case BOOLEAN:
return cellData.getBooleanValue().toString().getBytes().length;
case NUMBER:
return cellData.getNumberValue().toString().getBytes().length;
default:
return -1;
}
}
}
}
@Override
protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
if (isHead || !CollectionUtils.isEmpty(cellDataList)) {
Map<Integer, Integer> maxColumnWidthMap = CACHE.get(writeSheetHolder.getSheetNo());
if (CollectionUtils.isEmpty(maxColumnWidthMap)) {
maxColumnWidthMap = new HashMap<>();
CACHE.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap);
}
Integer columnWidth = this.dataLength(cellDataList, cell, isHead);
if (columnWidth >= 0) {
if (columnWidth > 255) {
columnWidth = 255;
}
Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());
if (maxColumnWidth == null || columnWidth > maxColumnWidth) {
maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);
writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), columnWidth * 256);
}
}
}
}
}