Как сделать так, чтобы гистограмма находилась между отметками? - PullRequest
0 голосов
/ 08 января 2020

Я добавил на фотографиях ниже пример того, что я хочу.

Это то, что я получаю. What I get

Это то, что я хочу. What I want

Я искал в библиотеке, чтобы попытаться найти что-то, чтобы внести это изменение, но я не могу его найти.

В качестве альтернативы Есть ли способ добавить отступы сверху или снизу? Основная проблема в том, что я не хочу, чтобы бар касался верхней или нижней границы графика.

Это XDDFChart, здесь приведен соответствующий код.

  XDDFCategoryAxis leftAxis = chart.createCategoryAxis(AxisPosition.LEFT);
  leftAxis.setTitle("Name");


  XDDFValueAxis bottomAxis = chart.createValueAxis(AxisPosition.BOTTOM);
  bottomAxis.setTitle("Volume");

1 Ответ

1 голос
/ 08 января 2020

В столбчатых диаграммах для оси значений должно быть установлено значение crossBetween val="between", поэтому ось значений пересекает ось категорий между категориями. В противном случае первая и последняя категории находятся точно в точках пересечения, а столбцы видны только наполовину.

Кроме того, левая ось никогда не будет осью категории, а нижняя ось никогда не будет осью значений, даже если для гистограмм, которые отображает BarDirection.BAR вместо BarDirection.COL. Там только направление бара XDDFBarChartData отличается. Оси остаются неизменными.

Так что для XDDFChart в целом, столбец с BarDirection.BAR должен иметь вид:

...
// create axis
XDDFCategoryAxis categoryAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
categoryAxis.setTickLabelPosition(AxisTickLabelPosition.NONE);
XDDFValueAxis valueAxis = chart.createValueAxis(AxisPosition.LEFT);
valueAxis.setCrosses(AxisCrosses.AUTO_ZERO);
// Set AxisCrossBetween, so the left axis crosses the category axis between the categories.
// Else first and last category is exactly on cross points and the bars are only half visible.
valueAxis.setCrossBetween(AxisCrossBetween.BETWEEN);

// create chart data
XDDFBarChartData data = (XDDFBarChartData)chart.createData(ChartTypes.BAR, categoryAxis, valueAxis);
data.setBarDirection(BarDirection.BAR);
 ...

Завершить пример создания XWPFChart в Word документ:

import java.io.*;

import org.apache.poi.xwpf.usermodel.*;

import org.apache.poi.ss.util.*;
import org.apache.poi.util.Units;

import org.apache.poi.xddf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;

import org.apache.poi.xssf.usermodel.*;

public class CreateWordXDDFChart {

 // methode to set title in the data sheet without creating a Table but using the sheet data only
 // creating a Table is not really necessary
 static CellReference setTitleInDataSheet(XDDFChart chart, String title, int column) throws Exception {
  XSSFWorkbook workbook = chart.getWorkbook();
  XSSFSheet sheet = workbook.getSheetAt(0);
  XSSFRow row = sheet.getRow(0); if (row == null) row = sheet.createRow(0);
  XSSFCell cell = row.getCell(column); if (cell == null) cell = row.createCell(column);
  cell.setCellValue(title);
  return new CellReference(sheet.getSheetName(), 0, column, true, true);
 }

 // methode to fill a series data into the underlying sheet
 static void fillSheet(XDDFChart chart, XDDFDataSource<?> categoryData, XDDFNumericalDataSource<?> valuesData) throws Exception {
  XSSFWorkbook workbook = chart.getWorkbook();
  XSSFSheet sheet = workbook.getSheetAt(0);
  int numOfPoints = categoryData.getPointCount();
  for (int i = 0; i < numOfPoints; i++) {
   XSSFRow row = sheet.getRow(i + 1); if (row == null) row = sheet.createRow(i + 1); // first row is for title
   XSSFCell cell = row.getCell(categoryData.getColIndex()); if (cell == null) cell = row.createCell(categoryData.getColIndex());
   cell.setCellValue(categoryData.getPointAt(i).toString());
   cell = row.getCell(valuesData.getColIndex()); if (cell == null) cell = row.createCell(valuesData.getColIndex());
   cell.setCellValue(valuesData.getPointAt(i).doubleValue());
  }
 }

 public static void main(String[] args) throws Exception {
  try (XWPFDocument document = new XWPFDocument()) {

   // create the data
   String[] categories = new String[]{"C1", "C2", "C3"};
   Double[] valuesA = new Double[]{300d, 20d, 10d};

   // create the chart
   XWPFChart chart = document.createChart(15*Units.EMU_PER_CENTIMETER, 10*Units.EMU_PER_CENTIMETER);

   // create data sources
   int numOfPoints = categories.length;
   String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
   String valuesDataRangeA = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
   XDDFDataSource<String> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0);
   XDDFNumericalDataSource<Double> valuesDataA = XDDFDataSourcesFactory.fromArray(valuesA, valuesDataRangeA, 1);

   // create axis
   XDDFCategoryAxis categoryAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
   categoryAxis.setTickLabelPosition(AxisTickLabelPosition.NONE);
   XDDFValueAxis valueAxis = chart.createValueAxis(AxisPosition.LEFT);
   valueAxis.setCrosses(AxisCrosses.AUTO_ZERO);
   // Set AxisCrossBetween, so the left axis crosses the category axis between the categories.
   // Else first and last category is exactly on cross points and the bars are only half visible.
   valueAxis.setCrossBetween(AxisCrossBetween.BETWEEN);

   // create chart data
   XDDFBarChartData data = (XDDFBarChartData)chart.createData(ChartTypes.BAR, categoryAxis, valueAxis);
   data.setBarDirection(BarDirection.BAR);

   // create series
   data.setVaryColors(true);
   XDDFBarChartData.Series series = (XDDFBarChartData.Series)data.addSeries(categoriesData, valuesDataA);
   // XDDFChart.setSheetTitle is buggy. It creates a Table but only half way and incomplete.
   // Excel cannot opening the workbook after creating that incomplete Table.
   // So updating the chart data in Word is not possible.
   //series.setTitle("Ser1", chart.setSheetTitle("Ser1", 1));
   series.setTitle("Ser1", setTitleInDataSheet(chart, "Ser1", 1));
   // since apache oi 4.1.1 XDDFChart does not fill the series in the sheet while plot. Apache poi 4.1.0 had done this: https://svn.apache.org/viewvc/poi/tags/REL_4_1_0/src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFChart.java?view=markup#l363
   // so we need doing this for each series now
   fillSheet(chart, categoriesData, valuesDataA);

   // plot chart data
   chart.plot(data);

   // Write the output to a file
   try (FileOutputStream fileOut = new FileOutputStream("CreateWordXDDFChart.docx")) {
    document.write(fileOut);
   }
  }
 }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...