最近需求是要根据检索的数据信息给excel模板表中插入对应的数据,数据可能有多条,如果超过两条的话那么需要新增行,对本人而言难点在于,很多单元格有函数公式在里面,以及下拉列表要附带到新增行中,例图如下:
经过很多次思考与痛苦,懂的都懂,excel的操作真的是头痛,初始使用的是easyexcel达到了以上需求,样例代码如下:当然要填写的位置需要加上模板{item.id}等等
/**
* 给ATS车站数据验证单模板写数据 --- > F:\workspace\卡斯柯项目\casco_project\文档\审核文档
* 附带实现下拉框功能
*/
@Test
public void Test010() {
List
总算以为事情可以告一段落,但是客户总是不让你如意,又说模板文件的列可能会变化,那么意味着下拉列表的复制需要支持列的动态变化,以上代码就不支持这个需求,于是经过痛苦的探索通过poi写出了如下模板,也是结合了网上的插入行模板做了升级修改,如作者看到!!本人只是借鉴以及分享,没有其他用意,
那么代码如下
package cn.com.casco.ats.utils;
import cn.hutool.poi.excel.ExcelWriter;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.CellCopyPolicy;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import java.util.List;
@Slf4j
public class ExcelCopyUtils {
// public static void main(String[] args) {
// ExcelWriter writer = ExcelUtil.getWriter(new File("F:\\workspace\\卡斯柯项目\\casco_project\\文档\\审核文档\\UEVOL-CASCO-7206-ATS车站数据验证单模板.xlsx"),"1-3 进路显示及控制");
// // startRow=5 行标为5的行后插入2行,样式拷贝第5行的样式
// int startRow= 5;
// int rows = 2;
// XSSFSheet sheet = (XSSFSheet)writer.getSheet();
//
// InsertRow(writer, startRow, rows, sheet,false,1);
// }
/**
*
* @param writer ExcelWriter
* @param startRow 插入行的行标,即在哪一行下插入
* @param rows 插入多少行
* @param sheet XSSFSheet
* @param copyvalue 新行复制(startRow-1)行的样式,而且在拷贝行的时候可以指定是否需要拷贝值
*/
public static void insertRow(ExcelWriter writer, int startRow, int rows, XSSFSheet sheet, Boolean copyvalue, int wirteIndex) {
if(sheet.getRow(startRow+1)==null){
// 如果复制最后一行,首先需要创建最后一行的下一行,否则无法插入,Bug 2023/03/20修复
sheet.createRow(startRow+1);
}
XSSFRow startRows = sheet.getRow(startRow);
XSSFCell cell = startRows.getCell(startRows.getLastCellNum() - 2);
System.out.println("cell---->" + cell);
XSSFCellStyle cellStyle = cell.getCellStyle();
//先获取原始的合并单元格address集合
List originMerged = sheet.getMergedRegions();
Row sourceRow = sheet.getRow(startRow - 1);
for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
log.info("复制样式下拉表--->第{}行", i);
//如果原有单元格的数据有效性为下拉框,则将新单元格也设置为下拉框,并进行动态更新
for (DataValidation sourceDataValidation : sheet.getDataValidations()) {
if (sourceDataValidation != null) {
if (i>wirteIndex) {
log.info("i等于----------->{}", i);
DataValidationHelper dataValidationHelper = sheet.getDataValidationHelper();
CellRangeAddressList addressList = new CellRangeAddressList(startRow, startRow + rows -1, i, i);
DataValidation dataValidation = dataValidationHelper.createValidation(sourceDataValidation.getValidationConstraint(), addressList);
sheet.addValidationData(dataValidation);
}
}
}
}
for (int i = sheet.getNumMergedRegions() - 1; i >= 0; i--) {
CellRangeAddress region = sheet.getMergedRegion(i);
//判断移动的行数后重新拆分
if(region.getFirstRow()>startRow){
sheet.removeMergedRegion(i);
}
}
sheet.shiftRows(startRow,sheet.getLastRowNum(),rows,true,false);
XSSFRow row = sheet.createRow(startRow);
for(CellRangeAddress cellRangeAddress : originMerged) {
//这里的8是插入行的index,表示这行之后才重新合并
if(cellRangeAddress.getFirstRow() > startRow) {
//你插入了几行就加几,我这里插入了一行,加1
int firstRow = cellRangeAddress.getFirstRow() + rows;
CellRangeAddress newCellRangeAddress = new CellRangeAddress(firstRow, (firstRow + (cellRangeAddress
.getLastRow() - cellRangeAddress.getFirstRow())), cellRangeAddress.getFirstColumn(),
cellRangeAddress.getLastColumn());
sheet.addMergedRegion(newCellRangeAddress);
}
}
writer.flush();
CellCopyPolicy cellCopyPolicy = new CellCopyPolicy();
cellCopyPolicy.setCopyCellValue(copyvalue);
cellCopyPolicy.isCopyCellValue();
for (int i = 0; i < rows; i++) {
sheet.copyRows(startRow-1,startRow-1,startRow+i,cellCopyPolicy);
}
writer.close();
}
/**
* @param startRow 插入行的行标,即在哪一行下插入
* @param rows 插入多少行
* @param sheet XSSFSheet
* @param copyvalue 新行复制(startRow-1)行的样式,而且在拷贝行的时候可以指定是否需要拷贝值
* @param wirteIndex 要填写的最后一个index
*/
public static void insertRow(int startRow, int rows, XSSFSheet sheet,Boolean copyvalue,int wirteIndex) {
if(sheet.getRow(startRow+1)==null){
// 如果复制最后一行,首先需要创建最后一行的下一行,否则无法插入,Bug 2023/03/20修复
sheet.createRow(startRow+1);
}
XSSFRow startRows = sheet.getRow(startRow);
XSSFCell cell = startRows.getCell(startRows.getLastCellNum() - 2);
XSSFCellStyle cellStyle = cell.getCellStyle();
//先获取原始的合并单元格address集合
List originMerged = sheet.getMergedRegions();
for (int i = sheet.getNumMergedRegions() - 1; i >= 0; i--) {
CellRangeAddress region = sheet.getMergedRegion(i);
//判断移动的行数后重新拆分
if(region.getFirstRow()>startRow){
sheet.removeMergedRegion(i);
}
}
sheet.shiftRows(startRow,sheet.getLastRowNum(),rows,true,false);
XSSFRow row = sheet.createRow(startRow);
Row sourceRow = sheet.getRow(startRow - 1);
for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
log.info("复制样式下拉表--->第{}行", i);
//如果原有单元格的数据有效性为下拉框,则将新单元格也设置为下拉框,并进行动态更新
for (DataValidation sourceDataValidation : sheet.getDataValidations()) {
if (sourceDataValidation != null) {
if (i > wirteIndex) {
log.info("i等于----------->{}", i);
DataValidationHelper dataValidationHelper = sheet.getDataValidationHelper();
CellRangeAddressList addressList = new CellRangeAddressList(startRow, startRow + rows, i, i);
DataValidation dataValidation = dataValidationHelper.createValidation(sourceDataValidation.getValidationConstraint(), addressList);
sheet.addValidationData(dataValidation);
break;
}
}
}
}
for(CellRangeAddress cellRangeAddress : originMerged) {
//这里的8是插入行的index,表示这行之后才重新合并
if(cellRangeAddress.getFirstRow() > startRow) {
//你插入了几行就加几,我这里插入了一行,加1
int firstRow = cellRangeAddress.getFirstRow() + rows;
CellRangeAddress newCellRangeAddress = new CellRangeAddress(firstRow, (firstRow + (cellRangeAddress
.getLastRow() - cellRangeAddress.getFirstRow())), cellRangeAddress.getFirstColumn(),
cellRangeAddress.getLastColumn());
sheet.addMergedRegion(newCellRangeAddress);
}
}
CellCopyPolicy cellCopyPolicy = new CellCopyPolicy();
cellCopyPolicy.setCopyCellValue(copyvalue);
cellCopyPolicy.isCopyCellValue();
for (int i = 0; i < rows; i++) {
sheet.copyRows(startRow-1,startRow-1,startRow+i,cellCopyPolicy);
}
}
}
开箱即用,如有问题欢迎来探讨,因为这个问题百度了很久没有发现有相应文章,才想发布一份给遇到困难的人提供一份帮助,
如果对你有帮助!请为我点个赞谢谢啦