CreateChartService.java
完成报表的生成,项目只要柱状图和折线图,所以只生成了2中图形,
类中还有JFreeChart 数据的转换方法,JFreeChart相关的配置方法
Java代码 收藏代码
3 import java.awt.Color; 4 import java.awt.Font; 5 import java.io.File; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 import java.util.ArrayList; 9 import java.util.HashMap; 10 import java.util.List; 11 import java.util.Map; 12 13 import net.bingosoft.common.config.Config; 14 15 import org.apache.commons.logging.Log; 16 import org.apache.commons.logging.LogFactory; 17 import org.jfree.chart.ChartFactory; 18 import org.jfree.chart.ChartUtilities; 19 import org.jfree.chart.JFreeChart; 20 import org.jfree.chart.axis.CategoryAxis; 21 import org.jfree.chart.axis.CategoryLabelPositions; 22 import org.jfree.chart.axis.NumberAxis; 23 import org.jfree.chart.axis.ValueAxis; 24 import org.jfree.chart.labels.ItemLabelAnchor; 25 import org.jfree.chart.labels.ItemLabelPosition; 26 import org.jfree.chart.labels.StandardCategoryItemLabelGenerator; 27 import org.jfree.chart.labels.StandardCategoryToolTipGenerator; 28 import org.jfree.chart.plot.CategoryPlot; 29 import org.jfree.chart.plot.PlotOrientation; 30 import org.jfree.chart.renderer.category.BarRenderer; 31 import org.jfree.chart.renderer.category.LineAndShapeRenderer; 32 import org.jfree.chart.title.TextTitle; 33 import org.jfree.data.category.CategoryDataset; 34 import org.jfree.data.general.DatasetUtilities; 35 import org.jfree.data.general.DefaultPieDataset; 36 import org.jfree.data.general.PieDataset; 37 import org.jfree.ui.TextAnchor; 38 39 public class CreateChartService { 40 41 private static Log log = LogFactory.getLog(CreateChartService.class); 42 43 // 图片的生成路径 44 private static final String CHART_PATH = Config.getString("image.filepath"); 45 46 /** 47 * 生成折线图 48 * 1.解析数据<br> 49 * 2.迭代数据,产出图片数据流,并添加到List<br> 50 * @throws IOException 51 */ 52 public List createLineAndShapeChart(double[][]data , String[]rowKeys,String[] columnKeys,ChartEntity entity) throws IOException { 53 List list = new ArrayList() ; 54 byte[] bytes = new byte[]{} ; 55 // 解析数据 56 Map map = this.parseDataForBarPage(data, rowKeys, columnKeys) ; 57 int pageNum = Integer.parseInt(""+map.get("pageNum")) ; 58 // 迭代,产生图片数据流 59 for(int i=0 ; i<pageNum ; i++){ 60 bytes = createSingleLineAndShapeChart((double[][])(map.get("data"+i)),(String[])(map.get("rowKeys"+i)), 61 (String[])(map.get("columnKeys"+i)),entity) ; 62 list.add(bytes) ; 63 } 64 return list ; 65 } 66 67 /** 68 * 生成单个折线图数据流 69 * @param data 70 * @param rowKeys 71 * @param columnKeys 72 * @param entity 73 * @return 74 * @throws IOException 75 */ 76 public byte[] createSingleLineAndShapeChart(double[][]data , String[]rowKeys,String[] columnKeys,ChartEntity entity) throws IOException { 77 CategoryDataset dataset = getBarData(data, rowKeys, columnKeys); 78 JFreeChart chart = createTimeXYChar(dataset, entity); 79 byte[] bytes = this.createImage(chart, entity) ; 80 return bytes ; 81 } 82 83 84 /** 85 * 生成柱状图<br> 86 * 1.解析数据<br> 87 * 2.迭代数据,产出图片数据流,并添加到List<br> 88 * @param data 数据 89 * @param rowKeys 行 90 * @param columnKeys 列 91 * @param entity 图片配置对象 92 * @return 包含多个图片数据流的List 93 * @throws IOException 94 */ 95 public List createStackedBarChart(double[][]data,String[]rowKeys,String[]columnKeys , ChartEntity entity) throws IOException { 96 // 解析数据 97 List list = new ArrayList() ; 98 byte[] bytes = new byte[]{} ; 99 Map map = this.parseDataForBarPage(data, rowKeys, columnKeys) ; 100 int pageNum = Integer.parseInt(""+map.get("pageNum")) ; 101 // 迭代数据,产出图片数据流,并添加到List 102 for(int i=0 ; i<pageNum ; i++){ 103 bytes = createSingleStackedBarChart((double[][])(map.get("data"+i)),(String[])(map.get("rowKeys"+i)), 104 (String[])(map.get("columnKeys"+i)),entity) ; 105 list.add(bytes) ; 106 } 107 return list ; 108 } 109 110 /** 111 * 解析生成柱状图分页数据 112 * @param data 113 * @param rowKeys 114 * @param columnKeys 115 * @return 116 */ 117 private Map parseDataForBarPage(double[][]data,String[]rowKeys,String[]columnKeys){ 118 Map map = new HashMap() ; 119 120 double [][] pageData = null ; 121 String [] pageColumn = null ; 122 123 int sumColumnNum = columnKeys.length ; // 总列数 124 int indexNum = Config.getInt("image.export.pagesize", 10) ;// 分页的列数 125 int pageNum = sumColumnNum%indexNum==0 ? sumColumnNum/indexNum : sumColumnNum/indexNum+1 ; // 分页数 126 int rowNum = rowKeys.length ; 127 128 // log.debug("data.length="+data.length+"sumColumnNum="+sumColumnNum+" indexNum="+indexNum+" pageNum="+pageNum+" rowNum="+rowNum+" "); 129 130 // 解析传递过来的数据 131 for(int i=0 ; i<pageNum ; i++){ 132 int columnNum = (sumColumnNum-i*indexNum)/indexNum>0 ? indexNum : (sumColumnNum-i*indexNum)%indexNum ;//当前页列数 133 pageData = new double[rowNum][columnNum] ; 134 // 取数据值 135 for(int j=0 ; j<rowNum ; j++){ 136 pageColumn = new String[columnNum] ; 137 for(int k=0 ; k<columnNum ; k ++){ 138 pageData[j][k] = data[j][k+i*indexNum] ; // 数据 139 } 140 } 141 // 取列值 142 for(int j=0 ; j<columnNum ; j++){ 143 pageColumn[j] = columnKeys[j+i*indexNum] ; // 列 144 } 145 // 保存数据并返回 146 map.put("data"+i, pageData) ; 147 map.put("rowKeys"+i, rowKeys) ; 148 map.put("columnKeys"+i, pageColumn) ; 149 } 150 // 保存分页数 151 map.put("pageNum", pageNum); 152 return map ; 153 } 154 155 /** 156 * 解析生成折线图分页数据 157 * @param data 158 * @param rowKeys 159 * @param columnKeys 160 * @return 161 */ 162 private Map parseDataForLinePage(double[][]data,String[]rowKeys,String[]columnKeys){ 163 Map map = new HashMap() ; 164 165 double [][] pageData = null ; 166 String [] pageColumn = null ; 167 168 int sumColumnNum = columnKeys.length ; // 总列数 169 int indexNum = Config.getInt("image.export.pagesize", 10) ;// 分页的列数 170 int pageNum = sumColumnNum%indexNum==0 ? sumColumnNum/indexNum : sumColumnNum/indexNum+1 ; // 分页数 171 int rowNum = rowKeys.length ; 172 173 // log.debug("data.length="+data.length+"sumColumnNum="+sumColumnNum+" indexNum="+indexNum+" pageNum="+pageNum+" rowNum="+rowNum+" "); 174 175 // 解析传递过来的数据 176 for(int i=0 ; i<pageNum ; i++){ 177 int columnNum = (sumColumnNum-i*indexNum)/indexNum>0 ? indexNum : (sumColumnNum-i*indexNum)%indexNum ;//当前页列数 178 pageData = new double[rowNum][columnNum] ; 179 // 取数据值 180 for(int j=0 ; j<rowNum ; j++){ 181 pageColumn = new String[columnNum] ; 182 for(int k=0 ; k<columnNum ; k ++){ 183 pageData[j][k] = data[j][k+i*indexNum] ; // 数据 184 } 185 } 186 // 取列值 187 for(int j=0 ; j<columnNum ; j++){ 188 pageColumn[j] = columnKeys[j+i*indexNum] ; // 列 189 } 190 // 保存数据并返回 191 map.put("data"+i, pageData) ; 192 map.put("rowKeys"+i, rowKeys) ; 193 map.put("columnKeys"+i, pageColumn) ; 194 } 195 // 保存分页数 196 map.put("pageNum", pageNum); 197 return map ; 198 } 199 200 /** 201 * 生成单个堆栈柱状图 202 * @return 图片数据流 203 * @throws IOException 204 */ 205 public byte[] createSingleStackedBarChart(double[][]data,String[]rowKeys,String[]columnKeys , ChartEntity entity) throws IOException { 206 CategoryDataset dataset = getBarData(data, rowKeys, columnKeys); 207 JFreeChart chart = createStackedBarChart(dataset, entity); 208 byte[] bytes = this.createImage(chart, entity) ; 209 return bytes ; 210 } 211 212 // 柱状图,折线图 数据集 213 private CategoryDataset getBarData(double[][] data, String[] rowKeys, 214 String[] columnKeys) { 215 return DatasetUtilities.createCategoryDataset(rowKeys, columnKeys, data); 216 217 } 218 219 /** 220 * 判断文件夹是否存在,如果不存在则新建 221 * @param chartPath 222 */ 223 private void isChartPathExist(String chartPath) { 224 File file = new File(chartPath); 225 if (!file.exists()) { 226 file.mkdirs(); 227 } 228 } 229 230 /** 231 * 折线图 232 * 233 * @param chartTitle 234 * @param x 235 * @param y 236 * @param xyDataset 237 * @param charName 238 * @return 239 */ 240 private JFreeChart createTimeXYChar(CategoryDataset xyDataset,ChartEntity entity) { 241 242 JFreeChart chart = ChartFactory.createLineChart( 243 entity.getTitle(), 244 entity.getXname(), 245 entity.getYname(), 246 xyDataset, 247 PlotOrientation.VERTICAL, 248 true, 249 true, 250 false); 251 252 chart.setTextAntiAlias(false); 253 chart.setBackgroundPaint(Color.WHITE); 254 255 CategoryPlot categoryplot = (CategoryPlot) chart.getPlot(); 256 // 没有数据时显示 257 this.configNoData(chart, "没有查询到数据 !") ; 258 259 // x轴 // 分类轴网格是否可见 260 categoryplot.setDomainGridlinesVisible(true); 261 // y轴 //数据轴网格是否可见 262 categoryplot.setRangeGridlinesVisible(true); 263 264 categoryplot.setRangeGridlinePaint(Color.WHITE);// 虚线色彩 265 266 categoryplot.setDomainGridlinePaint(Color.WHITE);// 虚线色彩 267 268 categoryplot.setBackgroundPaint(Color.lightGray); 269 270 271 // 配置字体 272 this.configFont(chart) ; 273 274 // x轴设置 275 CategoryAxis domainAxis = categoryplot.getDomainAxis(); 276 277 // 设置距离图片左端距离 278 domainAxis.setLowerMargin(0.0); 279 // 设置距离图片右端距离 280 domainAxis.setUpperMargin(0.0); 281 domainAxis.setTickLabelPaint(Color.BLUE) ; 282 domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45); // 横轴上的label斜显示 283 284 NumberAxis numberaxis = (NumberAxis) categoryplot.getRangeAxis(); 285 numberaxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); 286 numberaxis.setAutoRangeIncludesZero(true); 287 288 // 获得renderer 注意这里是下嗍造型到lineandshaperenderer!! 289 LineAndShapeRenderer lineandshaperenderer = (LineAndShapeRenderer) categoryplot.getRenderer(); 290 lineandshaperenderer.setBaseShapesVisible(true); // series 点(即数据点)可见 291 lineandshaperenderer.setBaseLinesVisible(true); // series 点(即数据点)间有连线可见 292 293 // 显示折点数据 294 lineandshaperenderer.setBaseItemLabelGenerator(new 295 StandardCategoryItemLabelGenerator()); 296 lineandshaperenderer.setBaseItemLabelsVisible(true); 297 298 return chart ; 299 } 300 301 /** 302 * 堆栈柱状图 303 * 304 * @param dataset 305 * @param xName 306 * @param yName 307 * @param chartTitle 308 * @param charName 309 * @return 310 */ 311 private JFreeChart createStackedBarChart(CategoryDataset dataset, ChartEntity entity) { 312 313 JFreeChart chart = ChartFactory.createStackedBarChart3D( 314 entity.getTitle(), 315 entity.getXname(), 316 entity.getYname(), 317 dataset, 318 PlotOrientation.VERTICAL, 319 true, 320 false, 321 false ); 322 323 // 没有数据配置 324 this.configNoData(chart,"没有查询到数据 !") ; 325 326 // 配置字体 327 this.configFont(chart) ; 328 329 // 配置 Renderer 330 this.configBarRenderer(chart) ; 331 332 // 其他配置 333 this.configOtherForBar(chart) ; 334 335 return chart ; 336 } 337 338 /** 339 * 配置字体 340 * @param chart JFreeChart 对象 341 */ 342 private void configFont(JFreeChart chart){ 343 // 配置字体 344 Font xfont = new Font("宋体",Font.PLAIN,12) ;// X轴 345 Font yfont = new Font("宋体",Font.PLAIN,12) ;// Y轴 346 Font kfont = new Font("宋体",Font.PLAIN,12) ;// 底部 347 Font titleFont = new Font("隶书", Font.BOLD , 25) ; // 图片标题 348 CategoryPlot plot = chart.getCategoryPlot();// 图形的绘制结构对象 349 350 // 图片标题 351 chart.setTitle(new TextTitle(chart.getTitle().getText(),titleFont)); 352 353 // 底部 354 chart.getLegend().setItemFont(kfont); 355 356 // X 轴 357 CategoryAxis domainAxis = plot.getDomainAxis(); 358 domainAxis.setLabelFont(xfont);// 轴标题 359 domainAxis.setTickLabelFont(xfont);// 轴数值 360 domainAxis.setTickLabelPaint(Color.BLUE) ; // 字体颜色 361 domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45); // 横轴上的label斜显示 362 363 // Y 轴 364 ValueAxis rangeAxis = plot.getRangeAxis(); 365 rangeAxis.setLabelFont(yfont); 366 rangeAxis.setLabelPaint(Color.BLUE) ; // 字体颜色 367 rangeAxis.setTickLabelFont(yfont); 368 369 } 370 371 /** 372 * 配置柱状图 373 * @param chart 374 */ 375 private void configBarRenderer(JFreeChart chart){ 376 377 CategoryPlot categoryplot = (CategoryPlot)chart.getPlot(); 378 // 自定义显示柱子上的总值 379 ExtendedStackedBarRenderer extendedstackedbarrenderer = new ExtendedStackedBarRenderer(); 380 extendedstackedbarrenderer.setBaseItemLabelsVisible(true); 381 extendedstackedbarrenderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator()); 382 extendedstackedbarrenderer.setBaseToolTipGenerator(new StandardCategoryToolTipGenerator()); 383 categoryplot.setRenderer(extendedstackedbarrenderer); 384 385 BarRenderer barrenderer = (BarRenderer)categoryplot.getRenderer(); 386 barrenderer.setDrawBarOutline(false); 387 barrenderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator()); 388 barrenderer.setBaseItemLabelsVisible(true); 389 barrenderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.CENTER, TextAnchor.CENTER)); 390 barrenderer.setBaseNegativeItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.CENTER, TextAnchor.CENTER)); 391 392 // 柱子显示数值 393 // barrenderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator("{2}",new DecimalFormat("0.0%"))); 394 // barrenderer.setItemLabelGenerator(new StandardCategoryItemLabelGenerator()); 395 barrenderer.setItemLabelFont(new Font("Arial Unicode MS",Font.PLAIN,9)); 396 barrenderer.setItemLabelsVisible(true); 397 398 // 如果数值没有显示空间,设置显示格式 399 // ItemLabelPosition itemLabelPositionFallback=new ItemLabelPosition( 400 // ItemLabelAnchor.OUTSIDE12,TextAnchor.BASELINE_LEFT, 401 // TextAnchor.HALF_ASCENT_LEFT,0D); 402 // barrenderer.setPositiveItemLabelPositionFallback(itemLabelPositionFallback); 403 // barrenderer.setNegativeItemLabelPositionFallback(itemLabelPositionFallback); 404 405 categoryplot.setRenderer(barrenderer) ; 406 } 407 408 /** 409 * 配置没有数据时的显示信息 410 * @param chart 411 */ 412 private void configNoData(JFreeChart chart,String message){ 413 CategoryPlot categoryplot = (CategoryPlot)chart.getPlot(); 414 // 没有数据时的显示 415 categoryplot.setNoDataMessage(message) ; 416 categoryplot.setNoDataMessageFont(new Font("黑体",Font.BOLD,25)) ; 417 } 418 419 /** 420 * 其他配置 421 * @param chart 422 */ 423 private void configOtherForBar(JFreeChart chart){ 424 425 chart.setTextAntiAlias(false); // 图例字体清晰 426 427 chart.setBackgroundPaint(Color.WHITE); // 背景颜色 428 429 CategoryPlot plot = chart.getCategoryPlot();// 图形的绘制结构对象 430 NumberAxis numberaxis = (NumberAxis) plot.getRangeAxis(); 431 numberaxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); 432 numberaxis.setAutoRangeIncludesZero(true); 433 } 434 435 /** 436 * 创建图片的数据流 437 * @param chart 438 * @param entity 图片配置对象 439 * @return 图片数据流 440 * @throws IOException 441 */ 442 private byte[] createImage(JFreeChart chart , ChartEntity entity) throws IOException{ 443 return ChartUtilities.encodeAsPNG(chart.createBufferedImage(entity.getWidth(), entity.getHeight())) ; 444 } 445 446 /** 447 * 创建图片文件到硬盘 448 * @param chart 449 * @param entity 450 * @throws IOException 451 */ 452 private void createImageFile(JFreeChart chart , ChartEntity entity) throws IOException{ 453 FileOutputStream fos_jpg = null; 454 try { 455 isChartPathExist(CHART_PATH); 456 String chartName = CHART_PATH + entity.getFileName(); 457 fos_jpg = new FileOutputStream(chartName); 458 ChartUtilities.writeChartAsJPEG(fos_jpg, chart, entity.getWidth(), entity.getHeight()) ; 459 } catch (Exception e) { 460 e.printStackTrace(); 461 } finally { 462 try { 463 fos_jpg.close(); 464 } catch (Exception e) { 465 e.printStackTrace(); 466 } 467 } 468 } 469 }