scanny / python-pptx

Create Open XML PowerPoint documents in Python
MIT License
2.37k stars 512 forks source link

Feature: Make it easier to adjust chart settings #764

Open SandervandenOord opened 2 years ago

SandervandenOord commented 2 years ago

I use your great package to create slides with quite some charts.

Most of my charts have a similar look and feel.

What I am missing in the package is an easy function / wrapper that changes default chart settings easily without having to remember all the nitty gritty.

So for now I have written this for my self, but maybe it's an idea to add this or similar functionality to the package. The code below is what I use now, it's not perfect, but better to show what I mean, when it's not so perfect, then until it's complete and finished :)

@scanny: What do you think? (maybe there's already functionality like this, or a request, but I couldn't find it)

def adjust_pptx_chart_settings(  
    # chart properties
    chart, 
    font_size=24, 
    has_title=False,
    has_legend=False, 
    legend_position=None,
    legend_include_in_layout=False,

    # plot properties
    has_data_labels=True,
    vary_color_by_categories=True,

    # properties for both value axis and category axis
    has_major_gridlines=False,

    # category axis properties
    category_axis_visible=True, 
    category_axis_font_size=None,
    category_axis_number_format=None,
    category_axis_major_tick_mark: bool = True,
    category_axis_title=None,
    category_axis_tick_labels=True,

    # value axis properties
    value_axis_visible=False,
    value_axis_major_tick_mark=None,
    minimum_scale=None,
    maximum_scale=None,

    # series properties
    marker_size=None,
    line_around_bar: bool = None,
):    

    """Adjust default settings of a pttx chart for a number of arguments"""

    # chart properties
    chart.font.size = Pt(font_size)
    chart.has_title = has_title
    chart.has_legend = has_legend
    if has_legend:
        chart.legend.position = legend_position
        chart.legend.include_in_layout = legend_include_in_layout

    # plot properties
    plot = chart.plots[0]
    plot.has_data_labels = has_data_labels
    if has_data_labels:
        text_frame = TextFrame(
            plot.data_labels._element.get_or_add_txPr(),
            None)
        text_frame.word_wrap = False
    plot.vary_by_categories = vary_color_by_categories

    # category axis properties
    category_axis = chart.category_axis
    category_axis.visible = category_axis_visible
    category_axis.has_major_gridlines = has_major_gridlines
    if category_axis_title:
        category_axis.has_title = True
        category_axis.axis_title.text_frame.text = category_axis_title
    if category_axis_font_size is not None:
        category_axis.tick_labels.font.size = Pt(category_axis_font_size)
    if category_axis_number_format is not None:
        category_axis.tick_labels.number_format = category_axis_number_format
    if not category_axis_major_tick_mark:
        category_axis.major_tick_mark = XL_TICK_MARK.NONE
    if not category_axis_tick_labels:
        category_axis.tick_label_position = XL_TICK_LABEL_POSITION.NONE

    # value axis properties
    value_axis = chart.value_axis
    value_axis.visible = value_axis_visible
    value_axis.has_major_gridlines = has_major_gridlines
    if minimum_scale is not None:
        value_axis.minimum_scale = minimum_scale
    if maximum_scale is not None:
        value_axis.maximum_scale = maximum_scale
    if value_axis_major_tick_mark is not None:
        value_axis.major_tick_mark = value_axis_major_tick_mark

    # series properties
    if marker_size is not None:
        for series in chart.series:
            series.marker.style = XL_MARKER_STYLE.CIRCLE
            series.marker.size = marker_size
    if line_around_bar:
        for chart_series in chart.series:
            chart_series.format.line.color.rgb = RGBColor(0, 0, 0) 

    return chart

And then I call the function as follows. I still want to translate for example the XL_TICK_MARK.NONE to just None, so I don't have to remember all the specific syntax.

  # change some chart settings if needed
  chart_settings = {
      "value_axis_visible": True,
      "value_axis_major_tick_mark": XL_TICK_MARK.NONE,
      "has_data_labels": False,
      "category_axis_font_size": 18,
      "category_axis_number_format": "dd-mmm",
      "category_axis_major_tick_mark": XL_TICK_MARK.NONE,
      "marker_size": 6,
      "vary_color_by_categories": False,
  }

  chart = adjust_pptx_chart_settings(chart, **chart_settings)
MartinPacker commented 2 years ago

If you want a platform for standardisation maybe my md2pptx package suits. A preprocessor for it is mdpre.

These are, of course, Markdown based.

I was looking for standardisation when I wrote these.