| | |
| | | import com.ruoyi.common.utils.reflect.ReflectUtils; |
| | | import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream; |
| | | import org.apache.poi.ss.usermodel.*; |
| | | import org.apache.poi.ss.usermodel.Workbook; |
| | | import org.apache.poi.ss.util.CellRangeAddress; |
| | | import org.apache.poi.ss.util.CellRangeAddressList; |
| | | import org.apache.poi.hssf.usermodel.HSSFClientAnchor; |
| | |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import javax.imageio.ImageIO; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.awt.image.BufferedImage; |
| | | import java.io.ByteArrayInputStream; |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.io.IOException; |
| | |
| | | this.init(list, sheetName, Excel.Type.EXPORT); |
| | | exportExcel(response.getOutputStream()); |
| | | } |
| | | private static double calculateScaleForCm(byte[] imageData, double widthCm, double heightCm) throws IOException { |
| | | // 读取图片获取原始尺寸 |
| | | BufferedImage img = ImageIO.read(new ByteArrayInputStream(imageData)); |
| | | double originalWidthPx = img.getWidth(); |
| | | double originalHeightPx = img.getHeight(); |
| | | |
| | | // Excel默认DPI(96) |
| | | double excelDpi = 96.0; |
| | | double pixelsPerCm = excelDpi / 2.54; |
| | | |
| | | // 目标像素尺寸 |
| | | double targetWidthPx = widthCm * pixelsPerCm; |
| | | double targetHeightPx = heightCm * pixelsPerCm; |
| | | |
| | | // 计算比例(取宽高中的较小比例,保持纵横比) |
| | | double scaleWidth = targetWidthPx / originalWidthPx; |
| | | double scaleHeight = targetHeightPx / originalHeightPx; |
| | | System.out.println("-=========67676"); |
| | | System.out.println(originalHeightPx); |
| | | System.out.println(originalWidthPx); |
| | | System.out.println(targetWidthPx); |
| | | System.out.println(targetHeightPx); |
| | | return Math.min(scaleWidth, scaleHeight); |
| | | } |
| | | /** |
| | | * 对list数据源将其里面的数据导入到excel表单 |
| | | * |
| | |
| | | if(index==1) |
| | | { |
| | | Row row = sheet.createRow(0); |
| | | row.setHeightInPoints(20); // 设置行高为20磅 |
| | | // row.setHeightInPoints(20); // 设置行高为20磅 |
| | | row.setHeight((short) (12.75*20)); |
| | | int column = 0; |
| | | row = sheet.createRow(0); |
| | | row = sheet.createRow(1); |
| | | row.setHeight((short) (12.75*20)); |
| | | sheet.addMergedRegion(new CellRangeAddress(2, 3, 0, 1)); |
| | | row = sheet.createRow(2); |
| | | row.setHeightInPoints(100); // 设置行高为20磅 |
| | | row.setHeight((short) (77.5*20)); |
| | | row = sheet.createRow(3); |
| | | row.setHeight((short) (35*20)); |
| | | // row.setHeightInPoints(100); // 设置行高为20磅 |
| | | |
| | | |
| | | // 页面布局设置 |
| | | sheet.setAutobreaks(true); |
| | | sheet.setFitToPage(true); |
| | | |
| | | // 获取打印设置 |
| | | PrintSetup printSetup = sheet.getPrintSetup(); |
| | | |
| | | // 设置为1页宽度 |
| | | printSetup.setFitWidth((short) 1); // 宽度调整为1页 |
| | | printSetup.setFitHeight((short) 0); // 高度不限制 |
| | | |
| | | // 其他打印设置 |
| | | printSetup.setPaperSize(PrintSetup.A4_PAPERSIZE); // A4纸 |
| | | printSetup.setLandscape(false); // 纵向打印 |
| | | sheet.setMargin(Sheet.LeftMargin, 1.04); |
| | | sheet.setMargin(Sheet.RightMargin, 1.04); |
| | | sheet.setMargin(Sheet.TopMargin, 0.97); |
| | | sheet.setMargin(Sheet.BottomMargin, 0.97); |
| | | //拿到图片 |
| | | // 创建单元格并添加图片 |
| | | Cell cell = row.createCell(0); |
| | |
| | | // 创建单元格 |
| | | Cell qrCell = sheet.createRow(2).createCell(1); |
| | | // 设置行高足够高以显示二维码 |
| | | sheet.getRow(2).setHeightInPoints(100); |
| | | sheet.getRow(2).setHeight((short) (77.5*20)); |
| | | // sheet.getRow(3).setHeight((short) (35*20)); |
| | | // sheet.getRow(2).setHeightInPoints(100); |
| | | // 二维码需要较大的列宽来显示,设置之前先保存当前列宽 |
| | | int currentColumnWidth = sheet.getColumnWidth(1); |
| | | // 设置足够宽的列宽以显示二维码 |
| | |
| | | // 创建图片锚点,设置在第2行第2列 |
| | | // 二维码显示在右上角且不填满整个格子 |
| | | // 缩小图片范围:只占用部分单元格空间 |
| | | ClientAnchor anchor = new HSSFClientAnchor(600, 20, 1000, 200, (short) 1, 2, (short) 1, 2); |
| | | |
| | | ClientAnchor anchor = new HSSFClientAnchor(699, 0, 1023, 97, (short) 1, 2, (short) 1, 3); |
| | | // 设置图片位置和大小 |
| | | anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_DONT_RESIZE); |
| | | |
| | | // 添加图片到工作表 |
| | | getDrawingPatriarch(sheet).createPicture(anchor, |
| | | org.apache.poi.ss.usermodel.Picture picture = getDrawingPatriarch(sheet).createPicture(anchor, |
| | | wb.addPicture(data, getImageType(data))); |
| | | |
| | | |
| | | int pictureIdx = wb.addPicture(data, getImageType(data)); |
| | | // Picture picture = drawing.createPicture(anchor, pictureIdx); |
| | | |
| | | // 关键:计算并应用3.15cm的缩放 |
| | | // double targetSizeCm = 3.15; |
| | | // |
| | | //// 方法1:使用精确计算 |
| | | // double scale = calculateScaleForCm(data, targetSizeCm, targetSizeCm); |
| | | // System.out.println(scale); |
| | | // picture.resize(scale); |
| | | |
| | | // 二维码添加完成后,恢复原来的列宽设置 |
| | | sheet.setColumnWidth(1, currentColumnWidth); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | // 以"档案馆 (室) 号:"为基准,统一所有标题的长度和格式 |
| | | String [] tits = { |
| | | "档 号:", |
| | | "档案馆 (室) 号:", |
| | | "缩 微 号:", |
| | | "发 文 号:", |
| | | "档 号:", |
| | | "档案馆 (室) 号:", |
| | | "缩 微 号:", |
| | | "发 文 号:", |
| | | "案 卷 题 名:", |
| | | "编 制 日 期:", |
| | | "编 制 单 位:", |
| | |
| | | System.out.println(declaredFields.length); |
| | | int i = 0; |
| | | for (Field field : declaredFields) { |
| | | if(i==9) |
| | | break; |
| | | // 设置字段的访问权限,以便于访问私有字段 |
| | | field.setAccessible(true); |
| | | |
| | |
| | | Object fieldValue = field1.get(obj); |
| | | if(fieldValue==null) |
| | | fieldValue=""; |
| | | |
| | | if(i <= 3) |
| | | row = sheet.createRow(i+4); |
| | | if(i > 3) |
| | | row = sheet.createRow(i+7); |
| | | if(i != 4) |
| | | row.setHeight((short) (35*20)); |
| | | // row.setHeight((short) 30); |
| | | // 不设置固定行高,后续使用autoSizeRow自动调整 |
| | | cell = row.createCell(0); |
| | |
| | | // 第一列宽度设置为27 |
| | | // 第二列宽度设置为51 |
| | | // 使用与addCell方法相同的计算公式设置列宽 |
| | | sheet.setColumnWidth(0, (int) ((29 + 0.72) * 256)); // 第一列:宽度27 |
| | | sheet.setColumnWidth(1, (int) ((52 + 0.72) * 256)); // 第二列:宽度51 |
| | | sheet.setColumnWidth(0, (int) ((27.86 + 0.72) * 256)); // 第一列:宽度27 |
| | | sheet.setColumnWidth(1, (int) ((51.57 + 0.72) * 256)); // 第二列:宽度51 |
| | | |
| | | CellStyle style = wb.createCellStyle(); |
| | | style.setAlignment(HorizontalAlignment.RIGHT); |
| | | style.setAlignment(HorizontalAlignment.LEFT); |
| | | style.setVerticalAlignment(VerticalAlignment.BOTTOM); // 设置垂直下对齐 |
| | | style.setWrapText(true); // 设置自动换行 |
| | | |
| | |
| | | font.setFontHeightInPoints((short) 18); |
| | | style.setFont(font); |
| | | style.setWrapText(true); // 设置自动换行 |
| | | |
| | | if(i==4) |
| | | { |
| | | style.setVerticalAlignment(VerticalAlignment.TOP); // 设置垂直下对齐 |
| | | |
| | | } |
| | | cell.setCellStyle(style); |
| | | cell.setCellValue(tits[i]); |
| | | |
| | | |
| | | Cell cel = row.createCell(1); |
| | | CellStyle style1 = wb.createCellStyle(); |
| | | style1.setBorderBottom(BorderStyle.THIN); // 添加下划线 |
| | | if(i!=4) |
| | | style1.setBorderBottom(BorderStyle.THIN); // 添加下划线 |
| | | style1.setWrapText(true); // 设置自动换行 |
| | | style1.setVerticalAlignment(VerticalAlignment.BOTTOM); // 设置垂直下对齐 |
| | | |
| | |
| | | { |
| | | // 确保案 卷 题 名:这一行能根据内容长度自动换行 |
| | | style1.setWrapText(true); // 明确设置自动换行 |
| | | style1.setVerticalAlignment(VerticalAlignment.TOP); // 设置垂直下对齐 |
| | | |
| | | cel.setCellStyle(style1); |
| | | row.setHeight((short) (110*20)); |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | | |
| | | // 处理日期格式化,特别是"编 制 日 期:"这一行 |
| | | if (i == 5 && fieldValue instanceof Date) { |
| | | // 设置日期格式为yyyy-MM-dd |
| | |
| | | } |
| | | |
| | | // 对于i==4的情况,确保行高能根据内容自动调整 |
| | | if(i==4) |
| | | { |
| | | // 设置行高为自动调整(-1表示自动高度) |
| | | row.setHeight((short) -1); |
| | | // 不限制最大行高,允许根据内容自动调整 |
| | | } else { |
| | | // 使用setHeight方法设置行高为自动调整(-1表示自动高度) |
| | | row.setHeight((short) -1); |
| | | // 确保行高至少为40磅,但不限制最大行高 |
| | | if (row.getHeightInPoints() < 40) { |
| | | row.setHeightInPoints(40); |
| | | } |
| | | } |
| | | // if(i==4) |
| | | // { |
| | | // // 设置行高为自动调整(-1表示自动高度) |
| | | // // row.setHeight((short) -1); |
| | | // // 不限制最大行高,允许根据内容自动调整 |
| | | // } else if (i > 4) { // 只对i>1的行应用这些设置,保留i<=1的行高设置 |
| | | // // 使用setHeight方法设置行高为自动调整(-1表示自动高度) |
| | | // row.setHeight((short) -1); |
| | | // // 确保行高至少为40磅,但不限制最大行高 |
| | | // if (row.getHeightInPoints() < 40) { |
| | | // row.setHeightInPoints(40); |
| | | // } |
| | | // } |
| | | // sheet.setColumnWidth(0, 60 * 256); |
| | | i++; |
| | | if(i==3) |
| | | { |
| | | row = sheet.createRow(8); |
| | | row.setHeight((short) (35*20)); |
| | | // 设置行高为自动调整 |
| | | row.setHeight((short) -1); |
| | | // row.setHeight((short) -1); |
| | | // row.setHeight((short) 30); |
| | | row.setHeightInPoints(20); // 设置行高为20磅 |
| | | // row.setHeightInPoints(20); // 设置行高为20磅 |
| | | row = sheet.createRow(9); |
| | | row.setHeight((short) (50*20)); |
| | | |
| | | //设置条形码 |
| | | // 设置条形码 |
| | | byte[] dat = list.get(index).getImgr(); |
| | |
| | | // 创建单元格 |
| | | Cell barcodeCell = sheet.createRow(9).createCell(0); |
| | | // 设置行高足够高以显示条形码 |
| | | sheet.getRow(9).setHeightInPoints(40); |
| | | // sheet.getRow(9).setHeightInPoints(40); |
| | | sheet.getRow(9).setHeight((short) (50*20)); |
| | | // 设置列宽足够宽以显示条形码,先保存当前列宽 |
| | | int currentColumnWidth0 = sheet.getColumnWidth(0); |
| | | sheet.setColumnWidth(0, 40 * 256); |
| | |
| | | // 条形码居中且不超出第二个格子 |
| | | // 调整结束列索引和位置参数 |
| | | // 增加dx1值,使条形码整体向右移动 |
| | | ClientAnchor anchor1 = new HSSFClientAnchor(660, 50, 900, 200, (short) 0, 9, (short) 1, 10); |
| | | ClientAnchor anchor1 = new HSSFClientAnchor(537, 0, 788, 245, (short) 0, 9, (short) 1, 9); |
| | | // 设置图片位置和大小 |
| | | anchor1.setAnchorType(ClientAnchor.AnchorType.MOVE_DONT_RESIZE); |
| | | |
| | |
| | | |
| | | |
| | | |
| | | row.setHeightInPoints(70); // 设置行高为20磅 |
| | | //row.setHeightInPoints(70); // 设置行高为20磅 |
| | | row = sheet.createRow(10); |
| | | row.setHeightInPoints(40); // 设置行高为20磅 |
| | | row.setHeight((short) (35*20)); |
| | | } |
| | | // 打印字段名称和值 |
| | | System.out.println(fieldName + ": " + fieldValue); |
| | |
| | | Cell cell = null; |
| | | try { |
| | | // 设置行高为自动调整 |
| | | row.setHeight((short) -1); |
| | | // row.setHeight((short) -1); |
| | | // 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列. |
| | | if (attr.isExport()) { |
| | | // 创建cell |
| | |
| | | // 设置列类型 |
| | | setCellVo(value, attr, cell); |
| | | } |
| | | |
| | | adjustRowHeightAfterSetValue(row, cell, value); |
| | | |
| | | addStatisticsData(column, Convert.toStr(value), attr); |
| | | } |
| | | } catch (Exception e) { |
| | |
| | | } |
| | | return cell; |
| | | } |
| | | /** |
| | | * 设置值后调整行高 |
| | | */ |
| | | private void adjustRowHeightAfterSetValue(Row row, Cell cell, Object value) { |
| | | if (value == null) return; |
| | | |
| | | String text = value.toString(); |
| | | Sheet sheet = row.getSheet(); |
| | | |
| | | // 1. 计算自动高度(基于内容) |
| | | short autoHeight = calculateSimpleAutoHeight(text, cell); |
| | | |
| | | // 2. 获取当前行高 |
| | | short currentHeight = row.getHeight(); |
| | | if (currentHeight == -1) { |
| | | currentHeight = sheet.getDefaultRowHeight(); |
| | | } |
| | | |
| | | // 3. 使用较大的高度(自动计算的高度或当前高度) |
| | | short baseHeight = (short) Math.max(currentHeight, autoHeight); |
| | | System.out.println(baseHeight+"aaaaaaaaatttttttt"); |
| | | // 4. 在基础上增加额外高度(100单位 = 5点) |
| | | short extraHeight = 80; |
| | | short newHeight = (short) (baseHeight + extraHeight); |
| | | |
| | | // 5. 限制最大高度 |
| | | short maxHeight = (short) 4000; // 100点 |
| | | row.setHeight((short) Math.min(maxHeight,newHeight)); |
| | | } |
| | | |
| | | /** |
| | | * 简化的自动高度计算 |
| | | */ |
| | | private short calculateSimpleAutoHeight(String text, Cell cell) { |
| | | if (text == null || text.isEmpty()) return 0; |
| | | |
| | | Sheet sheet = cell.getSheet(); |
| | | int colIndex = cell.getColumnIndex(); |
| | | |
| | | // 获取列宽(字符数) |
| | | int colWidthChars = sheet.getColumnWidth(colIndex) / 256; |
| | | if (colWidthChars <= 0) colWidthChars = 10; |
| | | |
| | | // 计算文本行数 |
| | | int lines = 1; |
| | | if (text.contains("\n")) { |
| | | // 有显式换行 |
| | | String[] parts = text.split("\n"); |
| | | for (String part : parts) { |
| | | lines += Math.max(1, (int) Math.ceil(part.length() * 1.5 / colWidthChars)); |
| | | } |
| | | } else { |
| | | // 自动换行 |
| | | lines = (int) Math.ceil(text.length() * 1.5 / colWidthChars); |
| | | } |
| | | |
| | | // 每行高度:假设18点(360 POI单位) |
| | | return (short) (lines * 360); |
| | | } |
| | | /** |
| | | * 设置 POI HSSFSheet 单元格提示 |
| | | * |
| | |
| | | |
| | | |
| | | |
| | | |
| | | |