1.maven的pom.xml引入相关依赖
<properties>
<poi-version>3.17</poi-version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi-version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi-version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>${poi-version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/jfree/jcommon -->
<dependency>
<groupId>jfree</groupId>
<artifactId>jcommon</artifactId>
<version>1.0.16</version>
</dependency>
<!-- https://mvnrepository.com/artifact/jfree/jfreechart -->
<dependency>
<groupId>jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.0.13</version>
</dependency>
</dependencies>
2.Demo
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.IntervalBarRenderer;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.renderer.category.StandardBarPainter;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.ui.TextAnchor;
import java.awt.*;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.List;
import java.util.*;
public class JfreeChartUtils {
public static void main(String[] args) throws Exception {
// 画图的顶级管理器,一个sheet只能获取一个(一定要注意这点)
HSSFWorkbook wb = new HSSFWorkbook();
//创建工作表
HSSFSheet sheet = wb.createSheet("Sheet 1");
//如果不使用Font,中文将显示不出来
Font font = new Font("新宋体", Font.BOLD, 15);
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
//1.创建饼图数据
List<NameValueVO> datas1 = new ArrayList<>();
datas1.add(new NameValueVO("录播主机",(double) 1000));
datas1.add(new NameValueVO("编码器",(double) 1000));
datas1.add(new NameValueVO("流转码服务器",(double) 1000));
datas1.add(new NameValueVO("设备网络掉线4",(double) 1000));
datas1.add(new NameValueVO("流转码服务器1",(double) 1000));
datas1.add(new NameValueVO("流转码服务器2",(double) 1000));
datas1.add(new NameValueVO("流转码服务器3",(double) 1000));
datas1.add(new NameValueVO("流转码服务器4",(double) 1000));
datas1.add(new NameValueVO("流转码服务器5",(double) 1000));
//2.创建棒图数据
List<NameValueVO> datas2 = new ArrayList<>();
datas2.add(new NameValueVO("设备掉线1",(double) 1000));
datas2.add(new NameValueVO("设备掉线2",(double) 1000));
datas2.add(new NameValueVO("设备掉线3",(double) 1000));
datas2.add(new NameValueVO("设备掉线4",(double) 1000));
datas2.add(new NameValueVO("设备掉线5",(double) 1000));
datas2.add(new NameValueVO("设备掉线6",(double) 1000));
datas2.add(new NameValueVO("设备掉线7",(double) 1000));
datas2.add(new NameValueVO("设备掉线8",(double) 1000));
datas2.add(new NameValueVO("设备掉线9",(double) 1000));
datas2.add(new NameValueVO("设备掉线10",(double) 1000));
//3.画饼图
testPieChart(wb,patriarch,font,datas1);
//4.画棒图
testBarChart(wb,patriarch,font,datas2);
//5.折线图
testLineChart(wb,patriarch,font);
File file =new File("D://excel-demo/1.xlsx");
if(file.exists()){
file.delete();
}
FileOutputStream fileOut = new FileOutputStream(new File("D://excel-demo/1.xlsx"));
wb.write(fileOut);
fileOut.close();
}
/**
* 创建饼图
* @throws Exception
*/
public static void testPieChart(HSSFWorkbook wb,HSSFPatriarch patriarch,Font font,List<NameValueVO> datas){
try {
//1.指定图片位置
JFreeChart chart = createPieChart("故障设备类型比例", datas, font);
//读取chart信息至字节输出流
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
ChartUtilities.writeChartAsPNG(byteArrayOut, chart, 1250, 680);
//anchor主要用于设置图片的属性,指定图片位置
HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0, (short) 2, (short) 1, (short) 19, (short) 40);
anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);
//2.插入图片
patriarch.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_PNG));
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 创建棒图
* @throws Exception
*/
public static void testBarChart(HSSFWorkbook wb,HSSFPatriarch patriarch,Font font,List<NameValueVO> datas){
try {
//1.构建JFreeChart
JFreeChart chart = createBarChart("故障类型比例",datas,"告警数量(个)",font);
//读取chart信息至字节输出流
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
ChartUtilities.writeChartAsPNG(byteArrayOut, chart, 1250, 680);
//anchor主要用于设置图片的属性,指定图片位置
HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0, (short) 2, (short) 45, (short) 19, (short) 84);
anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);
//2.插入图片
patriarch.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_PNG));
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 创建折线图
* @param wb
* @param patriarch
* @param font
*/
public static void testLineChart(HSSFWorkbook wb, HSSFPatriarch patriarch, Font font){
try {
String[] rowKeys = {"A平台","B平台"};
String[] colKeys = {"0:00", "1:00", "2:00", "7:00", "8:00", "9:00","10:00", "11:00", "12:00", "13:00", "16:00", "20:00", "21:00","23:00"};
double[][] data = {{4, 3, 1, 1, 1, 1, 2, 2, 2, 1, 8, 2, 1, 1},{6, 3, 8, 1, 1, 19, 2, 2, 5, 1, 8, 12, 1, 51}};
String categoryAxisLabel = "时间";
String valueAxisLabel = "告警数量(个)";
CategoryDataset categoryDataset = DatasetUtilities.createCategoryDataset(rowKeys,colKeys, data);
//1.指定图片位置
JFreeChart chart = createLineChart("折线图",categoryAxisLabel,valueAxisLabel,font,categoryDataset);
//读取chart信息至字节输出流
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
ChartUtilities.writeChartAsPNG(byteArrayOut, chart, 1250, 680);
//anchor主要用于设置图片的属性,指定图片位置
HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0, (short) 2, (short) 99, (short) 19, (short) 128);
anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);
//插入图片
patriarch.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_PNG));
}catch (Exception e){
e.printStackTrace();
}
}
/**
* JFreeChart-棒图
* @param title
* @param datas
* @param type
* @param font
* @return
*/
public static JFreeChart createBarChart(String title, List<NameValueVO> datas, String type,Font font){
try {
Map<String, String> dataMap = tranBeanToMap(datas);
DefaultCategoryDataset ds = new DefaultCategoryDataset();
dataMap.forEach((key,value)->{
ds.setValue(Double.parseDouble(value.toString()), "", key.toString());
});
//创建柱状图,柱状图分水平显示和垂直显示两种
JFreeChart chart = ChartFactory.createBarChart(title, null, type, ds, PlotOrientation.VERTICAL, true, true, true);
//设置整个图片的标题字体
chart.getTitle().setFont(new Font("新宋体", Font.BOLD, 12));
//设置提示条字体
chart.getLegend().setItemFont(font);
//得到绘图区
CategoryPlot plot = (CategoryPlot) chart.getPlot();
// 自定义柱状图中柱子的样式
CustomRender brender = new CustomRender();
brender.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
brender.setBaseItemLabelsVisible(true);
brender.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.BASELINE_CENTER));
brender.setShadowVisible(false);
brender.setIncludeBaseInRange(true);
brender.setBarPainter(new StandardBarPainter());
brender.setMaximumBarWidth(0.05);
brender.setMinimumBarLength(0.05);
plot.setRenderer(brender);
//得到绘图区的域轴(横轴),设置标签的字体
plot.getDomainAxis().setLabelFont(font);
//设置横轴标签项字体
plot.getDomainAxis().setTickLabelFont(font);
//设置范围轴(纵轴)字体
plot.getRangeAxis().setLabelFont(font);
plot.setForegroundAlpha(1.0f);
//设置plot的背景色透明度
plot.setBackgroundAlpha(0.0f);
return chart;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* JFreeChart-饼图
* @param title
* @param datas
* @param font
* @return
*/
public static JFreeChart createPieChart(String title, List<NameValueVO> datas, Font font) {
try {
Map<String, String> dataMap = tranBeanToMap(datas);
Set<Map.Entry<String, String>> set = dataMap.entrySet();
DefaultPieDataset pds = new DefaultPieDataset();
Iterator iterator = set.iterator();
Map.Entry entry;
while (iterator.hasNext()) {
entry = (Map.Entry) iterator.next();
pds.setValue(entry.getKey().toString(), Double.parseDouble(entry.getValue().toString()));
}
//生成一个饼图的图表:显示图表的标题、组装的数据、是否显示图例、是否生成贴士以及是否生成URL链接
JFreeChart chart = ChartFactory.createPieChart(title, pds, true, false, true);
// 设置图片标题的字体
chart.getTitle().setFont(font);
// 得到图块,准备设置标签的字体
PiePlot plot = (PiePlot) chart.getPlot();
// 设置标签字体
plot.setLabelFont(font);
// 设置图例项目字体
chart.getLegend().setItemFont(font);
//设置plot的前景色透明度
plot.setForegroundAlpha(0.7f);
//设置plot的背景色透明度
plot.setBackgroundAlpha(0.0f);
//设置标签生成器(默认{0})
//{0}:key {1}:value {2}:百分比 {3}:sum
plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}{1}({2})")); // 一般在{1}后面加单位,如:{0}({1}次)/{2}
return chart;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
*JFreeChart-折线图
* @param categoryDataset 数据集
* @param title 标题
* @param categoryAxisLabel x轴名称
* @param valueAxisLabel y轴名称
* @param font
*
* @return
*/
public static JFreeChart createLineChart(String title,String categoryAxisLabel, String valueAxisLabel,Font font,CategoryDataset categoryDataset) {
try {
JFreeChart chart = ChartFactory.createLineChart(title,categoryAxisLabel,valueAxisLabel,categoryDataset, PlotOrientation.VERTICAL, true, false, false);
//设置整个图片的标题字体
chart.getTitle().setFont(font);
//设置提示条字体
chart.getLegend().setItemFont(font);
CategoryPlot plot = (CategoryPlot)chart.getPlot();
LineAndShapeRenderer renderer = new LineAndShapeRenderer();
renderer.setBaseShapesVisible(true); // series 点(即数据点)可见
renderer.setBaseLinesVisible(true); // series 点(即数据点)间有连线可见
renderer.setUseSeriesOffset(true); // 设置偏移量
renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
renderer.setBaseItemLabelsVisible(true);
plot.setRenderer(renderer);
//得到绘图区的域轴(横轴),设置标签的字体
plot.getDomainAxis().setLabelFont(font);
//设置横轴标签项字体
plot.getDomainAxis().setTickLabelFont(font);
//设置范围轴(纵轴)字体
plot.getRangeAxis().setLabelFont(font);
plot.setForegroundAlpha(1.0f);
//设置plot的背景色透明度
plot.setBackgroundAlpha(0.0f);
return chart;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
/**
* 构建折线图数据
* @param rowKeys
* @param colKeys
* @param data
* @return
*/
public static CategoryDataset createCategoryDataset(String[] rowKeys,String[] colKeys, double[][] data){
return DatasetUtilities.createCategoryDataset(rowKeys, colKeys, data);
}
/**
* 数据机构转换,NameValueVO转map
* @param data
* @return
*/
public static Map<String, String> tranBeanToMap(List<NameValueVO> data){
if(CollectionUtils.isEmpty(data)){
return null;
}
Map<String, String> map = new LinkedHashMap<>();
for (NameValueVO nameValueVO : data){
map.put(nameValueVO.getName().toString(), nameValueVO.getValue().toString());
}
return map;
}
static class CustomRender extends IntervalBarRenderer {
private Paint[] colors;
//初始化柱子颜色
private String[] colorValues = {"#FF0000", "#0070C0", "#00AF4E", "#7030A0"};
public CustomRender() {
colors = new Paint[colorValues.length];
for (int i = 0; i < colorValues.length; i++) {
colors[i] = Color.decode(colorValues[i]);
}
}
//每根柱子以初始化的颜色不断轮循
public Paint getItemPaint(int i, int j) {
return colors[j % colors.length];
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class NameValueVO<T> {
private String name;
private T value;
}
}