parseTemplate(wb.getSheetAt(i),map,params.isColForEash())
,所以我们继续点,嘿嘿!setValueForCellByMap(row.getCell(i),map)
; //判断foreach 这种方法
if (oldString != null && oldString.contains(FOREACH)) {
addListDataToExcel(cell, map, oldString.trim());
}
所以继续点。
setForEeachRowCellValue(isCreate, cell.getRow(), cell.getColumnIndex(), t, columns, map,rowspan, colspan, mergedRegionHelper)
private void setForEeachRowCellValue(boolean isCreate, Row row, int columnIndex, Object t,
List<ExcelForEachParams> columns, Map<String, Object> map,
int rowspan, int colspan,
MergedRegionHelper mergedRegionHelper) throws Exception {
//所有的cell创建一遍
for (int i = 0; i < rowspan; i++) {
int size = columns.size();//判断是不是超出设置了
for (int j = columnIndex, max = columnIndex + colspan; j < max; j++) {
if (row.getCell(j) == null) {
row.createCell(j);
CellStyle style = row.getRowNum() % 2 == 0
? getStyles(false,
size >= j - columnIndex ? null : columns.get(j - columnIndex))
: getStyles(true,
size >= j - columnIndex ? null : columns.get(j - columnIndex));
//返回的styler不为空时才使用,否则使用Excel设置的,更加推荐Excel设置的样式
if (style != null) {
row.getCell(j).setCellStyle(style);
}
}
}
if (i < rowspan - 1) {
row = row.getSheet().getRow(row.getRowNum() + 1);
}
}
//填写数据
ExcelForEachParams params;
row = row.getSheet().getRow(row.getRowNum() - rowspan + 1);
for (int k = 0; k < rowspan; k++) {
int ci = columnIndex;//cell的序号
short high=columns.get(0).getHeight();
int n=k;
while (n>0) {
if ( columns.get(n * colspan).getHeight()==0) {
n--;
} else {
high= columns.get(n * colspan).getHeight();
break;
}
}
row.setHeight(high);
for (int i = 0; i < colspan && i < columns.size(); i++) {
boolean isNumber = false;
params = columns.get(colspan * k + i);
tempCreateCellSet.add(row.getRowNum() + "_" + (ci));
if (params == null) {
continue;
}
if (StringUtils.isEmpty(params.getName())
&& StringUtils.isEmpty(params.getConstValue())) {
row.getCell(ci).setCellStyle(params.getCellStyle());
ci = ci + params.getColspan();
continue;
}
String val = null;
Object obj = null;
//是不是常量
if (StringUtils.isEmpty(params.getName())) {
val = params.getConstValue();
} else {
String tempStr = new String(params.getName());
if (isNumber(tempStr)) {
isNumber = true;
tempStr = tempStr.replaceFirst(NUMBER_SYMBOL, "");
}
map.put(teplateParams.getTempParams(), t);
obj = eval(tempStr, map);
val = obj.toString();
}
if (obj != null && obj instanceof ImageEntity) {
ImageEntity img = (ImageEntity)obj;
row.getCell(ci).setCellValue("");
createImageCell(row.getCell(ci),img.getHeight(),img.getUrl(),img.getData());
}else if (isNumber && StringUtils.isNotEmpty(val)) {
row.getCell(ci).setCellValue(Double.parseDouble(val));
row.getCell(ci).setCellType(Cell.CELL_TYPE_NUMERIC);
} else {
try {
row.getCell(ci).setCellValue(val);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
row.getCell(ci).setCellStyle(params.getCellStyle()); // plq modify at 2017-11-13
//判断这个属性是不是需要统计
if (params.isNeedSum()) {
templateSumHandler.addValueOfKey(params.getName(), val);
}
//如果合并单元格,就把这个单元格的样式和之前的保持一致
setMergedRegionStyle(row, ci, params);
//合并对应单元格
if ((params.getRowspan() != 1 || params.getColspan() != 1)
&& !mergedRegionHelper.isMergedRegion(row.getRowNum() + 1, ci)) {
PoiMergeCellUtil.addMergedRegion(row.getSheet(), row.getRowNum(),
row.getRowNum() + params.getRowspan() - 1, ci,
ci + params.getColspan() - 1);
}
ci = ci + params.getColspan();
}
row = row.getSheet().getRow(row.getRowNum() + 1);
}
}
private void setForEeachRowCellValue(boolean isCreate, Row row, int columnIndex, Object t,
List<ExcelForEachParams> columns, Map<String, Object> map,
int rowspan, int colspan,
MergedRegionHelper mergedRegionHelper) throws Exception {
//所有的cell创建一遍
for (int i = 0; i < rowspan; i++) {
int size = columns.size();//判断是不是超出设置了
for (int j = columnIndex, max = columnIndex + colspan; j < max; j++) {
if (row.getCell(j) == null) {
row.createCell(j);
CellStyle style = row.getRowNum() % 2 == 0
? getStyles(false,
size >= j - columnIndex ? null : columns.get(j - columnIndex))
: getStyles(true,
size >= j - columnIndex ? null : columns.get(j - columnIndex));
//返回的styler不为空时才使用,否则使用Excel设置的,更加推荐Excel设置的样式
if (style != null) {
row.getCell(j).setCellStyle(style);
}
}
}
if (i < rowspan - 1) {
row = row.getSheet().getRow(row.getRowNum() + 1);
}
}
//填写数据
ExcelForEachParams params;
row = row.getSheet().getRow(row.getRowNum() - rowspan + 1);
List<CellRangeAddress> cellRangeAddressList = getCombineCellList(row.getSheet());
for (int k = 0; k < rowspan; k++) {
int ci = columnIndex;//cell的序号
short high=columns.get(0).getHeight();
int n=k;
while (n>0) {
if ( columns.get(n * colspan).getHeight()==0) {
n--;
} else {
high= columns.get(n * colspan).getHeight();
break;
}
}
row.setHeight(high);
for (int i = 0; i < colspan && i < columns.size(); i++) {
boolean isNumber = false;
params = columns.get(colspan * k + i);
tempCreateCellSet.add(row.getRowNum() + "_" + (ci));
if (params == null) {
continue;
}
if (StringUtils.isEmpty(params.getName())
&& StringUtils.isEmpty(params.getConstValue())) {
row.getCell(ci).setCellStyle(params.getCellStyle());
ci = ci + params.getColspan();
continue;
}
String val = null;
Object obj = null;
//是不是常量
if (StringUtils.isEmpty(params.getName())) {
val = params.getConstValue();
} else {
String tempStr = new String(params.getName());
if (isNumber(tempStr)) {
isNumber = true;
tempStr = tempStr.replaceFirst(NUMBER_SYMBOL, "");
}
map.put(teplateParams.getTempParams(), t);
obj = eval(tempStr, map);
val = obj.toString();
}
if (obj != null && obj instanceof ImageEntity) {
ImageEntity img = (ImageEntity)obj;
row.getCell(ci).setCellValue("");
createImageCell(row.getCell(ci),img.getHeight(),img.getUrl(),img.getData());
}else if (isNumber && StringUtils.isNotEmpty(val)) {
row.getCell(ci).setCellValue(Double.parseDouble(val));
row.getCell(ci).setCellType(Cell.CELL_TYPE_NUMERIC);
} else {
try {
int valLength = 0;
Map<String,Object> cellMap = isCombineCell(cellRangeAddressList,row.getCell(ci),row.getSheet());
// 合并的单元格列数
int mergeCellCount = ObjectUtils.isEmpty(cellMap.get("mergedCol"))? 0 : (Integer) cellMap.get("mergedCol");
char [] strs = val.toCharArray();
// 如果是汉字则为 两个字符
for (char e : strs) {
if(String.valueOf(e).matches("[\u4e00-\u9fa5]")){
valLength = valLength +2;
}else {
valLength = valLength + 1;
}
}
// 获取单元格宽
int width = (row.getSheet().getColumnWidth(row.getCell(ci).getColumnIndex()) / 256) +1 ;
// 获取单元格高度
BigDecimal height = new BigDecimal(row.getHeight()).divide(new BigDecimal(256));
// 如果该单元格被合并了
if(mergeCellCount > 0){
// 获取合并单元格宽度
for(int j = 1 ;j < mergeCellCount ; j++){
width = width + (row.getSheet().getColumnWidth(row.getCell(ci+j).getColumnIndex()) / 256) +1;
}
}
//向下取整
if (width * height.setScale(0,BigDecimal.ROUND_DOWN).intValue() < valLength) {
row.setHeight(new BigDecimal(256).multiply(height) .multiply(new BigDecimal((valLength / width) + 1)).shortValue());
}
row.getCell(ci).setCellValue(val);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
row.getCell(ci).setCellStyle(params.getCellStyle()); // plq modify at 2017-11-13
//判断这个属性是不是需要统计
if (params.isNeedSum()) {
templateSumHandler.addValueOfKey(params.getName(), val);
}
//如果合并单元格,就把这个单元格的样式和之前的保持一致
setMergedRegionStyle(row, ci, params);
//合并对应单元格
if ((params.getRowspan() != 1 || params.getColspan() != 1)
&& !mergedRegionHelper.isMergedRegion(row.getRowNum() + 1, ci)) {
PoiMergeCellUtil.addMergedRegion(row.getSheet(), row.getRowNum(),
row.getRowNum() + params.getRowspan() - 1, ci,
ci + params.getColspan() - 1);
}
ci = ci + params.getColspan();
}
row = row.getSheet().getRow(row.getRowNum() + 1);
}
}
这里解释一下代码。先说几个问题。
row.getSheet().getColumnWidth(row.getCell(ci).getColumnIndex()
来获取单元格宽度是一个什么样数字这里我debug到这里的时候发现是一个很大数值,这个数值除以256 等与一个字符的长度!!!!!
这是重点哦,这样我们才能完成后边的计算。 /**
* 判断cell是否为合并单元格,是的话返回合并行数和列数(只要在合并区域中的cell就会返回合同行列数,但只有左上角第一个有数据)
* @param listCombineCell 上面获取的合并区域列表
* @param cell
* @param sheet
* @return
* @throws Exception
*/
public static Map<String,Object> isCombineCell(List<CellRangeAddress> listCombineCell,Cell cell,Sheet sheet)
throws Exception{
int firstC = 0;
int lastC = 0;
int firstR = 0;
int lastR = 0;
String cellValue = null;
Boolean flag=false;
int mergedRow=0;
int mergedCol=0;
Map<String,Object> result=new HashMap<>();
result.put("flag",flag);
for(CellRangeAddress ca:listCombineCell)
{
//获得合并单元格的起始行, 结束行, 起始列, 结束列
firstC = ca.getFirstColumn();
lastC = ca.getLastColumn();
firstR = ca.getFirstRow();
lastR = ca.getLastRow();
//判断cell是否在合并区域之内,在的话返回true和合并行列数
if(cell.getRowIndex() >= firstR && cell.getRowIndex() <= lastR)
{
if(cell.getColumnIndex() >= firstC && cell.getColumnIndex() <= lastC)
{
flag=true;
mergedRow=lastR-firstR+1;
mergedCol=lastC-firstC+1;
result.put("flag",true);
result.put("mergedRow",mergedRow);
result.put("mergedCol",mergedCol);
break;
}
}
}
return result;
}
//获取合并单元格集合
public static List<CellRangeAddress> getCombineCellList(Sheet sheet) {
List<CellRangeAddress> list = new ArrayList<>();
//获得一个 sheet 中合并单元格的数量
int sheetmergerCount = sheet.getNumMergedRegions();
//遍历所有的合并单元格
for(int i = 0; i<sheetmergerCount;i++)
{
//获得合并单元格保存进list中
CellRangeAddress ca = sheet.getMergedRegion(i);
list.add(ca);
}
return list;
}
这两个方法 下边的是获取该sheet页所有合并单元格的对象。上边的方法是获取返回该位置被合并单元格的地址,长几个格高几个格!!!! 重点啊
.。在我们的主方法上我们可以看到我在上边的地方我调用方法获取了一个该sheet所有合并单元格集合的方法
然后在核心改动的地方调用了获取单元格合并大小的方法
该方法返回一个Map
,有两个主要字段就是mergeCol
和mergedRow
的字段,是合并的单元格数量。
然后后边就是计算该行行高应该扩展到多大。然后最后set我们的值就结束了。
最后说一下怎么更改源码。首先我们把这个类复制出来,然后建一个与这个类同样目录的地方。名字也要一样。上一波图片。
到这里EasyPOI改源码的过程就结束了,有问题的可以讨论哦,然后还有就是这是公司项目我不能发到git上 抱歉啦!