Source code for ooodev.office.chart

# region Imports
from __future__ import annotations
import contextlib
from typing import Tuple, overload

import uno
from com.sun.star.beans import XPropertySet
from com.sun.star.chart import XAxisXSupplier
from com.sun.star.chart import XAxisYSupplier
from com.sun.star.chart import XChartDataArray
from com.sun.star.chart import XChartDocument
from com.sun.star.chart import XDiagram
from com.sun.star.chart import XTwoAxisYSupplier
from com.sun.star.container import XNameAccess
from com.sun.star.document import XEmbeddedObjectSupplier
from com.sun.star.drawing import XDrawPage
from com.sun.star.drawing import XDrawPageSupplier
from com.sun.star.drawing import XShape
from com.sun.star.lang import XMultiServiceFactory
from com.sun.star.sheet import XSpreadsheet
from com.sun.star.table import XTableChart
from com.sun.star.table import XTableCharts
from com.sun.star.table import XTableChartsSupplier
from com.sun.star.text import XTextContent
from com.sun.star.text import XTextDocument

from ooo.dyn.awt.rectangle import Rectangle
from ooo.dyn.chart.chart_data_caption import ChartDataCaptionEnum as ChartDataCaptionEnum
from ooo.dyn.chart.chart_regression_curve_type import ChartRegressionCurveType as ChartRegressionCurveType
from ooo.dyn.chart.chart_solid_type import ChartSolidTypeEnum as ChartSolidTypeEnum
from ooo.dyn.chart.chart_symbol_type import ChartSymbolType as ChartSymbolType
from ooo.dyn.chart.data_label_placement import DataLabelPlacementEnum as DataLabelPlacementEnum
from ooo.dyn.table.cell_range_address import CellRangeAddress as CellRangeAddress
from ooo.dyn.text.hori_orientation import HoriOrientation
from ooo.dyn.text.vert_orientation import VertOrientation
from ooo.dyn.awt.size import Size as UnoSize


from ooodev.utils.kind.chart_diagram_kind import ChartDiagramKind as ChartDiagramKind
from ooodev.utils.kind.drawing_shape_kind import DrawingShapeKind as DrawingShapeKind
from ooodev.office import draw as mDraw
from ooodev.exceptions import ex as mEx
from ooodev.utils import info as mInfo
from ooodev.loader import lo as mLo
from ooodev.utils import props as mProps
from ooodev.utils.data_type.intensity import Intensity as Intensity


