报表在项目开发中经常使用,itext是生成报表的java组件,对比于之前使用的poi,itext侧重于pdf格式报表,并结合jfreechar制作图表,能够为用户多样化显示数据。本文结合项目应用案例使用进行描述。
首先用一张图来显示生成的报表样式:
1. pom文件导入itext引用
org.jfree
jfreechart
1.0.19
com.itextpdf
itextpdf
5.5.4
com.lowagie
itext
2.1.7
com.lowagie
itext-rtf
2.1.7
org.apache.poi
poi
3.7
com.itextpdf
itext-asian
5.2.0
2. 文本样式导入方法
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);//设置中文字体
Font font = new Font(bfChinese, 10);
Font headFont = new Font(bfChinese, 14, Font.BOLD);//设置字体
Font littleHeadFont = new Font(bfChinese, 12, Font.BOLD);
Document document = new com.itextpdf.text.Document(PageSize.A4,
MARGIN_OF_ONE_CM, MARGIN_OF_ONE_CM, MARGIN_OF_ONE_CM, MARGIN_OF_ONE_CM); //设置A4纸张样式,每页填充满后自动换行
PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());
//设置文本属性
document.addAuthor("gskj");
document.addSubject("Subject");
document.addLanguage("chinese");
document.addCreationDate();
document.addCreator("whp");
document.addTitle("title");
writer.setTagged();
writer.createXmpMetadata();
document.open();
//定义段落
Paragraph paragraph = new Paragraph();
//设置段落前后间距
paragraph.setSpacingAfter(10);
paragraph.setSpacingBefore(10);
paragraph.setFont(font);
ReportVo overView = exportVo.getOverView();
Paragraph bigTitle = new Paragraph("一、概述", headFont);
StringBuffer overViewBuffer = new StringBuffer("在2018年1月22号对大数据系统的审计总体状况如下:共有");
overViewBuffer.append(overView.getUserNumber());
overViewBuffer.append("个用户使用,进行了");
overViewBuffer.append(overView.getVisitsTotal());
overViewBuffer.append("次访问,出现高风险事件");
overViewBuffer.append(overView.getHighEventNumber());
overViewBuffer.append("次;该大数据系统的基本状况如下:");
paragraph.add(overViewBuffer.toString());
document.add(bigTitle);
document.add(paragraph); //document文件流中添加数据
3. 使用jFreeChart导出图表,前期经过一番实验,利用itext接口直接导入jfreechart图表只提供了绝对定位的接口(也许是没有找到相对定位),当表格数据或者图表数据无法确定大小的情况下,样式不好控制,因此采用一种巧妙的方式,将jfreeChart转化为图片,并将图片作为document元素导入,样式更加美观可控。
/**
* 柱状图
*
* @param dataset 数据集
* @param xName x轴的说明(如种类,时间等)
* @param yName y轴的说明(如速度,时间等)
* @param chartTitle 图标题
* @param charName 生成图片的名字
* @param plotOrientation 方向
* @return
*/
public JFreeChart createBarChart(CategoryDataset dataset, String xName,
String yName, String chartTitle, String charName, PlotOrientation plotOrientation) {
JFreeChart chart = ChartFactory.createBarChart(chartTitle, // 图表标题
xName, // 目录轴的显示标签
yName, // 数值轴的显示标签
dataset, // 数据集
plotOrientation, // 图表方向:水平、垂直
true, // 是否显示图例(对于简单的柱状图必须是false)
false, // 是否生成工具
false // 是否生成URL链接
);
java.awt.Font labelFont = new java.awt.Font("STSong-Light", java.awt.Font.PLAIN, 16);
/*
* VALUE_TEXT_ANTIALIAS_OFF表示将文字的抗锯齿关闭,
* 使用的关闭抗锯齿后,字体尽量选择12到14号的宋体字,这样文字最清晰好看
*/
// chart.getRenderingHints().put(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
chart.setTextAntiAlias(false);
chart.setBackgroundPaint(Color.white);
// create plot
CategoryPlot plot = chart.getCategoryPlot();
// 设置横虚线可见
plot.setRangeGridlinesVisible(true);
// 虚线色彩
plot.setRangeGridlinePaint(Color.gray);
// 数据轴精度
NumberAxis vn = (NumberAxis) plot.getRangeAxis();
// vn.setAutoRangeIncludesZero(true);
DecimalFormat df = new DecimalFormat("#0.00");
vn.setNumberFormatOverride(df); // 数据轴数据标签的显示格式
// x轴设置
CategoryAxis domainAxis = plot.getDomainAxis();
domainAxis.setLabelFont(labelFont);// 轴标题
domainAxis.setTickLabelFont(labelFont);// 轴数值
domainAxis.setMaximumCategoryLabelWidthRatio(0.6f);// 横轴上的 Lable 是否完整显示
// 设置距离图片左端距离
domainAxis.setLowerMargin(0.1);
// 设置距离图片右端距离
domainAxis.setUpperMargin(0.1);
// 设置 columnKey 是否间隔显示
// domainAxis.setSkipCategoryLabelsToFit(true);
plot.setDomainAxis(domainAxis);
// 设置柱图背景色(注意,系统取色的时候要使用16位的模式来查看颜色编码,这样比较准确)
plot.setBackgroundPaint(new Color(255, 255, 204));
// y轴设置
ValueAxis rangeAxis = plot.getRangeAxis();
rangeAxis.setLabelFont(labelFont);
rangeAxis.setTickLabelFont(labelFont);
// 设置最高的一个 Item 与图片顶端的距离
rangeAxis.setUpperMargin(0.15);
// 设置最低的一个 Item 与图片底端的距离
rangeAxis.setLowerMargin(0.15);
plot.setRangeAxis(rangeAxis);
BarRenderer renderer = new BarRenderer();
// 设置柱子宽度
renderer.setMaximumBarWidth(0.05);
// 设置柱子高度
renderer.setMinimumBarLength(0.2);
// 设置柱子边框颜色
renderer.setBaseOutlinePaint(Color.BLACK);
// 设置柱子边框可见
renderer.setDrawBarOutline(true);
// // 设置柱的颜色
renderer.setSeriesPaint(0, new Color(204, 255, 255));
renderer.setSeriesPaint(1, new Color(153, 204, 255));
renderer.setSeriesPaint(2, new Color(51, 204, 204));
// 设置每个地区所包含的平行柱的之间距离
renderer.setItemMargin(0.0);
// 显示每个柱的数值,并修改该数值的字体属性
renderer.setIncludeBaseInRange(true);
renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
renderer.setBaseItemLabelsVisible(true);
renderer.setBaseItemLabelFont(labelFont);
if(plotOrientation.equals(PlotOrientation.HORIZONTAL)){ //控制结果数据在柱状图的位置
renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE3, TextAnchor.BASELINE_LEFT));
}
plot.setRenderer(renderer);
// 设置柱的透明度
plot.setForegroundAlpha(1.0f);
FileOutputStream fos_jpg = null;
try {
isChartPathExist(CHART_PATH);
String chartName = CHART_PATH + charName;
fos_jpg = new FileOutputStream(chartName);
ChartUtilities.writeChartAsPNG(fos_jpg, chart, 500, 500, true, 10);
return chart;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
try {
fos_jpg.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 判断文件夹是否存在,如果不存在则新建
*
* @param chartPath
*/
private void isChartPathExist(String chartPath) {
File file = new File(chartPath);
if (!file.exists()) {
file.mkdirs();
// log.info("CHART_PATH="+CHART_PATH+"create.");
}
}
示例代码:
double[][] data = new double[][]{
{672, 766, 223, 540, 126}
};
String[] rowKeys = {"苹果"};
String[] columnKeys = {"北京", "上海", "广州", "成都", "深圳"};
CategoryDataset datasetBar = pm.getBarData(data, rowKeys, columnKeys);
JFreeChart chart =pm.createBarChart(datasetBar, "x坐标", "y坐标", "柱状图", "bar.png");
File fileName = new File("/root/jfreechart2.pdf");
JFreeChart chart = createBarChart(datasetBar, "", "", "", ".png", PlotOrientation.HORIZONTAL);
Image logoImage = Image.getInstance(ChartUtilities.encodeAsPNG(chart.createBufferedImage(1080, 920))); //转化为图片
logoImage.scaleAbsolute(500, 400); //设置图片大小
logoImage.setAccessibleAttribute(PdfName.ALT, new PdfString("Logo"));
document.add(logoImage);
4. 制做表格
private PdfPTable createTable(int numCloumns, int numRows, String[][] data, Font font) {
PdfPTable table = new PdfPTable(numCloumns);
table.setWidthPercentage(100); // 宽度100%填充
table.setSpacingBefore(10f); // 前间距
table.setSpacingAfter(10f); // 后间距
ArrayList listRow = table.getRows();
for (int i = 0; i < numRows; i++) {
//行1
PdfPCell cells[] = new PdfPCell[numCloumns];
PdfPRow row = new PdfPRow(cells);
for (int j = 0; j < numCloumns; j++) {
cells[j] = new PdfPCell(new Paragraph(data[i][j], font));
}
listRow.add(row);
}
return table;
}
举例:
array5[0][0] = "语句类型";
array5[0][1] = "语句数";
for (int i = 1; i < statementActionList.size() + 1; i++) {
array5[i][0] = statementActionList.get(i - 1).getStatementType(); //第一列数据
array5[i][1] = statementActionList.get(i - 1).getStatementNumber(); //第二列数据
}
PdfPTable table5 = createTable(2, statementActionList.size() + 1, array5, font);
document.add(table5);