LayoutsΒΆ

Apart from providing styling and formatting facilities, the library also provides a powerful way to layout multiple tables on one sheet. In this section we will look at some examples.

We will use the same presentation model from basic_example2(). We will layout the presentation models with different layouts.

 1import os
 2import tempfile
 3
 4import pandas as pd
 5
 6from table_compositor.table_compositor import build_presentation_model
 7from table_compositor.xlsx_styles import OpenPyxlStyleHelper
 8
 9# There are equivalent classes for using xlsxwriter library. Namely,
10# XlsxWriterCompositor and XlsxWriterStyleHelper
11from table_compositor.xlsx_writer import OpenPyxlCompositor
12
 1def layout_example1():
 2
 3    df = pd.DataFrame(
 4        dict(a=[10, 20, 30, 40, 50], b=[0.1, 0.9, 0.2, 0.6, 0.3]), index=[1, 2, 3, 4, 5]
 5    )
 6
 7    def style_func(idx, col):
 8        if col == "b":
 9            return OpenPyxlStyleHelper.get_style(number_format="0.00%")
10        else:
11            # for 'a' we do dollar format
12            return OpenPyxlStyleHelper.get_style(number_format="$#,##.00")
13
14    # create a presentation model
15    # note the OpenPyxlStyleHeloer function available in xlsx_styles module. But a return value of style function
16    # can be any dict whose keys are attributes of the OpenPyxl cell object.
17    presentation_model = build_presentation_model(
18        df=df,
19        data_value_func=lambda idx, col: df.loc[idx, col] * 10
20        if col == "a"
21        else df.loc[idx, col],
22        data_style_func=style_func,
23        header_value_func=lambda node: node.value.capitalize(),
24        header_style_func=lambda _: OpenPyxlStyleHelper.default_header_style(),
25        index_value_func=lambda node: node.value * 100,
26        index_style_func=lambda _: OpenPyxlStyleHelper.default_header_style(),
27        index_name_func=lambda _: "Basic Example",
28        index_name_style_func=lambda _: OpenPyxlStyleHelper.default_header_style(),
29    )
30
31    # start_layout_code_1
32    # create a layout, which is usually a nested list of presentation models
33    layout = [[presentation_model], [[presentation_model], [presentation_model]]]
34
35    # render to xlsx
36    output_fp = os.path.join(tempfile.gettempdir(), "layout_vertical_example1.xlsx")
37    # the default value for orientation is 'vertical'
38    OpenPyxlCompositor.to_xlsx(
39        layout=layout, output_fp=output_fp, orientation="vertical"
40    )
41
42    output_fp = os.path.join(tempfile.gettempdir(), "layout_horizontal_example1.xlsx")
43    OpenPyxlCompositor.to_xlsx(
44        layout=layout, output_fp=output_fp, orientation="horizontal"
45    )
46    print("Writing xlsx file=", output_fp)
47
48    # mutiple nesting
49    layout_complex = [
50        presentation_model,
51        [presentation_model, [presentation_model, presentation_model]],
52    ]
53
54    output_fp = os.path.join(tempfile.gettempdir(), "layout_complex_example1.xlsx")
55    OpenPyxlCompositor.to_xlsx(
56        layout=layout_complex, output_fp=output_fp, orientation="vertical"
57    )
58    print("Writing xlsx file=", output_fp)
59    # end_layout_code_1
60
61

In the preceding example, we create two layouts. On line 28, we have a layout defined and then rendered to two files with different orientations.

When the orientation is vertical, then each item (presentation_model) in the list is layed out vertically. The orientation flips between vertical and horizontal for every nested listed that is encountered. In this example, you will notice that since the second item in the outer list is a list, the two presentation models in the inner list are rendered side-by-side (i.e. with horizontal orientation)

_images/layout_example1_1.png

When the value of orientation argument is changed to horizontal, the renderer renders the outerlist horizontally and flips the orientation of inner lists to vertical. The second output is show below.

_images/layout_example1_2.png