You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ExcelChartWithTargetLine.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. * ====================================================================
  3. * Licensed to the Apache Software Foundation (ASF) under one or more
  4. * contributor license agreements. See the NOTICE file distributed with
  5. * this work for additional information regarding copyright ownership.
  6. * The ASF licenses this file to You under the Apache License, Version 2.0
  7. * (the "License"); you may not use this file except in compliance with
  8. * the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. * ====================================================================
  18. */
  19. package org.apache.poi.examples.xssf.usermodel;
  20. import java.io.FileOutputStream;
  21. import org.apache.poi.ss.util.CellRangeAddress;
  22. import org.apache.poi.ss.util.CellReference;
  23. import org.apache.poi.xddf.usermodel.PresetColor;
  24. import org.apache.poi.xddf.usermodel.XDDFColor;
  25. import org.apache.poi.xddf.usermodel.XDDFFillProperties;
  26. import org.apache.poi.xddf.usermodel.XDDFLineProperties;
  27. import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
  28. import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
  29. import org.apache.poi.xddf.usermodel.chart.AxisPosition;
  30. import org.apache.poi.xddf.usermodel.chart.AxisTickLabelPosition;
  31. import org.apache.poi.xddf.usermodel.chart.BarDirection;
  32. import org.apache.poi.xddf.usermodel.chart.ChartTypes;
  33. import org.apache.poi.xddf.usermodel.chart.LegendPosition;
  34. import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
  35. import org.apache.poi.xddf.usermodel.chart.XDDFCategoryAxis;
  36. import org.apache.poi.xddf.usermodel.chart.XDDFCategoryDataSource;
  37. import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
  38. import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
  39. import org.apache.poi.xddf.usermodel.chart.XDDFLegendEntry;
  40. import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
  41. import org.apache.poi.xddf.usermodel.chart.XDDFScatterChartData;
  42. import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
  43. import org.apache.poi.xddf.usermodel.text.XDDFRunProperties;
  44. import org.apache.poi.xssf.usermodel.XSSFCell;
  45. import org.apache.poi.xssf.usermodel.XSSFChart;
  46. import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
  47. import org.apache.poi.xssf.usermodel.XSSFDrawing;
  48. import org.apache.poi.xssf.usermodel.XSSFRow;
  49. import org.apache.poi.xssf.usermodel.XSSFSheet;
  50. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  51. /**
  52. * This example is based on original contributions by Axel Richter
  53. *
  54. * <em>Note from original author</em>:
  55. * This only works for Excel since OpenOffice or LibreOffice Calc is not able having series having literal numeric values set.
  56. */
  57. public final class ExcelChartWithTargetLine {
  58. private ExcelChartWithTargetLine() {}
  59. private static final int NUM_OF_ROWS = 6;
  60. private static void createChart(XSSFChart chart, XSSFSheet sheet, int[] chartedCols, double target) {
  61. // some colors
  62. XDDFFillProperties[] fills = new XDDFFillProperties[] {
  63. new XDDFSolidFillProperties(XDDFColor.from(PresetColor.TURQUOISE)),
  64. new XDDFSolidFillProperties(XDDFColor.from(PresetColor.CHARTREUSE)),
  65. new XDDFSolidFillProperties(XDDFColor.from(PresetColor.LAVENDER)),
  66. new XDDFSolidFillProperties(XDDFColor.from(PresetColor.CHOCOLATE)),
  67. new XDDFSolidFillProperties(XDDFColor.from(PresetColor.TOMATO)),
  68. new XDDFSolidFillProperties(XDDFColor.from(PresetColor.PLUM))
  69. };
  70. XDDFLineProperties solidTurquoise = new XDDFLineProperties(fills[0]);
  71. XDDFLineProperties solidTomato = new XDDFLineProperties(fills[4]);
  72. XDDFLineProperties solidPlum = new XDDFLineProperties(fills[5]);
  73. XDDFSolidFillProperties solidAlmond = new XDDFSolidFillProperties(XDDFColor.from(PresetColor.BLANCHED_ALMOND));
  74. XDDFSolidFillProperties solidGray = new XDDFSolidFillProperties(XDDFColor.from(PresetColor.DARK_SLATE_GRAY));
  75. // the bar chart
  76. XDDFCategoryAxis barCategories = chart.createCategoryAxis(AxisPosition.BOTTOM);
  77. XDDFValueAxis leftValues = chart.createValueAxis(AxisPosition.LEFT);
  78. leftValues.crossAxis(barCategories);
  79. barCategories.crossAxis(leftValues);
  80. // colored major grid lines
  81. leftValues.getOrAddMajorGridProperties().setLineProperties(solidTomato);
  82. //colored axis line
  83. leftValues.getOrAddShapeProperties().setLineProperties(solidPlum);
  84. // axis font
  85. XDDFRunProperties props = leftValues.getOrAddTextProperties();
  86. props.setFontSize(14.0);
  87. props.setFillProperties(fills[5]);
  88. XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, barCategories, leftValues);
  89. bar.setVaryColors(true);
  90. bar.setBarDirection(chartedCols.length > 1 ? BarDirection.COL : BarDirection.BAR);
  91. for (int c : chartedCols) {
  92. // the data sources
  93. XDDFCategoryDataSource xs = XDDFDataSourcesFactory.fromStringCellRange(sheet,
  94. new CellRangeAddress(1, NUM_OF_ROWS, 0, 0));
  95. XDDFNumericalDataSource<Double> ys = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
  96. new CellRangeAddress(1, NUM_OF_ROWS, c, c));
  97. XDDFBarChartData.Series series = (XDDFBarChartData.Series) bar.addSeries(xs, ys);
  98. series.setTitle(null, new CellReference(sheet.getSheetName(), 0, c, true, true));
  99. series.setFillProperties(fills[c]);
  100. series.setLineProperties(solidTurquoise); // bar border color different from fill
  101. }
  102. chart.plot(bar);
  103. // target line
  104. // line of a scatter chart from 0 (min) to 1 (max) having value of target
  105. XDDFValueAxis scatterX = chart.createValueAxis(AxisPosition.TOP);
  106. scatterX.setVisible(false);
  107. scatterX.setTickLabelPosition(AxisTickLabelPosition.NONE);
  108. XDDFValueAxis scatterY = chart.createValueAxis(AxisPosition.RIGHT);
  109. scatterY.setVisible(false);
  110. scatterY.setTickLabelPosition(AxisTickLabelPosition.NONE);
  111. scatterX.crossAxis(scatterY);
  112. scatterY.crossAxis(scatterX);
  113. if (chartedCols.length > 1) {
  114. scatterX.setMaximum(1.0);
  115. } else {
  116. scatterY.setMaximum(1.0);
  117. }
  118. XDDFScatterChartData scatter = (XDDFScatterChartData) chart.createData(ChartTypes.SCATTER, scatterX, scatterY);
  119. scatter.setVaryColors(false);
  120. // This only works for Excel since OpenOffice or LibreOffice Calc does not support literal numeric data series.
  121. XDDFNumericalDataSource<Double> targetDS = XDDFDataSourcesFactory.fromArray(new Double[] { target, target });
  122. XDDFNumericalDataSource<Double> zeroOneDS = XDDFDataSourcesFactory.fromArray(new Double[] { 0.0, 1.0 });
  123. if (chartedCols.length > 1) {
  124. // BarDirection.COL then X axis is from 0 to 1 and Y axis is target axis
  125. scatter.addSeries(zeroOneDS, targetDS).setLineProperties(solidTurquoise);
  126. } else {
  127. // BarDirection.BAR then X axis is target axis and Y axis is from 0 to 1
  128. scatter.addSeries(targetDS, zeroOneDS).setLineProperties(solidTurquoise);
  129. }
  130. chart.plot(scatter);
  131. // legend
  132. if (chartedCols.length > 1) {
  133. XDDFChartLegend legend = chart.getOrAddLegend();
  134. legend.setPosition(LegendPosition.LEFT);
  135. legend.setOverlay(false);
  136. // delete additional target line series legend entry
  137. XDDFLegendEntry entry = legend.addEntry();
  138. entry.setIndex(0);
  139. entry.setDelete(true);
  140. }
  141. // customize the chart
  142. // do not auto delete the title
  143. chart.setAutoTitleDeleted(false);
  144. // plot area background and border line
  145. XDDFShapeProperties chartProps = chart.getOrAddShapeProperties();
  146. chartProps.setFillProperties(solidAlmond);
  147. chartProps.setLineProperties(new XDDFLineProperties(solidGray));
  148. // line style of cat axis
  149. XDDFLineProperties categoriesProps = new XDDFLineProperties(solidGray);
  150. categoriesProps.setWidth(2.1);
  151. barCategories.getOrAddShapeProperties().setLineProperties(categoriesProps);
  152. }
  153. private static XSSFClientAnchor createAnchor(XSSFDrawing drawing, int[] chartedCols) {
  154. if (chartedCols.length > 1) {
  155. return drawing.createAnchor(0, 0, 0, 0, 0, 8, 10, 23);
  156. } else {
  157. return drawing.createAnchor(0, 0, 0, 0, 0, 8, 5, 23);
  158. }
  159. }
  160. public static void main(String[] args) throws Exception {
  161. try (XSSFWorkbook workbook = new XSSFWorkbook()) {
  162. XSSFSheet sheet = workbook.createSheet("targetline");
  163. final int NUM_OF_COLUMNS = 4;
  164. // create some data
  165. XSSFRow row;
  166. XSSFCell cell;
  167. String[] headings = new String[] { "Year", "Male", "Female", "Other" };
  168. int rowIndex = 0;
  169. row = sheet.createRow(rowIndex);
  170. for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
  171. cell = row.createCell(colIndex);
  172. cell.setCellValue(headings[colIndex]);
  173. }
  174. double[][] values = new double[][] { new double[] { 1980, 56.0, 44.1, 12.2 },
  175. new double[] { 1985, 34.5, 41.0, 4 }, new double[] { 1990, 65.0, 68.5, 9.1 },
  176. new double[] { 1995, 34.7, 47.6, 4.9 }, new double[] { 2000, 23.0, 64.5, 11.1 },
  177. new double[] { 2005, 56.3, 69.8, 9.5 } };
  178. for (; rowIndex < NUM_OF_ROWS; rowIndex++) {
  179. row = sheet.createRow(rowIndex + 1);
  180. for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
  181. cell = row.createCell(colIndex);
  182. cell.setCellValue(values[rowIndex][colIndex]);
  183. }
  184. }
  185. int[] chartedCols = new int[] { 1, 2 , 3 };
  186. XSSFDrawing drawing = sheet.createDrawingPatriarch();
  187. XSSFClientAnchor anchor = createAnchor(drawing, chartedCols);
  188. XSSFChart chart = drawing.createChart(anchor);
  189. createChart(chart, sheet, chartedCols, 42.0);
  190. try (FileOutputStream fos = new FileOutputStream("ExcelChartWithTargetLine.xlsx")) {
  191. workbook.write(fos);
  192. }
  193. }
  194. }
  195. }