# endregion Imports
[docs]class Chart: """Chart Class""" # region insert_chart() @overload @classmethod def insert_chart( cls, *, slide: XDrawPage, x: int, y: int, width: int, height: int, diagram_name: ChartDiagramKind | str ) -> XChartDocument: ... @overload @classmethod def insert_chart( cls, *, doc: XTextDocument, x: int, y: int, width: int, height: int, diagram_name: ChartDiagramKind | str ) -> XChartDocument: ... @overload @classmethod def insert_chart( cls, *, sheet: XSpreadsheet, chart_name: str, cells_range: CellRangeAddress, width: int, height: int, diagram_name: ChartDiagramKind | str, ) -> XChartDocument: ... @overload @classmethod def insert_chart( cls, *, sheet: XSpreadsheet, chart_name: str, cells_range: CellRangeAddress, x: int, y: int, width: int, height: int, diagram_name: ChartDiagramKind | str, ) -> XChartDocument: ... @classmethod def _insert_chart_slide( cls, slide: XDrawPage, x: int, y: int, width: int, height: int, diagram_name: ChartDiagramKind | str ) -> XChartDocument: try: shape = mDraw.Draw.add_shape( slide=slide, shape_type=DrawingShapeKind.OLE2_SHAPE, x=x, y=y, width=width, height=height, ) chart_doc = cls._get_chart_doc_shape(shape) cls.set_chart_type(chart_doc=chart_doc, diagram_name=diagram_name) return chart_doc except mEx.ChartError: raise except Exception as e: raise mEx.ChartError("Error inserting chart slide") from e @classmethod def _insert_chart_sheet( cls, sheet: XSpreadsheet, chart_name: str, cells_range: CellRangeAddress, x: int, y: int, width: int, height: int, diagram_name: ChartDiagramKind | str, ) -> XChartDocument: try: tbl_charts = cls.get_table_charts(sheet) tc_access = mLo.Lo.qi(XNameAccess, tbl_charts) if tc_access is None: raise mEx.ChartNoAccessError("Unable to get name access to chart table") if tc_access.hasByName(chart_name): raise mEx.ChartExistingError(f"A chart table called {chart_name} already exist") rect = Rectangle(x * 1000, y * 1000, width * 1000, height * 1000) addrs = [cells_range] # first boolean: has column headers?; second boolean: has row headers? tbl_charts.addNewByName(chart_name, rect, addrs, True, True) # type: ignore # 2nd last arg: whether the topmost row of the source data will be used # to set labels for the category axis or the legend. # last arg: whether the leftmost column of the source data will be # used to set labels for the category axis or the legend. tbl_chart = cls.get_table_chart(tc_access, chart_name) chart_doc = cls.get_chart_doc(tbl_chart) if diagram_name is not None: cls.set_chart_type(chart_doc, diagram_name) return chart_doc except mEx.ChartNoAccessError: raise except mEx.ChartExistingError: raise except mEx.ChartError: raise except Exception as e: raise mEx.ChartError(f'Error inserting "{chart_name}" into sheet') from e @classmethod def _insert_chart_doc( cls, doc: XTextDocument, x: int, y: int, width: int, height: int, diagram_name: ChartDiagramKind | str ) -> XChartDocument | None: try: tc = mLo.Lo.create_instance_msf(XTextContent, "com.sun.star.text.TextEmbeddedObject", raise_err=True) ps = mLo.Lo.qi(XPropertySet, tc, True) ps.setPropertyValue("CLSID", str(mLo.Lo.CLSID.CHART)) xtext = doc.getText() cursor = xtext.createTextCursor() # insert embedded object in text -> object will be created xtext.insertTextContent(cursor, tc, True) # set size and position shape = mLo.Lo.qi(XShape, tc, True) shape.setSize(UnoSize(width * 1_000, height * 1_000)) # type: ignore ps.setPropertyValue("VertOrient", VertOrientation.NONE) ps.setPropertyValue("HoriOrient", HoriOrientation.NONE) ps.setPropertyValue("VertOrientPosition", y * 1_000) ps.setPropertyValue("HoriOrientPosition", x * 1_000) # retrieve the chart document as model of the OLE shape chart_doc = mLo.Lo.qi(XChartDocument, ps.getPropertyValue("Model")) if chart_doc is not None: cls.set_chart_type(chart_doc=chart_doc, diagram_name=diagram_name) return chart_doc return None except Exception as e: raise mEx.ChartError("Unable to insert chart") from e
[docs] @classmethod def insert_chart(cls, *args, **kwargs) -> XChartDocument | None: """ Insert a chart using the given name as name of the OLE object and the range as corresponding range of data to be used for rendering. The chart is placed in the sheet for charts at position (1,1) extending as large as given in chart size. The diagram name must be the name of a diagram service (i.e one in ``com.sun.star.chart``) that can be instantiated via the factory of the chart document Args: slide (XDrawPage): Draw page doc (XTextDocument): Document sheet (XSpreadsheet): Spreadsheet chart_name (str): Name of chart cells_range (CellRangeAddress): Cells range width (int): Width height (int): Height diagram_name (DiagramKind | str): Diagram Name x (int, optional): Chart X position. Defaults to 1. y (int, optional): Chart y Position. Defaults to 1. Raises: ChartNoAccessError: If unable to get access to chart table. ChartExistingError: If chart already exist. ChartError: If unable to insert chart. Returns: XChartDocument: Chart Document on success; Otherwise, ``None``. """ if args: raise TypeError(f"Insert_chart() takes 0 positional arguments but {len(args)} was given") count = len(kwargs) if count not in {6, 8}: raise TypeError("insert_chart() got an invalid number of arguments") if count == 6: if "slide" in kwargs: # insert_chart( slide: XDrawPage, x: int, y: int, width: int, height: int, diagram_name: ChartDiagramKind | str) -> XChartDocument: return cls._insert_chart_slide(**kwargs) if "doc" in kwargs: # insert_chart(doc: XTextDocument, x: int, y: int, width: int, height: int, diagram_name: ChartDiagramKind | str) -> XChartDocument: return cls._insert_chart_doc(**kwargs) # else # insert_chart(sheet: XSpreadsheet, chart_name: str, cells_range: CellRangeAddress, width: int, height: int, diagram_name: ChartDiagramKind | str,) -> XChartDocument: kargs = kwargs.copy() kargs["x"] = 1 kargs["y"] = 1 return cls._insert_chart_sheet(**kargs) return cls._insert_chart_sheet(**kwargs)
# endregion insert_chart()
[docs] @classmethod def get_table_chart_access(cls, sheet: XSpreadsheet) -> XNameAccess: """ Get XNameAccess interface of sheet charts Args: sheet (XSpreadsheet): Spreadsheet Raises: ChartError: if error occurs. Returns: XNameAccess: Named Access interface """ try: tbl_charts = cls.get_table_charts(sheet) return mLo.Lo.qi(XNameAccess, tbl_charts, True) except Exception as e: raise mEx.ChartError("Error getting table chart access") from e
[docs] @staticmethod def get_table_charts(sheet: XSpreadsheet) -> XTableCharts: """ Gets Table Charts of a sheet Args: sheet (XSpreadsheet): Spreadsheet Raises: ChartError: if error occurs. Returns: XTableCharts: Table Charts interface """ try: # get the supplier for the charts charts_supplier = mLo.Lo.qi(XTableChartsSupplier, sheet, True) return charts_supplier.getCharts() except Exception as e: raise mEx.ChartError("Error getting table chart access") from e
[docs] @classmethod def get_chart_names_list(cls, sheet: XSpreadsheet) -> Tuple[str, ...]: """ Gets Tuple of chart names as strings Args: sheet (XSpreadsheet): Spreadsheet Returns: Tuple[str]: Tuple of strings or empty tuple if no charts are found """ try: tbl_charts = cls.get_table_charts(sheet) except mEx.ChartError: return () return tbl_charts.getElementNames()
[docs] @staticmethod def get_table_chart(tc_access: XNameAccess, chart_name: str) -> XTableChart: """ Gets a table chart. Args: tc_access (XNameAccess): Name Access chart_name (str): Chart Name Raises: ChartError: If unable to get Table Chart Returns: XTableChart: Table Chart Interface. """ try: return mLo.Lo.qi(XTableChart, tc_access.getByName(chart_name), True) except Exception as e: raise mEx.ChartError(f"Could Not Access: {chart_name}") from e
# region get_chart_doc() @staticmethod def _get_chart_doc_tbl_chart(tbl_chart: XTableChart) -> XChartDocument: """ Gets chart document Args: tbl_chart (XTableChart): Table Chart Returns: XChartDocument: Chart Document Interface """ try: eos = mLo.Lo.qi(XEmbeddedObjectSupplier, tbl_chart, True) embedded = eos.getEmbeddedObject() return mLo.Lo.qi(XChartDocument, embedded, True) except Exception as e: raise mEx.ChartError("Unable to get chart.") from e @classmethod def _get_chart_doc_sheet_chart_name(cls, sheet: XSpreadsheet, chart_name: str) -> XChartDocument: tc_access = cls.get_table_chart_access(sheet) if not tc_access.hasByName(chart_name): raise mEx.ChartNotExistingError(f'No table chart called "{chart_name}" found') tbl_chart = cls.get_table_chart(tc_access=tc_access, chart_name=chart_name) return cls._get_chart_doc_tbl_chart(tbl_chart) @staticmethod def _get_chart_doc_shape(shape: XShape) -> XChartDocument: try: # change the LOL shape into a chart try: shape_props = mLo.Lo.qi(XPropertySet, shape, True) except mEx.MissingInterfaceError as ex: raise mEx.ChartError("Unable to access shape properties") from ex return mLo.Lo.qi(XChartDocument, shape_props.getPropertyValue("Model"), True) except mEx.ChartError: raise except Exception as e: raise mEx.ChartError("Couldn't change the OLE shape into a chart.") from e @overload @classmethod def get_chart_doc(cls, shape: XShape) -> XChartDocument: ... @overload @classmethod def get_chart_doc(cls, tbl_chart: XTableChart) -> XChartDocument: ... @overload @classmethod def get_chart_doc(cls, sheet: XSpreadsheet, chart_name: str) -> XChartDocument: ...
[docs] @classmethod def get_chart_doc(cls, *args, **kwargs) -> XChartDocument: """ Gets chart document Args: shape (XShape): Shape object tbl_chart (XTableChart): Table Chart sheet: SpreadSheet chart_name (str): Chart Name Raises: ChartNotExistingError: If chart is not existing. ChartError: If chart error occurs. Returns: XChartDocument: Chart Document Interface """ ordered_keys = (1, 2) kargs_len = len(kwargs) count = len(args) + kargs_len def get_kwargs() -> dict: ka = {} if kargs_len == 0: return ka valid_keys = ("tbl_chart", "shape", "sheet", "chart_name") check = all(key in valid_keys for key in kwargs) if not check: raise TypeError("get_chart_doc() got an unexpected keyword argument") keys = ("tbl_chart", "sheet", "shape") for key in keys: if key in kwargs: ka[1] = kwargs[key] break if count == 1: return ka ka[2] = kwargs.get("chart_name", None) return ka if count not in (1, 2): raise TypeError("get_chart_doc() got an invalid number of arguments") kargs = get_kwargs() for i, arg in enumerate(args): kargs[ordered_keys[i]] = arg if count == 1: # def get_chart_doc(cls, shape: XShape) # def get_chart_doc(cls, tbl_chart: XTableChart) shape = mLo.Lo.qi(XShape, kargs[1]) if shape is None: return cls._get_chart_doc_tbl_chart(kargs[1]) else: return cls._get_chart_doc_shape(shape) return cls._get_chart_doc_sheet_chart_name(kargs[1], kargs[2])
# endregion get_chart_doc()
[docs] @staticmethod def set_chart_type(chart_doc: XChartDocument, diagram_name: ChartDiagramKind | str) -> None: """ Sets chart diagram name Args: chart_doc (XChartDocument): Chart Document diagram_name (DiagramEnum | str): Diagram Name Raises: ChartError: If error occurs. """ chart_type = f"com.sun.star.chart.{diagram_name}" try: msf = mLo.Lo.qi(XMultiServiceFactory, chart_doc, True) diagram = mLo.Lo.qi(XDiagram, msf.createInstance(chart_type), True) chart_doc.setDiagram(diagram) except Exception as e: raise mEx.ChartError(f"Could not set the chart type to: {chart_type}") from e
[docs] @staticmethod def get_chart_type(chart_doc: XChartDocument) -> str: """ Gets chart document chart type Args: chart_doc (XChartDocument): Chart Document Returns: str: Chart Type """ try: result = chart_doc.getDiagram().getDiagramType() if result is None: raise mEx.ChartError("Error, result of get chart type is None") return result except mEx.ChartError: raise except Exception as e: raise mEx.ChartError("Error getting chart type") from e
[docs] @classmethod def remove_chart(cls, sheet: XSpreadsheet, chart_name: str) -> bool: """ Removes a chart from spreadsheet current charts Args: sheet (XSpreadsheet): Spreadsheet chart_name (str): Chart Name to remove Returns: bool: ``True`` if chart is found and removed; Otherwise, ``False`` """ mLo.Lo.print(f'Removing chart "{chart_name}"') try: tbl_charts = cls.get_table_charts(sheet) tc_access = mLo.Lo.qi(XNameAccess, tbl_charts, True) except mEx.ChartError as ce: mLo.Lo.print(f'Error get table charts for "{chart_name}"') mLo.Lo.print(f" {ce}") return False except mEx.MissingInterfaceError as e: mLo.Lo.print("Unable to get name access to chart table") mLo.Lo.print(f" {e}") return False if tc_access.hasByName(chart_name): tbl_charts.removeByName(chart_name) mLo.Lo.print(f'Chart table "{chart_name}" removed.') return True mLo.Lo.print(f'Chart table "{chart_name}" not found.') return False
[docs] @staticmethod def set_visible(sheet: XSpreadsheet, is_visible: bool) -> None: """ Set visible state of charts. Args: sheet (XSpreadsheet): Spreadsheet is_visible (bool): Visible State. ``True`` shows charts, ``False`` hides charts. Raises: ChartError: If error occurs. Returns: None: Note: Any chart on sheet errors when attempting to set visibility then then it is skipped and no error is raised. """ # get draw page supplier for chart sheet try: page_supplier = mLo.Lo.qi(XDrawPageSupplier, sheet, True) draw_page = page_supplier.getDrawPage() num_shapes = draw_page.getCount() chart_class_id = str(mLo.Lo.CLSID.CHART) except Exception as e: raise mEx.ChartError("Error setting visibility of sheet") from e for i in range(num_shapes): try: shape = mLo.Lo.qi(XShape, draw_page.getByIndex(i), True) class_id = str(mProps.Props.get(shape, "CLSID")) if class_id.casefold() == chart_class_id: mProps.Props.set(shape, Visible=is_visible) except Exception as e: mLo.Lo.print("Error setting visibility of chart") mLo.Lo.print(f" {e}")
[docs] @staticmethod def get_chart_shape(sheet: XSpreadsheet) -> XShape: """ Gets the shape of the first found chart Args: sheet (XSpreadsheet): Spreadsheet Raises: ShapeMissingError: If unable to find a chart on the sheet. ShapeError: If any other error occurs. Returns: XShape: Chart Shape. """ try: # get draw page supplier for chart sheet page_supplier = mLo.Lo.qi(XDrawPageSupplier, sheet, True) draw_page = page_supplier.getDrawPage() num_shapes = draw_page.getCount() chart_class_id = str(mLo.Lo.CLSID.CHART) shape = None for i in range(num_shapes): with contextlib.suppress(Exception): shape = mLo.Lo.qi(XShape, draw_page.getByIndex(i), True) class_id = str(mProps.Props.get(shape, "CLSID")) if class_id.casefold() == chart_class_id: break if shape is None: raise mEx.ShapeMissingError("Unable to find any chart on sheet") else: mLo.Lo.print("Found a chart") return shape except mEx.ShapeMissingError: raise except Exception as e: raise mEx.ShapeError("Error getting chart shape") from e
# region adjust properties
[docs] @staticmethod def get_title(chart_doc: XChartDocument) -> str: """ Gets title for a chart document. Args: chart_doc (XChartDocument): Chart document Raises: ChartError: If error occurs. Returns: str: Chart Title """ try: title = mProps.Props.get(chart_doc.getTitle(), "String") if title is None: raise mEx.ChartError("Error getting title for chart document. Property returned None") return str(title) except mEx.ChartError: raise except Exception as e: raise mEx.ChartError("Error getting chart document title") from e
[docs] @staticmethod def set_title(chart_doc: XChartDocument, title: str) -> None: """ Set title for a chart document Args: chart_doc (XChartDocument): Chart document title (str): Title text Raises: ChartError: If error occurs Returns: None: """ try: shape = chart_doc.getTitle() mProps.Props.set(shape, String=title) except Exception as e: raise mEx.ChartError("Error setting title for chart document.") from e
[docs] @staticmethod def get_sub_title(chart_doc: XChartDocument) -> str: """ Gets subtitle for a chart document. Args: chart_doc (XChartDocument): Chart document Raises: ChartError: If error occurs. Returns: str: Chart Subtitle """ try: sub_title = mProps.Props.get(chart_doc.getSubTitle(), "String") if sub_title is None: raise mEx.ChartError("Error getting subtitle for chart document. Property returned None") return str(sub_title) except mEx.ChartError: raise except Exception as e: raise mEx.ChartError("Error getting chart document subtitle") from e
[docs] @staticmethod def set_subtitle(chart_doc: XChartDocument, subtitle: str) -> None: """ Set subtitle for a chart document Args: chart_doc (XChartDocument): Chart document subtitle (str): Subtitle text Raises: ChartError: If error occurs Returns: None: """ try: # in java this next line was in error and should have been getSubTitle() # chartDoc.getTitle(); shape = chart_doc.getSubTitle() mProps.Props.set(shape, String=subtitle) # mProps.Props.set_property(shape, "HasSubTitle", True) except Exception as e: raise mEx.ChartError("Error setting title for chart document.") from e
[docs] @staticmethod def set_x_axis_title(chart_doc: XChartDocument, title: str) -> None: """ Sets the X Axis Title Args: chart_doc (XChartDocument): Chart Document title (str): Title text Raises: DiagramNotExistingError: If ``chart_doc`` diagram does not exist ServiceNotSupported: If ``com.sun.star.chart.ChartAxisXSupplier`` service is not supported by diagram. ChartError: If any other error occurs. Returns: None: """ try: diagram = chart_doc.getDiagram() if diagram is None: raise mEx.DiagramNotExistingError("Diagram does not exist") if not mInfo.Info.support_service(diagram, "com.sun.star.chart.ChartAxisXSupplier"): raise mEx.ServiceNotSupported("com.sun.star.chart.ChartAxisXSupplier") mProps.Props.set(diagram, HasXAxisDescription=True) axis = mLo.Lo.qi(XAxisXSupplier, diagram, True) title_shape = axis.getXAxisTitle() mProps.Props.set_property(title_shape, "String", title) # mProps.Props.set_property(title_shape, "HasXAxisTitle", True) except mEx.DiagramNotExistingError: raise except Exception as e: raise mEx.ChartError("Error setting title for X Axis of chart document.") from e
[docs] @staticmethod def set_y_axis_title(chart_doc: XChartDocument, title: str) -> None: """ Sets the Y Axis Title Args: chart_doc (XChartDocument): Chart Document title (str): Title text Raises: DiagramNotExistingError: If ``chart_doc`` diagram does not exist ServiceNotSupported: If ``com.sun.star.chart.ChartAxisYSupplier`` service is not supported by diagram. ChartError: If any other error occurs. Returns: None: """ try: diagram = chart_doc.getDiagram() if diagram is None: raise mEx.DiagramNotExistingError("Diagram does not exist") if not mInfo.Info.support_service(diagram, "com.sun.star.chart.ChartAxisYSupplier"): raise mEx.ServiceNotSupported("com.sun.star.chart.ChartAxisYSupplier") mProps.Props.set(diagram, HasYAxisDescription=True) axis = mLo.Lo.qi(XAxisYSupplier, diagram, True) title_shape = axis.getYAxisTitle() mProps.Props.set(title_shape, String=title) # mProps.Props.set(title_shape, HasYAxisTitle=True) except mEx.DiagramNotExistingError: raise except Exception as e: raise mEx.ChartError("Error setting title for Y Axis of chart document.") from e
[docs] @staticmethod def set_second_y_axis(chart_doc: XChartDocument, title: str) -> None: """ Sets the second Y Axis Title Args: chart_doc (XChartDocument): Chart Document title (str): Title text Raises: DiagramNotExistingError: If ``chart_doc`` diagram does not exist ServiceNotSupported: If ``com.sun.star.chart.ChartTwoAxisYSupplier`` service is not supported by diagram. ChartError: If any other error occurs. Returns: None: """ try: diagram = chart_doc.getDiagram() if diagram is None: raise mEx.DiagramNotExistingError("Diagram does not exist") if not mInfo.Info.support_service(diagram, "com.sun.star.chart.ChartTwoAxisYSupplier"): raise mEx.ServiceNotSupported("com.sun.star.chart.ChartTwoAxisYSupplier") mProps.Props.set(diagram, HasSecondaryYAxis=True) axis = mLo.Lo.qi(XTwoAxisYSupplier, diagram, True) # y2_ps = axis.getSecondaryYAxis() # mProps.Props.show_props("Second y-axis", y2_ps) y2_title_ps = mLo.Lo.qi(XPropertySet, axis.getYAxisTitle(), True) mProps.Props.set(y2_title_ps, String=title) # mProps.Props.show_props("Second y-axis title", y2_title_ps) except mEx.DiagramNotExistingError: raise except Exception as e: raise mEx.ChartError("Error setting second Y Axis of chart document.") from e
[docs] @staticmethod def view_legend(chart_doc: XChartDocument, is_visible: bool) -> None: """ Set the visibility of chart document legend Args: chart_doc (XChartDocument): Chart Document is_visible (bool): Visibility Raises: ServiceNotSupported: If ``com.sun.star.chart.ChartDocument`` service is not supported. ChartError: If any other error occurs. Returns: None: """ # this was showLegend in java if not mInfo.Info.support_service(chart_doc, "com.sun.star.chart.ChartDocument"): raise mEx.ServiceNotSupported("com.sun.star.chart.ChartDocument") try: mProps.Props.set_property(chart_doc, "HasLegend", is_visible) except Exception as e: raise mEx.ChartError(f'Error setting chart document legend visibility to "{is_visible}"') from e
[docs] @staticmethod def set_use_horizontals(chart_doc: XChartDocument, is_vertical: bool = True) -> None: """ Determines if the bars of a Bar Diagram chart are drawn vertically or horizontally. Default is vertical. If ``is_vertical`` is ``False`` you get a column chart rather than a bar chart. Args: chart_doc (XChartDocument): Bar Diagram chart document is_vertical (bool, optional): Determines if chart is drawn vertically or horizontally. Default ``True``. Raises: DiagramNotExistingError: If ``chart_doc`` diagram does not exist ServiceNotSupported: If ``com.sun.star.chart.BarDiagram`` service is not supported by diagram. ChartError: If any other error occurs. Returns: None: """ # was useHorizontals in java try: diagram = chart_doc.getDiagram() if diagram is None: raise mEx.DiagramNotExistingError("Diagram does not exist") if not mInfo.Info.support_service(diagram, "com.sun.star.chart.BarDiagram"): raise mEx.ServiceNotSupported("com.sun.star.chart.BarDiagram") mProps.Props.set_property(diagram, "Vertical", is_vertical) except mEx.DiagramNotExistingError: raise except Exception as e: raise mEx.ChartError("Error setting use horizontals of chart document.") from e
[docs] @staticmethod def set_use_lines(chart_doc: XChartDocument, has_lines: bool) -> None: """ Sets if the chart type has lines connecting the data points or contains just symbols. Args: chart_doc (XChartDocument): ``LineDiagram`` or ``XYDiagram`` chart document. has_lines (bool): Determines if the chart type has lines connecting the data points or contains just symbols. Raises: DiagramNotExistingError: If ``chart_doc`` diagram does not exist ServiceNotSupported: If chart document is not a ``LineDiagram`` or ``XYDiagram`` ChartError: If any other error occurs. Returns: None: """ # usesLines in java try: # com.sun.star.chart.XYDiagram inherits from LineDiagram diagram = chart_doc.getDiagram() if diagram is None: raise mEx.DiagramNotExistingError("Diagram does not exist") if not mInfo.Info.support_service( diagram, "com.sun.star.chart.LineDiagram", "com.sun.star.chart.XYDiagram" ): raise mEx.ServiceNotSupported("com.sun.star.chart.LineDiagram", "com.sun.star.chart.XYDiagram") mProps.Props.set(diagram, Lines=has_lines) except mEx.ServiceNotSupported: raise except mEx.DiagramNotExistingError: raise except Exception as e: raise mEx.ChartError("Error setting use lines chart document.") from e
[docs] @staticmethod def set_data_caption(chart_doc: XChartDocument, label_types: ChartDataCaptionEnum) -> None: """ Sets how the caption of data points is displayed. Args: chart_doc (XChartDocument): Chart Document label_types (ChartDataCaptionEnum): Flags, specifies how the caption of data points is displayed. Raises: DiagramNotExistingError: If ``chart_doc`` diagram does not exist ServiceNotSupported: If ``com.sun.star.chart.Diagram`` service is not supported by diagram. ChartError: If any other error occurs. Returns: None: """ # ChartDataCaptionEnum is IntFlags enum. try: diagram = chart_doc.getDiagram() if diagram is None: raise mEx.DiagramNotExistingError("Diagram does not exist") if not mInfo.Info.support_service(diagram, "com.sun.star.chart.Diagram"): raise mEx.ServiceNotSupported("com.sun.star.chart.Diagram") mProps.Props.set(diagram, DataCaption=int(label_types)) except mEx.ServiceNotSupported: raise except mEx.DiagramNotExistingError: raise except Exception as e: raise mEx.ChartError("Error setting data caption of chart document.") from e
[docs] @staticmethod def set_data_placement(chart_doc: XChartDocument, placement: DataLabelPlacementEnum) -> None: """ Sets the relative position for the data label. Args: chart_doc (XChartDocument): Chart Document. placement (DataLabelPlacementEnum): Specifies a relative position for the data label. Raises: DiagramNotExistingError: If ``chart_doc`` diagram does not exist ServiceNotSupported: If ``com.sun.star.chart.ChartDataPointProperties`` service is not supported by diagram. ChartError: If any other error occurs. Returns: None: """ try: diagram = chart_doc.getDiagram() if diagram is None: raise mEx.DiagramNotExistingError("Diagram does not exist") if not mInfo.Info.support_service(diagram, "com.sun.star.chart.ChartDataPointProperties"): raise mEx.ServiceNotSupported("com.sun.star.chart.ChartDataPointProperties") data_arr = mLo.Lo.qi(XChartDataArray, chart_doc.getData(), True) arr_data = data_arr.getData() num_points = len(arr_data) for i in range(num_points): # first parameter is the index of the point, the second one is the series point_props = diagram.getDataPointProperties(i, 0) # point_props.setPropertyValue("CharHeight", 14.0) # point_props.setPropertyValue("CharWeight", FontWeight.BOLD) # point_props.setPropertyValue("CharColor", 0x993366) point_props.setPropertyValue("LabelPlacement", int(placement)) if mInfo.Info.support_service(diagram, "com.sun.star.chart.PieDiagram"): # for pie chart ps = diagram.getDataPointProperties(0, 0) else: ps = diagram.getDataRowProperties(0) mProps.Props.set(ps, LabelPlacement=int(placement)) mProps.Props.show_props("Data Row", ps) except mEx.ServiceNotSupported: raise except mEx.DiagramNotExistingError: raise except Exception as e: raise mEx.ChartError("Error setting data placement of chart document.") from e
[docs] @staticmethod def show_data_array(chart_doc: XChartDocument) -> None: """ Prints data array info to console. Args: chart_doc (XChartDocument): Chart Document. """ chart_data = chart_doc.getData() data_arr = mLo.Lo.qi(XChartDataArray, chart_data, True) if data := data_arr.getData(): print(f"No. of Data columns: {len(data[0])}") print(f"No. of Data rows: {len(data)}") for row in data: for col in row: print(f" {col}") else: print("No data found") print() row_descriptions = data_arr.getRowDescriptions() if not row_descriptions: print("No row description found") else: print(f"No. of rows: {len(row_descriptions)}") for row in row_descriptions: print(f' "{row}"') print() if col_descriptions := data_arr.getColumnDescriptions(): print(f"No. of columns: {len(row_descriptions)}") for col in col_descriptions: print(f' "{col}"') else: print("No column description found") print()
[docs] @staticmethod def set_area_transparency(chart_doc: XChartDocument, val: Intensity) -> None: """ Set the transparency of chart areas surrounding the diagram/ Args: chart_doc (XChartDocument): Chart Document. val (Intensity): Transparency intensity, Higher values is more transparent. Raises: ChartError: If error occurs. Returns: None: """ try: mProps.Props.set(chart_doc.getArea(), FillTransparence=val.value) except Exception as e: raise mEx.ChartError("Error setting chart transparency") from e
# region set_3d() @overload @staticmethod def set_3d(chart_doc: XChartDocument, is_3d: bool) -> None: ... @overload @staticmethod def set_3d(chart_doc: XChartDocument, is_3d: bool, solid_type: ChartSolidTypeEnum) -> None: ...
[docs] @staticmethod def set_3d(chart_doc: XChartDocument, is_3d: bool, solid_type: ChartSolidTypeEnum | None = None) -> None: """ Sets chart 3d option. Args: chart_doc (XChartDocument): Chart Document. is_3d (bool): Specifies if chart is 3d. solid_type (ChartSolidTypeEnum): Chart Solid Type. Defaults to ``ChartSolidTypeEnum.CYLINDER``. Raises: DiagramNotExistingError: If ``chart_doc`` diagram does not exist ChartError: If any other error occurs. Returns: None: """ try: diagram = chart_doc.getDiagram() if diagram is None: raise mEx.DiagramNotExistingError("Diagram does not exist") is_vert = bool(mProps.Props.get(diagram, "Vertical")) if solid_type is None: solid_type = ChartSolidTypeEnum.CYLINDER mProps.Props.set(diagram, Dim3D=is_3d, SolidType=int(solid_type), Vertical=is_vert) except mEx.DiagramNotExistingError: raise except Exception as e: raise mEx.ChartError("Error setting chart to 3d.") from e
# endregion set_3d()
[docs] @staticmethod def set_symbol(chart_doc: XChartDocument, has_symbol: bool) -> None: """ Sets chart symbol. Args: chart_doc (XChartDocument): Chart Document. has_symbol (bool): Specifies if chart is 3d. Raises: DiagramNotExistingError: If ``chart_doc`` diagram does not exist ServiceNotSupported: If chart document is not a ``LineDiagram`` or ``XYDiagram`` ChartError: If any other error occurs. Returns: None: """ # In this interface, only the two values ChartSymbolType::NONE and # ChartSymbolType::AUTO are supported. Later versions may support the selection of the symbols shape. # XYDiagram inherits LineDiagram try: diagram = chart_doc.getDiagram() if diagram is None: raise mEx.DiagramNotExistingError("Diagram does not exist") if not mInfo.Info.support_service( diagram, "com.sun.star.chart.LineDiagram", "com.sun.star.chart.XYDiagram" ): raise mEx.ServiceNotSupported("com.sun.star.chart.LineDiagram", "com.sun.star.chart.XYDiagram") if has_symbol: mProps.Props.set(diagram, SymbolType=ChartSymbolType.AUTO) else: mProps.Props.set(diagram, SymbolType=ChartSymbolType.NONE) except mEx.ServiceNotSupported: raise except mEx.DiagramNotExistingError: raise except Exception as e: raise mEx.ChartError("Error setting chart symbol.") from e
[docs] @staticmethod def set_trend(chart_doc: XChartDocument, curve_type: ChartRegressionCurveType) -> None: """ Sets chart trend Args: chart_doc (XChartDocument): Chart Document. curve_type (ChartRegressionCurveType): determines a type of regression for the data row values. Raises: DiagramNotExistingError: If ``chart_doc`` diagram does not exist ServiceNotSupported: If ``com.sun.star.chart.ChartStatistics`` service is not supported by diagram. ChartError: If any other error occurs. Returns: None: """ # determines a type of regression for the data row values. try: diagram = chart_doc.getDiagram() if diagram is None: raise mEx.DiagramNotExistingError("Diagram does not exist") if not mInfo.Info.support_service(diagram, "com.sun.star.chart.ChartStatistics"): raise mEx.ServiceNotSupported("com.sun.star.chart.ChartStatistics") # data_arr = mLo.Lo.qi(XChartDataArray, chart_doc.getData(), True) # data = data_arr.getData() # num_points = len(data) if curve_type in ( ChartRegressionCurveType.NONE, ChartRegressionCurveType.LINEAR, ChartRegressionCurveType.LOGARITHM, ChartRegressionCurveType.EXPONENTIAL, ChartRegressionCurveType.POWER, ): mProps.Props.set(diagram, RegressionCurves=curve_type) else: mLo.Lo.print(f"Did not recognize curve type: {curve_type}") except mEx.ServiceNotSupported: raise except mEx.DiagramNotExistingError: raise except Exception as e: raise mEx.ChartError("Error setting chart trend.") from e
[docs] @staticmethod def set_data_row_descriptions(chart_doc: XChartDocument, *descs: str) -> None: """ Set data row descriptions for chart. Args: chart_doc (XChartDocument): Chart Document. *descs (str): Variable length argument list of descriptions. Must match the same number of descriptions in the chart. Raises: ValueError: If wrong number of descriptions are provided. ChartError: If any other error occurs Returns: None: Note: This method works, but affects the graphic data point position. """ try: chart_data = chart_doc.getData() data_arr = mLo.Lo.qi(XChartDataArray, chart_data, True) row_descs = data_arr.getRowDescriptions() if not row_descs: mLo.Lo.print("No row description found") return if len(row_descs) != len(descs): raise ValueError(f"Row length mismatch; No. of rows == {len(row_descs)}") data_arr.setRowDescriptions(descs) except ValueError: raise except Exception as e: raise mEx.ChartError("Error setting chart row descriptions.") from e
[docs] @staticmethod def show_data_row_props(chart_doc: XChartDocument) -> None: """ Prints data row info to console. Args: chart_doc (XChartDocument): Chart Document. """ try: diagram = chart_doc.getDiagram() if diagram is None: raise mEx.DiagramNotExistingError("Diagram does not exist") data_arr = mLo.Lo.qi(XChartDataArray, chart_doc.getData(), True) data = data_arr.getData() num_points = len(data) print(f"No. of points: {num_points}") for i in range(num_points): point_ps = diagram.getDataPointProperties(i, 0) mProps.Props.show_props(f"{i}. Data Point", point_ps) if mInfo.Info.support_service(diagram, "com.sun.star.chart.PieDiagram"): # for pie chart ps = diagram.getDataPointProperties(0, 0) else: ps = diagram.getDataRowProperties(0) mProps.Props.show_props("Data Row", ps) except Exception as e: print("Could not get DataPointProperties:") print(f" {e}")
# endregion adjust properties __all__ = ("Chart",)