Форматирование диаграмм презентаций в Python
Обзор
Эта статья объясняет, как форматировать диаграммы в презентациях PowerPoint, используя Aspose.Slides. Она показывает, как настраивать ключевые элементы диаграммы, такие как оси, линии сетки, заголовки, легенды, область построения и заливки стен, чтобы улучшить внешний вид и читаемость данных диаграммы. Также она демонстрирует, как устанавливать свойства шрифта для текста диаграммы, применять предустановленные числовые форматы к данным диаграммы и включать закруглённые углы области диаграммы. Вместе эти примеры показывают, как управлять как визуальным стилем, так и представлением данных диаграмм в презентации.
Форматирование сущностей диаграммы
Используйте Chart для форматирования заголовков диаграммы, осей, линий сетки, легенд и области построения. Этот пример создает линейную диаграмму с маркерами и данными по умолчанию, затем применяет отдельные стили текста и линии к её оси значений и оси категорий. Размеры шрифта и толщины линий указаны в пунктах; подписи категорий повернуты на 45 градусов.
Ось значений использует setNumberFormat независимо от исходных ячеек. Её диапазон идёт от -2 до 15, с основными интервалами 2 и второстепенными интервалами 0,5. Пример также комбинирует процентное форматирование с setDisplayUnit, установленным в тысячи, поэтому адаптируйте эти настройки к смыслу и масштабу ваших данных. Легенда остается вне области построения, потому что setOverlay вызывается с False. Заполнение задней стенки и пола настраивается через getBackWall и getFloor, но эти поверхности видны только в 3D‑диаграммах.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import ChartType, DisplayUnitType, FillType, FontData, LineDashStyle, NullableBool, Presentation, PresetColor, SaveFormat, TickLabelPositionType
Color = jpype.JClass("java.awt.Color")
presentation = Presentation()
try:
slide = presentation.getSlides().get_Item(0)
chart = slide.getShapes().addChart(ChartType.LineWithMarkers, 50, 50, 500, 400)
chart.setTitle(True)
chart.getChartTitle().addTextFrameForOverriding("")
chart_title = chart.getChartTitle().getTextFrameForOverriding().getParagraphs().get_Item(0).getPortions().get_Item(0)
chart_title.setText("Sample Chart")
chart_title.getPortionFormat().getFillFormat().setFillType(FillType.Solid)
chart_title.getPortionFormat().getFillFormat().getSolidFillColor().setColor(Color.GRAY)
chart_title.getPortionFormat().setFontHeight(20)
chart_title.getPortionFormat().setFontBold(NullableBool.True_)
chart_title.getPortionFormat().setFontItalic(NullableBool.True_)
chart.getAxes().getVerticalAxis().getMajorGridLinesFormat().getLine().getFillFormat().setFillType(FillType.Solid)
chart.getAxes().getVerticalAxis().getMajorGridLinesFormat().getLine().getFillFormat().getSolidFillColor().setColor(Color.BLUE)
chart.getAxes().getVerticalAxis().getMajorGridLinesFormat().getLine().setWidth(5)
chart.getAxes().getVerticalAxis().getMajorGridLinesFormat().getLine().setDashStyle(LineDashStyle.DashDot)
chart.getAxes().getVerticalAxis().getMinorGridLinesFormat().getLine().getFillFormat().setFillType(FillType.Solid)
chart.getAxes().getVerticalAxis().getMinorGridLinesFormat().getLine().getFillFormat().getSolidFillColor().setColor(Color.RED)
chart.getAxes().getVerticalAxis().getMinorGridLinesFormat().getLine().setWidth(3)
chart.getAxes().getVerticalAxis().setNumberFormatLinkedToSource(False)
chart.getAxes().getVerticalAxis().setDisplayUnit(DisplayUnitType.Thousands)
chart.getAxes().getVerticalAxis().setNumberFormat("0.0%")
chart.getAxes().getVerticalAxis().setAutomaticMajorUnit(False)
chart.getAxes().getVerticalAxis().setAutomaticMaxValue(False)
chart.getAxes().getVerticalAxis().setAutomaticMinorUnit(False)
chart.getAxes().getVerticalAxis().setAutomaticMinValue(False)
chart.getAxes().getVerticalAxis().setMaxValue(15)
chart.getAxes().getVerticalAxis().setMinValue(-2)
chart.getAxes().getVerticalAxis().setMinorUnit(0.5)
chart.getAxes().getVerticalAxis().setMajorUnit(2.0)
value_axis_text = chart.getAxes().getVerticalAxis().getTextFormat().getPortionFormat()
value_axis_text.setFontBold(NullableBool.True_)
value_axis_text.setFontHeight(16)
value_axis_text.setFontItalic(NullableBool.True_)
value_axis_text.getFillFormat().setFillType(FillType.Solid)
value_axis_text.getFillFormat().getSolidFillColor().setPresetColor(PresetColor.DarkGreen)
value_axis_font = FontData("Times New Roman")
value_axis_text.setLatinFont(value_axis_font)
chart.getAxes().getVerticalAxis().setTitle(True)
chart.getAxes().getVerticalAxis().getTitle().addTextFrameForOverriding("")
value_axis_title = chart.getAxes().getVerticalAxis().getTitle().getTextFrameForOverriding().getParagraphs().get_Item(0).getPortions().get_Item(0)
value_axis_title.setText("Primary Axis")
value_axis_title.getPortionFormat().getFillFormat().setFillType(FillType.Solid)
value_axis_title.getPortionFormat().getFillFormat().getSolidFillColor().setColor(Color.GRAY)
value_axis_title.getPortionFormat().setFontHeight(20)
value_axis_title.getPortionFormat().setFontBold(NullableBool.True_)
value_axis_title.getPortionFormat().setFontItalic(NullableBool.True_)
chart.getAxes().getHorizontalAxis().getMajorGridLinesFormat().getLine().getFillFormat().setFillType(FillType.Solid)
category_grid_color = Color(0, 128, 0)
chart.getAxes().getHorizontalAxis().getMajorGridLinesFormat().getLine().getFillFormat().getSolidFillColor().setColor(category_grid_color)
chart.getAxes().getHorizontalAxis().getMajorGridLinesFormat().getLine().setWidth(5)
chart.getAxes().getHorizontalAxis().getMinorGridLinesFormat().getLine().getFillFormat().setFillType(FillType.Solid)
chart.getAxes().getHorizontalAxis().getMinorGridLinesFormat().getLine().getFillFormat().getSolidFillColor().setColor(Color.YELLOW)
chart.getAxes().getHorizontalAxis().getMinorGridLinesFormat().getLine().setWidth(3)
category_axis_text = chart.getAxes().getHorizontalAxis().getTextFormat().getPortionFormat()
category_axis_text.setFontBold(NullableBool.True_)
category_axis_text.setFontHeight(16)
category_axis_text.setFontItalic(NullableBool.True_)
category_axis_text.getFillFormat().setFillType(FillType.Solid)
category_axis_text.getFillFormat().getSolidFillColor().setColor(Color.BLUE)
category_axis_font = FontData("Arial")
category_axis_text.setLatinFont(category_axis_font)
chart.getAxes().getHorizontalAxis().setTitle(True)
chart.getAxes().getHorizontalAxis().getTitle().addTextFrameForOverriding("")
category_axis_title = chart.getAxes().getHorizontalAxis().getTitle().getTextFrameForOverriding().getParagraphs().get_Item(0).getPortions().get_Item(0)
category_axis_title.setText("Sample Category")
category_axis_title.getPortionFormat().getFillFormat().setFillType(FillType.Solid)
category_axis_title.getPortionFormat().getFillFormat().getSolidFillColor().setColor(Color.GRAY)
category_axis_title.getPortionFormat().setFontHeight(20)
category_axis_title.getPortionFormat().setFontBold(NullableBool.True_)
category_axis_title.getPortionFormat().setFontItalic(NullableBool.True_)
chart.getAxes().getHorizontalAxis().setTickLabelPosition(TickLabelPositionType.Low)
chart.getAxes().getHorizontalAxis().setTickLabelRotationAngle(45)
legend_text = chart.getLegend().getTextFormat().getPortionFormat()
legend_text.setFontBold(NullableBool.True_)
legend_text.setFontHeight(16)
legend_text.setFontItalic(NullableBool.True_)
legend_text.getFillFormat().setFillType(FillType.Solid)
legend_text.getFillFormat().getSolidFillColor().setPresetColor(PresetColor.DarkRed)
chart.getLegend().setOverlay(False)
chart.getBackWall().setThickness(1)
chart.getBackWall().getFormat().getFill().setFillType(FillType.Solid)
back_wall_color = Color(255, 165, 0)
chart.getBackWall().getFormat().getFill().getSolidFillColor().setColor(back_wall_color)
chart.getFloor().getFormat().getFill().setFillType(FillType.Solid)
chart.getFloor().getFormat().getFill().getSolidFillColor().setColor(Color.RED)
chart.getPlotArea().getFormat().getFill().setFillType(FillType.Solid)
chart.getPlotArea().getFormat().getFill().getSolidFillColor().setPresetColor(PresetColor.LightCyan)
presentation.save("FormattedChart_out.pptx", SaveFormat.Pptx)
finally:
presentation.dispose()
Установить свойства шрифта для диаграммы
Задайте размер шрифта по умолчанию для текста диаграммы через Chart.getTextFormat. Пример создает сгруппированную столбчатую диаграмму с 20‑пунктовым шрифтом и включает подписи значений для первого ряда с помощью setShowValue. Текстовые элементы с собственными явными настройками шрифта могут переопределять значение по умолчанию диаграммы.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import ChartType, Presentation, SaveFormat
presentation = Presentation()
try:
slide = presentation.getSlides().get_Item(0)
chart = slide.getShapes().addChart(ChartType.ClusteredColumn, 100, 100, 500, 400)
chart.getTextFormat().getPortionFormat().setFontHeight(20)
chart.getChartData().getSeries().get_Item(0).getLabels().getDefaultDataLabelFormat().setShowValue(True)
presentation.save("FontPropertiesForChart.pptx", SaveFormat.Pptx)
finally:
presentation.dispose()
Установить числовой формат
Используйте ChartDataCell.setPresetNumberFormat, чтобы применить встроенный числовой формат к ячейкам рабочей книги диаграммы. Этот пример создает сгруппированную столбчатую диаграмму с данными по умолчанию, привязанными к ячейкам, и применяет индекс формата 10 (0.00%) к каждой ячейке значения ряда. Это меняет способ отображения значений в рабочей книге без изменения самих чисел; например, 0,25 отображается как 25,00 %. Форматы осей и подписей данных можно настраивать отдельно.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import ChartType, Presentation, SaveFormat
presentation = Presentation()
try:
slide = presentation.getSlides().get_Item(0)
chart = slide.getShapes().addChart(ChartType.ClusteredColumn, 50, 50, 500, 400)
chart_series_collection = chart.getChartData().getSeries()
for chart_series in chart_series_collection:
for data_point in chart_series.getDataPoints():
data_point.getValue().getAsCell().setPresetNumberFormat(jpype.JByte(10)) # 0.00%
presentation.save("PresetNumberFormat_out.pptx", SaveFormat.Pptx)
finally:
presentation.dispose()
В следующей таблице перечислены встроенные индексы числовых форматов с типичными форматами Excel для локали English (United States). Точные строки форматов и их отображение могут различаться в зависимости от приложения и локали, особенно для валют и дат. Некоторые форматы Excel также отличаются от значений по умолчанию в стандарте OOXML, как описано в Microsoft’s number format implementation notes.
| Индекс | Формат |
|---|---|
| 0 | General |
| 1 | 0 |
| 2 | 0.00 |
| 3 | #,##0 |
| 4 | #,##0.00 |
| 5 | "$"#,##0_);("$"#,##0) |
| 6 | "$"#,##0_);[Red]("$"#,##0) |
| 7 | "$"#,##0.00_);("$"#,##0.00) |
| 8 | "$"#,##0.00_);[Red]("$"#,##0.00) |
| 9 | 0% |
| 10 | 0.00% |
| 11 | 0.00E+00 |
| 12 | # ?/? |
| 13 | # ??/?? |
| 14 | m/d/yyyy |
| 15 | d-mmm-yy |
| 16 | d-mmm |
| 17 | mmm-yy |
| 18 | h:mm AM/PM |
| 19 | h:mm:ss AM/PM |
| 20 | h:mm |
| 21 | h:mm:ss |
| 22 | m/d/yyyy h:mm |
| 37 | #,##0_);(#,##0) |
| 38 | #,##0_);[Red](#,##0) |
| 39 | #,##0.00_);(#,##0.00) |
| 40 | #,##0.00_);[Red](#,##0.00) |
| 41 | _(* #,##0_);_(* (#,##0);_(* "-"_);_(@_) |
| 42 | _("$"* #,##0_);_("$"* (#,##0);_("$"* "-"_);_(@_) |
| 43 | _(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_) |
| 44 | _("$"* #,##0.00_);_("$"* (#,##0.00);_("$"* "-"??_);_(@_) |
| 45 | mm:ss |
| 46 | [h]:mm:ss |
| 47 | mm:ss.0 |
| 48 | ##0.0E+0 |
| 49 | @ |
Установить закруглённые границы области диаграммы
Вызовите Chart.setRoundedCorners с True, чтобы закруглить углы области диаграммы. Пример создает сгруппированную столбчатую диаграмму и использует getLineFormat, чтобы задать её контуру сплошной серый цвет и одиночный стиль линии перед сохранением презентации.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import ChartType, FillType, LineStyle, Presentation, SaveFormat
Color = jpype.JClass("java.awt.Color")
presentation = Presentation()
try:
slide = presentation.getSlides().get_Item(0)
chart = slide.getShapes().addChart(ChartType.ClusteredColumn, 20, 100, 600, 400)
chart.getLineFormat().getFillFormat().setFillType(FillType.Solid)
chart.getLineFormat().getFillFormat().getSolidFillColor().setColor(Color.GRAY)
chart.getLineFormat().setStyle(LineStyle.Single)
chart.setRoundedCorners(True)
presentation.save("out.pptx", SaveFormat.Pptx)
finally:
presentation.dispose()
Редактировать существующие аннотации диаграммы
Диаграмма может содержать пользовательские фигуры, такие как текстовая аннотация, объясняющая статус отчёта. Получайте доступ к этим фигурам через Chart.getUserShapes. Коллекция, возвращаемая getShapes, содержит фигуры, принадлежащие диаграмме.
Обычный текстовый фрейм, помещённый поверх диаграммы, принадлежит слайду, даже если выглядит как часть диаграммы. Итерация по Slide.getShapes находит диаграмму и обычные фигуры слайда, но не перечисляет отдельные фигуры внутри диаграммы. Заголовки диаграмм и подписи данных являются отдельными элементами диаграммы, а не пользовательскими аннотациями в этой коллекции.
Скачайте chart-annotations.pptx и разместите его в рабочем каталоге приложения. На первом слайде находится диаграмма с несгруппированной аннотацией «Preliminary results», линией, принадлежащей диаграмме, и обычным текстовым фреймом слайда с надписью «Slide overlay». Пример находит первую диаграмму на этом слайде и меняет аннотацию на «Final results», когда отчёт готов к публикации. Он проверяет, не пустая ли коллекция, и редактирует только AutoShape с текстовым кадром, отличным от None, возвращаемым getTextFrame, и соответствующим ожидаемым текстом.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import AutoShape, Chart, Presentation, SaveFormat
presentation = Presentation("chart-annotations.pptx")
try:
slide = presentation.getSlides().get_Item(0)
chart = None
for shape in slide.getShapes():
if isinstance(shape, Chart):
chart = shape
break
if chart is None or chart.getUserShapes().getShapes().size() == 0:
print("No chart or chart-owned shapes found.")
else:
updated = False
for shape in chart.getUserShapes().getShapes():
if isinstance(shape, AutoShape):
text_frame = shape.getTextFrame()
if text_frame is not None and text_frame.getText() == "Preliminary results":
text_frame.setText("Final results")
updated = True
break
if updated:
presentation.save("chart-annotations-updated.pptx", SaveFormat.Pptx)
else:
print("No matching text annotation found.")
finally:
presentation.dispose()
Линия и текстовый фрейм слайда остаются без изменений. Ниже показаны исходное изображение и сохранённый, повторно открытый результат:
| До редактирования | После редактирования |
|---|---|
![]() |
![]() |
Note
Пример проверяет только фигуры верхнего уровня, принадлежащие диаграмме. Если аннотация находится внутри GroupShape, также проверьте коллекцию getShapes этой группы. Повторяйте это рекурсивно для вложенных групп, применяя те же проверки текста к их дочерним фигурам. Сама группа является контейнером; не рассматривайте её как текстовый фрейм.FAQ
Можно ли установить полупрозрачные заливки для столбцов/областей, сохраняя границу непрозрачной?
Да. Прозрачность заливки и контур настраиваются отдельно. Это полезно для улучшения читаемости сетки и данных в плотных визуализациях.
Как справиться с подписями данных, когда они перекрываются?
Уменьшите размер шрифта, отключите несущественные компоненты подписи (например, категории), измените позицию подписи, при необходимости показывайте подписи только для выбранных точек или переключите формат на «значение + легенда».
Можно ли применять градиентные или шаблонные заливки к рядам?
Да. Ряды поддерживают сплошные, градиентные и шаблонные заливки. На практике используйте градиенты умеренно и избегайте сочетаний, которые снижают контрастность с сеткой и текстом.

