fix cell style

This commit is contained in:
Looly 2019-08-21 20:20:19 +08:00
parent 9ed6412bac
commit def6b802f3
7 changed files with 228 additions and 25 deletions

View File

@ -11,10 +11,13 @@
* 【core】 MapUtil、CollUtil增加emptyIfNullissue#502@Github
* 【core】 增加emptyIfNull等issue#503@Github
* 【setting】 Props增加toBean方法issue#499@Github
* 【poi】 CellUtil增加getMergedRegionValue方法ExcelWriter增加getDisposition方法
* 【http】 HttpBase增加headerMap方法
### Bug修复
* 【http】 修复HttpRquest中body方法长度计算问题issue#I10UPG@Gitee
* 【system】 修复获取本地IP问题pr#65@Gitee
* 【poi】 修复设置单元格样式无效问题
-------------------------------------------------------------------------------------------------------------

View File

@ -134,6 +134,25 @@ public abstract class HttpBase<T> {
return header(name, value, true);
}
/**
* 设置请求头
*
* @param headers 请求头
* @param isOverride 是否覆盖已有头信息
* @return this
* @since 4.6.3
*/
public T headerMap(Map<String, String> headers, boolean isOverride) {
if(CollectionUtil.isEmpty(headers)) {
return (T)this;
}
for (Entry<String, String> entry : headers.entrySet()) {
this.header(entry.getKey(), StrUtil.nullToEmpty(entry.getValue()), isOverride);
}
return (T)this;
}
/**
* 设置请求头<br>
* 不覆盖原有请求头
@ -146,8 +165,7 @@ public abstract class HttpBase<T> {
}
/**
* 设置请求头<br>
* 不覆盖原有请求头
* 设置请求头
*
* @param headers 请求头
* @param isOverride 是否覆盖已有头信息

View File

@ -14,6 +14,7 @@ import org.apache.poi.xssf.usermodel.XSSFSheet;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.poi.excel.cell.CellUtil;
import cn.hutool.poi.excel.style.StyleUtil;
/**
* Excel基础类用于抽象ExcelWriter和ExcelReader中共用部分的对象和方法
@ -198,45 +199,74 @@ public class ExcelBase<T extends ExcelBase<T>> implements Closeable {
* @since 4.1.4
*/
public CellStyle getOrCreateCellStyle(int x, int y) {
final CellStyle cellStyle = getOrCreateCell(x, y).getCellStyle();
return StyleUtil.isNullOrDefaultStyle(this.workbook, cellStyle) ? createCellStyle(x, y) : cellStyle;
}
/**
* 为指定单元格创建样式返回样式后可以设置样式内容
*
* @param x X坐标从0计数既列号
* @param y Y坐标从0计数既行号
* @return {@link CellStyle}
* @since 4.6.3
*/
public CellStyle createCellStyle(int x, int y) {
final Cell cell = getOrCreateCell(x, y);
CellStyle cellStyle = cell.getCellStyle();
if (null == cellStyle) {
cellStyle = this.workbook.createCellStyle();
cell.setCellStyle(cellStyle);
}
final CellStyle cellStyle = this.workbook.createCellStyle();
cell.setCellStyle(cellStyle);
return cellStyle;
}
/**
* 获取或创建某一行的样式返回样式后可以设置样式内容
* 获取或创建某一行的样式返回样式后可以设置样式内容<br>
* 需要注意此方法返回行样式设置背景色在单元格设置值后会被覆盖需要单独设置其单元格的样式
*
* @param y Y坐标从0计数既行号
* @return {@link CellStyle}
* @since 4.1.4
*/
public CellStyle getOrCreateRowStyle(int y) {
final Row row = getOrCreateRow(y);
CellStyle rowStyle = row.getRowStyle();
if (null == rowStyle) {
rowStyle = this.workbook.createCellStyle();
row.setRowStyle(rowStyle);
}
CellStyle rowStyle = getOrCreateRow(y).getRowStyle();
return StyleUtil.isNullOrDefaultStyle(this.workbook, rowStyle) ? createRowStyle(y) : rowStyle;
}
/**
* 创建某一行的样式返回样式后可以设置样式内容
*
* @param y Y坐标从0计数既行号
* @return {@link CellStyle}
* @since 4.6.3
*/
public CellStyle createRowStyle(int y) {
final CellStyle rowStyle = this.workbook.createCellStyle();
getOrCreateRow(y).setRowStyle(rowStyle);
return rowStyle;
}
/**
* 获取或创建某一行的样式返回样式后可以设置样式内容
* 获取或创建某一行的样式返回样式后可以设置样式内容<br>
* 需要注意此方法返回行样式设置背景色在单元格设置值后会被覆盖需要单独设置其单元格的样式
*
* @param x X坐标从0计数既列号
* @return {@link CellStyle}
* @since 4.1.4
*/
public CellStyle getOrCreateColumnStyle(int x) {
CellStyle columnStyle = this.sheet.getColumnStyle(x);
if (null == columnStyle) {
columnStyle = this.workbook.createCellStyle();
this.sheet.setDefaultColumnStyle(x, columnStyle);
}
final CellStyle columnStyle = this.sheet.getColumnStyle(x);
return StyleUtil.isNullOrDefaultStyle(this.workbook, columnStyle) ? createColumnStyle(x) : columnStyle;
}
/**
* 创建某一行的样式返回样式后可以设置样式内容
*
* @param x X坐标从0计数既列号
* @return {@link CellStyle}
* @since 4.6.3
*/
public CellStyle createColumnStyle(int x) {
final CellStyle columnStyle = this.workbook.createCellStyle();
this.sheet.setDefaultColumnStyle(x, columnStyle);
return columnStyle;
}

