报告查询,出库检验报告样式优化以及改为PDF
This commit is contained in:
parent
a1ab7cda31
commit
6635f25c6f
|
|
@ -118,6 +118,17 @@
|
|||
<version>4.12.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>5.2.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.pdfbox</groupId>
|
||||
<artifactId>pdfbox</artifactId>
|
||||
<version>2.0.27</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
|||
|
|
@ -635,7 +635,7 @@ public class BmReportController extends BaseController {
|
|||
|
||||
// 1. 生成合并的出库检验报告
|
||||
byte[] mergedReport = DocxUtil.generateReportByList(items);
|
||||
addToZip(zipOut, baseDatePath + "出库检验报告.docx", mergedReport);
|
||||
addToZip(zipOut, baseDatePath + "出库检验报告.pdf", mergedReport);
|
||||
|
||||
// 2. 遍历每个类型-规格,创建文件夹并添加附加文件
|
||||
Map<String, List<DownloadRequest.ItemInfo>> typeMap = items.stream()
|
||||
|
|
@ -688,9 +688,9 @@ public class BmReportController extends BaseController {
|
|||
String matFolder = sanitize(item.getTypeName() + "-" + item.getTypeModelName());
|
||||
String basePath = projectFolder + "/" + matFolder + "/";
|
||||
|
||||
// 1. 生成出库检验报告.docx
|
||||
byte[] docBytes = DocxUtil.generateReport(item);
|
||||
addToZip(zipOut, basePath + "出库检验报告.docx", docBytes);
|
||||
// 1. 生成出库检验报告.pdf
|
||||
byte[] pdfBytes = DocxUtil.generateReport(item);
|
||||
addToZip(zipOut, basePath + "出库检验报告.pdf", pdfBytes);
|
||||
|
||||
// 2. 附加各类报告文件
|
||||
addFileIfExists(zipOut, basePath, "合格证", item.getQualifiedUrl());
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
package com.bonus.material.common.utils;
|
||||
|
||||
import com.bonus.common.core.utils.poi.PdfUtil;
|
||||
import com.bonus.material.basic.domain.report.DownloadRequest;
|
||||
import org.apache.poi.xwpf.usermodel.*;
|
||||
import org.apache.poi.util.Units;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.apache.pdfbox.pdmodel.font.PDFont;
|
||||
import org.apache.pdfbox.pdmodel.font.PDType0Font;
|
||||
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
||||
|
||||
import java.io.*;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
|
@ -16,96 +21,97 @@ import java.util.List;
|
|||
public class DocxUtil {
|
||||
|
||||
public static byte[] generateReport(DownloadRequest.ItemInfo item) {
|
||||
try (XWPFDocument doc = new XWPFDocument(); ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
|
||||
try (PDDocument document = new PDDocument();
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
|
||||
|
||||
// ===== 页面方向设为横向 =====
|
||||
CTSectPr sectPr = doc.getDocument().getBody().addNewSectPr();
|
||||
CTPageSz pageSize = sectPr.addNewPgSz();
|
||||
pageSize.setOrient(STPageOrientation.LANDSCAPE);
|
||||
pageSize.setW(BigInteger.valueOf(16840)); // A4横向宽
|
||||
pageSize.setH(BigInteger.valueOf(11900)); // A4横向高
|
||||
PDType0Font font = PDType0Font.load(document,
|
||||
PdfUtil.class.getClassLoader().getResourceAsStream("fonts/syht.ttf"));
|
||||
|
||||
// ===== 标题 =====
|
||||
XWPFParagraph title = doc.createParagraph();
|
||||
title.setAlignment(ParagraphAlignment.CENTER);
|
||||
XWPFRun runTitle = title.createRun();
|
||||
runTitle.setText("施工机具设备出库检验记录表");
|
||||
runTitle.setBold(true);
|
||||
runTitle.setFontFamily("宋体");
|
||||
runTitle.setFontSize(16);
|
||||
PDRectangle pageSize = new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth());
|
||||
float margin = 50;
|
||||
float yStart = pageSize.getHeight() - margin;
|
||||
float yPosition = yStart;
|
||||
|
||||
// ===== 工程、单位信息 =====
|
||||
XWPFParagraph info = doc.createParagraph();
|
||||
info.setAlignment(ParagraphAlignment.LEFT);
|
||||
XWPFRun runInfo = info.createRun();
|
||||
runInfo.setFontFamily("宋体");
|
||||
runInfo.setFontSize(12);
|
||||
runInfo.setText("领用工程:" + safe(item.getProName()) + " 使用单位:" + safe(item.getDepartName()));
|
||||
runInfo.addBreak();
|
||||
|
||||
// ===== 表格(1标题行 + 数据行) =====
|
||||
int colNum = 12;
|
||||
XWPFTable table = doc.createTable(1, colNum);
|
||||
table.setWidth("100%");
|
||||
|
||||
// 表头文字
|
||||
float[] colWidths = {80, 80, 40, 40, 80, 70, 70, 75, 65, 80, 60, 40};
|
||||
String[] headers = {
|
||||
"机具名称", "规格型号", "单位", "数量", "设备编码",
|
||||
"额定载荷KN", "试验载荷KN", "持荷时间min",
|
||||
"试验日期", "下次试验日期", "检验结论", "备注"
|
||||
};
|
||||
|
||||
// 设置表头样式
|
||||
XWPFTableRow headerRow = table.getRow(0);
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
XWPFTableCell cell = headerRow.getCell(i);
|
||||
setCellText(cell, headers[i], true);
|
||||
}
|
||||
|
||||
// 数据行
|
||||
XWPFTableRow dataRow = table.createRow();
|
||||
String[] values = {
|
||||
safe(item.getTypeName()),
|
||||
safe(item.getTypeModelName()),
|
||||
safe(item.getUnit()),
|
||||
safe(String.valueOf(item.getNum())),
|
||||
safe(item.getMaCode()),
|
||||
safe(item.getRatedLoad()),
|
||||
safe(item.getTestLoad()),
|
||||
safe(item.getHoldingTime()),
|
||||
safe(item.getTestTime()),
|
||||
safe(item.getNextTestTime()),
|
||||
safe(item.getCheckResult()),
|
||||
safe(item.getRemark())
|
||||
String[][] rows = {
|
||||
{
|
||||
safe(item.getTypeName()), safe(item.getTypeModelName()), safe(item.getUnit()),
|
||||
safe(String.valueOf(item.getNum())), safe(item.getMaCode()),
|
||||
safe(item.getRatedLoad()), safe(item.getTestLoad()), safe(item.getHoldingTime()),
|
||||
safe(item.getTestTime()), safe(item.getNextTestTime()),
|
||||
safe(item.getCheckResult()), safe(item.getRemark())
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 0; i < colNum; i++) {
|
||||
XWPFTableCell cell = dataRow.getCell(i);
|
||||
setCellText(cell, values[i], false);
|
||||
PDPage page = new PDPage(pageSize);
|
||||
document.addPage(page);
|
||||
PDPageContentStream content = new PDPageContentStream(document, page);
|
||||
|
||||
// ===== 标题 =====
|
||||
String titleText = "施工机具设备出库检验记录表";
|
||||
content.beginText();
|
||||
content.setFont(font, 16);
|
||||
content.newLineAtOffset((pageSize.getWidth() - getStringWidth(titleText, font, 16)) / 2, yPosition);
|
||||
content.showText(titleText);
|
||||
content.endText();
|
||||
|
||||
yPosition -= 50;
|
||||
|
||||
// ===== 工程与单位 =====
|
||||
content.beginText();
|
||||
content.setFont(font, 12);
|
||||
content.newLineAtOffset(margin, yPosition);
|
||||
content.showText("领用工程:" + safe(item.getProName()));
|
||||
content.newLineAtOffset(0, -20);
|
||||
content.showText("使用单位:" + safe(item.getDepartName()));
|
||||
content.endText();
|
||||
|
||||
yPosition -= 40;
|
||||
|
||||
// ===== 表格绘制方法 =====
|
||||
float tableWidth = 0;
|
||||
for (float w : colWidths) {
|
||||
tableWidth += w;
|
||||
}
|
||||
float tableBottomMargin = 100;
|
||||
float rowMargin = 5;
|
||||
float fontSize = 10;
|
||||
|
||||
// 绘制表头 + 数据
|
||||
yPosition = drawTable(document, page, content, font, margin, yPosition, tableWidth, colWidths,
|
||||
headers, rows, fontSize, rowMargin, pageSize, yStart, tableBottomMargin);
|
||||
|
||||
// ===== 检验单位与印章 =====
|
||||
yPosition -= 60;
|
||||
content.beginText();
|
||||
content.setFont(font, 12);
|
||||
content.newLineAtOffset(margin, yPosition);
|
||||
content.showText("检验单位:");
|
||||
content.endText();
|
||||
|
||||
InputStream is = PdfUtil.class.getClassLoader().getResourceAsStream("template/gaizhang.png");
|
||||
if (is != null) {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
byte[] data = new byte[1024];
|
||||
int nRead;
|
||||
while ((nRead = is.read(data, 0, data.length)) != -1) {
|
||||
buffer.write(data, 0, nRead);
|
||||
}
|
||||
byte[] imageBytes = buffer.toByteArray();
|
||||
|
||||
PDImageXObject image = PDImageXObject.createFromByteArray(document, imageBytes, "gaizhang");
|
||||
content.drawImage(image, margin + 70, yPosition - 60, 100, 100);
|
||||
is.close();
|
||||
}
|
||||
|
||||
// ===== 检验单位 =====
|
||||
XWPFParagraph footer = doc.createParagraph();
|
||||
footer.setAlignment(ParagraphAlignment.LEFT);
|
||||
footer.setSpacingBefore(400);
|
||||
XWPFRun runFooter = footer.createRun();
|
||||
runFooter.setFontFamily("宋体");
|
||||
runFooter.setFontSize(12);
|
||||
runFooter.setText("检验单位:");
|
||||
|
||||
// ===== 插入印章图片 =====
|
||||
// 使用类路径读取图片
|
||||
InputStream is = DocxUtil.class.getClassLoader().getResourceAsStream("template/gaizhang.png");
|
||||
if (is == null) {
|
||||
throw new FileNotFoundException("找不到资源:template/gaizhang.png");
|
||||
}
|
||||
|
||||
// 在同一个 Run 后面插入图片
|
||||
runFooter.addPicture(is, XWPFDocument.PICTURE_TYPE_PNG, "gaizhang.png", Units.toEMU(100), Units.toEMU(100));
|
||||
is.close();
|
||||
|
||||
|
||||
doc.write(bos);
|
||||
content.close();
|
||||
document.save(bos);
|
||||
return bos.toByteArray();
|
||||
|
||||
} catch (Exception e) {
|
||||
|
|
@ -114,62 +120,142 @@ public class DocxUtil {
|
|||
}
|
||||
}
|
||||
|
||||
/** 单元格通用设置 */
|
||||
private static void setCellText(XWPFTableCell cell, String text, boolean isHeader) {
|
||||
XWPFParagraph p = cell.getParagraphs().get(0);
|
||||
p.setAlignment(ParagraphAlignment.CENTER);
|
||||
XWPFRun run = p.createRun();
|
||||
run.setFontFamily("宋体");
|
||||
run.setFontSize(10);
|
||||
run.setText(text == null ? "" : text);
|
||||
if (isHeader) {
|
||||
run.setBold(true);
|
||||
}
|
||||
// 设置单元格宽度
|
||||
cell.getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(1200));
|
||||
|
||||
private static String safe(String v) {
|
||||
return v == null ? "" : v;
|
||||
}
|
||||
|
||||
private static String safe(String s) {
|
||||
return s == null ? "" : s;
|
||||
private static float getStringWidth(String text, PDFont font, float fontSize) throws IOException {
|
||||
return font.getStringWidth(text) / 1000 * fontSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取图片文件为 byte 数组
|
||||
* @param file 图片文件
|
||||
* @return 图片的字节数据
|
||||
* 自动换行表格绘制
|
||||
*/
|
||||
private static byte[] getImageBytes(File file) throws IOException {
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
try (FileInputStream fileInputStream = new FileInputStream(file)) {
|
||||
byte[] buffer = new byte[1024];
|
||||
int length;
|
||||
while ((length = fileInputStream.read(buffer)) != -1) {
|
||||
byteArrayOutputStream.write(buffer, 0, length);
|
||||
private static float drawTable(PDDocument doc, PDPage page, PDPageContentStream content,
|
||||
PDFont font, float startX, float startY, float tableWidth,
|
||||
float[] colWidths, String[] headers, String[][] rows,
|
||||
float fontSize, float cellMargin, PDRectangle pageSize,
|
||||
float yStart, float bottomMargin) throws IOException {
|
||||
|
||||
float y = startY;
|
||||
float pageHeight = pageSize.getHeight();
|
||||
float usableHeight = pageHeight - bottomMargin;
|
||||
|
||||
// 绘制表头
|
||||
y = drawRow(doc, page, content, font, startX, y, colWidths, headers, fontSize, cellMargin, true);
|
||||
|
||||
for (String[] row : rows) {
|
||||
float rowHeight = getRowHeight(row, font, fontSize, colWidths, cellMargin);
|
||||
|
||||
if (y - rowHeight < bottomMargin) {
|
||||
content.close();
|
||||
PDPage newPage = new PDPage(pageSize);
|
||||
doc.addPage(newPage);
|
||||
content = new PDPageContentStream(doc, newPage);
|
||||
y = yStart;
|
||||
|
||||
// 重绘表头
|
||||
y = drawRow(doc, newPage, content, font, startX, y, colWidths, headers, fontSize, cellMargin, true);
|
||||
}
|
||||
|
||||
y = drawRow(doc, page, content, font, startX, y, colWidths, row, fontSize, cellMargin, false);
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制一行,支持自动换行 + 表头加粗变黑
|
||||
*/
|
||||
private static float drawRow(PDDocument doc, PDPage page, PDPageContentStream content,
|
||||
PDFont font, float startX, float startY, float[] colWidths,
|
||||
String[] texts, float fontSize, float cellMargin, boolean header) throws IOException {
|
||||
|
||||
float y = startY;
|
||||
float maxHeight = getRowHeight(texts, font, fontSize, colWidths, cellMargin);
|
||||
float x = startX;
|
||||
|
||||
for (int i = 0; i < texts.length; i++) {
|
||||
float cellWidth = colWidths[i];
|
||||
|
||||
// ===== 表头灰底 =====
|
||||
if (header) {
|
||||
// 灰色
|
||||
content.setNonStrokingColor(220, 220, 220);
|
||||
content.addRect(x, y - maxHeight, cellWidth, maxHeight);
|
||||
content.fill();
|
||||
}
|
||||
|
||||
// 绘制单元格边框
|
||||
// 黑色
|
||||
content.setNonStrokingColor(0, 0, 0);
|
||||
content.addRect(x, y - maxHeight, cellWidth, maxHeight);
|
||||
content.stroke();
|
||||
|
||||
List<String> lines = wrapText(texts[i], font, fontSize, cellWidth - 2 * cellMargin);
|
||||
float textY = y - cellMargin - fontSize;
|
||||
|
||||
for (String line : lines) {
|
||||
content.beginText();
|
||||
// 黑色字体
|
||||
content.setNonStrokingColor(0, 0, 0);
|
||||
content.setFont(font, header ? fontSize + 1.5f : fontSize);
|
||||
|
||||
// ===== 居中计算 =====
|
||||
float textWidth = font.getStringWidth(line) / 1000 * (header ? fontSize + 1.5f : fontSize);
|
||||
float textX = x + (cellWidth - textWidth) / 2;
|
||||
content.newLineAtOffset(textX, textY);
|
||||
|
||||
content.showText(line);
|
||||
content.endText();
|
||||
textY -= fontSize + 2;
|
||||
}
|
||||
|
||||
x += cellWidth;
|
||||
}
|
||||
|
||||
return y - maxHeight;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 计算行高(取最长文本行数)
|
||||
*/
|
||||
private static float getRowHeight(String[] texts, PDFont font, float fontSize, float[] colWidths, float cellMargin) throws IOException {
|
||||
float max = 0;
|
||||
for (int i = 0; i < texts.length; i++) {
|
||||
List<String> lines = wrapText(texts[i], font, fontSize, colWidths[i] - 2 * cellMargin);
|
||||
max = Math.max(max, lines.size());
|
||||
}
|
||||
return (fontSize + 2) * max + 2 * cellMargin;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文本自动换行
|
||||
*/
|
||||
private static List<String> wrapText(String text, PDFont font, float fontSize, float width) throws IOException {
|
||||
List<String> lines = new ArrayList<>();
|
||||
if (text == null || text.isEmpty()) {
|
||||
lines.add("");
|
||||
return lines;
|
||||
}
|
||||
|
||||
StringBuilder line = new StringBuilder();
|
||||
for (char c : text.toCharArray()) {
|
||||
String temp = line.toString() + c;
|
||||
float textWidth = font.getStringWidth(temp) / 1000 * fontSize;
|
||||
if (textWidth > width) {
|
||||
lines.add(line.toString());
|
||||
line = new StringBuilder(String.valueOf(c));
|
||||
} else {
|
||||
line.append(c);
|
||||
}
|
||||
}
|
||||
return byteArrayOutputStream.toByteArray();
|
||||
lines.add(line.toString());
|
||||
return lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件扩展名获取图片类型
|
||||
* @param fileName 文件名
|
||||
* @return 图片类型
|
||||
*/
|
||||
private static int getPictureType(String fileName) {
|
||||
String ext = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
|
||||
switch (ext) {
|
||||
case "png":
|
||||
return XWPFDocument.PICTURE_TYPE_PNG;
|
||||
case "jpeg":
|
||||
case "jpg":
|
||||
return XWPFDocument.PICTURE_TYPE_JPEG;
|
||||
case "gif":
|
||||
return XWPFDocument.PICTURE_TYPE_GIF;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported image type: " + ext);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] generateReportByList(List<DownloadRequest.ItemInfo> items) {
|
||||
if (items == null || items.isEmpty()) {
|
||||
return new byte[0];
|
||||
|
|
@ -177,74 +263,99 @@ public class DocxUtil {
|
|||
|
||||
DownloadRequest.ItemInfo first = items.get(0);
|
||||
|
||||
try (XWPFDocument doc = new XWPFDocument(); ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
|
||||
// 页面横向
|
||||
CTSectPr sectPr = doc.getDocument().getBody().addNewSectPr();
|
||||
CTPageSz pageSize = sectPr.addNewPgSz();
|
||||
pageSize.setOrient(STPageOrientation.LANDSCAPE);
|
||||
pageSize.setW(BigInteger.valueOf(16840));
|
||||
pageSize.setH(BigInteger.valueOf(11900));
|
||||
try (PDDocument document = new PDDocument();
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
|
||||
|
||||
// 标题
|
||||
XWPFParagraph title = doc.createParagraph();
|
||||
title.setAlignment(ParagraphAlignment.CENTER);
|
||||
XWPFRun runTitle = title.createRun();
|
||||
runTitle.setText("施工机具设备出库检验记录表");
|
||||
runTitle.setBold(true);
|
||||
runTitle.setFontFamily("宋体");
|
||||
runTitle.setFontSize(16);
|
||||
PDType0Font font = PDType0Font.load(document,
|
||||
PdfUtil.class.getClassLoader().getResourceAsStream("fonts/syht.ttf"));
|
||||
|
||||
// 工程、单位
|
||||
XWPFParagraph info = doc.createParagraph();
|
||||
info.setAlignment(ParagraphAlignment.LEFT);
|
||||
XWPFRun runInfo = info.createRun();
|
||||
runInfo.setFontFamily("宋体");
|
||||
runInfo.setFontSize(12);
|
||||
runInfo.setText("领用工程:" + safe(first.getProName()) + " 使用单位:" + safe(first.getDepartName()));
|
||||
runInfo.addBreak();
|
||||
|
||||
// 表格
|
||||
int colNum = 12;
|
||||
XWPFTable table = doc.createTable(1, colNum);
|
||||
table.setWidth("100%");
|
||||
PDRectangle pageSize = new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth());
|
||||
float margin = 50;
|
||||
float yStart = pageSize.getHeight() - margin;
|
||||
float yPosition = yStart;
|
||||
|
||||
float[] colWidths = {80, 80, 40, 40, 80, 70, 70, 75, 65, 80, 60, 40};
|
||||
String[] headers = {
|
||||
"机具名称", "规格型号", "单位", "数量", "设备编码",
|
||||
"额定载荷KN", "试验载荷KN", "持荷时间min",
|
||||
"试验日期", "下次试验日期", "检验结论", "备注"
|
||||
};
|
||||
XWPFTableRow headerRow = table.getRow(0);
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
setCellText(headerRow.getCell(i), headers[i], true);
|
||||
}
|
||||
|
||||
for (DownloadRequest.ItemInfo item : items) {
|
||||
XWPFTableRow row = table.createRow();
|
||||
String[] values = {
|
||||
safe(item.getTypeName()), safe(item.getTypeModelName()), safe(item.getUnit()), safe(String.valueOf(item.getNum())),
|
||||
safe(item.getMaCode()), safe(item.getRatedLoad()), safe(item.getTestLoad()), safe(item.getHoldingTime()),
|
||||
safe(item.getTestTime()), safe(item.getNextTestTime()), safe(item.getCheckResult()), safe(item.getRemark())
|
||||
// 数据转为二维数组
|
||||
String[][] rows = new String[items.size()][headers.length];
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
DownloadRequest.ItemInfo item = items.get(i);
|
||||
rows[i] = new String[]{
|
||||
safe(item.getTypeName()), safe(item.getTypeModelName()), safe(item.getUnit()),
|
||||
safe(String.valueOf(item.getNum())), safe(item.getMaCode()),
|
||||
safe(item.getRatedLoad()), safe(item.getTestLoad()), safe(item.getHoldingTime()),
|
||||
safe(item.getTestTime()), safe(item.getNextTestTime()),
|
||||
safe(item.getCheckResult()), safe(item.getRemark())
|
||||
};
|
||||
for (int i = 0; i < colNum; i++) {
|
||||
setCellText(row.getCell(i), values[i], false);
|
||||
}
|
||||
}
|
||||
|
||||
// 检验单位 + 印章
|
||||
XWPFParagraph footer = doc.createParagraph();
|
||||
footer.setAlignment(ParagraphAlignment.LEFT);
|
||||
footer.setSpacingBefore(400);
|
||||
XWPFRun runFooter = footer.createRun();
|
||||
runFooter.setFontFamily("宋体");
|
||||
runFooter.setFontSize(12);
|
||||
runFooter.setText("检验单位:");
|
||||
PDPage page = new PDPage(pageSize);
|
||||
document.addPage(page);
|
||||
PDPageContentStream content = new PDPageContentStream(document, page);
|
||||
|
||||
InputStream is = DocxUtil.class.getClassLoader().getResourceAsStream("template/gaizhang.png");
|
||||
// ===== 标题 =====
|
||||
String titleText = "施工机具设备出库检验记录表";
|
||||
content.beginText();
|
||||
content.setFont(font, 16);
|
||||
content.newLineAtOffset((pageSize.getWidth() - getStringWidth(titleText, font, 16)) / 2, yPosition);
|
||||
content.showText(titleText);
|
||||
content.endText();
|
||||
|
||||
yPosition -= 50;
|
||||
|
||||
// ===== 工程与单位 =====
|
||||
content.beginText();
|
||||
content.setFont(font, 12);
|
||||
content.newLineAtOffset(margin, yPosition);
|
||||
content.showText("领用工程:" + safe(first.getProName()));
|
||||
content.newLineAtOffset(0, -20);
|
||||
content.showText("使用单位:" + safe(first.getDepartName()));
|
||||
content.endText();
|
||||
|
||||
yPosition -= 40;
|
||||
|
||||
// ===== 表格绘制(多行) =====
|
||||
float tableWidth = 0;
|
||||
for (float w : colWidths) {
|
||||
tableWidth += w;
|
||||
}
|
||||
float bottomMargin = 100;
|
||||
float rowMargin = 5;
|
||||
float fontSize = 10;
|
||||
|
||||
yPosition = drawTable(document, page, content, font, margin, yPosition, tableWidth,
|
||||
colWidths, headers, rows, fontSize, rowMargin, pageSize, yStart, bottomMargin);
|
||||
|
||||
// ===== 检验单位与印章 =====
|
||||
yPosition -= 60;
|
||||
content.beginText();
|
||||
content.setFont(font, 12);
|
||||
content.newLineAtOffset(margin, yPosition);
|
||||
content.showText("检验单位:");
|
||||
content.endText();
|
||||
|
||||
InputStream is = PdfUtil.class.getClassLoader().getResourceAsStream("template/gaizhang.png");
|
||||
if (is != null) {
|
||||
runFooter.addPicture(is, XWPFDocument.PICTURE_TYPE_PNG, "gaizhang.png", Units.toEMU(100), Units.toEMU(100));
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
byte[] data = new byte[1024];
|
||||
int nRead;
|
||||
while ((nRead = is.read(data, 0, data.length)) != -1) {
|
||||
buffer.write(data, 0, nRead);
|
||||
}
|
||||
byte[] imageBytes = buffer.toByteArray();
|
||||
|
||||
PDImageXObject image = PDImageXObject.createFromByteArray(document, imageBytes, "gaizhang");
|
||||
content.drawImage(image, margin + 70, yPosition - 60, 100, 100);
|
||||
is.close();
|
||||
}
|
||||
|
||||
doc.write(bos);
|
||||
content.close();
|
||||
document.save(bos);
|
||||
return bos.toByteArray();
|
||||
|
||||
} catch (Exception e) {
|
||||
|
|
@ -253,4 +364,5 @@ public class DocxUtil {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue