diff --git a/njcn-common/src/main/java/com/njcn/common/pojo/poi/PullDown.java b/njcn-common/src/main/java/com/njcn/common/pojo/poi/PullDown.java new file mode 100644 index 0000000..2f8a9d1 --- /dev/null +++ b/njcn-common/src/main/java/com/njcn/common/pojo/poi/PullDown.java @@ -0,0 +1,26 @@ +package com.njcn.common.pojo.poi; + +import lombok.Data; + +import java.util.List; + +/** + * @author caozehui 设置下拉 + * @description + * @date 2025-01-15 + */ +@Data +public class PullDown { + + //起始列 + private Integer firstCol; + + //结束列 + private Integer lastCol; + + //是否设置单元格(文本) + private Boolean isText = false; + + //属性值 + private List strings; +} \ No newline at end of file diff --git a/njcn-springboot/spingboot2.3.12/src/main/java/com/njcn/web/utils/ExcelUtil.java b/njcn-springboot/spingboot2.3.12/src/main/java/com/njcn/web/utils/ExcelUtil.java index 0ba99bf..2e6c4a6 100644 --- a/njcn-springboot/spingboot2.3.12/src/main/java/com/njcn/web/utils/ExcelUtil.java +++ b/njcn-springboot/spingboot2.3.12/src/main/java/com/njcn/web/utils/ExcelUtil.java @@ -3,11 +3,16 @@ package com.njcn.web.utils; import cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.entity.ExportParams; import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.ObjectUtil; +import com.njcn.common.pojo.poi.PullDown; import lombok.extern.slf4j.Slf4j; import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddressList; +import org.apache.poi.ss.util.CellReference; +import org.apache.poi.xssf.usermodel.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletOutputStream; @@ -18,6 +23,7 @@ import java.net.URLEncoder; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Objects; /** * @author caozehui @@ -87,6 +93,229 @@ public class ExcelUtil { } } + + /** + * 指定名称、数据下载报表(带指定标题将*显示比必填信息),带有下拉信息 + * + * @param fileName 文件名 + */ + public static void exportExcelPullDown(ExportParams exportParams, String fileName, List pullDowns, Class pojoClass, Collection dataSet) { + HttpServletResponse response = HttpServletUtil.getResponse(); + try (ServletOutputStream outputStream = response.getOutputStream()) { + fileName = URLEncoder.encode(fileName, CharsetUtil.UTF_8); + response.reset(); + response.setHeader("Content-Disposition", "attachment;filename=" + fileName); + response.setContentType("application/octet-stream;charset=UTF-8"); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, dataSet); + setTopLevel(workbook, pullDowns); + if (CollUtil.isNotEmpty(pullDowns)) { + int num = 1; + CellStyle cellStyle = workbook.createCellStyle(); + DataFormat format = workbook.createDataFormat(); + cellStyle.setDataFormat(format.getFormat("@")); + for (PullDown pullDown : pullDowns) { + if (pullDown.getIsText()) { + ExcelUtil.selectListText(workbook, pullDown.getFirstCol(),cellStyle); + } else { + String colName = numberToExcelColumn(num); + int sum = pullDown.getStrings().stream().mapToInt(String::length).sum(); + if (sum == 0) { + continue; + } + if (sum > 255) { + ExcelUtil.selectListMaxLength(workbook, pullDown.getFirstCol(), pullDown.getLastCol(), pullDown.getStrings().size(), colName); + num++; + } else { + ExcelUtil.selectList(workbook, pullDown.getFirstCol(), pullDown.getLastCol(), pullDown.getStrings().toArray(new String[]{})); + } + } + + } + } + Sheet sheetAt = workbook.getSheetAt(0); + //获取列数 + int physicalNumberOfCells = sheetAt.getRow(0).getPhysicalNumberOfCells(); + //没有表格标题,只有表格头 + for (int i = 0; i < 1; i++) { + //获取行 + Row row = sheetAt.getRow(i); + if (Objects.isNull(row)) { + continue; + } + for (int j = 0; j < physicalNumberOfCells; j++) { + //获取单元格对象 + Cell cell = row.getCell(j); + //获取单元格样式对象 + CellStyle cellStyle = workbook.createCellStyle(); + //获取单元格内容对象 + Font font = workbook.createFont(); + font.setFontHeightInPoints((short) 12); + //一定要装入 样式中才会生效 + cellStyle.setFont(font); + //设置居中对齐 + cellStyle.setAlignment(HorizontalAlignment.CENTER); + cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); + //设置单元格字体颜色 + cell.setCellStyle(cellStyle); + //获取当前值 + String stringCellValue = cell.getStringCellValue(); + if (stringCellValue.contains("*")) { + // 创建一个富文本 + XSSFRichTextString xssfRichTextString = new XSSFRichTextString(stringCellValue); + int startIndex = stringCellValue.indexOf("*"); + int entIndex = stringCellValue.lastIndexOf("*"); + if (entIndex != 0) { + Font font3 = workbook.createFont(); + font3.setFontHeightInPoints((short) 12); + font3.setColor(Font.COLOR_NORMAL); + xssfRichTextString.applyFont(0, entIndex, font3); + } + //设置带*样式 + Font font1 = workbook.createFont(); + font1.setFontHeightInPoints((short) 12); + font1.setColor(Font.COLOR_RED); + xssfRichTextString.applyFont(startIndex, entIndex + 1, font1); + //其他样式 + Font font2 = workbook.createFont(); + font2.setFontHeightInPoints((short) 12); + font2.setColor(Font.COLOR_NORMAL); + xssfRichTextString.applyFont(entIndex + 1, stringCellValue.length(), font2); + cell.setCellValue(xssfRichTextString); + } + } + } + workbook.write(outputStream); + } catch (IOException e) { + log.error(">>> 导出数据异常:{}", e.getMessage()); + } + } + + /** + * @Description: + * @param workbook + * @param firstCol + * @Author: wr + * @Date: 2024/8/20 10:44 + */ + public static void selectListText(Workbook workbook, int firstCol,CellStyle cellStyle) { + Sheet sheet = workbook.getSheetAt(0); + for (int i = 2; i < 65535; i++) { + Row row = sheet.getRow(i); + if(ObjectUtil.isNull(row)){ + row = sheet.createRow(i); + } + Cell cell = row.createCell(firstCol); + cell.setCellStyle(cellStyle); + } + } + + /** + * 设置隐藏表单来进行下拉框 + * + * @param workbook + * @param pullDowns + */ + private static void setTopLevel(Workbook workbook, List pullDowns) { + int num = 0; + for (PullDown pullDown : pullDowns) { + if (!pullDown.getIsText()) { + int sum = pullDown.getStrings().stream().mapToInt(String::length).sum(); + if (sum == 0) { + continue; + } + if (sum > 255) { + // 创建隐藏sheet + String hiddenSheetName = "hiddenSheetA"; + if (num == 0) { + workbook.createSheet(hiddenSheetName); + } + //false展示隐藏sheet ,true不展示隐藏sheet + workbook.setSheetHidden(workbook.getSheetIndex(workbook.getSheet(hiddenSheetName)), true); + Sheet sheet = workbook.getSheet(hiddenSheetName); + if (num == 0) { + //sheet.getLastRowNum无法区分 有一行和没有 所以这里先建一行 + sheet.createRow(0); + } + Row row; //创建数据行 + sheet.setColumnWidth(num, 4000); //设置每列的列宽 + for (int j = 0; j < pullDown.getStrings().size(); j++) { + if (sheet.getLastRowNum() < j) { + row = sheet.createRow(j); //创建数据行 + } else { + row = sheet.getRow(j); + } + //设置对应单元格的值 + row.createCell(num).setCellValue(pullDown.getStrings().get(j)); + } + num++; + } + } + } + } + + /** + * 获取根据数值获取列字母(1=A,2=B,3=C,.......,27=AA) + * + * @param n + * @return + */ + public static String numberToExcelColumn(int n) { + CellReference cellRef = new CellReference(0, n - 1, false, false); // Row and column are 0-based + int colIndex = cellRef.getCol(); + StringBuilder columnName = new StringBuilder(); + while (colIndex >= 0) { + columnName.insert(0, (char) ('A' + (colIndex % 26))); + colIndex /= 26; + colIndex--; + } + return columnName.toString(); + } + + /** + * @param workbook + * @param firstCol + * @param lastCol + * @param colName 列A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z + * @Description: 当下拉框超过最大字符255,设置隐藏表单来进行展示 + * @Author: wr + * @Date: 2024/8/13 15:07 + */ + public static void selectListMaxLength(Workbook workbook, int firstCol, int lastCol, int row, String colName) { + Sheet sheet = workbook.getSheetAt(0); + // 生成下拉列表 + // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列 + CellRangeAddressList regions = new CellRangeAddressList(2, 65535, firstCol, lastCol); + String strFormula = workbook.getSheetName(1) + "!$" + colName + "$1:$" + colName + "$" + row; + XSSFDataValidationConstraint hiddentConstraint = new XSSFDataValidationConstraint(DataValidationConstraint.ValidationType.LIST, strFormula); + // 数据有效性对象 + DataValidationHelper help = new XSSFDataValidationHelper((XSSFSheet) sheet); + DataValidation validation = help.createValidation(hiddentConstraint, regions); + sheet.addValidationData(validation); + } + + /** + * firstRow 開始行號 根据此项目,默认为2(下标0开始) + * lastRow 根据此项目,默认为最大65535 + * + * @param firstCol 区域中第一个单元格的列号 (下标0开始) + * @param lastCol 区域中最后一个单元格的列号 + * @param strings 下拉内容 + */ + public static void selectList(Workbook workbook, int firstCol, int lastCol, String[] strings) { + Sheet sheet = workbook.getSheetAt(0); + // 生成下拉列表 + // 只对(x,x)单元格有效 + CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(1, 65535, firstCol, lastCol); + // 生成下拉框内容 + DataValidationHelper dvHelper = sheet.getDataValidationHelper(); + XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint) + dvHelper.createExplicitListConstraint(strings); + XSSFDataValidation validation = (XSSFDataValidation) dvHelper.createValidation( + dvConstraint, cellRangeAddressList); + // 对sheet页生效 + sheet.addValidationData(validation); + } + /** * 获取workbook对象 * diff --git a/njcn-springboot/spingboot2.3.12/src/main/java/com/njcn/web/utils/FileUtil.java b/njcn-springboot/spingboot2.3.12/src/main/java/com/njcn/web/utils/FileUtil.java new file mode 100644 index 0000000..78182ba --- /dev/null +++ b/njcn-springboot/spingboot2.3.12/src/main/java/com/njcn/web/utils/FileUtil.java @@ -0,0 +1,171 @@ +package com.njcn.web.utils; + +import cn.hutool.core.text.StrPool; +import cn.hutool.core.util.StrUtil; +import org.springframework.web.multipart.MultipartFile; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.UUID; + +/** + * @author hongawen + * @version 1.0.0 + * @date 2023年04月19日 16:02 + */ +public class FileUtil { + + /*** + * 随机生成文件名 + * @author hongawen + * @date 2023/4/19 16:02 + * @param originalFileName 原文件名 + * @return String + */ + public static String generateFileName(String originalFileName) { + String suffix; + if (originalFileName.contains(StrPool.DOT)) { + suffix = originalFileName.substring(originalFileName.lastIndexOf(StrPool.DOT)); + } else { + suffix = StrPool.DOT + originalFileName; + } + return UUID.randomUUID().toString().replace("-", "").toUpperCase() + suffix; + } + + /** + * MultipartFile 转 String + * + * @param multipartFile 原字符串 + * @return 成功标记 + */ + public static String multipartFileToString(MultipartFile multipartFile) { + StringBuilder txtResult = new StringBuilder(); + try ( + InputStreamReader isr = new InputStreamReader(multipartFile.getInputStream(), StandardCharsets.UTF_8); + BufferedReader br = new BufferedReader(isr) + ) { + String lineTxt; + while ((lineTxt = br.readLine()) != null) { + txtResult.append(lineTxt); + } + return txtResult.toString(); + } catch (IOException e) { + e.printStackTrace(); + return ""; + } + } + + /** + * 判断文件是否为word格式 + * + * @param fileName 文件名 + */ + public static boolean judgeFileIsWord(String fileName) { + // 检查文件名是否为空 + if (StrUtil.isBlank(fileName)) { + return false; + } + // 获取文件扩展名 + String fileExtension = getFileExtension(fileName); + // 定义支持的文件类型 + String[] allowedExtensions = {"doc", "docx"}; + + // 检查扩展名是否在允许的列表中 + for (String ext : allowedExtensions) { + if (ext.equalsIgnoreCase(fileExtension)) { + return true; + } + } + return false; + } + + /** + * 判断文件是否为pdf格式 + * + * @param fileName 文件名 + */ + public static boolean judgeFileIsPdf(String fileName) { + // 检查文件名是否为空 + if (StrUtil.isBlank(fileName)) { + return false; + } + // 获取文件扩展名 + String fileExtension = getFileExtension(fileName); + // 定义支持的文件类型 + String[] allowedExtensions = {"pdf"}; + + // 检查扩展名是否在允许的列表中 + for (String ext : allowedExtensions) { + if (ext.equalsIgnoreCase(fileExtension)) { + return true; + } + } + return false; + } + + /** + * 判断文件是否为excel格式 + * + * @param fileName 文件名 + */ + public static boolean judgeFileIsExcel(String fileName) { + // 检查文件名是否为空 + if (StrUtil.isBlank(fileName)) { + return false; + } + // 获取文件扩展名 + String fileExtension = getFileExtension(fileName); + // 定义支持的文件类型 + String[] allowedExtensions = {"xls", "xlsx"}; + + // 检查扩展名是否在允许的列表中 + for (String ext : allowedExtensions) { + if (ext.equalsIgnoreCase(fileExtension)) { + return true; + } + } + return false; + } + + /** + * 判断文件是否为excel格式 + * + * @param fileName 文件名 + */ + public static boolean judgeFileIsZip(String fileName) { + // 检查文件名是否为空 + if (StrUtil.isBlank(fileName)) { + return false; + } + // 获取文件扩展名 + String fileExtension = getFileExtension(fileName); + // 定义支持的文件类型 + String[] allowedExtensions = {"zip", "rar"}; + + // 检查扩展名是否在允许的列表中 + for (String ext : allowedExtensions) { + if (ext.equalsIgnoreCase(fileExtension)) { + return true; + } + } + return false; + } + + + /** + * 从文件名中提取扩展名 + * + * @param fileName 文件名 + * @return 扩展名 + */ + private static String getFileExtension(String fileName) { + int dotIndex = fileName.lastIndexOf('.'); + if (dotIndex == -1) { + return ""; + } + return fileName.substring(dotIndex + 1); + } + +}