报告查询,出库检验报告样式优化以及改为PDF
This commit is contained in:
parent
a1ab7cda31
commit
6635f25c6f
|
|
@ -118,6 +118,17 @@
|
||||||
<version>4.12.0</version>
|
<version>4.12.0</version>
|
||||||
</dependency>
|
</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>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
||||||
|
|
@ -635,7 +635,7 @@ public class BmReportController extends BaseController {
|
||||||
|
|
||||||
// 1. 生成合并的出库检验报告
|
// 1. 生成合并的出库检验报告
|
||||||
byte[] mergedReport = DocxUtil.generateReportByList(items);
|
byte[] mergedReport = DocxUtil.generateReportByList(items);
|
||||||
addToZip(zipOut, baseDatePath + "出库检验报告.docx", mergedReport);
|
addToZip(zipOut, baseDatePath + "出库检验报告.pdf", mergedReport);
|
||||||
|
|
||||||
// 2. 遍历每个类型-规格,创建文件夹并添加附加文件
|
// 2. 遍历每个类型-规格,创建文件夹并添加附加文件
|
||||||
Map<String, List<DownloadRequest.ItemInfo>> typeMap = items.stream()
|
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 matFolder = sanitize(item.getTypeName() + "-" + item.getTypeModelName());
|
||||||
String basePath = projectFolder + "/" + matFolder + "/";
|
String basePath = projectFolder + "/" + matFolder + "/";
|
||||||
|
|
||||||
// 1. 生成出库检验报告.docx
|
// 1. 生成出库检验报告.pdf
|
||||||
byte[] docBytes = DocxUtil.generateReport(item);
|
byte[] pdfBytes = DocxUtil.generateReport(item);
|
||||||
addToZip(zipOut, basePath + "出库检验报告.docx", docBytes);
|
addToZip(zipOut, basePath + "出库检验报告.pdf", pdfBytes);
|
||||||
|
|
||||||
// 2. 附加各类报告文件
|
// 2. 附加各类报告文件
|
||||||
addFileIfExists(zipOut, basePath, "合格证", item.getQualifiedUrl());
|
addFileIfExists(zipOut, basePath, "合格证", item.getQualifiedUrl());
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,17 @@
|
||||||
package com.bonus.material.common.utils;
|
package com.bonus.material.common.utils;
|
||||||
|
|
||||||
|
import com.bonus.common.core.utils.poi.PdfUtil;
|
||||||
import com.bonus.material.basic.domain.report.DownloadRequest;
|
import com.bonus.material.basic.domain.report.DownloadRequest;
|
||||||
import org.apache.poi.xwpf.usermodel.*;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
import org.apache.poi.util.Units;
|
import org.apache.pdfbox.pdmodel.PDPage;
|
||||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
|
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.io.*;
|
||||||
import java.math.BigInteger;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -16,96 +21,97 @@ import java.util.List;
|
||||||
public class DocxUtil {
|
public class DocxUtil {
|
||||||
|
|
||||||
public static byte[] generateReport(DownloadRequest.ItemInfo item) {
|
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()) {
|
||||||
|
|
||||||
// ===== 页面方向设为横向 =====
|
PDType0Font font = PDType0Font.load(document,
|
||||||
CTSectPr sectPr = doc.getDocument().getBody().addNewSectPr();
|
PdfUtil.class.getClassLoader().getResourceAsStream("fonts/syht.ttf"));
|
||||||
CTPageSz pageSize = sectPr.addNewPgSz();
|
|
||||||
pageSize.setOrient(STPageOrientation.LANDSCAPE);
|
|
||||||
pageSize.setW(BigInteger.valueOf(16840)); // A4横向宽
|
|
||||||
pageSize.setH(BigInteger.valueOf(11900)); // A4横向高
|
|
||||||
|
|
||||||
// ===== 标题 =====
|
PDRectangle pageSize = new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth());
|
||||||
XWPFParagraph title = doc.createParagraph();
|
float margin = 50;
|
||||||
title.setAlignment(ParagraphAlignment.CENTER);
|
float yStart = pageSize.getHeight() - margin;
|
||||||
XWPFRun runTitle = title.createRun();
|
float yPosition = yStart;
|
||||||
runTitle.setText("施工机具设备出库检验记录表");
|
|
||||||
runTitle.setBold(true);
|
|
||||||
runTitle.setFontFamily("宋体");
|
|
||||||
runTitle.setFontSize(16);
|
|
||||||
|
|
||||||
// ===== 工程、单位信息 =====
|
float[] colWidths = {80, 80, 40, 40, 80, 70, 70, 75, 65, 80, 60, 40};
|
||||||
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%");
|
|
||||||
|
|
||||||
// 表头文字
|
|
||||||
String[] headers = {
|
String[] headers = {
|
||||||
"机具名称", "规格型号", "单位", "数量", "设备编码",
|
"机具名称", "规格型号", "单位", "数量", "设备编码",
|
||||||
"额定载荷KN", "试验载荷KN", "持荷时间min",
|
"额定载荷KN", "试验载荷KN", "持荷时间min",
|
||||||
"试验日期", "下次试验日期", "检验结论", "备注"
|
"试验日期", "下次试验日期", "检验结论", "备注"
|
||||||
};
|
};
|
||||||
|
String[][] rows = {
|
||||||
// 设置表头样式
|
{
|
||||||
XWPFTableRow headerRow = table.getRow(0);
|
safe(item.getTypeName()), safe(item.getTypeModelName()), safe(item.getUnit()),
|
||||||
for (int i = 0; i < headers.length; i++) {
|
safe(String.valueOf(item.getNum())), safe(item.getMaCode()),
|
||||||
XWPFTableCell cell = headerRow.getCell(i);
|
safe(item.getRatedLoad()), safe(item.getTestLoad()), safe(item.getHoldingTime()),
|
||||||
setCellText(cell, headers[i], true);
|
safe(item.getTestTime()), safe(item.getNextTestTime()),
|
||||||
}
|
safe(item.getCheckResult()), safe(item.getRemark())
|
||||||
|
}
|
||||||
// 数据行
|
|
||||||
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())
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < colNum; i++) {
|
PDPage page = new PDPage(pageSize);
|
||||||
XWPFTableCell cell = dataRow.getCell(i);
|
document.addPage(page);
|
||||||
setCellText(cell, values[i], false);
|
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("检验单位:");
|
|
||||||
|
|
||||||
// ===== 插入印章图片 =====
|
content.close();
|
||||||
// 使用类路径读取图片
|
document.save(bos);
|
||||||
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);
|
|
||||||
return bos.toByteArray();
|
return bos.toByteArray();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
@ -114,62 +120,142 @@ public class DocxUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 单元格通用设置 */
|
|
||||||
private static void setCellText(XWPFTableCell cell, String text, boolean isHeader) {
|
private static String safe(String v) {
|
||||||
XWPFParagraph p = cell.getParagraphs().get(0);
|
return v == null ? "" : v;
|
||||||
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 s) {
|
private static float getStringWidth(String text, PDFont font, float fontSize) throws IOException {
|
||||||
return s == null ? "" : s;
|
return font.getStringWidth(text) / 1000 * fontSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 读取图片文件为 byte 数组
|
* 自动换行表格绘制
|
||||||
* @param file 图片文件
|
|
||||||
* @return 图片的字节数据
|
|
||||||
*/
|
*/
|
||||||
private static byte[] getImageBytes(File file) throws IOException {
|
private static float drawTable(PDDocument doc, PDPage page, PDPageContentStream content,
|
||||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
PDFont font, float startX, float startY, float tableWidth,
|
||||||
try (FileInputStream fileInputStream = new FileInputStream(file)) {
|
float[] colWidths, String[] headers, String[][] rows,
|
||||||
byte[] buffer = new byte[1024];
|
float fontSize, float cellMargin, PDRectangle pageSize,
|
||||||
int length;
|
float yStart, float bottomMargin) throws IOException {
|
||||||
while ((length = fileInputStream.read(buffer)) != -1) {
|
|
||||||
byteArrayOutputStream.write(buffer, 0, length);
|
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) {
|
public static byte[] generateReportByList(List<DownloadRequest.ItemInfo> items) {
|
||||||
if (items == null || items.isEmpty()) {
|
if (items == null || items.isEmpty()) {
|
||||||
return new byte[0];
|
return new byte[0];
|
||||||
|
|
@ -177,74 +263,99 @@ public class DocxUtil {
|
||||||
|
|
||||||
DownloadRequest.ItemInfo first = items.get(0);
|
DownloadRequest.ItemInfo first = items.get(0);
|
||||||
|
|
||||||
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));
|
|
||||||
pageSize.setH(BigInteger.valueOf(11900));
|
|
||||||
|
|
||||||
// 标题
|
PDType0Font font = PDType0Font.load(document,
|
||||||
XWPFParagraph title = doc.createParagraph();
|
PdfUtil.class.getClassLoader().getResourceAsStream("fonts/syht.ttf"));
|
||||||
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());
|
||||||
XWPFParagraph info = doc.createParagraph();
|
float margin = 50;
|
||||||
info.setAlignment(ParagraphAlignment.LEFT);
|
float yStart = pageSize.getHeight() - margin;
|
||||||
XWPFRun runInfo = info.createRun();
|
float yPosition = yStart;
|
||||||
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%");
|
|
||||||
|
|
||||||
|
float[] colWidths = {80, 80, 40, 40, 80, 70, 70, 75, 65, 80, 60, 40};
|
||||||
String[] headers = {
|
String[] headers = {
|
||||||
"机具名称", "规格型号", "单位", "数量", "设备编码",
|
"机具名称", "规格型号", "单位", "数量", "设备编码",
|
||||||
"额定载荷KN", "试验载荷KN", "持荷时间min",
|
"额定载荷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[][] rows = new String[items.size()][headers.length];
|
||||||
String[] values = {
|
for (int i = 0; i < items.size(); i++) {
|
||||||
safe(item.getTypeName()), safe(item.getTypeModelName()), safe(item.getUnit()), safe(String.valueOf(item.getNum())),
|
DownloadRequest.ItemInfo item = items.get(i);
|
||||||
safe(item.getMaCode()), safe(item.getRatedLoad()), safe(item.getTestLoad()), safe(item.getHoldingTime()),
|
rows[i] = new String[]{
|
||||||
safe(item.getTestTime()), safe(item.getNextTestTime()), safe(item.getCheckResult()), safe(item.getRemark())
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检验单位 + 印章
|
PDPage page = new PDPage(pageSize);
|
||||||
XWPFParagraph footer = doc.createParagraph();
|
document.addPage(page);
|
||||||
footer.setAlignment(ParagraphAlignment.LEFT);
|
PDPageContentStream content = new PDPageContentStream(document, page);
|
||||||
footer.setSpacingBefore(400);
|
|
||||||
XWPFRun runFooter = footer.createRun();
|
|
||||||
runFooter.setFontFamily("宋体");
|
|
||||||
runFooter.setFontSize(12);
|
|
||||||
runFooter.setText("检验单位:");
|
|
||||||
|
|
||||||
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) {
|
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();
|
return bos.toByteArray();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
@ -253,4 +364,5 @@ public class DocxUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue