修订记录逻辑新增,大于3条显示最后三条。且完整文件添加至附件当中

This commit is contained in:
yujh_java 2025-10-29 10:45:51 +08:00
parent 24b8bef478
commit e0433d3faa
2 changed files with 354 additions and 1 deletions

View File

@ -0,0 +1,327 @@
package com.actionsoft.apps.coe.pal.pal.output.util;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import java.io.*;
import java.math.BigInteger;
public class FileUtil {
/**
* 生成版本历史表格的Word文档输入流
* @param versionHistoryTable 版本历史数据JSONArray
* @return 包含表格的Word文档InputStream
* @throws IOException IO异常
*/
public static InputStream generateVersionHistoryStream(JSONArray versionHistoryTable) throws IOException {
// 创建Word文档对象
try (XWPFDocument document = new XWPFDocument();
// 内存输出流用于临时存储文档内容
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
// 定义表格列名与需求对应
String[] columnNames = {
"版本", "发布部门", "拟制人", "拟制日期",
"审核人", "复核人", "审批人", "修订内容及理由"
};
// 创建表格1行表头8列
XWPFTable table = document.createTable(1, columnNames.length);
// 表格整体设置
// 设置表格水平居中对齐POI 3.17兼容方式
CTTblPr tblPr = table.getCTTbl().getTblPr();
if (tblPr == null) {
tblPr = table.getCTTbl().addNewTblPr();
}
CTJc jc = tblPr.isSetJc() ? tblPr.getJc() : tblPr.addNewJc();
jc.setVal(STJc.CENTER);
// 设置表格自动适应窗口宽度
CTTblWidth tblWidth = tblPr.isSetTblW() ? tblPr.getTblW() : tblPr.addNewTblW();
tblWidth.setW(new BigInteger("9000")); // 设置一个较大的宽度值
tblWidth.setType(STTblWidth.DXA);
// 设置表格布局为自动适应内容
CTTblLayoutType layout = tblPr.isSetTblLayout() ? tblPr.getTblLayout() : tblPr.addNewTblLayout();
layout.setType(STTblLayoutType.AUTOFIT);
// 设置列宽 - 增大列宽值以确保内容不会缩在一起
// 根据列内容性质设置不同宽度
// 1. 版本 - 适中宽度
// 2. 发布部门 - 较宽
// 3-7. 人员信息 - 适中宽度
// 8. 修订内容及理由 - 最宽
int[] columnWidths = {1200, 2500, 1500, 1800, 1800, 1800, 1800, 4500};
setTableColumnsWidth(table, columnWidths);
// 创建表头样式
XWPFTableRow headerRow = table.getRow(0);
// 设置为表头行
// 设置固定行高20转换为twip单位1点20twip
headerRow.setHeight((int) (20 * 20)); // twip单位
// 填充表头并设置样式
for (int i = 0; i < columnNames.length; i++) {
XWPFTableCell cell = headerRow.getCell(i);
if (cell == null) {
cell = headerRow.createCell();
}
// 设置表头单元格样式
setHeaderCellStyle(cell);
cell.setText(columnNames[i]);
}
// 填充数据行
for (int i = 0; i < versionHistoryTable.size(); i++) {
JSONObject rowData = versionHistoryTable.getJSONObject(i);
XWPFTableRow dataRow = table.createRow();
// 设置数据行行高自动
dataRow.setHeight(400);
// 按列顺序填充数据并设置样式与JSON的key对应
for (int j = 0; j < columnNames.length; j++) {
XWPFTableCell cell = dataRow.getCell(j);
if (cell == null) {
cell = dataRow.createCell();
}
// 设置数据单元格样式
boolean isLastColumn = (j == 7); // 第8列索引7
setDataCellStyle(cell, isLastColumn);
// 设置对应列的数据
switch (j) {
case 0: cell.setText(getSafeString(rowData, "versions")); break;
case 1: cell.setText(getSafeString(rowData, "Issuing_department")); break;
case 2: cell.setText(getSafeString(rowData, "Drafted_and_revised_by")); break;
case 3: cell.setText(getSafeString(rowData, "Drafted_and_revised_date")); break;
case 4: cell.setText(getSafeString(rowData, "auditor")); break;
case 5: cell.setText(getSafeString(rowData, "reviewer")); break;
case 6: cell.setText(getSafeString(rowData, "approver")); break;
case 7: cell.setText(getSafeString(rowData, "Contents_and_reasons_for_revision")); break;
}
}
}
// 将文档写入内存输出流
document.write(out);
out.flush(); // 确保所有数据写入完成
// 将内存中的字节数组转换为InputStream返回
return new ByteArrayInputStream(out.toByteArray());
}
}
/**
* 设置表格各列宽度
* @param table 表格对象
* @param columnWidths 列宽数组与列数对应
*/
private static void setTableColumnsWidth(XWPFTable table, int[] columnWidths) {
// 获取或创建表格网格
CTTblGrid tblGrid = table.getCTTbl().getTblGrid();
if (tblGrid == null) {
tblGrid = table.getCTTbl().addNewTblGrid();
} else {
// 清除原有网格列
while (tblGrid.getGridColList().size() > 0) {
tblGrid.removeGridCol(0);
}
}
// 为每一列设置宽度
for (int width : columnWidths) {
CTTblGridCol gridCol = tblGrid.addNewGridCol();
gridCol.setW(new BigInteger(String.valueOf(width)));
}
}
/**
* 设置表头单元格样式
*/
private static void setHeaderCellStyle(XWPFTableCell cell) {
// 设置单元格垂直居中
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
// 设置单元格边距确保内容不紧贴边框
setCellMargins(cell);
// 设置段落样式
XWPFParagraph paragraph = cell.getParagraphs().get(0);
// 文字水平居中
paragraph.setAlignment(ParagraphAlignment.CENTER);
// 设置段落行距使用兼容的方式
CTP ctp = paragraph.getCTP();
CTPPr pPr = ctp.isSetPPr() ? ctp.getPPr() : ctp.addNewPPr();
CTSpacing spacing = pPr.isSetSpacing() ? pPr.getSpacing() : pPr.addNewSpacing();
spacing.setAfter(new BigInteger("0"));
spacing.setBefore(new BigInteger("0"));
spacing.setLine(new BigInteger("240")); // 12pt 对应240
spacing.setLineRule(STLineSpacingRule.EXACT);
// 设置字体样式
XWPFRun run = paragraph.getRuns().isEmpty() ? paragraph.createRun() : paragraph.getRuns().get(0);
run.setBold(true); // 加粗
run.setFontSize(10); // 10.5号字体近似10号
run.setFontFamily("宋体");
}
/**
* 设置数据单元格样式
*/
private static void setDataCellStyle(XWPFTableCell cell, boolean isLastColumn) {
// 设置单元格垂直居中
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
// 设置单元格边距确保内容不紧贴边框
setCellMargins(cell);
// 设置背景色为白色
cell.setColor("FFFFFF");
// 设置段落样式
XWPFParagraph paragraph = cell.getParagraphs().get(0);
// 根据是否为第8列设置水平对齐方式
paragraph.setAlignment(isLastColumn ? ParagraphAlignment.LEFT : ParagraphAlignment.CENTER);
// 设置段落行距使用兼容的方式
CTP ctp = paragraph.getCTP();
CTPPr pPr = ctp.isSetPPr() ? ctp.getPPr() : ctp.addNewPPr();
CTSpacing spacing = pPr.isSetSpacing() ? pPr.getSpacing() : pPr.addNewSpacing();
spacing.setAfter(new BigInteger("0"));
spacing.setBefore(new BigInteger("0"));
spacing.setLine(new BigInteger("240")); // 12pt 对应240
spacing.setLineRule(STLineSpacingRule.EXACT);
// 设置字体样式
XWPFRun run = paragraph.getRuns().isEmpty() ? paragraph.createRun() : paragraph.getRuns().get(0);
run.setFontSize(10); // 10.5号字体近似10号
run.setFontFamily("宋体");
}
/**
* 设置单元格边距
*/
private static void setCellMargins(XWPFTableCell cell) {
CTTc cttc = cell.getCTTc();
CTTcPr tcPr = cttc.isSetTcPr() ? cttc.getTcPr() : cttc.addNewTcPr();
// 设置单元格左边距
CTTcMar tcMar = tcPr.isSetTcMar() ? tcPr.getTcMar() : tcPr.addNewTcMar();
if (!tcMar.isSetLeft()) {
tcMar.addNewLeft();
}
tcMar.getLeft().setW(new BigInteger("100"));
tcMar.getLeft().setType(STTblWidth.DXA);
if (!tcMar.isSetRight()) {
tcMar.addNewRight();
}
tcMar.getRight().setW(new BigInteger("100"));
tcMar.getRight().setType(STTblWidth.DXA);
if (!tcMar.isSetTop()) {
tcMar.addNewTop();
}
tcMar.getTop().setW(new BigInteger("50"));
tcMar.getTop().setType(STTblWidth.DXA);
if (!tcMar.isSetBottom()) {
tcMar.addNewBottom();
}
tcMar.getBottom().setW(new BigInteger("50"));
tcMar.getBottom().setType(STTblWidth.DXA);
}
/**
* 安全获取JSON字段值避免null
*/
private static String getSafeString(JSONObject jsonObject, String key) {
return jsonObject.getString(key) == null ? "" : jsonObject.getString(key);
}
/**
* 将InputStream保存到本地文件
* @param inputStream 输入流
* @param filePath 保存路径
* @throws IOException IO异常
*/
private static void saveInputStreamToFile(InputStream inputStream, String filePath) throws IOException {
// 创建文件目录如果不存在
File file = new File(filePath);
File parentDir = file.getParentFile();
if (parentDir != null && !parentDir.exists()) {
boolean created = parentDir.mkdirs();
if (!created) {
throw new IOException("无法创建目录: " + parentDir.getAbsolutePath());
}
}
// 使用try-with-resources确保流正确关闭
try (FileOutputStream outputStream = new FileOutputStream(file)) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
}
}
// 使用示例
public static void main(String[] args) {
try {
// 1. 构造示例JSON数据实际使用时替换为你的versionHistoryTable
JSONArray versionHistory = new JSONArray();
// 添加V1.0数据
JSONObject v1 = new JSONObject();
v1.put("versions", "V1.0");
v1.put("Issuing_department", "总部国际业务部国贸部");
v1.put("Drafted_and_revised_by", "吴赞涛");
v1.put("Drafted_and_revised_by", "2023年1月1日");
v1.put("auditor", "高扬,王煜");
v1.put("reviewer", "王志军");
v1.put("approver", "黄新峰");
v1.put("Contents_and_reasons_for_revision", "初始版本创建,包含基本功能");
versionHistory.add(v1);
// 添加V2.0数据
JSONObject v2 = new JSONObject();
v2.put("版本", "V2.0");
v2.put("发布部门", "总部国际业务部国贸部");
v2.put("拟制人", "吴赞涛");
v2.put("拟制日期", "2023年7月10日");
v2.put("审核人", "高扬,王煜");
v2.put("复核人", "王志军");
v2.put("审批人", "齐文川");
v2.put("修订内容及理由", "优化系统流程,提升用户体验,修复已知问题");
versionHistory.add(v2);
// 2. 生成InputStream
InputStream wordStream = generateVersionHistoryStream(versionHistory);
// 3. 此处可使用流进行后续操作如保存为文件作为附件等
System.out.println("InputStream生成成功可进行后续处理");
// 将流保存到本地文件
String savePath = "/Users/yuyia/Desktop/临时文件/修订记录.docx";
saveInputStreamToFile(wordStream, savePath);
System.out.println("文件已成功保存到: " + savePath);
// 注意使用完毕后需关闭流
wordStream.close();
} catch (Exception e) {
// 捕获所有异常以提供更详细的错误信息
e.printStackTrace();
System.out.println("生成失败:" + e.getMessage());
}
}
}

