Java实战-优雅的合并Excel列中的相同内容
/**
* 列值重复合并策略
*/
@Slf4j
public class ColRepeatStrategy<T> implements MergeStrategy<T> {
@Override
public List<CellRangeAddress> handle(List list, Class clazz, boolean hasTitle) {
List<CellRangeAddress> ret = new ArrayList<>();
Field[] fields = clazz.getDeclaredFields();
List<Field> mergeFields = new ArrayList<>(); // field with merge annotation
List<Integer> mergeFieldsIndex = new ArrayList<>(); // col index with merge cell
for (int i=0; i<fields.length; i++) {
Field field = fields[i];
if (field.isAnnotationPresent(CellMerge.class)) {
CellMerge cm = field.getAnnotation(CellMerge.class);
if (MergeType.Col_Repeat_Val.getVal() == cm.type().getVal()) {
mergeFields.add(field);
mergeFieldsIndex.add(cm.index() == -1 ? i : cm.index());
} else {
log.warn("currently only support merge row repeat val");
}
}
}
// row merger begin index
int rowIndex = hasTitle ? 1 : 0;
// dictionary
Map<Field, RepeatCell> map = new HashMap<>();
// generate CellRangeAddress 2 merge cells
for (int i=0; i<list.size(); i++) {
for (int j=0; j<mergeFields.size(); j++) {
Field field = mergeFields.get(j);
Object val = ClassUtil.getProperty(field, list.get(i), clazz);
int colNum = mergeFieldsIndex.get(j);
if (!map.containsKey(field)) {
// dictionary without the field
map.put(field, new RepeatCell(val, i));
} else {
// current val not equal with the val in dictionary
if (map.get(field).getVal() != val) {
if (i - map.get(field).getCurrent() > 1)
ret.add(new CellRangeAddress(map.get(field).getCurrent()+rowIndex, i+rowIndex-1, colNum, colNum));
map.put(field, new RepeatCell(val, i));
} else if (i == list.size() - 1) {
if (i > map.get(field).getCurrent())
ret.add(new CellRangeAddress(map.get(field).getCurrent() + rowIndex, i+rowIndex, colNum, colNum));
}
}
}
}
return ret;
}
@Override
public WriteHandler build(List<CellRangeAddress> list) {
return new AbstractMergeStrategy() {
// merge cells
@Override
protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
// judge the list is not null
if (CollectionUtils.isNotEmpty(list)) {
// the judge is necessary
if (cell.getRowIndex() == 1 && cell.getColumnIndex() == 0) {
for (CellRangeAddress item : list) {
sheet.addMergedRegion(item);
}
}
}
}
};
}
static class RepeatCell {
private Object val;
private int current;
}
}