|
@@ -24,10 +24,14 @@ public class SafetyObservationCardGenerator {
|
|
|
|
|
|
|
|
document.createParagraph();
|
|
document.createParagraph();
|
|
|
|
|
|
|
|
- // 2. 创建表格
|
|
|
|
|
- XWPFTable table = document.createTable(1, 3);
|
|
|
|
|
|
|
+ // 2. 创建表格(先创建足够行数,方便后续垂直合并)
|
|
|
|
|
+ XWPFTable table = document.createTable(9, 3); // 预创建9行3列(标题行+提示行+7行内容)
|
|
|
|
|
+ table.setWidth("100%");
|
|
|
|
|
+ // 清空预创建的行(重新自定义行内容)
|
|
|
|
|
+ while (table.getRows().size() > 0) {
|
|
|
|
|
+ table.removeRow(0);
|
|
|
|
|
+ }
|
|
|
table.setWidth("100%");
|
|
table.setWidth("100%");
|
|
|
- table.removeRow(0);
|
|
|
|
|
|
|
|
|
|
// 标题行(文字浅蓝色)
|
|
// 标题行(文字浅蓝色)
|
|
|
XWPFTableRow titleRow = table.createRow();
|
|
XWPFTableRow titleRow = table.createRow();
|
|
@@ -39,7 +43,7 @@ public class SafetyObservationCardGenerator {
|
|
|
XWPFTableRow tipRow = table.createRow();
|
|
XWPFTableRow tipRow = table.createRow();
|
|
|
mergeCellsHorizontally(tipRow, 0, 2);
|
|
mergeCellsHorizontally(tipRow, 0, 2);
|
|
|
XWPFTableCell tipCell = tipRow.getCell(0);
|
|
XWPFTableCell tipCell = tipRow.getCell(0);
|
|
|
- setCellStyle(tipCell, "若有任何不安全,请在小项前面□内打√。大项完全安全,请在大项后面□内打√。", false, ParagraphAlignment.LEFT, "FFFF00");
|
|
|
|
|
|
|
+ setCellStyle(tipCell, "若有任何不安全,请在小项前面□内打√。大项完全安全,请在大项后面□内打√。", true, ParagraphAlignment.LEFT, "FFFF00");
|
|
|
|
|
|
|
|
// 行3:个人防护 | 规范操作 | 观察描述
|
|
// 行3:个人防护 | 规范操作 | 观察描述
|
|
|
XWPFTableRow headerRow1 = table.createRow();
|
|
XWPFTableRow headerRow1 = table.createRow();
|
|
@@ -47,7 +51,7 @@ public class SafetyObservationCardGenerator {
|
|
|
setCellStyle(headerRow1.getCell(1), "规范操作□", true, ParagraphAlignment.LEFT, "DCE6F1");
|
|
setCellStyle(headerRow1.getCell(1), "规范操作□", true, ParagraphAlignment.LEFT, "DCE6F1");
|
|
|
setCellStyle(headerRow1.getCell(2), "观察描述:", true, ParagraphAlignment.LEFT, "DCE6F1");
|
|
setCellStyle(headerRow1.getCell(2), "观察描述:", true, ParagraphAlignment.LEFT, "DCE6F1");
|
|
|
|
|
|
|
|
- // 行4(修复换行:改用新段落实现)
|
|
|
|
|
|
|
+ // 行4:个人防护明细 | 规范操作明细 | 空(后续垂直合并)
|
|
|
XWPFTableRow row4 = table.createRow();
|
|
XWPFTableRow row4 = table.createRow();
|
|
|
String ppeText = "个人防护用品是否齐全、规范?\n" +
|
|
String ppeText = "个人防护用品是否齐全、规范?\n" +
|
|
|
"□ 头部\n" +
|
|
"□ 头部\n" +
|
|
@@ -63,28 +67,28 @@ public class SafetyObservationCardGenerator {
|
|
|
setCellStyle(row4.getCell(1), opText, false, ParagraphAlignment.LEFT, "FFFFFF");
|
|
setCellStyle(row4.getCell(1), opText, false, ParagraphAlignment.LEFT, "FFFFFF");
|
|
|
setCellStyle(row4.getCell(2), "", false, ParagraphAlignment.LEFT, "E6EBF5");
|
|
setCellStyle(row4.getCell(2), "", false, ParagraphAlignment.LEFT, "E6EBF5");
|
|
|
|
|
|
|
|
- // 行5
|
|
|
|
|
|
|
+ // 行5:规范指挥 | 人员位置 | 空(后续垂直合并)
|
|
|
XWPFTableRow headerRow2 = table.createRow();
|
|
XWPFTableRow headerRow2 = table.createRow();
|
|
|
setCellStyle(headerRow2.getCell(0), "规范指挥□", true, ParagraphAlignment.LEFT, "DCE6F1");
|
|
setCellStyle(headerRow2.getCell(0), "规范指挥□", true, ParagraphAlignment.LEFT, "DCE6F1");
|
|
|
setCellStyle(headerRow2.getCell(1), "人员位置□", true, ParagraphAlignment.LEFT, "DCE6F1");
|
|
setCellStyle(headerRow2.getCell(1), "人员位置□", true, ParagraphAlignment.LEFT, "DCE6F1");
|
|
|
setCellStyle(headerRow2.getCell(2), "", false, ParagraphAlignment.LEFT, "E6EBF5");
|
|
setCellStyle(headerRow2.getCell(2), "", false, ParagraphAlignment.LEFT, "E6EBF5");
|
|
|
|
|
|
|
|
- // 行6
|
|
|
|
|
|
|
+ // 行6:规范指挥明细 | 人员位置明细 | 安全行为描述(后续垂直合并)
|
|
|
XWPFTableRow row6 = table.createRow();
|
|
XWPFTableRow row6 = table.createRow();
|
|
|
String cmdText = "是否违章指挥?\n□ 指挥信号不正确/不清楚\n□ 多人指挥,信号不统一\n□ 非特殊情况下越权指挥\n□ 明知危险仍强令冒险作业\n□ 特殊作业前没有进行作业申请/风险分析\n□ 其他 _______________";
|
|
String cmdText = "是否违章指挥?\n□ 指挥信号不正确/不清楚\n□ 多人指挥,信号不统一\n□ 非特殊情况下越权指挥\n□ 明知危险仍强令冒险作业\n□ 特殊作业前没有进行作业申请/风险分析\n□ 其他 _______________";
|
|
|
String posText = "人员站位是否安全?\n□ 碰撞到物体\n□ 被物体夹住/手扶握物体部位不正确\n□ 跌倒/坠落/陷入物体之中\n□ 被物体砸到\n□ 接触极高/极低温度/电流/电击\n□ 吸入/吸收/吞食有害物质\n□ 姿势不良/用力过度\n□ 其他 _______________";
|
|
String posText = "人员站位是否安全?\n□ 碰撞到物体\n□ 被物体夹住/手扶握物体部位不正确\n□ 跌倒/坠落/陷入物体之中\n□ 被物体砸到\n□ 接触极高/极低温度/电流/电击\n□ 吸入/吸收/吞食有害物质\n□ 姿势不良/用力过度\n□ 其他 _______________";
|
|
|
String safeText = "-观察到的安全行为或安全状态\n-鼓励安全行为或安全状态所采取的行动";
|
|
String safeText = "-观察到的安全行为或安全状态\n-鼓励安全行为或安全状态所采取的行动";
|
|
|
setCellStyle(row6.getCell(0), cmdText, false, ParagraphAlignment.LEFT, "FFFFFF");
|
|
setCellStyle(row6.getCell(0), cmdText, false, ParagraphAlignment.LEFT, "FFFFFF");
|
|
|
setCellStyle(row6.getCell(1), posText, false, ParagraphAlignment.LEFT, "FFFFFF");
|
|
setCellStyle(row6.getCell(1), posText, false, ParagraphAlignment.LEFT, "FFFFFF");
|
|
|
- setCellStyle(row6.getCell(2), safeText, false, ParagraphAlignment.LEFT, "E6EBF5");
|
|
|
|
|
|
|
+ setCellStyle(row6.getCell(2), safeText, true, ParagraphAlignment.LEFT, "E6EBF5");
|
|
|
|
|
|
|
|
- // 行7
|
|
|
|
|
|
|
+ // 行7:作业场所 | 空 | 空(后续垂直合并)
|
|
|
XWPFTableRow headerRow3 = table.createRow();
|
|
XWPFTableRow headerRow3 = table.createRow();
|
|
|
mergeCellsHorizontally(headerRow3, 0, 1);
|
|
mergeCellsHorizontally(headerRow3, 0, 1);
|
|
|
setCellStyle(headerRow3.getCell(0), "作业场所□", true, ParagraphAlignment.LEFT, "DCE6F1");
|
|
setCellStyle(headerRow3.getCell(0), "作业场所□", true, ParagraphAlignment.LEFT, "DCE6F1");
|
|
|
setCellStyle(headerRow3.getCell(2), "", false, ParagraphAlignment.LEFT, "E6EBF5");
|
|
setCellStyle(headerRow3.getCell(2), "", false, ParagraphAlignment.LEFT, "E6EBF5");
|
|
|
|
|
|
|
|
- // 行8
|
|
|
|
|
|
|
+ // 行8:作业场所明细 | 空 | 不安全行为描述(后续垂直合并)
|
|
|
XWPFTableRow row8 = table.createRow();
|
|
XWPFTableRow row8 = table.createRow();
|
|
|
mergeCellsHorizontally(row8, 0, 1);
|
|
mergeCellsHorizontally(row8, 0, 1);
|
|
|
String houseText = "作业场所、工作环境是否存在不安全状态或其他安全隐患?\n□ 作业场所杂乱 □ 带电装置带电部分裸露\n□ 作业空间狭小 □ 设备无防护/防护装置不当\n□ 堵塞安全通道 □ 未工完料净场地清/垃圾未分类存放\n□ 地面滑(水/雨/雪/油污等) □ 通风不良/氧气含量未达标\n□ 物体/工具放置位置不当 □ 其他 _______________\n□ 危险场所没有标志/标志不清\n□ 照明光线不良";
|
|
String houseText = "作业场所、工作环境是否存在不安全状态或其他安全隐患?\n□ 作业场所杂乱 □ 带电装置带电部分裸露\n□ 作业空间狭小 □ 设备无防护/防护装置不当\n□ 堵塞安全通道 □ 未工完料净场地清/垃圾未分类存放\n□ 地面滑(水/雨/雪/油污等) □ 通风不良/氧气含量未达标\n□ 物体/工具放置位置不当 □ 其他 _______________\n□ 危险场所没有标志/标志不清\n□ 照明光线不良";
|
|
@@ -92,12 +96,16 @@ public class SafetyObservationCardGenerator {
|
|
|
setCellStyle(row8.getCell(0), houseText, false, ParagraphAlignment.LEFT, "FFFFFF");
|
|
setCellStyle(row8.getCell(0), houseText, false, ParagraphAlignment.LEFT, "FFFFFF");
|
|
|
setCellStyle(row8.getCell(2), unsafeText, false, ParagraphAlignment.LEFT, "E6EBF5");
|
|
setCellStyle(row8.getCell(2), unsafeText, false, ParagraphAlignment.LEFT, "E6EBF5");
|
|
|
|
|
|
|
|
- // 底部信息
|
|
|
|
|
|
|
+ // 底部信息行
|
|
|
XWPFTableRow footerRow = table.createRow();
|
|
XWPFTableRow footerRow = table.createRow();
|
|
|
mergeCellsHorizontally(footerRow, 0, 2);
|
|
mergeCellsHorizontally(footerRow, 0, 2);
|
|
|
String footerText = "观察区域: _______________ 实施观察人员: _______________ 被观察岗位:_______________\n被观察人员: □员工 □承包商 □供应商 日期: _______________ 时间:____点____分到____点____分";
|
|
String footerText = "观察区域: _______________ 实施观察人员: _______________ 被观察岗位:_______________\n被观察人员: □员工 □承包商 □供应商 日期: _______________ 时间:____点____分到____点____分";
|
|
|
setCellStyle(footerRow.getCell(0), footerText, false, ParagraphAlignment.LEFT, "FFFFFF");
|
|
setCellStyle(footerRow.getCell(0), footerText, false, ParagraphAlignment.LEFT, "FFFFFF");
|
|
|
|
|
|
|
|
|
|
+ // 核心修复:垂直合并第三列的单元格(行3到行8的第三列)
|
|
|
|
|
+ // 行索引说明:table.getRow(2) = 行3(标题行是0,提示行是1),table.getRow(7) = 行8
|
|
|
|
|
+ mergeCellsVertically(table, 2, 4, 2);
|
|
|
|
|
+
|
|
|
document.write(out);
|
|
document.write(out);
|
|
|
System.out.println("生成成功:行为安全观察与沟通卡-数智化.docx");
|
|
System.out.println("生成成功:行为安全观察与沟通卡-数智化.docx");
|
|
|
|
|
|
|
@@ -106,7 +114,7 @@ public class SafetyObservationCardGenerator {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // ====================== 标题专用:文字浅蓝色 ======================
|
|
|
|
|
|
|
+ // 标题样式设置
|
|
|
private static void setTitleStyle(XWPFTableCell cell, String text, boolean bold, ParagraphAlignment align, String bgColor) {
|
|
private static void setTitleStyle(XWPFTableCell cell, String text, boolean bold, ParagraphAlignment align, String bgColor) {
|
|
|
clearCellContent(cell);
|
|
clearCellContent(cell);
|
|
|
|
|
|
|
@@ -122,9 +130,8 @@ public class SafetyObservationCardGenerator {
|
|
|
setCellBorder(cell);
|
|
setCellBorder(cell);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // ====================== 修复换行:每行创建独立段落 ======================
|
|
|
|
|
|
|
+ // 单元格样式设置(支持换行)
|
|
|
private static void setCellStyle(XWPFTableCell cell, String text, boolean bold, ParagraphAlignment align, String bgColor) {
|
|
private static void setCellStyle(XWPFTableCell cell, String text, boolean bold, ParagraphAlignment align, String bgColor) {
|
|
|
- // 安全清空单元格内容
|
|
|
|
|
clearCellContent(cell);
|
|
clearCellContent(cell);
|
|
|
|
|
|
|
|
// 设置单元格垂直对齐为顶部
|
|
// 设置单元格垂直对齐为顶部
|
|
@@ -132,24 +139,23 @@ public class SafetyObservationCardGenerator {
|
|
|
CTVerticalJc vAlign = tcPr.addNewVAlign();
|
|
CTVerticalJc vAlign = tcPr.addNewVAlign();
|
|
|
vAlign.setVal(STVerticalJc.TOP);
|
|
vAlign.setVal(STVerticalJc.TOP);
|
|
|
|
|
|
|
|
- // 按换行符分割,每行创建一个新段落(确保换行生效)
|
|
|
|
|
|
|
+ // 按换行符分割,每行创建一个新段落
|
|
|
String[] lines = text.split("\n");
|
|
String[] lines = text.split("\n");
|
|
|
for (String line : lines) {
|
|
for (String line : lines) {
|
|
|
XWPFParagraph paragraph = cell.addParagraph();
|
|
XWPFParagraph paragraph = cell.addParagraph();
|
|
|
paragraph.setAlignment(align);
|
|
paragraph.setAlignment(align);
|
|
|
- paragraph.setSpacingAfter(0); // 取消段落间距
|
|
|
|
|
|
|
+ paragraph.setSpacingAfter(0);
|
|
|
paragraph.setSpacingBefore(0);
|
|
paragraph.setSpacingBefore(0);
|
|
|
|
|
|
|
|
XWPFRun run = paragraph.createRun();
|
|
XWPFRun run = paragraph.createRun();
|
|
|
- run.setText(line.trim()); // 去除行首尾空格(可选)
|
|
|
|
|
|
|
+ run.setText(line.trim());
|
|
|
run.setFontSize(10);
|
|
run.setFontSize(10);
|
|
|
run.setFontFamily("宋体");
|
|
run.setFontFamily("宋体");
|
|
|
run.setBold(bold);
|
|
run.setBold(bold);
|
|
|
- // 取消行间距,避免换行后间距过大
|
|
|
|
|
run.setTextPosition(0);
|
|
run.setTextPosition(0);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 处理空文本情况(至少创建一个空段落)
|
|
|
|
|
|
|
+ // 处理空文本
|
|
|
if (lines.length == 0 && text.isEmpty()) {
|
|
if (lines.length == 0 && text.isEmpty()) {
|
|
|
XWPFParagraph paragraph = cell.addParagraph();
|
|
XWPFParagraph paragraph = cell.addParagraph();
|
|
|
paragraph.setAlignment(align);
|
|
paragraph.setAlignment(align);
|
|
@@ -161,17 +167,13 @@ public class SafetyObservationCardGenerator {
|
|
|
setCellBorder(cell);
|
|
setCellBorder(cell);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 安全清空单元格内容(解决 UnmodifiableCollection 问题)
|
|
|
|
|
- */
|
|
|
|
|
|
|
+ // 清空单元格内容
|
|
|
private static void clearCellContent(XWPFTableCell cell) {
|
|
private static void clearCellContent(XWPFTableCell cell) {
|
|
|
- // 先移除所有段落
|
|
|
|
|
List<XWPFParagraph> paragraphs = cell.getParagraphs();
|
|
List<XWPFParagraph> paragraphs = cell.getParagraphs();
|
|
|
while (paragraphs != null && !paragraphs.isEmpty()) {
|
|
while (paragraphs != null && !paragraphs.isEmpty()) {
|
|
|
cell.removeParagraph(0);
|
|
cell.removeParagraph(0);
|
|
|
- paragraphs = cell.getParagraphs(); // 重新获取列表(避免并发修改)
|
|
|
|
|
|
|
+ paragraphs = cell.getParagraphs();
|
|
|
}
|
|
}
|
|
|
- // 移除所有嵌套表格
|
|
|
|
|
List<XWPFTable> tables = cell.getTables();
|
|
List<XWPFTable> tables = cell.getTables();
|
|
|
while (tables != null && !tables.isEmpty()) {
|
|
while (tables != null && !tables.isEmpty()) {
|
|
|
cell.removeTable(0);
|
|
cell.removeTable(0);
|
|
@@ -179,14 +181,14 @@ public class SafetyObservationCardGenerator {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 设置单元格边框
|
|
|
private static void setCellBorder(XWPFTableCell cell) {
|
|
private static void setCellBorder(XWPFTableCell cell) {
|
|
|
CTTcPr tcPr = cell.getCTTc().getTcPr() != null ? cell.getCTTc().getTcPr() : cell.getCTTc().addNewTcPr();
|
|
CTTcPr tcPr = cell.getCTTc().getTcPr() != null ? cell.getCTTc().getTcPr() : cell.getCTTc().addNewTcPr();
|
|
|
CTTcBorders borders = tcPr.getTcBorders() != null ? tcPr.getTcBorders() : tcPr.addNewTcBorders();
|
|
CTTcBorders borders = tcPr.getTcBorders() != null ? tcPr.getTcBorders() : tcPr.addNewTcBorders();
|
|
|
|
|
|
|
|
- // 设置边框样式和颜色(确保边框显示)
|
|
|
|
|
STBorder.Enum borderStyle = STBorder.SINGLE;
|
|
STBorder.Enum borderStyle = STBorder.SINGLE;
|
|
|
borders.addNewTop().setVal(borderStyle);
|
|
borders.addNewTop().setVal(borderStyle);
|
|
|
- borders.getTop().setColor("000000"); // 黑色边框
|
|
|
|
|
|
|
+ borders.getTop().setColor("000000");
|
|
|
borders.addNewBottom().setVal(borderStyle);
|
|
borders.addNewBottom().setVal(borderStyle);
|
|
|
borders.getBottom().setColor("000000");
|
|
borders.getBottom().setColor("000000");
|
|
|
borders.addNewLeft().setVal(borderStyle);
|
|
borders.addNewLeft().setVal(borderStyle);
|
|
@@ -195,20 +197,30 @@ public class SafetyObservationCardGenerator {
|
|
|
borders.getRight().setColor("000000");
|
|
borders.getRight().setColor("000000");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 水平合并单元格
|
|
|
private static void mergeCellsHorizontally(XWPFTableRow row, int fromCol, int toCol) {
|
|
private static void mergeCellsHorizontally(XWPFTableRow row, int fromCol, int toCol) {
|
|
|
- // 确保列数足够
|
|
|
|
|
while (row.getTableCells().size() <= toCol) {
|
|
while (row.getTableCells().size() <= toCol) {
|
|
|
row.createCell();
|
|
row.createCell();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 第一个单元格设为RESTART
|
|
|
|
|
CTTcPr firstPr = row.getCell(fromCol).getCTTc().getTcPr() != null ? row.getCell(fromCol).getCTTc().getTcPr() : row.getCell(fromCol).getCTTc().addNewTcPr();
|
|
CTTcPr firstPr = row.getCell(fromCol).getCTTc().getTcPr() != null ? row.getCell(fromCol).getCTTc().getTcPr() : row.getCell(fromCol).getCTTc().addNewTcPr();
|
|
|
firstPr.addNewHMerge().setVal(STMerge.RESTART);
|
|
firstPr.addNewHMerge().setVal(STMerge.RESTART);
|
|
|
|
|
|
|
|
- // 后续单元格设为CONTINUE
|
|
|
|
|
for (int i = fromCol + 1; i <= toCol; i++) {
|
|
for (int i = fromCol + 1; i <= toCol; i++) {
|
|
|
CTTcPr pr = row.getCell(i).getCTTc().getTcPr() != null ? row.getCell(i).getCTTc().getTcPr() : row.getCell(i).getCTTc().addNewTcPr();
|
|
CTTcPr pr = row.getCell(i).getCTTc().getTcPr() != null ? row.getCell(i).getCTTc().getTcPr() : row.getCell(i).getCTTc().addNewTcPr();
|
|
|
pr.addNewHMerge().setVal(STMerge.CONTINUE);
|
|
pr.addNewHMerge().setVal(STMerge.CONTINUE);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // 新增:垂直合并单元格
|
|
|
|
|
+ private static void mergeCellsVertically(XWPFTable table, int fromRow, int toRow, int col) {
|
|
|
|
|
+ for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
|
|
|
|
|
+ XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
|
|
|
|
|
+ CTTcPr tcPr = cell.getCTTc().getTcPr() != null ? cell.getCTTc().getTcPr() : cell.getCTTc().addNewTcPr();
|
|
|
|
|
+ STMerge.Enum mergeVal = (rowIndex == fromRow) ? STMerge.RESTART : STMerge.CONTINUE;
|
|
|
|
|
+ tcPr.addNewVMerge().setVal(mergeVal);
|
|
|
|
|
+ // 确保合并后边框正常
|
|
|
|
|
+ setCellBorder(cell);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|