基于easyPoi框架导出excel工具类
使用到的技术框架
- SpringBoot、
- easyPoi
相信大家平时业务上肯定都会遇到将表单数据导出excel的情况,这个工具主要是在easyPoi框架的基础上封装了一个工具类,并加上了一些使用的操作表格的方法,可以方便的导出excel。
这里的方法,只是用于导出格式较为简单地excel文件,复杂格式的还是要手写poi,一个单元格的写。
看源码:
ExcelUtil.java
/**
* Excel工具方法
*
* @author: 一位大帅哥(a very handsome man)
* @date: 2023/2/21:10:30
* @description: TODO
*/
@Slf4j
public class ExcelUtil {
/**
* 设置Excel工作表中某个单元格的值
*
* @param workbook excel文件
* @param sheetNum 工作表号
* @param rowNum 行号
* @param cellNum 列号
* @param cellValue 单元格的值
*/
public static void setCellValue(Workbook workbook,
int sheetNum,
int rowNum,
int cellNum,
Object cellValue) {
// 获取sheet
Sheet sheet = workbook.getSheetAt(sheetNum);
// 获取工作表中的某一行
Row row = sheet.getRow(rowNum);
// 在这行创建单元格
Cell cell = row.getCell(cellNum);
// 创建一个格式
CellStyle cellStyle = workbook.createCellStyle();
cellStyle.setAlignment(HorizontalAlignment.CENTER);
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
cellStyle.setDataFormat((short) BuiltinFormats.getBuiltinFormat("TEXT"));
// 设置这个单元格的格式
cell.setCellStyle(cellStyle);
// 如果单元格的值是字符串
if (cellValue instanceof String) {
cell.setCellValue((String) cellValue);
// 如果单元格的值是数字double
} else if (cellValue instanceof Double) {
cell.setCellValue((Double) cellValue);
// 如果单元格的值是数字日期
} else if (cellValue instanceof Date) {
cell.setCellValue((Date) cellValue);
// 如果单元格的值是富文本
} else if (cellValue instanceof RichTextString) {
cell.setCellValue((RichTextString) cellValue);
}
}
/**
* XSSF
* excel添加下拉数据校验
*
* @param workbook 哪个 sheet 页添加校验
* @param dataSource 数据源数组
* @param col 第几列校验(0开始)
*/
public static void createXssfOfSelected(Workbook workbook, String[] dataSource, int col) {
Sheet sheet = workbook.getSheetAt(0);
CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(1, 65535, col, col);
DataValidationHelper helper = sheet.getDataValidationHelper();
DataValidationConstraint constraint = helper.createExplicitListConstraint(dataSource);
DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList);
//处理Excel兼容性问题
if (dataValidation instanceof XSSFDataValidation) {
dataValidation.setSuppressDropDownArrow(true);
dataValidation.setShowErrorBox(true);
} else {
dataValidation.setSuppressDropDownArrow(false);
}
dataValidation.setEmptyCellAllowed(true);
dataValidation.setShowPromptBox(true);
dataValidation.createPromptBox("提示", "只能选择下拉框里面的数据!");
sheet.addValidationData(dataValidation);
}
/**
* 为excel文件某一列设置数字,小数整数都可以校验
*
* @param workbook 文件
* @param startCol 第几列校验(0开始)
* @param endCol 第几列校验(0开始)
*/
public static void createXssfOfDecimal(Workbook workbook, int startCol, int endCol) {
Sheet sheet = workbook.getSheetAt(0);
CellRangeAddressList cell = new CellRangeAddressList(1, 65535, startCol, endCol);
DataValidationHelper helper = sheet.getDataValidationHelper();
// 创建一个大于等于0的数值约束
DataValidationConstraint constraint = helper.createDecimalConstraint(DataValidationConstraint.OperatorType.GREATER_OR_EQUAL, "0.0", null);
DataValidation validation = helper.createValidation(constraint, cell);
//处理Excel兼容性问题
if (validation instanceof XSSFDataValidation) {
validation.setSuppressDropDownArrow(true);
validation.setShowErrorBox(true);
} else {
validation.setSuppressDropDownArrow(false);
}
// 允许空值
validation.setEmptyCellAllowed(true);
validation.setShowErrorBox(true);
validation.createErrorBox("提示", "该列只能是纯数字或小数!");
sheet.addValidationData(validation);
}
/**
* 为excel文件某一列设置数字整数校验
*
* @param workbook 文件
* @param startCol 第几列校验(0开始)
* @param endCol 第几列校验(0开始)
*/
public static void createXssfOfInteger(Workbook workbook, int startCol, int endCol) {
Sheet sheet = workbook.getSheetAt(0);
CellRangeAddressList cell = new CellRangeAddressList(1, 65535, startCol, endCol);
DataValidationHelper helper = sheet.getDataValidationHelper();
// 创建一个大于等于0的数值约束
DataValidationConstraint constraint = helper.createIntegerConstraint(DataValidationConstraint.OperatorType.GREATER_OR_EQUAL, "0", null);
DataValidation validation = helper.createValidation(constraint, cell);
//处理Excel兼容性问题
if (validation instanceof XSSFDataValidation) {
validation.setSuppressDropDownArrow(true);
validation.setShowErrorBox(true);
} else {
validation.setSuppressDropDownArrow(false);
}
// 允许空值
validation.setEmptyCellAllowed(true);
validation.setShowErrorBox(true);
validation.createErrorBox("提示", "该列只能是纯数字且不可为小数和负数!");
sheet.addValidationData(validation);
}
/**
* 获取Workbook。
* 带序号, 默认ExcelExportMyStyler格式
*
* @param exportClass 要导出的类
* @param exportList 要导出类集合
* @param response 响应流
*/
public static Workbook getWorkbook(Class exportClass,
Collection exportList,
HttpServletResponse response) throws UnsupportedEncodingException {
ExportParams params = new ExportParams();
params.setAddIndex(true);
params.setStyle(ExcelExportMyStyler.class);
FileUtils.setResponseXlsxData(response, FileUtils.getExportFileName(".xlsx"));
log.info("获取Workbook");
return CustomExcelExportUtils.exportExcel(params, exportClass, exportList);
}
/**
* 获取Workbook。
* 带序号, 默认ExcelExportMyStyler格式
*
* @param exportClass 要导出的类
* @param exportList 要导出类集合
* @param sheetName 工作表名称
* @param response 响应流
*/
public static Workbook getWorkbook(Class exportClass,
Collection exportList,
String sheetName,
HttpServletResponse response) throws UnsupportedEncodingException {
ExportParams params = new ExportParams();
params.setAddIndex(true);
params.setStyle(ExcelExportMyStyler.class);
params.setSheetName(sheetName);
FileUtils.setResponseXlsxData(response, FileUtils.getExportFileName(".xlsx"));
log.info("获取Workbook");
return CustomExcelExportUtils.exportExcel(params, exportClass, exportList);
}
/**
* 获取Workbook。
* 不带序号, 默认ExcelExportMyStyler格式
*
* @param exportClass 要导出的类
* @param exportList 要导出类集合
* @param response 响应流
*/
public static Workbook getWorkbookNoNum(Class exportClass,
Collection exportList,
HttpServletResponse response) throws UnsupportedEncodingException {
ExportParams params = new ExportParams();
// params.setAddIndex(true);
params.setStyle(ExcelExportMyStyler.class);
FileUtils.setResponseXlsxData(response, FileUtils.getExportFileName(".xlsx"));
log.info("获取Workbook");
return CustomExcelExportUtils.exportExcel(params, exportClass, exportList);
}
/**
* 获取Workbook。
* 不带序号, 默认ExcelExportMyStyler格式
*
* @param exportClass 要导出的类
* @param exportList 要导出类集合
* @param sheetName 工作表名称
* @param response 响应流
*/
public static Workbook getWorkbookNoNum(Class exportClass,
Collection exportList,
String sheetName,
HttpServletResponse response) throws UnsupportedEncodingException {
ExportParams params = new ExportParams();
// params.setAddIndex(true);
params.setStyle(ExcelExportMyStyler.class);
params.setSheetName(sheetName);
FileUtils.setResponseXlsxData(response, FileUtils.getExportFileName(".xlsx"));
log.info("获取Workbook");
return CustomExcelExportUtils.exportExcel(params, exportClass, exportList);
}
/**
* 通用导出方法
* 带序号, 默认ExcelExportMyStyler格式
*
* @param exportClass 要导出的类
* @param exportList 要导出类集合
* @param response 响应流
*/
public static void exportExcelGeneral(Class exportClass,
Collection exportList,
HttpServletResponse response) {
ServletOutputStream outputStream = null;
try {
ExportParams params = new ExportParams();
params.setAddIndex(true);
params.setStyle(ExcelExportMyStyler.class);
outputStream = response.getOutputStream();
FileUtils.setResponseXlsxData(response, FileUtils.getExportFileName(".xlsx"));
CustomExcelExportUtils.exportExcel(params, exportClass, exportList).write(outputStream);
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.info("通用方法导出!");
} catch (Exception e) {
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.error(LogConstant.EXPORT_FAIL, e.getMessage());
} finally {
PoitlIOUtils.closeQuietlyMulti(outputStream);
}
}
/**
* 通用导出方法
* 带序号, 默认ExcelExportMyStyler格式
*
* @param exportClass 要导出的类
* @param exportList 要导出类集合
* @param sheetName 导出工作表名
* @param titleName 标题名称
* @param response 响应流
*/
public static void exportExcelGeneral(Class exportClass,
Collection exportList,
String sheetName,
String titleName,
HttpServletResponse response) {
ServletOutputStream outputStream = null;
try {
ExportParams params = new ExportParams();
params.setAddIndex(true);
params.setStyle(ExcelExportMyStyler.class);
params.setSheetName(sheetName);
params.setTitle(titleName);
outputStream = response.getOutputStream();
FileUtils.setResponseXlsxData(response, FileUtils.getExportFileName(".xlsx"));
CustomExcelExportUtils.exportExcel(params, exportClass, exportList).write(outputStream);
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.info("通用方法导出!");
} catch (Exception e) {
e.printStackTrace();
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.error(LogConstant.EXPORT_FAIL, e.getMessage());
} finally {
PoitlIOUtils.closeQuietlyMulti(outputStream);
}
}
/**
* 通用导出方法
* 带序号, 默认ExcelExportMyStyler格式
* 支持校验某一列数据
*
* @param exportClass 要导出的类
* @param exportList 要导出类集合
* @param checkColumnData 校验列选择框提示内容
* @param col 第几列校验
* @param response 响应流
*/
public static void exportExcelGeneral(Class exportClass,
Collection exportList,
String[] checkColumnData,
int col,
HttpServletResponse response) {
ServletOutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
ExportParams params = new ExportParams();
params.setAddIndex(true);
params.setStyle(ExcelExportMyStyler.class);
FileUtils.setResponseXlsxData(response, FileUtils.getExportFileName(".xlsx"));
Workbook workbook = CustomExcelExportUtils.exportExcel(params, exportClass, exportList);
createXssfOfSelected(workbook, checkColumnData, col);
workbook.write(outputStream);
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.info("通用方法导出!");
} catch (Exception e) {
e.printStackTrace();
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.error(LogConstant.EXPORT_FAIL, e.getMessage());
} finally {
PoitlIOUtils.closeQuietlyMulti(outputStream);
}
}
/**
* 通用导出方法
* 带序号, 默认ExcelExportMyStyler格式
* 支持校验某一列数据
*
* @param exportClass 要导出的类
* @param exportList 要导出类集合
* @param checkColumnData 校验列选择框提示内容
* @param col 第几列校验
* @param sheetName 导出文件的工作表名称
* @param response 响应流
*/
public static void exportExcelGeneral(Class exportClass,
Collection exportList,
String[] checkColumnData,
int col,
String sheetName,
HttpServletResponse response) {
ServletOutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
ExportParams params = new ExportParams();
params.setAddIndex(true);
params.setStyle(ExcelExportMyStyler.class);
params.setSheetName(sheetName);
FileUtils.setResponseXlsxData(response, FileUtils.getExportFileName(".xlsx"));
Workbook workbook = CustomExcelExportUtils.exportExcel(params, exportClass, exportList);
createXssfOfSelected(workbook, checkColumnData, col);
workbook.write(outputStream);
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.info("通用导出方法!");
} catch (Exception e) {
e.printStackTrace();
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.error(LogConstant.EXPORT_FAIL, e.getMessage());
} finally {
PoitlIOUtils.closeQuietlyMulti(outputStream);
}
}
/**
* 通用导出方法
* 带序号, 默认ExcelExportMyStyler格式
* 支持校验多列数据
* for example
* {
* 如果需要导出的数据校验第三列和第八列
* 则:
* checkColumnData: {
* 3,["提示数据1","提示数据2","提示数据3",...],
* 8,["提示数据1","提示数据2","提示数据3",...]
* }
* col: [3,8]
* }
*
* @param exportClass 要导出的类
* @param exportList 要导出类集合
* @param checkColumnData 校验列选择框提示内容 , 可多个
* @param col 需要校验的列 , 可多个
* @param response 响应流
*/
public static void exportExcelGeneral(Class exportClass,
Collection exportList,
Map<Integer, String[]> checkColumnData,
Integer[] col,
HttpServletResponse response) {
ServletOutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
ExportParams params = new ExportParams();
params.setAddIndex(true);
params.setStyle(ExcelExportMyStyler.class);
FileUtils.setResponseXlsxData(response, FileUtils.getExportFileName(".xlsx"));
Workbook workbook = CustomExcelExportUtils.exportExcel(params, exportClass, exportList);
for (Integer columnNumber : col) {
createXssfOfSelected(workbook, checkColumnData.get(columnNumber), columnNumber);
}
workbook.write(outputStream);
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.info("通用导出方法!");
} catch (Exception e) {
e.printStackTrace();
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.error(LogConstant.EXPORT_FAIL, e.getMessage());
} finally {
PoitlIOUtils.closeQuietlyMulti(outputStream);
}
}
/**
* 通用导出方法
* 带序号, 默认ExcelExportMyStyler格式
* 支持校验多列数据
* for example
* {
* 如果需要导出的数据校验第三列和第八列
* 则:
* checkColumnData: {
* 3,["提示数据1","提示数据2","提示数据3",...],
* 8,["提示数据1","提示数据2","提示数据3",...]
* }
* col: [3,8]
* }
*
* @param exportClass 要导出的类
* @param exportList 要导出类集合
* @param checkColumnData 校验列选择框提示内容 , 可多个
* @param col 需要校验的列 , 可多个
* @param sheetName 工作表名称
* @param response 响应流
*/
public static void exportExcelGeneral(Class exportClass,
Collection exportList,
Map<Integer, String[]> checkColumnData,
Integer[] col,
String sheetName,
HttpServletResponse response) {
ServletOutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
ExportParams params = new ExportParams();
params.setAddIndex(true);
params.setStyle(ExcelExportMyStyler.class);
params.setSheetName(sheetName);
FileUtils.setResponseXlsxData(response, FileUtils.getExportFileName(".xlsx"));
Workbook workbook = CustomExcelExportUtils.exportExcel(params, exportClass, exportList);
for (Integer columnNumber : col) {
createXssfOfSelected(workbook, checkColumnData.get(columnNumber), columnNumber);
}
workbook.write(outputStream);
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.info("通用导出方法!");
} catch (Exception e) {
e.printStackTrace();
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.error(LogConstant.EXPORT_FAIL, e.getMessage());
} finally {
PoitlIOUtils.closeQuietlyMulti(outputStream);
}
}
}
CustomExcelExportUtils.java
主要用来实现导出自动带序号列
/**
* 自定义Excel导出工具类, 带序号列
*
* @author: a very handsome man
* @date: 2022-10-25 09:55
* @description: TODO
*/
public class CustomExcelExportUtils {
public static Workbook exportExcel(ExportParams entity, List entityList, Collection dataSet) {
Workbook workbook = getWorkbook(entity.getType(), dataSet.size());
new CustomExcelExportService().createSheetForMap(workbook, entity, entityList, dataSet);
return workbook;
}
public static Workbook exportExcel(ExportParams entity, Class pojoClass, Collection dataSet) {
Workbook workbook = getWorkbook(entity.getType(), dataSet.size());
new CustomExcelExportService().createSheet(workbook, entity, pojoClass, dataSet);
return workbook;
}
private static Workbook getWorkbook(ExcelType type, int size) {
if (ExcelType.HSSF.equals(type)) {
return new HSSFWorkbook();
} else if (size < 100000) {
return new XSSFWorkbook();
} else {
return new SXSSFWorkbook();
}
}
public static void exportExcel(HttpServletResponse response, Workbook workbook) throws Exception {
response.reset();
response.setContentType("application/vnd.ms-excel");
String fileName = System.currentTimeMillis() + ".xlsx";
response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
response.setCharacterEncoding("UTF-8");
OutputStream output = response.getOutputStream();
workbook.write(output);
workbook.close();
output.close();
}
}
CustomExcelExportService.java
主要用来实现导出自动带序号列
/**
* 导出excel Service
* @author: a very handsome man
* @date: 2022-10-25 09:57
* @description: TODO
*/
public class CustomExcelExportService extends ExcelExportService {
private static int MAX_NUM = 60000;
@Override
protected void insertDataToSheet(Workbook workbook, ExportParams entity, List<ExcelExportEntity> entityList, Collection<?> dataSet, Sheet sheet) {
try {
dataHandler = entity.getDataHandler();
if (dataHandler != null && dataHandler.getNeedHandlerFields() != null) {
needHandlerList = Arrays.asList(dataHandler.getNeedHandlerFields());
}
dictHandler = entity.getDictHandler();
i18nHandler = entity.getI18nHandler();
// 创建表格样式
setExcelExportStyler((IExcelExportStyler) entity.getStyle().getConstructor(Workbook.class).newInstance(workbook));
Drawing patriarch = PoiExcelGraphDataUtil.getDrawingPatriarch(sheet);
List excelParams = new ArrayList();
if (entity.isAddIndex()) {
excelParams.add(indexExcelEntity(entity));
}
excelParams.addAll(entityList);
int index = entity.isCreateHeadRows() ? createHeaderAndTitle(entity, sheet, workbook, excelParams) : 0;
int titleHeight = index;
setCellWith(excelParams, sheet);
setColumnHidden(excelParams, sheet);
short rowHeight = entity.getHeight() != 0 ? entity.getHeight() : getRowHeight(excelParams);
setCurrentIndex(1);
Iterator its = dataSet.iterator();
List tempList = new ArrayList();
while (its.hasNext()) {
Object t = its.next();
index += createCells(patriarch, index, t, excelParams, sheet, workbook, rowHeight, 0)[0];
tempList.add(t);
if (index >= MAX_NUM) {
break;
}
}
if (entity.getFreezeCol() != 0) {
sheet.createFreezePane(entity.getFreezeCol(), 0, entity.getFreezeCol(), 0);
}
mergeCells(sheet, excelParams, titleHeight);
its = dataSet.iterator();
for (int i = 0, le = tempList.size(); i < le; i++) {
its.next();
its.remove();
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("List data more than max ,data size is {}", dataSet.size());
}
// 发现还有剩余list 继续循环创建Sheet
if (dataSet.size() > 0) {
createSheetForMap(workbook, entity, entityList, dataSet);
} else {
// 创建合计信息
addStatisticsRow(getExcelExportStyler().getStyles(true, null), sheet);
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
try {
dataHandler = entity.getDataHandler();
if (dataHandler != null && dataHandler.getNeedHandlerFields() != null) {
needHandlerList = Arrays.asList(dataHandler.getNeedHandlerFields());
}
dictHandler = entity.getDictHandler();
i18nHandler = entity.getI18nHandler();
// 创建表格样式
setExcelExportStyler((IExcelExportStyler) entity.getStyle().getConstructor(Workbook.class).newInstance(workbook));
Drawing patriarch = PoiExcelGraphDataUtil.getDrawingPatriarch(sheet);
List excelParams = new ArrayList();
if (entity.isAddIndex()) {
excelParams.add(indexExcelEntity(entity));
}
excelParams.addAll(entityList);
int index = entity.isCreateHeadRows() ? createHeaderAndTitle(entity, sheet, workbook, excelParams) : 0;
int titleHeight = index;
setCellWith(excelParams, sheet);
setColumnHidden(excelParams, sheet);
short rowHeight = entity.getHeight() != 0 ? entity.getHeight() : getRowHeight(excelParams);
setCurrentIndex(1);
Iterator its = dataSet.iterator();
List tempList = new ArrayList();
while (its.hasNext()) {
Object t = its.next();
index += createCells(patriarch, index, t, excelParams, sheet, workbook, rowHeight, 0)[0];
tempList.add(t);
if (index >= MAX_NUM) {
break;
}
}
if (entity.getFreezeCol() != 0) {
sheet.createFreezePane(entity.getFreezeCol(), 0, entity.getFreezeCol(), 0);
}
mergeCells(sheet, excelParams, titleHeight);
its = dataSet.iterator();
for (int i = 0, le = tempList.size(); i < le; i++) {
its.next();
its.remove();
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("List data more than max ,data size is {}", dataSet.size());
}
// 发现还有剩余list 继续循环创建Sheet
if (dataSet.size() > 0) {
createSheetForMap(workbook, entity, entityList, dataSet);
} else {
// 创建合计信息
addStatisticsRow(getExcelExportStyler().getStyles(true, null), sheet);
}
} catch (Exception exception) {
LOGGER.error(exception.getMessage(), exception);
throw new ExcelExportException(ExcelExportEnum.EXPORT_ERROR, exception.getCause());
}
}
}
}
ExcelExportMyStyler.java
excel导出样式类
/**
* excel导出样式类
* @author: a very handsome man
* @date: 2022-12-29 19:41
* @description: TODO
*/
public class ExcelExportMyStyler extends AbstractExcelExportStyler implements IExcelExportStyler {
public ExcelExportMyStyler(Workbook workbook) {
super.createStyles(workbook);
}
@Override
public CellStyle getTitleStyle(short color) {
return getCellStyle(workbook);
}
@SuppressWarnings("deprecation")
@Override
public CellStyle stringSeptailStyle(Workbook workbook, boolean isWarp) {
CellStyle style = workbook.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setDataFormat(STRING_FORMAT);
if (isWarp) {
style.setWrapText(true);
}
return style;
}
@Override
public CellStyle getHeaderStyle(short color) {
CellStyle titleStyle = workbook.createCellStyle();
Font font = workbook.createFont();
font.setBold(true);// 加粗
font.setColor(IndexedColors.RED.index);
font.setFontHeightInPoints((short) 12);
titleStyle.setFont(font);
titleStyle.setAlignment(HorizontalAlignment.CENTER);// 居中
titleStyle.setFillForegroundColor(IndexedColors.WHITE.index);// 设置颜色
titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 垂直居中
titleStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
titleStyle.setBorderRight(BorderStyle.THIN);
titleStyle.setWrapText(true);
return titleStyle;
}
@SuppressWarnings("deprecation")
@Override
public CellStyle stringNoneStyle(Workbook workbook, boolean isWarp) {
CellStyle style = workbook.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setDataFormat(STRING_FORMAT);
style.setWrapText(isWarp);
return style;
}
/**
* 标题行样式
*
* @param workbook
* @return
*/
public static CellStyle getCellStyle(Workbook workbook) {
CellStyle titleStyle = workbook.createCellStyle();
Font font = workbook.createFont();
font.setBold(true);// 加粗
font.setFontHeightInPoints((short) 12);
titleStyle.setFont(font);
titleStyle.setAlignment(HorizontalAlignment.CENTER);// 居中
titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 垂直居中
titleStyle.setFillForegroundColor(IndexedColors.AQUA.index);// 设置颜色
titleStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
titleStyle.setBorderRight(BorderStyle.THIN);
titleStyle.setBorderBottom(BorderStyle.THIN);
titleStyle.setBorderTop(BorderStyle.THIN);
titleStyle.setBorderLeft(BorderStyle.THIN);
titleStyle.setBorderRight(BorderStyle.THIN);
titleStyle.setWrapText(true);
return titleStyle;
}
}
FileUtils.java
/**
* 文件操作工具类
*
* @author: 一位大帅哥
* @date: 2022/9/22 10:27
* @description: TODO
*/
@Slf4j
public class FileUtils {
@Value("${upload.path}")
private String fileUploadPath;
/**
* 文件下载方法
*
* @param path 文件地址, 包含文件名及其扩展名
* @param res
*/
public static void downloadFile(String path, HttpServletResponse res) {
OutputStream toClient = null;
try {
// 获取下载的路径
File file = new File(path);
// 获取文件名
String filename = file.getName();
res.setCharacterEncoding("UTF-8");
res.setContentType("application/octet-stream");
filename = URLEncoder.encode(filename, "UTF-8");
// 设置文件下载后的指定文件名
res.addHeader("Content-Disposition", filename);
byte[] readBytes = FileUtil.readBytes(path);
toClient = res.getOutputStream();
toClient.write(readBytes);
toClient.flush();
log.info("文件下载成功,文件名:{}", filename);
} catch (IOException e) {
e.printStackTrace();
log.error("下载文件错误:{}", e.getMessage());
} finally {
try {
// 关闭缓冲输出流
if (toClient != null) {
toClient.close();
}
} catch (IOException e) {
e.printStackTrace();
log.error("下载文件错误:{}", e.getMessage());
}
}
}
/**
* 上传文件
*
* @param file 文件
* @param fileUrl 欲要上传到服务器的文件地址
*/
public static void uploadFile(MultipartFile file, String fileUrl) {
// 获取文件的后缀 这个获取是会携带.的 注意
String suffixName = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
// 防止文件名重复 , 导致文件创建失败, 文件名后加uuid区分
fileUrl = fileUrl + UUID.randomUUID() + suffixName;
// 判断该文件夹是否存在 不存在的话就创建
File dest = new File(fileUrl);
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
try {
// 保存文件
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(fileUrl));
outputStream.write(file.getBytes());
outputStream.flush();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
log.error("文件上传错误: {}", e.getMessage());
}
}
/**
* 返回带.的文件扩展名
*
* @param fileName 文件名
* @return 扩展名
*/
public static String getFileExtension(String fileName) {
// 返回带.的文件扩展名
return fileName.substring(fileName.lastIndexOf("."));
}
/**
* 导出多个文件 , 打包为压缩文件
*
* @param fileList 文件集合 , 字符串, 文件的绝对地址
* @param zipFileName 打包后的压缩文件名
* @param response 响应流
* @throws IOException 异常
*/
public static void zipFiles(List<String> fileList,
String zipFileName,
HttpServletResponse response) throws IOException {
byte[] buf = new byte[1024];
BufferedOutputStream bos = null;
ZipOutputStream out = null;
try {
bos = new BufferedOutputStream(response.getOutputStream());
//响应到浏览器
setResponseZipData(response, zipFileName);
out = new ZipOutputStream(bos);
setResponseZipData(response, getExportFileName(".zip"));
for (String filePath : fileList) {
File file = new File(filePath);
FileInputStream in = new FileInputStream(file);
out.putNextEntry(new ZipEntry(file.getName()));
int len;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
PoitlIOUtils.closeQuietlyMulti(in);
}
} catch (IOException e) {
log.error("打包失败: {}!", e.getMessage());
} finally {
PoitlIOUtils.closeQuietlyMulti(out, bos);
}
}
/**
* 设置response响应头参数 --> .xls版
*
* @param response 响应流
* @param fileName 文件名
*/
public static void setResponseXlsData(HttpServletResponse response, String fileName) {
response.setContentType("application/octet-stream");
URLEncodeUtil.encode(fileName, StandardCharsets.UTF_8);
log.info("导出文件名为: {}", fileName);
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
response.setHeader("content-Type", "application/vnd.ms-excel");
}
/**
* 设置response响应头参数 --> .xlsx版
*
* @param response 响应流
* @param fileName 文件名
*/
public static void setResponseXlsxData(HttpServletResponse response, String fileName) throws UnsupportedEncodingException {
// response.setContentType("application/octet-stream");
// URLEncodeUtil.encode(fileName, StandardCharsets.UTF_8);
fileName = URLEncoder.encode(fileName, "UTF-8");
log.info("导出文件名为: {}", fileName);
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
}
/**
* 设置response响应头参数 --> 通用版
*
* @param response 响应流
* @param fileName 文件名
*/
public static void setResponseData(HttpServletResponse response, String fileName) {
response.setContentType("application/octet-stream");
URLEncodeUtil.encode(fileName, StandardCharsets.UTF_8);
log.info("导出文件名为: {}", fileName);
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
}
/**
* 设置response响应头参数 --> .doc版
*
* @param response 响应流
* @param fileName 文件名
*/
public static void setResponseDocData(HttpServletResponse response, String fileName) {
response.setContentType("application/octet-stream");
URLEncodeUtil.encode(fileName, StandardCharsets.UTF_8);
log.info("导出文件名为: {}", fileName);
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
response.setHeader("content-Type", "application/msword");
}
/**
* 设置response响应头参数 --> .docx版
*
* @param response 响应流
* @param fileName 文件名
*/
public static void setResponseDocxData(HttpServletResponse response, String fileName) {
response.setContentType("application/octet-stream");
URLEncodeUtil.encode(fileName, StandardCharsets.UTF_8);
log.info("导出文件名为: {}", fileName);
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
response.setHeader("content-Type", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
}
/**
* 设置response响应头参数 --> .jpe / .jpeg / .jpz / .jpg版
*
* @param response 响应流
* @param fileName 文件名
*/
public static void setResponseJpgData(HttpServletResponse response, String fileName) {
response.setContentType("application/octet-stream");
URLEncodeUtil.encode(fileName, StandardCharsets.UTF_8);
log.info("导出文件名为: {}", fileName);
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
response.setHeader("content-Type", "image/jpeg");
}
/**
* 设置response响应头参数 --> .zip
*
* @param response 响应流
* @param fileName 文件名
*/
public static void setResponseZipData(HttpServletResponse response, String fileName) {
response.setContentType("application/x-msdownload");
URLEncodeUtil.encode(fileName, StandardCharsets.UTF_8);
log.info("导出文件名为: {}", fileName);
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
response.setHeader("content-Type", "application/x-msdownload");
}
/**
* 压缩图片大小
*
* @param pictureUrl 图片url , 或者图片地址
* @param scale 压缩比例 , 0 - 1之间
* @return 压缩后的图像
*/
public static BufferedImage compressedPicture(String pictureUrl, float scale) {
try {
// 获取原始图像
BufferedImage templateImage = ImageIO.read(new URL(pictureUrl));
// 获取原始图像的长度和宽度
int height = templateImage.getHeight();
int width = templateImage.getWidth();
// 压缩之后的长度和宽度
int doHeight = (int) (scale * height);
int doWidth = (int) (scale * width);
BufferedImage finalImage = new BufferedImage(doWidth, doHeight, BufferedImage.TYPE_INT_RGB);
finalImage.getGraphics().drawImage(templateImage.getScaledInstance(doWidth, doHeight, Image.SCALE_SMOOTH), 0, 0, null);
return finalImage;
} catch (Exception e) {
e.printStackTrace();
log.error("压缩图片失败:{}", e.getMessage());
return null;
}
}
/**
* 获取全英文时间戳的文件名
*
* @param suffix 文件后缀
* @return 文件名
*/
public static String getExportFileName(String suffix) {
return "export_" + DateTimeUtils.getDateTimeFormat(DateConstant.DATETIME_FORMAT24_NOT_LINE) + suffix;
}
}
前提要了解easyPoi使用方法,没有了解过可以了解下,也很简单。
ok,到这里ExcelUtil的工具类的全部代码就这些了,下面我们挑一些方法,调用看看,试试效果是什么样子的。
首先来看看,参数最少的通用导出方法:可以看到,只有三个参数,一个是导出类的Class,一个要导出的集合,一个是响应流。
当然,既然是基于easyPoi,那么我下面的演示肯定都是实体类中都加了easyPoi导出对应的注解,下面只是一个示例:
/**
* @author: GM
* @date: 2023/11/1 15:27
* @description: 项目用章申请台账resultVo
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class ProjectStampLedgerResultVo extends PageResultDTO implements Serializable {
private static final long serialVersionUID = 2803170257569474013L;
/**
* 流程编码
*/
@Excel(name = "流程编码", width = 32)
private String processNumber;
/**
* 项目名称
*/
@Excel(name = "项目名称", width = 15)
private String projectName;
/**
* 合同名称
*/
@Excel(name = "合同名称", width = 20)
private String contractName;
/**
* 用章原因
*/
@Excel(name = "用章原因", width = 25)
private String reasonForChapter;
/**
* 用章事项
*/
@Excel(name = "用章事项", width = 15)
private String administrativeMatters;
/**
* 用章份数
*/
@Excel(name = "用章份数", width = 12)
private Integer inChapters;
/**
* 审批结束时间
*/
@Excel(name = "审批结束时间", width = 20, format = DateConstant.DATE_FORMAT)
private Date approvalEndTime;
}
LogConstant是一个日志变量类,一些常用的日志打印字符串:
/**
* 日志常量
* @author: 一位大帅哥
* @date: 2022/11/8 11:54
* @description: TODO
*/
public interface LogConstant {
/**
* 导入开始时间
*/
String IMPORT_START_TIME = "导入startTime: {}";
/**
* 导入结束时间
*/
String IMPORT_END_TIME = "导入endTime: {}";
/**
* 导入失败
*/
String IMPORT_FAIL = "导入失败:{}";
/**
* 获取文件中的记录错误
*/
String GET_FILE_RECORD_FAIL = "获取文件中的记录错误: {}";
/**
* 导出开始时间
*/
String EXPORT_START_TIME = "导出startTime: {}";
/**
* 导出结束时间
*/
String EXPORT_END_TIME = "导出endTime: {}";
/**
* 导出失败
*/
String EXPORT_FAIL = "导出失败: {}";
/**
* 查询失败
*/
String QUERY_FAIL = "查询失败: {}";
/**
* 查询开始时间
*/
String QUERY_START_TIME = "查询开始时间 : {}";
/**
* 查询结束时间
*/
String QUERY_END_TIME = "查询结束时间 : {}";
/**
* 接口调用
*/
String CALL_INTERFACE = "接口调用 : {} ";
/**
* 保存失败
*/
String SAVE_FAIL = "保存失败 : {}";
/**
* 获取下一步流程节点用户信息失败
*/
String GET_NEXT_ACTIVITIES_FAIL = "获取下一步流程节点用户信息失败 :{}";
/**
* 下载文件失败
*/
String DOWNLOAD_FILE_FAIL = "下载文件失败:{}";
/**
* 下载文件成功
*/
String DOWNLOAD_FILE_SUS = "下载文件成功:{}";
/**
* 请求处理时间
*/
String REQUEST_PROCESSING_TIME = "请求处理时间: {}";
}
/**
* 通用导出方法
* 带序号, 默认ExcelExportMyStyler格式
*
* @param exportClass 要导出的类
* @param exportList 要导出类集合
* @param response 响应流
*/
public static void exportExcelGeneral(Class exportClass,
Collection exportList,
HttpServletResponse response) {
ServletOutputStream outputStream = null;
try {
ExportParams params = new ExportParams();
params.setAddIndex(true);
params.setStyle(ExcelExportMyStyler.class);
outputStream = response.getOutputStream();
FileUtils.setResponseXlsxData(response, FileUtils.getExportFileName(".xlsx"));
CustomExcelExportUtils.exportExcel(params, exportClass, exportList).write(outputStream);
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.info("通用方法导出!");
} catch (Exception e) {
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.error(LogConstant.EXPORT_FAIL, e.getMessage());
} finally {
PoitlIOUtils.closeQuietlyMulti(outputStream);
}
}
// PoitlIOUtils.closeQuietlyMulti(outputStream);该方法是Poi-tl依赖的类方法,就是简单地判断该流是否为空,如果不为空则关闭。可用下面的方法实现同样的效果
/*
if (outputStream != null) {
outputStream.close();
}
*/
导出的文件截图:
可以看到,导出的东西很简单, 即没有标题行,也没有自定义的sheet名称。不过调用方法极其简单,提供数据和调用一下方法即可。
下面看一下重载的方法,多了写参数:sheetName,titleName。
/**
* 通用导出方法
* 带序号, 默认ExcelExportMyStyler格式
*
* @param exportClass 要导出的类
* @param exportList 要导出类集合
* @param sheetName 导出工作表名
* @param titleName 标题名称
* @param response 响应流
*/
public static void exportExcelGeneral(Class exportClass,
Collection exportList,
String sheetName,
String titleName,
HttpServletResponse response) {
ServletOutputStream outputStream = null;
try {
ExportParams params = new ExportParams();
params.setAddIndex(true);
params.setStyle(ExcelExportMyStyler.class);
params.setSheetName(sheetName);
params.setTitle(titleName);
outputStream = response.getOutputStream();
FileUtils.setResponseXlsxData(response, FileUtils.getExportFileName(".xlsx"));
CustomExcelExportUtils.exportExcel(params, exportClass, exportList).write(outputStream);
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.info("通用方法导出!");
} catch (Exception e) {
e.printStackTrace();
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.error(LogConstant.EXPORT_FAIL, e.getMessage());
} finally {
PoitlIOUtils.closeQuietlyMulti(outputStream);
}
}
多加了参数,看看导出的效果:
相信有时候大家也会遇到导入导出excel时的字典码转换问题,用户导出了之后,你可以自己把字典值翻译到文档上面,但是文档到了用户手里,他就不会那么规矩的按常理出牌了,往往是自己乱填,导入的结果和字典值对不上,就会导致空值,这时候用户还要反映bug,你说这找谁说理去。
所以下面这个方法就是来对某个为字典值的列来的,给他锁住这一列,让他选择,只能选择数据,而不是手填数据,这就能完美避免用户手填数据不标准和字典值对不上的情况,话不多说,看代码:
/**
* 通用导出方法
* 带序号, 默认ExcelExportMyStyler格式
* 支持校验某一列数据
*
* @param exportClass 要导出的类
* @param exportList 要导出类集合
* @param checkColumnData 校验列选择框提示内容
* @param col 第几列校验
* @param response 响应流
*/
public static void exportExcelGeneral(Class exportClass,
Collection exportList,
String[] checkColumnData,
int col,
HttpServletResponse response) {
ServletOutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
ExportParams params = new ExportParams();
params.setAddIndex(true);
params.setStyle(ExcelExportMyStyler.class);
FileUtils.setResponseXlsxData(response, FileUtils.getExportFileName(".xlsx"));
Workbook workbook = CustomExcelExportUtils.exportExcel(params, exportClass, exportList);
createXssfOfSelected(workbook, checkColumnData, col);
workbook.write(outputStream);
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.info("通用方法导出!");
} catch (Exception e) {
e.printStackTrace();
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.error(LogConstant.EXPORT_FAIL, e.getMessage());
} finally {
PoitlIOUtils.closeQuietlyMulti(outputStream);
}
}
创建选择列的方法:
/**
* XSSF
* excel添加下拉数据校验
*
* @param workbook 哪个 sheet 页添加校验
* @param dataSource 数据源数组
* @param col 第几列校验(0开始)
*/
public static void createXssfOfSelected(Workbook workbook, String[] dataSource, int col) {
Sheet sheet = workbook.getSheetAt(0);
CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(1, 65535, col, col);
DataValidationHelper helper = sheet.getDataValidationHelper();
DataValidationConstraint constraint = helper.createExplicitListConstraint(dataSource);
DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList);
//处理Excel兼容性问题
if (dataValidation instanceof XSSFDataValidation) {
dataValidation.setSuppressDropDownArrow(true);
dataValidation.setShowErrorBox(true);
} else {
dataValidation.setSuppressDropDownArrow(false);
}
dataValidation.setEmptyCellAllowed(true);
dataValidation.setShowPromptBox(true);
dataValidation.createPromptBox("提示", "只能选择下拉框里面的数据!");
sheet.addValidationData(dataValidation);
}
OK,这种情况主要用来做导入模板用,只有表头,数据用户自己手填,然后填完导入到页面中。
看看效果:
设置了某一列只可选择数据的效果:
选择框内容为数组数据,这个自行获取,我是查询数据库字典表获取的对应编码值。
只能选择,不能手填,是不是很好用,妈妈再也不用担心我手填的数据不标准了。哈哈哈
下面就也是个重载的方法,和上面的区别就是加了表头和sheet名称,就不演示了:
/**
* 通用导出方法
* 带序号, 默认ExcelExportMyStyler格式
* 支持校验某一列数据
*
* @param exportClass 要导出的类
* @param exportList 要导出类集合
* @param checkColumnData 校验列选择框提示内容
* @param col 第几列校验
* @param sheetName 导出文件的工作表名称
* @param response 响应流
*/
public static void exportExcelGeneral(Class exportClass,
Collection exportList,
String[] checkColumnData,
int col,
String sheetName,
HttpServletResponse response) {
ServletOutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
ExportParams params = new ExportParams();
params.setAddIndex(true);
params.setStyle(ExcelExportMyStyler.class);
params.setSheetName(sheetName);
FileUtils.setResponseXlsxData(response, FileUtils.getExportFileName(".xlsx"));
Workbook workbook = CustomExcelExportUtils.exportExcel(params, exportClass, exportList);
createXssfOfSelected(workbook, checkColumnData, col);
workbook.write(outputStream);
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.info("通用导出方法!");
} catch (Exception e) {
e.printStackTrace();
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.error(LogConstant.EXPORT_FAIL, e.getMessage());
} finally {
PoitlIOUtils.closeQuietlyMulti(outputStream);
}
}
下面就是这个锁定数据列方法的延伸了,一个文档可以同时锁定多个列,每个锁定列也可以保持独立的选择框内容。
ok,看看方法:
/**
* 通用导出方法
* 带序号, 默认ExcelExportMyStyler格式
* 支持校验多列数据
* for example
* {
* 如果需要导出的数据校验第三列和第八列
* 则:
* checkColumnData: {
* 3,["提示数据1","提示数据2","提示数据3",...],
* 8,["提示数据1","提示数据2","提示数据3",...]
* }
* col: [3,8]
* }
*
* @param exportClass 要导出的类
* @param exportList 要导出类集合
* @param checkColumnData 校验列选择框提示内容 , 可多个
* @param col 需要校验的列 , 可多个
* @param response 响应流
*/
public static void exportExcelGeneral(Class exportClass,
Collection exportList,
Map<Integer, String[]> checkColumnData,
Integer[] col,
HttpServletResponse response) {
ServletOutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
ExportParams params = new ExportParams();
params.setAddIndex(true);
params.setStyle(ExcelExportMyStyler.class);
FileUtils.setResponseXlsxData(response, FileUtils.getExportFileName(".xlsx"));
Workbook workbook = CustomExcelExportUtils.exportExcel(params, exportClass, exportList);
for (Integer columnNumber : col) {
createXssfOfSelected(workbook, checkColumnData.get(columnNumber), columnNumber);
}
workbook.write(outputStream);
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.info("通用导出方法!");
} catch (Exception e) {
e.printStackTrace();
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.error(LogConstant.EXPORT_FAIL, e.getMessage());
} finally {
PoitlIOUtils.closeQuietlyMulti(outputStream);
}
}
列数据Map中,key就是要锁定的列号,从0开始,对应的value就是他需要的数据。
看效果:
同时做了两列验证。
下面的一个方法也就是一个重载,多了两个参数,就不展示了,和第一个一样,多了表头和工作表名称自定义。
/**
* 通用导出方法
* 带序号, 默认ExcelExportMyStyler格式
* 支持校验多列数据
* for example
* {
* 如果需要导出的数据校验第三列和第八列
* 则:
* checkColumnData: {
* 3,["提示数据1","提示数据2","提示数据3",...],
* 8,["提示数据1","提示数据2","提示数据3",...]
* }
* col: [3,8]
* }
*
* @param exportClass 要导出的类
* @param exportList 要导出类集合
* @param checkColumnData 校验列选择框提示内容 , 可多个
* @param col 需要校验的列 , 可多个
* @param sheetName 工作表名称
* @param response 响应流
*/
public static void exportExcelGeneral(Class exportClass,
Collection exportList,
Map<Integer, String[]> checkColumnData,
Integer[] col,
String sheetName,
HttpServletResponse response) {
ServletOutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
ExportParams params = new ExportParams();
params.setAddIndex(true);
params.setStyle(ExcelExportMyStyler.class);
params.setSheetName(sheetName);
FileUtils.setResponseXlsxData(response, FileUtils.getExportFileName(".xlsx"));
Workbook workbook = CustomExcelExportUtils.exportExcel(params, exportClass, exportList);
for (Integer columnNumber : col) {
createXssfOfSelected(workbook, checkColumnData.get(columnNumber), columnNumber);
}
workbook.write(outputStream);
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.info("通用导出方法!");
} catch (Exception e) {
e.printStackTrace();
PoitlIOUtils.closeQuietlyMulti(outputStream);
log.error(LogConstant.EXPORT_FAIL, e.getMessage());
} finally {
PoitlIOUtils.closeQuietlyMulti(outputStream);
}
}
下面方法就是针对于数字列的处理了,估计大家也会遇到一些情况,就是说,数字列,用户填了除了数字的其他字段,比如字母,中英文标点之类的,这样的话就会导致导入数据异常,因为数字类型是无法接收,这就很尴尬了。。。其实这种情况来说,我觉得我后端程序员是不粘锅的。嘿嘿。
OK,不多说,来看方法:
/**
* 为excel文件某一列设置数字,小数整数都可以校验
*
* @param workbook 文件
* @param startCol 第几列校验(0开始)
* @param endCol 第几列校验(0开始)
*/
public static void createXssfOfDecimal(Workbook workbook, int startCol, int endCol) {
Sheet sheet = workbook.getSheetAt(0);
CellRangeAddressList cell = new CellRangeAddressList(1, 65535, startCol, endCol);
DataValidationHelper helper = sheet.getDataValidationHelper();
// 创建一个大于等于0的数值约束
DataValidationConstraint constraint = helper.createDecimalConstraint(DataValidationConstraint.OperatorType.GREATER_OR_EQUAL, "0.0", null);
DataValidation validation = helper.createValidation(constraint, cell);
//处理Excel兼容性问题
if (validation instanceof XSSFDataValidation) {
validation.setSuppressDropDownArrow(true);
validation.setShowErrorBox(true);
} else {
validation.setSuppressDropDownArrow(false);
}
// 允许空值
validation.setEmptyCellAllowed(true);
validation.setShowErrorBox(true);
validation.createErrorBox("提示", "该列只能是纯数字或小数!");
sheet.addValidationData(validation);
}
来看看导出效果:
不是数字 ,就提示,然后不许你保存,这样是不是就能避免很多问题发生呢。
下面的就是属于锦上添花了,校验该数字只能是正整数。OK,看看方法:
/**
* 为excel文件某一列设置数字整数校验
*
* @param workbook 文件
* @param startCol 第几列校验(0开始)
* @param endCol 第几列校验(0开始)
*/
public static void createXssfOfInteger(Workbook workbook, int startCol, int endCol) {
Sheet sheet = workbook.getSheetAt(0);
CellRangeAddressList cell = new CellRangeAddressList(1, 65535, startCol, endCol);
DataValidationHelper helper = sheet.getDataValidationHelper();
// 创建一个大于等于0的数值约束
DataValidationConstraint constraint = helper.createIntegerConstraint(DataValidationConstraint.OperatorType.GREATER_OR_EQUAL, "0", null);
DataValidation validation = helper.createValidation(constraint, cell);
//处理Excel兼容性问题
if (validation instanceof XSSFDataValidation) {
validation.setSuppressDropDownArrow(true);
validation.setShowErrorBox(true);
} else {
validation.setSuppressDropDownArrow(false);
}
// 允许空值
validation.setEmptyCellAllowed(true);
validation.setShowErrorBox(true);
validation.createErrorBox("提示", "该列只能是纯数字且不可为小数和负数!");
sheet.addValidationData(validation);
}
这个就没有效果图了,因为还没有用过,有兴趣看到这里的朋友们,可以自己导出试试,我觉得,必是没有毛病的代码,奥力给!
ppressDropDownArrow(false);
}
// 允许空值
validation.setEmptyCellAllowed(true);
validation.setShowErrorBox(true);
validation.createErrorBox(“提示”, “该列只能是纯数字或小数!”);
sheet.addValidationData(validation);
}
来看看导出效果:
[外链图片转存中...(img-WYEW1S4c-1702021273538)]
不是数字 ,就提示,然后不许你保存,这样是不是就能避免很多问题发生呢。
下面的就是属于锦上添花了,校验该数字只能是正整数。OK,看看方法:
```java
/**
* 为excel文件某一列设置数字整数校验
*
* @param workbook 文件
* @param startCol 第几列校验(0开始)
* @param endCol 第几列校验(0开始)
*/
public static void createXssfOfInteger(Workbook workbook, int startCol, int endCol) {
Sheet sheet = workbook.getSheetAt(0);
CellRangeAddressList cell = new CellRangeAddressList(1, 65535, startCol, endCol);
DataValidationHelper helper = sheet.getDataValidationHelper();
// 创建一个大于等于0的数值约束
DataValidationConstraint constraint = helper.createIntegerConstraint(DataValidationConstraint.OperatorType.GREATER_OR_EQUAL, "0", null);
DataValidation validation = helper.createValidation(constraint, cell);
//处理Excel兼容性问题
if (validation instanceof XSSFDataValidation) {
validation.setSuppressDropDownArrow(true);
validation.setShowErrorBox(true);
} else {
validation.setSuppressDropDownArrow(false);
}
// 允许空值
validation.setEmptyCellAllowed(true);
validation.setShowErrorBox(true);
validation.createErrorBox("提示", "该列只能是纯数字且不可为小数和负数!");
sheet.addValidationData(validation);
}
这个就没有效果图了,因为还没有用过,有兴趣看到这里的朋友们,可以自己导出试试,我觉得,必是没有毛病的代码,奥力给!
到这里也就结束了,能看到这里的我相信也是确实对这方面有需要,也想了解的,代码放心食用,没有毛病,如果可以的话,动动大家发财的小手给博主点点赞,也是花了一下午在公司摸鱼写的文档,嘿嘿。三连莫负。