View File

@ -3,6 +3,7 @@ package cn.hutool.poi.excel;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.Map;
@ -34,6 +35,10 @@ import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.poi.excel.cell.CellUtil;
import cn.hutool.poi.excel.style.Align;
@ -263,6 +268,17 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
this.sheet.autoSizeColumn(columnIndex, useMergedCells);
return this;
}
/**
* 禁用默认样式
*
* @return this
* @see #setStyleSet(StyleSet)
* @since 4.6.3
*/
public ExcelWriter disableDefaultStyle() {
return setStyleSet(null);
}
/**
* 设置样式集如果不使用样式传入{@code null}
@ -319,6 +335,31 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
public int getCurrentRow() {
return this.currentRow.get();
}
/**
* 获取Content-Disposition头对应的值可以通过调用以下方法快速设置下载Excel的头信息
*
* <pre>
* response.setHeader("Content-Disposition", excelWriter.getDisposition("test.xlsx", CharsetUtil.CHARSET_UTF_8));
* </pre>
*
* @param fileName 文件名如果文件名没有扩展名会自动按照生成Excel类型补齐扩展名如果提供空使用随机UUID
* @param charset 编码null则使用默认UTF-8编码
* @return Content-Disposition值
*/
public String getDisposition(String fileName, Charset charset) {
if(null == charset) {
charset = CharsetUtil.CHARSET_UTF_8;
}
if(StrUtil.isBlank(fileName)) {
// 未提供文件名使用随机UUID作为文件名
fileName = IdUtil.fastSimpleUUID();
}
fileName = StrUtil.addSuffixIfNot(URLUtil.encodeAll(fileName, charset), isXlsx() ? ".xlsx" : ".xls");
return StrUtil.format("attachment; filename=\"{}\"; filename*={}''{}", fileName, charset.name(), fileName);
}
/**
* 设置当前所在行
@ -824,7 +865,7 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
* @param y Y坐标从0计数既行号
* @return {@link CellStyle}
* @since 4.0.9
* @deprecated 请使用{@link #getOrCreateCellStyle(int, int)}
* @deprecated 请使用{@link #createCellStyle(int, int)}
*/
@Deprecated
public CellStyle createStyleForCell(int x, int y) {
@ -833,6 +874,25 @@ public class ExcelWriter extends ExcelBase<ExcelWriter> {
cell.setCellStyle(cellStyle);
return cellStyle;
}
/**
* 设置某个单元格的样式<br>
* 此方法用于多个单元格共享样式的情况<br>
* 可以调用{@link #getOrCreateCellStyle(int, int)} 方法创建或取得一个样式对象
*
* <p>
* 需要注意的是共享样式会共享同一个{@link CellStyle}一个单元格样式改变全部改变
*
* @param x X坐标从0计数既列号
* @param y Y坐标从0计数既行号
* @return this
* @since 4.6.3
*/
public ExcelWriter setStyle(CellStyle style, int x, int y) {
final Cell cell = getOrCreateCell(x, y);
cell.setCellStyle(style);
return this;
}
/**
* 创建字体

View File

@ -3,6 +3,7 @@ package cn.hutool.poi.excel.cell;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
@ -13,6 +14,7 @@ import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.ss.util.SheetUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
@ -26,7 +28,18 @@ import cn.hutool.poi.excel.editors.TrimEditor;
* @since 4.0.7
*/
public class CellUtil {
/**
* 获取单元格值
*
* @param cell {@link Cell}单元格
* @return 类型可能为DateDoubleBooleanString
* @since 4.6.3
*/
public static Object getCellValue(Cell cell) {
return getCellValue(cell, false);
}
/**
* 获取单元格值
*
@ -121,7 +134,11 @@ public class CellUtil {
* @param isHeader 是否为标题单元格
*/
public static void setCellValue(Cell cell, Object value, StyleSet styleSet, boolean isHeader) {
if(null != styleSet) {
if(null == cell) {
return;
}
if (null != styleSet) {
final CellStyle headCellStyle = styleSet.getHeadCellStyle();
final CellStyle cellStyle = styleSet.getCellStyle();
if (isHeader && null != headCellStyle) {
@ -148,7 +165,7 @@ public class CellUtil {
} else if (value instanceof RichTextString) {
cell.setCellValue((RichTextString) value);
} else if (value instanceof Number) {
if ((value instanceof Double || value instanceof Float || value instanceof BigDecimal) && null != styleSet && null != styleSet.getCellStyleForNumber()) {
if ((value instanceof Double || value instanceof Float || value instanceof BigDecimal) && null != styleSet && null != styleSet.getCellStyleForNumber()) {
cell.setCellStyle(styleSet.getCellStyleForNumber());
}
cell.setCellValue(((Number) value).doubleValue());
@ -221,6 +238,40 @@ public class CellUtil {
return sheet.addMergedRegion(cellRangeAddress);
}
/**
* 获取合并单元格的值<br>
* 传入的x,y坐标列行数可以是合并单元格范围内的任意一个单元格
*
*
* @param sheet {@link Sheet}
* @param y 行号从0开始可以是合并单元格范围中的任意一行
* @param x 列号从0开始可以是合并单元格范围中的任意一列
* @return 合并单元格的值
* @since 4.6.3
*/
public static Object getMergedRegionValue(Sheet sheet, int x, int y) {
final List<CellRangeAddress> addrs = sheet.getMergedRegions();
int firstColumn;
int lastColumn;
int firstRow;
int lastRow;
for (CellRangeAddress ca : addrs) {
firstColumn = ca.getFirstColumn();
lastColumn = ca.getLastColumn();
firstRow = ca.getFirstRow();
lastRow = ca.getLastRow();
if (y >= firstRow && y <= lastRow) {
if (x >= firstColumn && x <= lastColumn) {
return getCellValue(SheetUtil.getCell(sheet, firstRow, firstColumn));
}
}
}
return null;
}
// -------------------------------------------------------------------------------------------------------------- Private method start
/**
* 获取数字类型的单元格值

View File

@ -175,4 +175,18 @@ public class StyleUtil {
setColor(cellStyle, IndexedColors.GREY_25_PERCENT, FillPatternType.SOLID_FOREGROUND);
return cellStyle;
}
/**
* 给定样式是否为null无样式或默认样式默认样式为<code>workbook.getCellStyleAt(0)</code>
* @param workbook 工作簿
* @param style 被检查的样式
* @return 是否为null无样式或默认样式
* @since 4.6.3
*/
public static boolean isNullOrDefaultStyle(Workbook workbook, CellStyle style) {
if(null == style || style.equals(workbook.getCellStyleAt(0))) {
return true;
}
return false;
}
}

View File

@ -208,6 +208,33 @@ public class ExcelWriteTest {
// 关闭writer释放内存
writer.close();
}
@Test
@Ignore
public void writeMapWithStyleTest() {
Map<String, Object> row1 = MapUtil.newHashMap(true);
row1.put("姓名", "张三");
row1.put("年龄", 23);
row1.put("成绩", 88.32);
row1.put("是否合格", true);
row1.put("考试日期", DateUtil.date());
// 通过工具类创建writer
String path = "f:/test/writeMapWithStyleTest.xlsx";
FileUtil.del(path);
ExcelWriter writer = ExcelUtil.getWriter(path);
writer.setStyleSet(null);
// 一次性写出内容使用默认样式
writer.writeRow(row1, true);
// 设置某个单元格样式
CellStyle orCreateRowStyle = writer.getOrCreateCellStyle(0, 1);
StyleUtil.setColor(orCreateRowStyle,IndexedColors.RED.getIndex(),FillPatternType.SOLID_FOREGROUND );
// 关闭writer释放内存
writer.close();
}
@Test
@Ignore
@ -278,7 +305,7 @@ public class ExcelWriteTest {
}
@Test
// @Ignore
@Ignore
public void writeMapOnlyAliasTest2() {
Map<Object, Object> row1 = new LinkedHashMap<>();
row1.put("name", "张三");