Search code examples
pythonchartslegendlibreofficeuno

how do I give a name to a data range in a data series?


I'm creating a chart by means of a python uno script. I added a range, categories, and I managed to set min a max values for the y axis.

The only thing I'm unable to do so is to change the 'range for name'.

Right now my chart shows 'Column AP' for the first data series, and 'Column AQ' for the second data series. The chart looks like https://i.sstatic.net/Kd2iV.jpg but I want it to look like https://i.sstatic.net/bIFaz.jpg. I want to change the legends into 'Bought' for the first data series, and 'Now' for the second.

I tried creating a data series as described in https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=8991#p46467 but can't get it to work in python. https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=8991#p46467 seems overkill as I have everything except for the 'range for name'.

def create_data_sequence(data_provider, ran, rol):
    data_sequence = data_provider.createDataSequenceByRangeRepresentation(ran)
    if data_sequence:
        data_sequence.Role = rol
    return data_sequence

# TODO: move to end when done
# https://forum.openoffice.org/en/forum/viewtopic.php?t=53750
# https://forum.openoffice.org/en/forum/viewtopic.php?f=44&t=55115
dashboard_sheet = sheets.getByName('DASHBOARD')
values_sheet = sheets.getByName('Values') # TODO: remove, because it's referenced later
charts = dashboard_sheet.getCharts()

rect = Rectangle()
rect.Width, rect.Height, rect.X, rect.Y = 22000, 12000, 1000, 9200

range_address = []
range_address.append(CellRangeAddress())

range_address[0].Sheet = values_sheet.RangeAddress.Sheet
range_address[0].StartColumn = 41
range_address[0].StartRow = 550
range_address[0].EndColumn = 42
range_address[0].EndRow = 807

charts.addNewByName("Total Value Over Time", rect , tuple(range_address), False, False)
chart = charts.getByName("Total Value Over Time").getEmbeddedObject()
chart.createInstance("com.sun.star.chart.LineDiagram")

data_provider = chart.getDataProvider()
categories_sequence = smgr.createInstanceWithContext(\
                                        "com.sun.star.chart2.data.LabeledDataSequence", ctx)
categories_range = "$Values.$A$551:$A$808"
categories_sequence.setValues(create_data_sequence(data_provider,\
                                                   categories_range, "categories"))

coordinate_system = chart.getFirstDiagram().getCoordinateSystems()[0]

x_axis = coordinate_system.getAxisByDimension(0, 0) # TODO : why chart.getFirstDiagram()?
y_axis = chart.getDiagram().YAxis                   # TODO : why chart.getDiagram()? diff?
scale_x_data = x_axis.getScaleData()
scale_x_data.Categories = categories_sequence
x_axis.setScaleData(scale_x_data)
y_axis.Min = 55000
y_axis.Max = 125000
y_axis.NumberFormat = number_format_id

chart.HasMainTitle = True
chart.HasLegend = True
chart.Title.String = "Total Value Over Time"
chart.Title.CharHeight = 24
chart.HasSubTitle = True
chart.SubTitle.String = "Funds and Structured Products"
chart.SubTitle.CharHeight = 12

My chart shows two lines. I want the legend to show 'Bought' for the first line, 'Now' for the second.


Solution

  • The following code was adapted from the link in your question. Not sure if it's what you meant by "overkill", but it seems to be the proper way to set a label.

    set_sequence_label(chart, 0, "bought")
    set_sequence_label(chart, 1, "now")
    
    def set_sequence_label(chart, series_index, label):
        data_series = chart.FirstDiagram.getCoordinateSystems()[0].getChartTypes(
            )[0].getDataSeries()[series_index]
        data_sequence = data_series.getDataSequences()[0]
        oSequenceLabel = (
            chart.getDataProvider().createDataSequenceByRangeRepresentation(label))
        data_sequence.setLabel(oSequenceLabel)
    

    Documentation: XLabeledDataSequence.setLabel().