使用JfreeChart+itextpdf+POI将Excel中的图表和数据导出到PDF
前言
业务需要将原本的Excel导出改为PDF导出
一、版本说明
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.3</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>kernel</artifactId>
<version>7.1.5</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>io</artifactId>
<version>7.1.5</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>layout</artifactId>
<version>7.1.5</version>
</dependency>
<dependency>
<groupId>jfree</groupId>
<artifactId>jcommon</artifactId>
<version>1.0.16</version>
</dependency>
<dependency>
<groupId>jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.0.13</version>
</dependency>
二、使用步骤
1.JfreeChart
由于业务数据X轴是时间,所以关于图表大致有两种可用:
1. JFreeChart chart = ChartFactory.createTimeSeriesChart("title",
"timeAxisLabel",
"valueAxisLabel",
dataSet,
legend,
tooltips,
urls
);
数据集:
TimeSeries s1 = new TimeSeries(Comparable, Day.class);
s1.addOrUpdate(new Day(businessTime.get(Calendar.DAY_OF_MONTH), businessTime.get(Calendar.MONTH) + 1, businessTime.get(Calendar.YEAR)), Double.valueOf(businessValue));
时序图:通过描述对象之间发送消息的时间顺序显示多个对象之间的动态协作。它可以表示用例的行为顺序。(来自百度百科)
这里注意有个坑就是如果时间是有重复的,可以使用addOrUpdate方法。并且JfreeChart会在渲染数据时,自动按照时间排序。同时将X轴设置个默认的间隔日期. 如果数据不连续,可能造成chart和预想的效果不符合。
![](https://img-blog.csdnimg.cn/916078a61fb9488c847ba2cef71147b4.png)
2. JFreeChart chart = ChartFactory.createLineChart("title",
"timeAxisLabel",
"valueAxisLabel",
dataSet,
PlotOrientation,
legend,
tooltips,
urls
);
数据集:
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(Double.valueOf(yValue), "type1", xValue));
线图: 常见的线图。
这里业务最后确认了时间连续可以使用时序图~
2.部分核心代码
代码如下(示例):
private static JFreeChart createTimeSeriesLineChart(String title, List originalDataSet) throws Exception {
TimeSeriesCollection dataSet = createDataset(originalDataSet);
StandardChartTheme standardChartTheme = new StandardChartTheme("EN");
standardChartTheme.setRegularFont(new Font("Arial", Font.PLAIN, 14));
ChartFactory.setChartTheme(standardChartTheme);
JFreeChart chart = ChartFactory.createTimeSeriesChart("",
"Date",
"Last 100 Value",
dataSet,
true,
false,
false
);
chart.getXYPlot().setRenderer(new XYSplineRenderer(7));
chart.setBackgroundPaint(Color.white);
TextTitle t = new TextTitle();
t.setMargin(0,0,20,0);
t.setText(title);
Font f = new Font("Arial", Font.BOLD, 14);
t.setFont(f);
t.setTextAlignment(HorizontalAlignment.LEFT);
chart.setTitle(t);
XYPlot plot = (XYPlot) chart.getPlot();
plot.setDomainGridlinesVisible(false);
plot.setBackgroundPaint(Color.white);
plot.setOutlineVisible(false);
plot.setDomainGridlinePaint(Color.LIGHT_GRAY);
plot.setRangeGridlinePaint(Color.LIGHT_GRAY);
plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
plot.setDomainCrosshairVisible(false);
plot.setRangeCrosshairVisible(false);
// set series shapes
XYItemRenderer xyItemRenderer = plot.getRenderer();
if (xyItemRenderer instanceof XYLineAndShapeRenderer) {
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) xyItemRenderer;
renderer.setSeriesShape(0, new Ellipse2D.Double(0, 0, 0, 0));
renderer.setSeriesShape(1, new Ellipse2D.Double(-3.0, -3.0, 6.0, 6.0));
renderer.setSeriesShape(2, new Ellipse2D.Double(0, 0, 0, 0));
renderer.setSeriesShape(3, new Ellipse2D.Double(0, 0, 0, 0));
renderer.setSeriesStroke(0, new BasicStroke(2F));
renderer.setSeriesStroke(2, new BasicStroke(2F));
renderer.setSeriesStroke(3, new BasicStroke(2F));
}
xyItemRenderer.setSeriesPaint(0, new Color(255,0,128));
xyItemRenderer.setSeriesPaint(1, new Color(0, 0, 255));
xyItemRenderer.setSeriesPaint(2, new Color(124,130,96));
xyItemRenderer.setSeriesPaint(3, new Color(128,0,128));
DateAxis axis = (DateAxis) plot.getDomainAxis();
axis.setDateFormatOverride(new SimpleDateFormat("MM/dd/yy"));
axis.setTickMarksVisible(false);
plot.getRenderer().setBaseItemLabelGenerator(new StandardXYItemLabelGenerator());
plot.getRenderer().setBaseItemLabelsVisible(false);
plot.getRenderer().setBaseItemLabelFont(new Font("Arial", Font.PLAIN, 8));
plot.setNoDataMessage("No Message!");
plot.setNoDataMessageFont(new Font("Arial", Font.PLAIN, 20));
ValueAxis y_range = plot.getRangeAxis();
y_range.setAutoRange(true);
y_range.setAutoRangeMinimumSize(0.05);
y_range.setRange(0, 0.25);
plot.setRangeAxis(y_range);
return chart;
}
/**
*
* @param doc The pdf file location for outputting
* @param title The chart title
* @param fileInput The Excel file location for inputting
*/
public static void writeChartToPDF(Document doc, String title, File fileInput) {
XLSXReader xlsxReader = new XLSXReader();
List<Map<String, String>> list = xlsxReader.readerToMAP(fileInput, 1,
Integer.parseInt("100"));
try {
JFreeChart chart = createTimeSeriesLineChart(title, list);
BufferedImage image1 = chart.createBufferedImage(800, 600);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image1, "png", baos);
Image iTextImages = Image.getInstance(baos.toByteArray());
iTextImages.setSpacingBefore(50);
iTextImages.scaleAbsolute(520, 390);
iTextImages.setPaddingTop(20);
doc.add(iTextImages);
} catch (Exception e) {
e.printStackTrace();
}
}
如果报出读取文件过大的异常,可以尝试在POI读取Excel之前调用:
ZipSecureFile.setMinInflateRatio(-1.0d);
总结
例如:以上就是今天要讲的内容,本文仅仅简单介绍了JfreeChart的使用,之后可能再会说说PdfPTable遇到的一些坑。