List controller

List controller

Product line

Standard

|

Expert

Operating mode

CLOUD ABO

|

ON-PREMISES

Modules

Services & CRM

Budget & Phases

Purchases

Resource Planning

Business Intelligence

Created: 16.11.2022
Updated: 08.09.2024 | Fixed bug on first screenshot.

A list controller is used to calculate and preload data for lists.

Folders (incl. query folderSQL folder and expression folder ), link types and Resource Planning views can be assigned a list controller.

You can access these from the lists via a custom renderer . In this way, list views can be expanded and data can be preloaded to improve the performance of the lists.

The use of list controllers in Resource Planning is described in the article OCL, Python, custom renderers and list controllers for Resource Planning  due to the extended handling and the requirement for the Resource Planning module.

Functional scope of a list controller

  • A list controller is a Python script (actually a Python class), in which arbitrary calculations can be made and data can be preloaded, see creating a list controller .
  • A list controller is assigned to a list, see assigning a list controller .
  • This does not change the behavior of the list; the list controller does not calculate any objects in the list.
  • If you want to use data from the list controller in certain columns, you need a custom renderer .
  • A list controller can manage dynamic columns. Columns can be defined as Dynamic and are repeated on the right. The number of repetitions and headings can be controlled via the list controller, see dynamic columns.

Creating a list controller

A list controller is a Python class. To create a list controller, create a new script  in the folder Settings > Customizing > Reports & scripts.

You are free to choose the name of the script and the Python class (all written together).

The script designation is the module name. The name of the Python class is the controller name. Example:

 

 

  • Module name: Controller
  • Controller name: RechnungsListController

In the form ModuleName.ControlName (in example, Controller.RechnungsListController ), the list controller is later assigned .

Methods

A list controller class can define the following methods:

initialize(self, subscriber)
Called up when the list is calculated. The initialize method pre-calculates the data that should be available for the renderer cells of the list.
get_dynamic_column_count(self, subscriber)

Returns the number of repetitions of the Dynamic defined columns of the list. Each repetition is displayed in the list as a group with a group title.

For lists that should display a column for each date range that you want to show, this value corresponds to the number of intervals that you want to display (e.g., months).

For more information about dynamic columns, see further down .

get_dynamic_column_title(self, column_index, subscriber)

Calculates the group title of a dynamic column group. The column_index can accept values from 0 (first group) to number of groups-1 (last group).

In the case of date column groups, the date interval (e.g. month name) is returned as a string.

For more information about dynamic columns and column groups, see further down .

You can also inherit from the controllers supplied via the Resource Planning module. Then there are many other methods available. You can find many examples in the article Vertec Python functions .

The object instance (self) of a list controller offers the following attributes and methods:

self.evalocl(expression, rootobj=None)
Enables OCL to be evaluated on the self OCL evaluator. When called up, the appropriate subscriber is used automatically. If optional rootobj is specified, the evaluation is carried out on this object; otherwise globally.
self.context

Is the context object of the list. For folders and link containers, this is the container object (folder or link container).

In the case of lists for individual objects defined via the resource planning view, the context is the individual (user entry) object.

self.get_context_entries()

Returns a list of the following objects when called up, depending on self.context:

If self.context is a container object, the container’s entries are returned. In this case, the container’s entries are automatically subscribed.

Otherwise, a list is returned that contains only the self.context object.

self.owner

Indicates the owner (can be of type LinkRolle , ViewType (Resource planning view) or Folder) of the list controller.

Assigning a list controller

The assignment takes place via Modulname.Controllername (see creating a list controller ):

Folder

In the folder properties (right mouse button > Properties) of folders , SQL folders , expression folders and query folders in the list controller field:

 

 

Link container

On the link type (custom link type , wrapper link type ) in the list controller field on the relevant page:

 

 

As soon as a list controller is defined in a list controller field, the button with the three dots appears. By clicking on it, the code appears for viewing:

 

 

Access to a list controller in the list

To access a list controller in a list column, you need a custom renderer . This has access to the list controller instance via the attribute self.controller.

Dynamic columns

Columns in the list settings can have the checkbox Dynamic set

Always enter %col% as an expression for dynamic columns. This dynamically defines the index and you can access this in the list controller (via column_index ) and in the custom renderers (via expression ) and output the data accordingly.

Dynamically defined columns are repeated as many times as the methods get_dynamic_column_count() of the list controller give back.

Several dynamic columns must be defined consecutively. They are then repeated as a group. The first group receives the index 0 , the second 1, etc. Within a group, the number of columns cannot be varied, the groups are always repeated en bloc.

Example

In the example, an invoice analysis is made on a project. It is a standard invoice list, but the amounts are sorted by year.

The data is calculated in the list controller. A custom renderer  controls how the relevant columns are displayed in the list.

For this, the following script is registered , in our example, under the name Controller .

It includes the list controller and a total renderer:

class RechnungsListController:
    def initialize(self, subscriber):
        invoices = self.evalocl("varParent.rechnungen->orderby(datum)")
        self.yearlist = []
        if invoices:
            fromyear = invoices[0].datum.year
            toyear = invoices[-1].datum.year
            self.yearlist = list(range(fromyear, toyear+1))
    def get_dynamic_column_count(self, subscriber):
        return len(self.yearlist)
    def get_dynamic_column_title(self, column_index, subscriber):
        return self.yearlist[column_index]

class RendererYearTotal:    
    def get_value(self, rowobj, expression, subscriber):
        year = self.controller.yearlist[int(expression)]
        if rowobj.datum.year == year:
            return rowobj.evalocl("total", subscriber)
        else:
            return 0.0
Explanation
  • First, all the project invoices (varParent ) are loaded, sorted by date.
  • fromyear is the year of the first invoice
  • toyear is the year of the last invoice
  • In the yearlist, all the years from fromyear up to and including toyear are inserted
  • There is one repetition column per year ( get_dynamic_column_count )
  • The title is the year ( get_dynamic_column_title )

A wrapper link type is created for the list, and the list controller in defined in the form <Modulname>.<Klassenname>:

 

In the list settings , a dynamic column is created. It is entered as the expression %col%, and the renderer is also defined in the form <Scriptname>.<Renderername>:

 

Bitte wählen Sie Ihren Standort