1. 生成 pdf 文件
package com.leinovo.npi.datacenter.module.dashboard.helper;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;
import com.leinovo.npi.datacenter.report.core.model.ReportInstanceInfo;
import com.leinovo.npi.datacenter.report.core.model.ReportProfile;
import com.leinovo.npi.util.DateUtils;
import com.leinovo.platform.util.JwtUtil;
import org.apache.commons.collections.CollectionUtils;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.Date;
import java.util.List;
/**
* @description: CustomerPdfHelper
* @author: leiming5
* @date: 2021/12/30 15:12
*/
public class CustomerPdfHelper extends DownloadHelper {
public CustomerPdfHelper(ReportProfile reportProfile, ReportInstanceInfo recentlyReportInstanceInfo, HttpServletResponse response) {
super(reportProfile, recentlyReportInstanceInfo, response);
}
/**
* pdf 写入响应流
* 1. 获取响应流
* 2. 生成 pdf 文档
* 3. 文档放入输出流
* 4. pdf 文档 放入数据
* 5. 关闭 pdf 文档
*
* @author leiming5
*/
@Override
public void download() {
String dateString = DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN_YYYY_MM_DD_HH_MM_SS);
response.setHeader("content-disposition", "attachment;filename=" + fileName + "_" + dateString + ".pdf");
response.setContentType("application/octet-stream");
try (OutputStream out = response.getOutputStream()) {
// 1.新建document对象
Document document = new Document(PageSize.A4);// 建立一个Document对象
// 2.文档写入输出流
PdfWriter.getInstance(document, out);
// 3.打开文档
document.open();
// 4.向文档中添加内容
appendDataToDocument(document);
// 5.关闭文档
document.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 将 数据放入 文档
*
* @param document
*/
public void appendDataToDocument(Document document) {
addDocumentProperties(document);
for (int i = 0; i < elementKeys.size(); i++) {
String elementKey = elementKeys.get(i);
appendDataToDocumentByKey(document, elementKey);
}
}
private void addDocumentProperties(Document document) {
document.addTitle(fileName);// 标题
String username = JwtUtil.getUsername();
document.addAuthor(username);// 作者
document.addSubject(fileName);// 主题
document.addKeywords(fileName);// 关键字
document.addCreator(username);// 创建者
}
private void addGraph(Document document, String word) {
try {
document.add(new Paragraph(word));
} catch (DocumentException e) {
e.printStackTrace();
}
}
/**
* 通过 报表元素 key 添加数据到 sheet
*
* @param document pdf 文档
* @param excelKey 当前报表的 key
* @return 下一个报表的起始行
* @author leiming5
*/
private void appendDataToDocumentByKey(Document document, String excelKey) {
String elementTitle = getTitle(excelKey);
List<String> elementHeader = getHeader(excelKey);
if (CollectionUtils.isEmpty(elementHeader)) {
return;
}
List<List<String>> elementData = getData(excelKey);
DocumentHelper documentHelper = new DocumentHelper(elementTitle, elementHeader, elementData, document);
documentHelper.appendElementToDocument(excelKey,elementTitle);
}
}
2 pdf 中添加表格
package com.leinovo.npi.datacenter.module.dashboard.helper;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.leinovo.npi.datacenter.report.core.component.ProductPictureElement;
import com.leinovo.npi.datacenter.report.core.component.SupplyProfileElement;
import org.jfree.chart.JFreeChart;
import org.jfree.data.category.CategoryDataset;
import java.io.File;
import java.io.IOException;
import java.util.List;
/**
* @description: DocumentHelper
* @author: leiming5
* @date: 2021/12/30 18:31
*/
public class DocumentHelper {
private String elementTitle;
private List<String> elementHeader;
private List<List<String>> elementData;
private Document document;
private static int maxWidth = 520;
private static int titleSize = 6;
private static int fontSize = 5;
private static BaseColor whiteColor = UiHelper.getWhiteColor();
private static BaseColor blackColor = UiHelper.getBlackColor();
private static BaseColor greyColor = UiHelper.getGreyColor();
private static BaseColor blueColor = UiHelper.getBlueColor();
private static Font titlefont = FontFactory.getFont(FontFactory.TIMES_ROMAN, titleSize, Font.NORMAL, blackColor);
private static Font headfont = FontFactory.getFont(FontFactory.TIMES_ROMAN, fontSize, Font.BOLD, whiteColor);
private static Font bodyfont = FontFactory.getFont(FontFactory.TIMES_ROMAN, fontSize, Font.NORMAL, blackColor);
public DocumentHelper(String elementTitle, List<String> elementHeader, List<List<String>> elementData, Document document) {
this.elementTitle = elementTitle;
this.elementHeader = elementHeader;
this.elementData = elementData;
this.document = document;
}
/**
* 放入 表格、图表
*
* @return 下一个 报表元素的 开始index
* @author leiming5
*/
public void appendElementToDocument(String excelKey, String elementTitle) {
appendTableToDocument();
// 折线图+柱状图(同时出现;FG Demand Supply与 Material Demand Supply 动他选择)
if (excelKey.contains(SupplyProfileElement.getECode())) {
appendImageToDocument(excelKey, elementTitle);
// 图片列表 Product Picture(翻页功能)
} else if (excelKey.contains(ProductPictureElement.getECode())) {
appendImageToDocument(excelKey, elementTitle);
} else {
appendImageToDocument(excelKey, elementTitle);
}
}
/**
* 插件无法直接生成 图表,只能通过前端生成 图标的图片,然后把连接放入 pdf
*
* @param excelKey element key
* @author leiming5
*/
private void appendImageToDocument(String excelKey, String elementTitle) {
String chartName = excelKey + ".jpg";
addGraph("");
CategoryDataset dataset = ChartHelper.getDataset();
JFreeChart chart = ChartHelper.getChart(dataset, elementTitle, "", "");
ChartHelper.generateChart(chartName, chart);
try {
Image image = Image.getInstance(chartName);
image.setAlignment(Image.ALIGN_CENTER);
image.scalePercent(40);
document.add(image);
} catch (IOException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
}
File file = new File(chartName);
file.delete();
}
private void addGraph(String value) {
try {
document.add(new Paragraph(value));
} catch (DocumentException e) {
e.printStackTrace();
}
}
/**
* 1. 放入 标题
* 2. 放入 excel 表头
* 3. 放入 excel 数据
* 4. 设置列的样式
*
* @return 下一个 报表元素的 开始index
* @author leiming5
*/
private void appendTableToDocument() {
PdfPTable table = createTable(elementHeader.size());
appendElementTitle(table);
appendElementHeader(table);
appendElementData(table);
addTable(table);
}
private void addTable(PdfPTable table) {
try {
document.add(table);
} catch (DocumentException e) {
e.printStackTrace();
}
}
private void appendElementTitle(PdfPTable table) {
table.addCell(createTitleCell(elementTitle, elementHeader.size()));
}
private void appendElementHeader(PdfPTable table) {
for (String fieldName : elementHeader) {
table.addCell(createHeadCell(fieldName));
}
}
private void appendElementData(PdfPTable table) {
for (List<String> row : elementData) {
for (String cellData : row) {
table.addCell(createBodyCell(cellData));
}
}
}
/**
* 创建指定列宽、列数的表格
*
* @param headerSize 表头字段数量
* @return 创建的表格
* @author leiming5
*/
public PdfPTable createTable(int headerSize) {
float[] fieldNums = new float[headerSize];
for (int i = 0; i < headerSize; i++) {
fieldNums[i] = 30f;
}
PdfPTable table = new PdfPTable(fieldNums);
try {
table.setTotalWidth(maxWidth);
table.setLockedWidth(true);
table.setHorizontalAlignment(Element.ALIGN_CENTER);
UiHelper.setDefaultCell(table.getDefaultCell());
} catch (Exception e) {
e.printStackTrace();
}
return table;
}
/**
* 创建单元格(指定字体、水平居..、单元格跨x列合并、设置单元格内边距)
*
* @param value
* @param colspan
* @return
*/
public PdfPCell createTitleCell(String value, int colspan) {
PdfPCell cell = new PdfPCell();
cell.setPhrase(new Phrase(value, titlefont));
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_LEFT);
cell.setColspan(colspan);
cell.setBorder(0);
cell.setPadding(3.0f);
cell.setPaddingTop(15.0f);
cell.setPaddingBottom(8.0f);
return cell;
}
/**
* 创建单元格(指定字体)
*
* @param value
* @return
*/
public PdfPCell createBodyCell(String value) {
PdfPCell cell = new PdfPCell();
cell.setPhrase(new Phrase(value, bodyfont));
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setBorderColor(greyColor);
return cell;
}
public PdfPCell createHeadCell(String value) {
PdfPCell cell = new PdfPCell();
cell.setPhrase(new Phrase(value, headfont));
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setBackgroundColor(blueColor);
cell.setBorderColor(greyColor);
return cell;
}
}
3. pdf 放入chart
其实,是通过 jfree生成一张图片,再将图片放入pdf
package com.leinovo.npi.datacenter.module.dashboard.helper;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import java.awt.*;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* 参考连接 : https://www.cnblogs.com/antlord/p/8325937.html
* https://blog.csdn.net/u012373815/article/details/50327907
*
* @description: ChartHelper
* @author: leiming5
* @date: 2022/1/3 14:49
*/
public class ChartHelper {
public static void generateChart(String chartName,JFreeChart chart ) {
characterFix(chart);
saveCharToFile(chart, chartName);
}
public static void saveCharToFile(JFreeChart chart, String fileName) {
OutputStream out = null;
int width = 1023;
int height = 511;
try {
out = new BufferedOutputStream(new FileOutputStream(fileName));
if (fileName.endsWith("png")) {
ChartUtilities.writeChartAsPNG(out, chart, width, height);
} else {
ChartUtilities.writeChartAsJPEG(out, 1.0f, chart, width, height, null);
}
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static CategoryDataset getDataset() {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(1310, "plan", "PEL Exit");
dataset.addValue(720.68, "plan", "POR Exit");
dataset.addValue(675.3, "plan", "TR");
dataset.addValue(560, "plan", "EVT Start");
dataset.addValue(680.88, "plan", "DVT1 Start");
dataset.addValue(780, "plan", "DVT2 Start");
dataset.addValue(13100, "actual", "PEL Exit");
dataset.addValue(720.680, "actual", "POR Exit");
dataset.addValue(6750.3, "actual", "TR");
dataset.addValue(5600, "actual", "EVT Start");
dataset.addValue(680.88, "actual", "DVT1 Start");
dataset.addValue(7800, "actual", "DVT2 Start");
return dataset;
}
public static JFreeChart getChart(CategoryDataset dataset, String title, String yAxisName, String xAxisName) {
JFreeChart chart = ChartFactory.createLineChart(
// JFreeChart chart = ChartFactory.createBarChart3D(
title,// 图形名称
xAxisName,// 分类名称,为横坐标名称
yAxisName,// 值名称,为纵坐标名称
dataset,// 数据集合
PlotOrientation.VERTICAL,// 垂直显示
true,// 是否显示图例
false,// 是否使用工具提示
false);// 是否使用url
return chart;
}
public static void characterFix(JFreeChart chart) {
// 配置字体
Font xfont = new Font("宋体", Font.PLAIN, 12);// X轴
Font yfont = new Font("宋体", Font.PLAIN, 12);// Y轴
Font kfont = new Font("宋体", Font.PLAIN, 12);// 底部
Font titleFont = new Font("宋体", Font.BOLD, 15); // 图片标题
// 图形的绘制结构对象,对于饼图不适用
CategoryPlot plot = chart.getCategoryPlot();
// 图片标题
chart.setTitle(new TextTitle(chart.getTitle().getText(), titleFont));
// 底部
LegendTitle legendTitle = chart.getLegend();
if (legendTitle != null) {
legendTitle.setItemFont(kfont);
}
// X 轴
CategoryAxis domainAxis = plot.getDomainAxis();
domainAxis.setLabelFont(xfont);// 轴标题
domainAxis.setTickLabelFont(xfont);// 轴数值
domainAxis.setTickLabelPaint(Color.BLUE); // 字体颜色
domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);
// Y 轴
ValueAxis rangeAxis = plot.getRangeAxis();
rangeAxis.setLabelFont(yfont);
rangeAxis.setLabelPaint(Color.BLUE); // 字体颜色
rangeAxis.setTickLabelFont(yfont);
}
}
4. 字体等样式
package com.leinovo.npi.datacenter.module.dashboard.helper;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Font;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
/**
* @description: UiHelper
* @author: leiming5
* @date: 2021/12/31 11:20
*/
public final class UiHelper {
public static void setDefaultCell(PdfPCell cell) {
// 大小
cell.setFixedHeight(14);
// 边框
cell.setBorder(1);
cell.setBorderWidth(1);
cell.setBorderColor(getBorderColor());
// 字体,字体的样式、COLOR
cell.addElement(getPhrase("second content"));
// 背景
cell.setBackgroundColor(getBlueColor());
}
/**
* 短语
*
* @return
*/
public static Phrase getPhrase(String content) {
Phrase phrase = new Phrase();
phrase.setFont(getDefaultFont());
phrase.setLeading(12);// 行距
phrase.add(content);
return phrase;
}
/**
* 设置字体
* 有四种属性(字体,字号,字型,颜色)
*/
public static Font getFont(int size, BaseColor color) {
return FontFactory.getFont(FontFactory.TIMES_ROMAN, size, Font.NORMAL, color);
}
public static Font getDefaultFont() {
return getFont(8, getBlackColor());
}
/**
* 边框颜色
*/
public static BaseColor getBorderColor() {
return new BaseColor(231, 237, 243);
}
/**
* 白色 表头字体,body背景
*/
public static BaseColor getWhiteColor() {
return new BaseColor(255, 255, 255);
}
/**
* 蓝色 表头背景
*/
public static BaseColor getBlueColor() {
return new BaseColor(88, 135, 227);
}
/**
* 黑色 body 字体颜色
*/
public static BaseColor getBlackColor() {
return new BaseColor(34, 34, 34);
}
/**
* 灰色 body 背景颜色
*/
public static BaseColor getGreyColor() {
return new BaseColor(217, 226, 243);
}
}