> For the complete documentation index, see [llms.txt](https://wfsys.gitbook.io/wt-practice/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wfsys.gitbook.io/wt-practice/main/additionally/array.md).

# Array

Элемент `<Array>` позволяет объединять матрицы, фильтровать, сортировать и группировать данные, а так же изменять структуру данных и многое другое.

О всех возможностях \<Array> можно узнать в статье по [ссылке](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/values/array).

## Логика <a href="#logic" id="logic"></a>

Логика элемента `<Array>` заключается в последовательном применении описанных операторов. Таким образом, результат выполнения предыдущей операции будет входным значением следующего оператора.&#x20;

Рассмотрим пример фильтрации матрицы, сортировки значений и изменение структуры итоговой матрицы:

```xml
<Array>
  <Source>
    <DataConnection SourceDataConnection="CityPrimaryGetDataConnection">
      <Fields>
        <Field Name="CityId" />
        <Field Name="Title" />
        <Field Name="Archive" />
      </Fields>
    </DataConnection>
  </Source>
  <Filter>
    <Index Value="2" />
    <Value>False</Value>
  </Filter>
  <Order>
    <By Index="1" />
  </Order>
  <Select>
    <Items>
      <Item Type="Number" Start="1"/>
      <Item Type="Index">0</Item>
      <Item Type="Index">1</Item>
    </Items>
  </Select>
</Array>
```

Исходная матрица (массив) всегда задается в тэге `<Source>`. В нем можно указывать загружающее соединение с данными любого типа, результат выполнения команды либо значения любого объекта на форме.

В примере передаем PrimaryGetDataConnection со значениями:

```
+---+--------------+-------+
| 1 | Екатеринбург | False |
| 2 | Челябинск    | False |
| 3 | Москва       | False |
| 6 | Уфа          | True  |
+---+--------------+-------+
```

Первым выполнится оператор [`<Filter>`](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/values/array#filter) с типом **Equal** (по умолчанию), который отфильтрует строки матрицы по значению False в колонке Archive. Данные после фильтрации:

```
+---+--------------+-------+
| 1 | Екатеринбург | False |
| 2 | Челябинск    | False |
| 3 | Москва       | False |
+---+--------------+-------+
```

Затем оператор [`<Order>`](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/values/array#order) отсортирует значения по колонке Title по возрастанию (по умолчанию).

```
+---+--------------+-------+
| 1 | Екатеринбург | False |
| 3 | Москва       | False |
| 2 | Челябинск    | False |
+---+--------------+-------+
```

Последним оператором идет [`<Select>`](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/values/array#select), который задает набор селекторов для формирования структуры результирующей матрицы. Первой колонкой идет селектор [Number](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/values/array#select-number), который задает порядковый номер строки. Для второй и третьей колонок используется самый простой и распространенный вариант селекторов - [Index](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/values/array#select-index) - индекс колонки входной матрицы. Порядок описания селекторов задает порядок столбцов результирующей матрицы.

```
+---+---+--------------+
| 1 | 1 | Екатеринбург |
| 2 | 3 | Москва       |
| 3 | 2 | Челябинск    |
+---+---+--------------+
```

На последовательном выполнении различных операторов строится работа с элементом `<Array>`. Главное соблюдать соответствие разрядности результата одной операции и ожидаемой разрядности входных данных следующего оператора.

***

Дальше рассмотрим несколько задач, в которых познакомимся с другими операторами и возможностью их комбинировать. Работать будем с формой и запросами из раздела [Подготовка](/wt-practice/main/additionally.md#preparation).

## Входные значения <a href="#tag-source" id="tag-source"></a>

В предыдущем примере рассмотрели вариант, когда в качестве источника данных для  `<Array>` используется загружающий [DataConnection](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/dataconnections). Матрицу можно получить и из таблицы [DatabaseTable](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/objects/databasetable) через get-проперти [ArrayData](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/objects/databasetable#get_array_data). Но для получения данных из таблицы можно использовать get-проперти [DictionaryArrayData](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/objects/databasetable#get_dictionary_array_data), чтобы получить массив словарей.

```xml
<Array>
  <Source>
    <Object Name="ClientDatabaseTable">
      <Property Name="DictionaryArrayData" />
    </Object>
  </Source>
  <Select>
    <Items>
      <Item Type="Field">ClientId</Item>
      <Item Type="Field">Title</Item>
      <Item Type="Field">Archive</Item>
    </Items>
  </Select>
  <Filter>
    <Index Value="2" />
    <Value>False</Value>
  </Filter>
  <Order>
    <By Index="1" />
  </Order>
  <Select>
    <Items>
      <Item Type="Number" Start="1"/>
      <Item Type="Index">0</Item>
      <Item Type="Index">1</Item>
    </Items>
  </Select>
</Array>
```

При работе со словарями используется селектор [Field](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/values/array#select-field), который по имени колонки вернет значения  всех ее ячеек. Так будет удобнее извлекать нужные колонки таблицы и не нужно следить за индексами колонок, которые могут сдвинутся, если добавится или удалится непоследняя колонка.

После получения нужных колонок, можно применять различные операторы для получения нужных значений. Например, фильтровать матрицу, упорядочивать значения и т.д.

## Значение `<Array>` в текст <a href="#tag-string_join" id="tag-string_join"></a>

Чтобы значение тэга `<Array>` преобразовать в строку и отобразить в текстовом поле, следует использовать оператор [`<StringJoin>`](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/values/array#string_join).

```xml
<Array>
  <Source>
    <DataConnection SourceDataConnection="OrderPositionPrimaryGetDataConnection">
      <Fields>
        <Field Name="ClientId" />
        <Field Name="MaterialCategoryTitle" />
        <Field Name="MaterialTitle" />
        <Field Name="UnitShortTitle" />
        <Field Name="Quantity" />
        <Field Name="UnitPrice" />
      </Fields>
    </DataConnection>
  </Source>
  <StringJoin Separator="\t" LineSeparator="\r\n" />
</Array>
```

Оператор задает разделители между элементами одной строки матрицы (атрибут `Separator`) и между строками матрицы (атрибут `LineSeparator`). Для линейных массивов будет использоваться только разделитель из атрибута `Separator`.

{% hint style="info" %}
Кстати, оператор StringJoin можно использовать для проверки значений DataConnection или массива, отображение которых не предусмотрено на форме, но необходимо проверить корректность промежуточных расчетов.

Для этого нужно в тэг `<Hint>` любого доступного графического элемент добавить `<Array>` с оператором StringJoin.&#x20;
{% endhint %}

На форме есть **ResultTextBox**, его будем использовать для отображения результата применения операторов элемента `<Array>`. Давайте выведем в текстовое поле содержимое OrderPositionPrimaryGetDataConnection, для этого в тэг `<Text>` объекта ResultTextBox вставим код приведенный выше.

Откроем форму в приложении и проверим результат:

<figure><img src="/files/bY6FBam8uEUYkzoeFDoG" alt=""><figcaption></figcaption></figure>

## Join двух матриц <a href="#tag-join" id="tag-join"></a>

Один из самых простых примеров использования массивов является соединение двух матриц. У нас на форме есть список клиентов с идентификаторами городов и список самих городов. Давайте соединим оба списка с помощью оператора [`<Join>`](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/values/array#join), так чтобы в новом списке для каждого клиента было название его города.

```xml
<Array>
  <Source>
    <DataConnection SourceDataConnection="ClientPrimaryGetDataConnection">
      <Fields>
        <Field Name="ClientId" />
        <Field Name="Title" />
        <Field Name="CityId" />
      </Fields>
    </DataConnection>
  </Source>
  <Join>
    <OuterArray>
      <DataConnection SourceDataConnection="CityPrimaryGetDataConnection">
        <Fields>
          <Field Name="CityId" />
          <Field Name="Title" />
        </Fields>
      </DataConnection>
    </OuterArray>
    <Keys>
      <Inner Index="2" />
      <Outer Index="0" />
    </Keys>
    <Result>
      <Inner Index="0" /><!-- ClientId -->
      <Inner Index="1" /><!-- ClientTitle -->
      <Outer Index="0" /><!-- CityId -->
      <Outer Index="1" /><!-- CityTitle -->
    </Result>
  </Join>
</Array>
```

В тэге `<OuterArray>` указываем внешнюю матрицу, которая будет соединяться с исходной матрицей по ключам, заданным в тэге `<Keys>`.

{% hint style="warning" %}
Количество `<Inner>` и `<Outer>` индексов в тэге `<Keys>`должно совпадать.

Если ключей (пар индексов) больше одного, то **важен порядок** их описания, так как `<Inner>` и `<Outer>` индексы сравниваются по парно в порядке описания.
{% endhint %}

В тэге `<Result>` задаем структуру результирующей матрицы, указывая индексы колонок внутренней и внешней матрицы и их порядок.

Скопируйте код выше и замените значение тэга `<Text>` у объекта ResultTextBox. Не забудьте добавить оператор `<StringJoin>`.

<figure><img src="/files/OPMBTUmo36nhLTW1VBZB" alt=""><figcaption></figcaption></figure>

Чтобы результат был понятнее, добавим пробелы в строки для выравнивания колонок.

## Подстановка значений <a href="#substitution-values" id="substitution-values"></a>

Задачу из предыдущего примера можно решить с помощью селектора [Substitution](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/values/array#select-substitution), который по ключу выбирает значение из таблицы подстановки и добавляет его в строку результирующей матрицы.

```xml
<Array>
  <Source>
    <DataConnection SourceDataConnection="ClientPrimaryGetDataConnection">
      <Fields>
        <Field Name="ClientId" />
        <Field Name="Title" />
        <Field Name="CityId" />
      </Fields>
    </DataConnection>
  </Source>
  <Select>
    <Items>
      <Item Type="Index">0</Item>
      <Item Type="Index">1</Item>
      <Item Type="Index">2</Item>
      <Item Type="Substitution">
        <Index>2</Index>
        <Value>
          <DataConnection SourceDataConnection="CityPrimaryGetDataConnection">
            <Fields>
              <Field Name="CityId" />
              <Field Name="Title" />
            </Fields>
          </DataConnection>
        </Value>
      </Item>
    </Items>
  </Select>
</Array>
```

В тэге `<Index>` селектора **Substitution** указываем колонку исходной матрицы, по значениям которой будет происходить выборка значений из таблицы подстановки.

В качестве таблицы подстановки должна быть матрица, состоящая из двух столбцов. В первом столбце должен быть ключ, по которому будет идти подстановка, а во втором - значение, которое будет использоваться при подстановке. В нашем случае это CityPrimaryGetDataConnection.

## Выражение <a href="#select-expression" id="select-expression"></a>

Селектор [Expression](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/values/array#select-expression) вычисляет выражение на основе элементов исходного массива (указываются в квадратных скобках `[]`) и/или дополнительных значений (указываются в фигурных скобках `{}`), перечисленные в тэге `<Items>` вложенном в `<Item Type="Expression">`.

Давайте с помощью селектора Expression подсчитаем стоимость для каждой позиции заказа:

```xml
<Array>
  <Source>
    <DataConnection SourceDataConnection="OrderPositionPrimaryGetDataConnection">
      <Fields>
        <Field Name="ClientId" />
        <Field Name="MaterialTitle" />
        <Field Name="UnitShortTitle" />
        <Field Name="Quantity" />
        <Field Name="UnitPrice" />
      </Fields>
    </DataConnection>
  </Source>
  <Select>
    <Items>
      <Item Type="Index">0</Item>
      <Item Type="Index">1</Item>
      <Item Type="Index">2</Item>
      <Item Type="Index">3</Item>
      <Item Type="Index">4</Item>
      <Item Type="Expression">
        <Expression>[3] * [4]</Expression>
      </Item>
    </Items>
  </Select>
</Array>
```

Проверим результат на форме:

<figure><img src="/files/7rqVoR4sM7bVH8YyRcZi" alt=""><figcaption></figcaption></figure>

## Group By Id <a href="#tag-group" id="tag-group"></a>

В этом примере рассмотрим, как подсчитать стоимость всех товаров для каждого клиента. Для этого будем использовать операторы [`<Group>`](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/values/array#group) и [`<Aggregate>`](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/values/array#aggregate), а так же селектор [Action](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/values/array#action).

```xml
<Array>
  <Source>
    <DataConnection SourceDataConnection="OrderPositionPrimaryGetDataConnection">
      <Fields>
        <Field Name="ClientId" />
        <Field Name="MaterialTitle" />
        <Field Name="Quantity" />
        <Field Name="UnitPrice" />
      </Fields>
    </DataConnection>
  </Source>
  <Group>
    <By Index="0" />
  </Group>
  <Select>
    <Items>
      <!-- элемент группировки -->
      <Item Type="Index">0</Item>
      <Item Type="Action">
        <Index>1</Index>
        <!-- работаем с вложенным массивом -->
        <Actions>
          <Aggregate>
            <Items>
              <Item>
                <Result>0</Result>
                <Expression>{Result} + [2] * [3]</Expression>
              </Item>
            </Items>
          </Aggregate>
        </Actions>
      </Item>
    </Items>
  </Select>
</Array>
```

Результатом выполнения оператора [`<Group>`](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/values/array#group) будет матрица вида:

```
+---+-------------------------------------+
| 2 | +---+------------------+----+-----+ |
|   | |	2 | SvetoCopy пачка  | 20 | 350 | |
|   | |	2 | Ручка шариковая  | 15 | 25  | |
|   | +---+------------------+----+-----+ |
+---+-------------------------------------+
| 4 | +---+------------------+----+-----+ |
|   | |	4 | Карандаш простой | 10 | 7   | |
|   | |	4 | Линейка 30 см    | 10 | 20  | |
|   | +---+------------------+----+-----+ |
+---+-------------------------------------+
| 9 | +---+------------------+----+-----+ |
|   | |	9 | SvetoCopy пачка  | 10 | 350 | |
|   | | 9 | Ручка шариковая  | 60 | 25  | |
|   | +---+------------------+----+-----+ |
+---+-------------------------------------+
```

Так как в тэге `<By>` в качестве условия группировки указали индекс колонки ClientId, то первая колонка результата содержит уникальные значения идентификаторов клиентов.  Вторая колонка - вложенные таблицы с записями, соответствующими идентификатору группы. Вложенные таблицы имеют ту же структуру, что и входная матрица.

Чтобы подсчитать сумму значений всех строк матрицы используется оператор [`<Aggregate>`](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/values/array#aggregate), который для каждой строки вычисляет выражение из тэга `<Expression>` и суммирует полученное значение с суммой значений выражения для предыдущих строк.

```xml
<Aggregate>
  <Items>
    <Item>
      <Result>0</Result>
      <Expression>{Result} + [2] * [3]</Expression>
    </Item>
  </Items>
</Aggregate>
```

В выражении `<Expression>` в квадратных скобках указаны индексы элементов исходного массива - Quantity и UnitPrice. Переменная `{Result}`*,* используется для хранения значения, вычисленного для предыдущей строки. В тэге `<Result>` задали начальное значение для переменной результата.

Когда оператор завершит вычисление, то вернет получившееся значение переменной `{Result}`. Так как в нашем примере только один элемент `<Item>` в тэге `<Items>`, то вернется скалярное значение. Если бы их было несколько, то вернулся бы массив результатов агрегации.

Так как матрицы, для которых нужно подсчитать сумму, являются вложенными, то используем селектор [Action](https://wfsys.gitbook.io/workflow-forms-syntax/workflow_forms/values/array#action), чтобы к матрице в каждой строке применить оператор `<Aggregate>` .

```xml
<Select>
  <Items>
    <!-- элемент группировки -->
    <Item Type="Index">0</Item>
    <Item Type="Action">
      <Index>1</Index>
      <!-- работаем с вложенным массивом -->
      <Actions>
        <Aggregate>
          <Items>
            <Item>
              <Result>0</Result>
              <Expression>{Result} + [2] * [3]</Expression>
            </Item>
          </Items>
        </Aggregate>
      </Actions>
    </Item>
  </Items>
</Select>
```

В тэге `<Index>` указали индекс колонки с вложенными массивами.

В тэге `<Actions>` указали операцию над массивами. Этот тэг аналогичен тэгу `<Array>` - мы можем в нем использовать любые операторы и их комбинации. Эти операции будут применяться к каждой строке отдельно. Исходным массивом для первой операции будет элемент массива с индексом из тэга `<Index>`.

Таким образом, тэгом `<Select>` мы задали структуру результирующей матрицы, которая будет хранить значения:

```
+-----+--------+
|  2  |  7375  |
|  4  |  270   |
|  9  |  5000  |
+-----+--------+
```

Добавьте в массив оператор `<Join>`, чтобы в ответе были фамилии клиентов. Откройте форму и проверьте ответ:

<figure><img src="/files/LSSmGGUWgvH45W3gYWaH" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://wfsys.gitbook.io/wt-practice/main/additionally/array.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
