> For the complete documentation index, see [llms.txt](https://docs.qvantum-plan.de/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.qvantum-plan.de/dev/forms.md).

# Managing Folders and Forms

Forms are essential tools for users to navigate and manipulate data in the context of plans. Forms are designed interactively using the QVANTUM Web application frontend. Forms can be structured by using folders. On top of interactive form design, QVANTUM provides means for exporting and importing all folders and forms using a JSON-based representation format. This functionality is also available as part of the QVANTUM Public API.

## Folders and Forms Export

An export of a JSON representation of all existing folder and form definitions (including invalid form definitions) is possible with a single GET request to the `allExternalForms` link under a cube resource. In order to retrieve folder and form definition data, request header `Accept` must be set to the custom MIME type `application/x.de.qvantum-plan.external-forms+json`.

**Folders and Forms Export**

```sh
curl --silent --request GET \
  --header "Authorization:Bearer ${TOKEN}" \
  --header "Accept:application/x.de.qvantum-plan.external-forms+json" \
  "${ALL_FORMS_LINK}"
```

## Folders and Forms Import

An import of an existing JSON representation of all folder and form definitions is possible with a single PUT request to the `allForms` link under a cube resource. In order to import folder and form definition data, request header `Content-Type` must be set to the custom MIME type `application/x.de.qvantum-plan.external-forms+json`.

{% hint style="warning" %}
An import of folder and form definitions effectively replaces all previously existing folder and form definitions in the context of the given plan.
{% endhint %}

**Folders and Forms Import**

```sh
curl --silent --show-headers --request PUT \
  --header "Authorization:Bearer ${TOKEN}" \
  --header "Content-Type:application/x.de.qvantum-plan.external-forms+json" \
  --data @../json/forms-exported.json \
  "${ALL_FORMS_LINK}"
```

## Folder and Form Definition

This section provides information on the syntax elements of the JSON representation for folder and form definitions, breaking down from a list of folders or forms to the individual elements of a single folder or form definition.

### List of Folders and Forms

On top-level, a forms definition consists of one element `forms` holding an array of single folder and form definitions.

**Folder and Forms Definition List**

```json
{
  "forms": [
    <FOLDER_OR_FORM_DEFINITION_1>,
    ...
    <FOLDER_OR_FORM_DEFINITION_N>
  ]
}
```

### Single Folder

A folder is defined by the type "FOLDER", a *display name*, and an array of children representing the folders and forms contained within this folder.

**Folder Definition**

```json
{
  "type": "FOLDER",
  "displayName": "Folder 1",
  "children": [
    <FOLDER_OR_FORM_DEFINITION_1>,
    ...
    <FOLDER_OR_FORM_DEFINITION_N>
  ]
}
```

### Single Form

A form is defined by the type "FORM", a *display name*, a *form header*, a *row axis* and a *column axis*.

**Form Definition**

```json
{
  "type": "FORM",
  "displayName": "Form 1",
  "sharedWith": <SHARED_WITH_DEFINITION>,
  "formats": <FORMATS_DEFINITION>,
  "formHeader": <FORM_HEADER_DEFINITION>,
  "rowAxis": <FORM_AXIS_DEFINITION>,
  "columnAxis": <FORM_AXIS_DEFINITION>
}
```

#### Shared With

The "shared with" setting defines who is allowed to see the form. Controller users will always be able to see all forms, the restrictions only apply to planner users.

There are two possible configurations: sharing the form with all planners or no planners.

{% tabs %}
{% tab title="Shared With All Definition" %}

```json
{
  "type": "ALL"
}
```

{% endtab %}

{% tab title="Shared With None Definition" %}

```json
{
  "type": "NONE"
}
```

{% endtab %}
{% endtabs %}

### Formats

Most cells of a form can be formatted. All formatting of a form is defined in a single place: the optional top-level element `formats`. It consists of up to three arrays of format entries:

* `rows`: entries formatting entire rows
* `columns`: entries formatting entire columns
* `cells`: entries formatting individual cells

**Formats Definition**

```json
<FORMATS_DEFINITION> = {
  "rows": [ <FORMAT_ENTRY>, ... ],
  "columns": [ <FORMAT_ENTRY>, ... ],
  "cells": [ <FORMAT_ENTRY>, ... ]
}
```

Each format entry addresses one or two axis elements and defines a style and/or a column width for them:

* `rowElement`: a reference to an element of the row axis (cf. [Axis Element References](#axis-element-references)). Required for `rows` and `cells` entries, not allowed for `columns` entries.
* `columnElement`: a reference to an element of the column axis. Required for `columns` and `cells` entries, not allowed for `rows` entries.
* `style`: an optional style applied to all addressed cells.
* `columnWidth`: an optional width in pixels. Only relevant for entries addressing a column.

**Example Format Entries**

```json
<FORMATS_DEFINITION> = {
  "rows": [
    {
      "rowElement": <AXIS_ELEMENT_REFERENCE>,
      "style": {
        "bold": true,
        "backgroundColor": "#00FF00"
      }
    }
  ],
  "columns": [
    {
      "columnElement": <AXIS_ELEMENT_REFERENCE>,
      "style": {
        "italic": true,
        "textColor": "#0000FF"
      },
      "columnWidth": 142
    }
  ],
  "cells": [
    {
      "rowElement": <AXIS_ELEMENT_REFERENCE>,
      "columnElement": <AXIS_ELEMENT_REFERENCE>,
      "style": {
        "bold": true
      }
    }
  ]
}
```

A style consists of the optional properties `bold`, `italic`, `backgroundColor` and `textColor`. For the `bold` and `italic` options, only the value `true` is allowed. Elements will be not bold (not italic) by default, that is if no format indicates they should be bold (italic). It is not possible to explicitly format elements as not bold or not italic. Colors are defined via their RGB hex codes (e.g. #FF0000 for red).

#### Axis Element References

How an axis element is referenced depends on the type of the axis it belongs to (cf. [Form Axis](#form-axis)). The `type` of the reference must match the type of the axis on the corresponding side of the form.

An element of a dimension axis is referenced with `type` `DIMENSION_AXIS_ELEMENT` and a `path` containing the dimension and the structure element business key:

```json
<AXIS_ELEMENT_REFERENCE> = {
  "type": "DIMENSION_AXIS_ELEMENT",
  "path": [
    {
      "dimension": "Costs",
      "structureElementBusinessKey": "CST050"
    }
  ]
}
```

An element of a nested leaves axis is referenced with `type` `NESTED_LEAVES_AXIS_ELEMENT`. Here, the `path` consists of the elements displayed in the axis, starting from the root to the element to be formatted. For example, to format an element of the first dimension, the path only consists of a single entry with the first dimension key and the business key of the structure element to be formatted. To format an element in the second dimension, it is necessary to define the element in the first dimension under which the element in the second dimension should be formatted. This example references the element "CCT020" under the element "CST050":

```json
<AXIS_ELEMENT_REFERENCE> = {
  "type": "NESTED_LEAVES_AXIS_ELEMENT",
  "path": [
    {
      "dimension": "Costs",
      "structureElementBusinessKey": "CST050"
    },
    {
      "dimension": "Cost Centers",
      "structureElementBusinessKey": "CCT020"
    }
  ]
}
```

An element of a nested layers axis is referenced with `type` `NESTED_LAYERS_AXIS_ELEMENT` and uses the same `path` structure as `NESTED_LEAVES_AXIS_ELEMENT`. However, the path consists of the structure elements in the used layers (as opposed to only leaves). The entry at each index of the path must refer to an element on the layer with the same index or it can be `null` if no element exists on that layer under the current path. The last element cannot be `null`. Similar to nested leaves axes the path can have less elements than there are layers.

An element of a custom axis is referenced with `type` `CUSTOM_AXIS_ELEMENT` and the `key` of the custom axis element (cf. [Form Custom Axis](#form-custom-axis)). With `isComment` set to `true`, the reference addresses the comment fields of a stored custom axis element instead of its value cells.

```json
<AXIS_ELEMENT_REFERENCE> = {
  "type": "CUSTOM_AXIS_ELEMENT",
  "key": "0",
  "isComment": false
}
```

Custom attributes displayed in a form can be formatted as well. A custom attribute is always displayed on the opposite side of the axis that uses its dimension: for example, custom attributes of a dimension used in the row axis are displayed as columns. A custom attribute is referenced on the side where it is displayed, with `type` `CUSTOM_ATTRIBUTE_ELEMENT`, its `dimension` and its `customAttributeBusinessKey`:

```json
<AXIS_ELEMENT_REFERENCE> = {
  "type": "CUSTOM_ATTRIBUTE_ELEMENT",
  "dimension": "Costs",
  "customAttributeBusinessKey": "attribute"
}
```

### Form Header

A form header defines which element is selected for each dimension in terms of cube navigation. Such an element selection is only relevant for dimensions used in form dimension axes and for dimensions not used in any axis. For dimensions used in form custom axes, element selection is given in each individual custom axis element definition and thus irrelevant for the form header definition. A special element selection is possible for the synthetic super-root node of each dimension structure. Additionally, header dimensions can be fixed to a single element or configured to force explicit element selection for planners.

Consider the following form:

* All Scenarios are put into the rows as form dimension axis.
* Cost Centers are put into the columns as only dimension in a form custom axis.
* Regarding Costs, the form selects dimension element with business key "CST000".
* For Variants dimension element selection is disabled for planners.
* For Years dimension element selection is explicitly forced for all planners.

The following form header definition represents this:

```json
<FORM_HEADER_DEFINITION> = {
  "Scenarios": {
    "type": "ALL"
  },
  "Cost Centers": {
    "type": "DEFINED_BY_AXIS"
  },
  "Costs": {
    "type": "NODE",
    "structureElementBusinessKey": "CST000",
    "fixationMode": "NOT_FIXED"
  },
  "Variants": {
    "type": "NODE",
    "structureElementBusinessKey": "FINAL",
    "fixationMode": "FIXED"
  },
  "Years": {
    "type": "NONE"
  }
}
```

* The Scenarios dimension is used in a form dimension axis. Thus, a selection is relevant, and we select all elements by setting `type` to `_ALL_`.
* The Cost Centers dimension is used in a form custom axis. A header selection is not possible. Thus, we use `type` `_DEFINED_BY_AXIS_`.
* The Costs dimension is not used in any axis and thus requires selection. Here, we select a specific element by its business key. Thus, we set `type` to `_NODE_` and `structureElementBusinessKey` to `CST000`. Selection is not fixed, thus using `fixationMode` `NOT_FIXED`.
* The Variants dimension is also not used in any axis. Here we not only select the specific element "FINAL", but we also prevent planners from changing this element by setting `fixationMode` to `_FIXED_`.
* The Years dimension is also not used in any axis. Here, we define no prior selection by using `type` `_NONE_`, thus explicitly forcing element selection by planners.

### Form Axis

Forms support multiple different types of axes which can be independently selected for rows and columns. These types are

* *dimension axis* which simply represents the whole forest or a sub tree of the underlying structure
* *nested leaves axis* which interleaves (physical) leaves of multiple dimensions
* *nested layers axis* which interleaves elements on multiple layers in one or more dimensions
* *custom axis* which allows to define elements representing specific combinations of dimension elements, cell comments and elements calculating formulas based on other elements in this axis.

It is not possible to use the same dimension in both the rows and the columns at the same time.

{% hint style="info" %}
These axis types correspond to the three row/column configuration modes in the QVANTUM Web application: "nested layers axis" ≈ "Automatisch nach Ebenen", and "custom axis" ≈ "Manuell". "Automatisch nach Dimensionen" is not a single axis type: it maps to a *dimension axis* when exactly one dimension is selected, and to a *nested leaves axis* when multiple dimensions are nested. For the business implications of this distinction (e.g. for Merkmal columns) and a walkthrough with screenshots, see the German user documentation: [Die drei Modi der Achsenkonfiguration](/user/owner/planung/formulare/konfiguration-der-formulare/die_drei_modi_der_achsenkonfiguration.md) (German)
{% endhint %}

#### Common Properties

Some properties are shared by all axis types.

* `hideElements` allows for defining filters about what elements are shown in an axis (cf. [Form Axis Element Display Filter](#form-axis-element-filter)).
* `widthInPixels` specifies the width of the axis header column if the axis is used as a row axis in a form.

```json
<FORM_AXIS_DEFINITION> = {
  "hideElements": <HIDE_ELEMENTS_FILTER>,
  "widthInPixels": 255,
  ...
}
```

#### Form Dimension Axis

An axis with a `type` of `DIMENSION_AXIS` is a dimension axis. It has exactly one specific `dimension`, referred to by its business key and an `expansionState` describing which structure elements are expanded or collapsed. Its axis elements and custom attributes displayed in the other axis can be formatted (cf. [Formats](#formats)).

```json
{
  "type": "DIMENSION_AXIS",
  "hideElements": <HIDE_ELEMENTS_FILTER>,
  "widthInPixels": 145,
  "dimension": "Costs",
  "expansionState": <DIMENSION_AXIS_EXPANSION_STATE>
}
```

**Form Dimension Axis Expansion State - Collapse all Elements except First and Second Quarter of the Year**

```json
<DIMENSION_AXIS_EXPANSION_STATE> = {
  "default": "COLLAPSED",
  "exceptions": [
    {
      "path": [
        {
          "dimension": "Months",
          "structureElementBusinessKey": "Q1"
        }
      ]
    },
    {
      "path": [
        {
          "dimension": "Months",
          "structureElementBusinessKey": "Q2"
        }
      ]
    }
  ]
}
```

#### Form Nested Leaves Axis

An axis of `type` of `NESTED_LEAVES_AXIS` is a nested leaves axis. It has a list of `dimensions`, given by their business keys. The list of dimensions for nesting together with their definitions of corresponding form header elements define, which elements are finally part of the resulting synthetic nested structure.

The example below shows a nested leaves axis nesting two dimensions.

```json
{
  "type": "NESTED_LEAVES_AXIS",
  "hideElements": <HIDE_ELEMENTS_FILTER>,
  "widthInPixels": 145,
  "dimensions": [
    "Scenarios",
    "Cost Centers"
  ],
  "expansionState": <NESTED_LEAVES_AXIS_EXPANSION_STATE>
}
```

Similar to a dimension axis it is possible to specify which elements are expanded or collapsed and how they are formatted (cf. [Formats](#formats)).

The expansion state uses the path to the element to be expanded or collapsed. Such a path consists of the elements displayed in the axis, starting from the root to the element to be addressed. Note that these are always leaves in the underlying structure. Here all but the two elements "Department North" and "Department South" under "Total Year" are expanded.

```json
<NESTED_LEAVES_AXIS_EXPANSION_STATE> = {
  "default": "EXPANDED",
  "exceptions": [
    {
      "path": [
        {
          "dimension": "Months",
          "structureElementBusinessKey": "Total Year"
        },
        {
          "dimension": "Cost Centers",
          "structureElementBusinessKey": "Department North"
        }
      ]
    },
    {
      "path": [
        {
          "dimension": "Months",
          "structureElementBusinessKey": "Total Year"
        },
        {
          "dimension": "Cost Centers",
          "structureElementBusinessKey": "Department South"
        }
      ]
    }
  ]
}
```

In addition to the above definition of a nested leaves axis, involving the two dimensions Scenarios and Cost Centers, consider the following selection of form header elements for the two dimensions.

* Scenarios: All
* Cost Centers: Administration

The resulting nested axis structure is the following:

```
* Actual
  * General Administration
  * IT Administration
* Forecast
  * General Administration
  * IT Administration
* Plan
  * General Administration
  * IT Administration
```

Also consider another selection of form header elements.

* Scenarios: Plan
* Cost Centers: All

The resulting nested axis structure is the following:

```
* Plan
  * Sales
  * General Administration
  * IT Administration
```

#### Form Nested Layers Axis

An axis with `type` `NESTED_LAYERS_AXIS` is a nested layers axis. Nested layer axes must always hide empty elements. They have `layers` which are identified by the dimension and a layer in the structure in this dimension.

```json
{
  "type": "NESTED_LAYERS_AXIS",
  ...
  "hideElements": [ "EMPTY" ],
  "layers": [
    {
      "dimension": { "pluralName": <dimension.pluralName> },
      "layer": { "businessKey": <layer.businessKey> }
    }, ...
  ]
  "expansionState": <NESTED_LAYERS_AXIS_EXPANSION_STATE>
}
```

The `<NESTED_LAYERS_AXIS_EXPANSION_STATE>` uses the same JSON structure as `<NESTED_LEAVES_AXIS_EXPANSION_STATE>`. However, the paths consists of the structure elements in the used layers (as opposed to only leaves). The index in the path must refer to an element on the layer with the same index or it can be `null` if no element exists on that layer under the current path. The last element cannot be `null`. Similar to nested leaves axes the path can have less elements than there are layers.

Axis elements and custom attributes displayed in the other axis can be formatted (cf. [Formats](#formats)).

#### Form Custom Axis

An axis with `type` `CUSTOM_AXIS` is a custom axis. Custom axes are fundamentally different from the previous types as each element is specified explicitly. It has a `customAxisHeaderDimensions` definition, and a `customAxisElements` definition. First and foremost, a custom axis is defined for a list of dimensions. Each custom axis element definition in turn consists of a tuple of business keys referring to structure elements of the respective dimensions. Custom axes also can be formatted (cf. [Formats](#formats)), but expanding is not meaningful.

```json
{
  "type": "CUSTOM_AXIS",
  "hideElements": <HIDE_ELEMENTS_FILTER>,
  "customAxisHeaderDimensions": <CUSTOM_AXIS_HEADER_DIMENSIONS_DEFINITION>,
  "customAxisElements": <CUSTOM_AXIS_ELEMENTS_DEFINITION>
  "widthInPixels": 145
}
```

Custom axis header dimensions are defined as an array consisting of a `dimension` specified by its business key, and an `aspectElementLabelMode`, allowing to control rendering of axis element labels either as display name (`DISPLAY_NAME`) or business key (`BUSINESS_KEY`). The name of this property is deprecated and will probably change in the future.

**Form Custom Axis Definition - Header Dimensions**

```json
<CUSTOM_AXIS_HEADER_DIMENSIONS_DEFINITION> = [
  {
    "dimension": "Scenarios",
    "aspectElementLabelMode": "DISPLAY_NAME"
  },
  {
    "dimension": "Cost Centers",
    "aspectElementLabelMode": "BUSINESS_KEY"
  }
]
```

Custom axis elements support two different types, i.e. *stored* and *formula* elements.

A stored custom axis element is defined by its `type` `STORED`, a list of *aspectElements* for the respective custom axis header dimensions, given as business keys, thus providing partial coordinates of a stored cube cell. The name `aspectElements` is deprecated. In order to refer to these custom axis elements in formulas, as defined for formula custom axis elements, each custom axis element defines a *key*. Furthermore, a stored custom axis element can be defined as *input allowed* (`YES`) or not (`NO`). Each stored custom axis element additionally allows to optionally display comment fields for the respective cube cells shown in this axis. Comment fields are defined with a `comment type` and a list of `comment suggestions`.

* `commentType`
  * `NONE`: comment fields disabled
  * `FREE`: comment fields enabled for free text comments
  * `FREE_WITH_SUGGESTIONS`: comment fields enabled for free text comments, supported with a list of suggestions as defined in `commentSuggestions`

The value cells and comment fields of a stored custom axis element can be formatted via its `key` (cf. [Axis Element References](#axis-element-references)).

Continuing with the dimensions used in the previous example, an individual custom axis element representing the scenario "ACTUAL" and the Cost Center "CCT021" can look like this.

```json
{
  "type": "STORED",
  "key": "0",
  "inputAllowed": "NO",
  "aspectElements": [
    "ACTUAL",
    "CCT021"
  ],
  "commentType": "NONE",
  "commentSuggestions": [
    "good",
    "bad"
  ]
}
```

The definition of a formula custom axis element consists of the following fields:

* `type`: always `FORMULA`
* `key`: a unique key for reference in other formula elements
* `formula`: the formula of this element. Supports the same syntax as described in the German [Formeln](/user/owner/planung/modell/rechenoperationen_und_formelsyntax.md) reference, except for the `sumOfChildren`, `timeOffset` and `istimeelementwithoutchildren` functions (and their aliases). Other axis elements are referenced via their keys (e.g. `[0]`)
* `header`: the header label describing the axis element
* `negativeValuesHighlighted`: whether negative values are highlighted
* `valueTypeReference`: a reference to a value type. Used for formatting (cf. [value types](/dev/model.md#value-types))

The cells of a formula custom axis element can be formatted via its `key` (cf. [Axis Element References](#axis-element-references)).

```json
{
  "type": "FORMULA",
  "key": "2",
  "header": "Abweichung Actual/Plan %",
  "formula": "(([1]-[0])/[0])*100",
  "negativeValuesHighlighted": true,
  "valueTypeReference": {
    "businessKey": "Menge"
  }
}
```

#### Form Axis Element Filter

Each axis definition includes a filter `hideElements`, stating whether certain axis elements are hidden or not. Currently, QVANTUM supports only one filter *EMPTY* stating whether axis elements with all involved cube cells being empty are hidden or not.

{% tabs %}
{% tab title="Form Axis Element Filter - Hide No Elements" %}

```json
"hideElements": []
```

{% endtab %}

{% tab title="Form Axis Element Filter - Hide Empty Elements" %}

```json
"hideElements": [
  "EMPTY"
]
```

{% endtab %}
{% endtabs %}

## Converting Old Format Definitions

In earlier versions of QVANTUM, form formatting was defined differently: the top-level element `formats` was a map of reusable cell formats keyed by identifiers, and the formatted elements referenced these identifiers in properties spread across the form definition:

* `formats` arrays (with `path`, `format` and `widthInPixels`) on dimension, nested leaves and nested layers axes
* `customAttributeFormats` arrays on dimension, nested layers and custom axes
* `format`, `widthInPixels`, `commentFormat` and `commentWidthInPixels` properties on custom axis elements

These properties are no longer supported.

{% hint style="warning" %}
Importing a form definition that still uses the old format model does not fail: the old format properties are simply ignored and the forms are imported without any formatting. Make sure to convert old form definitions to the new format model before importing them.
{% endhint %}

Form definitions stored in QVANTUM were converted automatically when the format model changed, so a fresh [export](#folders-and-forms-export) always uses the new format model.

If you maintain your own tooling that produces form definitions, adjust it according to the following rules:

| Old definition                                                           | New definition                                                                                                        |
| ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| top-level `formats` map of cell formats                                  | removed; each style is written directly into the format entries that used its identifier                              |
| axis `formats` entry with a `path`                                       | entry in `rows` or `columns` with a `DIMENSION`, `NESTED_LEAVES` or `NESTED_LAYERS` element reference                 |
| `customAttributeFormats` entry                                           | entry in `rows` or `columns` on the side *opposite* to the axis, with a `CUSTOM_ATTRIBUTE` element reference          |
| `format` / `widthInPixels` on a custom axis element                      | entry in `rows` or `columns` (the side of the custom axis) with a `CUSTOM` element reference and `"isComment": false` |
| `commentFormat` / `commentWidthInPixels` on a stored custom axis element | entry with a `CUSTOM` element reference and `"isComment": true`                                                       |
| `widthInPixels` in any of the above                                      | `columnWidth` of the new format entry                                                                                 |