View File

@ -846,7 +846,13 @@ public class OutputWordUtil {
String[] header = {"版本", "发布部门","拟制人","拟制日期","审核人","复核人","审批人","修订内容及理由"}; String[] header = {"版本", "发布部门","拟制人","拟制日期","审核人","复核人","审批人","修订内容及理由"};
String[][] strArray2 = new String[versionHistoryTable.size()][]; String[][] strArray2 = new String[versionHistoryTable.size()][];
List<String[]> list = new LinkedList<>(); List<String[]> list = new LinkedList<>();
for (int i = 0; i < versionHistoryTable.size(); i++) {
//增加逻辑 修订记录大于3条时则只保留最后三条
int startIndex = 0;
if (versionHistoryTable.size() > 3) {
startIndex = versionHistoryTable.size() - 3; // 只取最后三条记录
}
for (int i = startIndex; i < versionHistoryTable.size(); i++) {
JSONObject jsonObject = versionHistoryTable.getJSONObject(i); JSONObject jsonObject = versionHistoryTable.getJSONObject(i);
String[] strArray = new String[8]; String[] strArray = new String[8];
@ -1817,6 +1823,26 @@ public class OutputWordUtil {
+ (b2 - b1) / 1000 + ""); + (b2 - b1) / 1000 + "");
} }
//新增修订记录逻辑
JSONArray versionHistoryTable = getVersionHistoryTable(repositoryModel);
if(versionHistoryTable!=null && versionHistoryTable.size()>3){
InputStream versionHistoryStream = null;
try {
versionHistoryStream = FileUtil.generateVersionHistoryStream(versionHistoryTable);
} catch (IOException e) {
throw new RuntimeException(e);
}
//添加段落
Paragraph paragraph5 = section.addParagraph();
//加载一个图片它将作为外部文件的符号显示在Word文档中
//获取文件的后缀名 .jpg
DocPicture pic1 = new DocPicture(doc);
pic1.loadImage("../doccenter/com.awspaas.user.apps.coe.pal.output.zd/filepic/word.png");
paragraph5.appendText("修订记录.docx");
paragraph5.applyStyle(BuiltinStyle.Body_Text); //应用标题1样式
paragraph5.appendOleObject(versionHistoryStream, pic1, "docx");
}
try { try {
System.out.println("Filed=================="+repositoryModel.getId()); System.out.println("Filed=================="+repositoryModel.getId());
doc.saveToFile(outFile.getPath(), FileFormat.Docx_2013); doc.saveToFile(outFile.getPath(), FileFormat.Docx_2013);