WT. Практика (Desktop)
Платформа WTПрактикаСинтаксисБаза знаний
  • Приветствие
  • Основной
    • Урок 1. Форма списка и добавление записей
    • Урок 2. Редактирование таблицы
    • Урок 3. Выпадающий список
    • Урок 4. Паттерн onClose
    • Урок 5. Удаление связанных данных
    • Урок 6. Главная форма
    • Урок 7. Фильтры
    • Урок 8. Редактирование выпадающего списка
    • Урок 9. Список категорий
    • Урок 10. Паттерн Add/Edit
    • Урок 11. Экспорт данных в документ
    • Урок 12. Дерево в таблице
    • Урок 13. Самостоятельная
    • Урок 14. Постраничный просмотр
    • Дополнительно
      • Array
      • ArrayGetDataConnection
      • ConvertDataConnection
  • Загрузка данных
    • Урок 15. Режимы загрузки данных
    • Урок 16. Режим блокировки форм (Lock)
  • Многопользовательский режим
    • Урок 17. Аутентификация пользователей в программе
    • Урок 18. Права доступа
    • Урок 19. Динамические права доступа
    • Урок 20. Пользовательские настройки
    • Урок 21. Автоматическое обновление данных
  • Кастомизация
    • Урок 22. Создание кастомных команд для форм
    • Урок 23. Создание кастомных команд для серверной части
    • Урок 24. Планировщик задач
  • Продвинутый уровень
    • Урок 25. Создание API-запросов
    • Урок 26. Работа с JSON на форме
    • Урок 27. Разделение формы на несколько файлов
Powered by GitBook
On this page
  • Логика
  • Входные значения
  • Значение <Array> в текст
  • Join двух матриц
  • Подстановка значений
  • Выражение
  • Group By Id
  1. Основной
  2. Дополнительно

Array

Универсальное значение для работы с массивами/матрицами на форме

Last updated 1 year ago

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

О всех возможностях <Array> можно узнать в статье по .

Логика

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

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

<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  |
+---+--------------+-------+
+---+--------------+-------+
| 1 | Екатеринбург | False |
| 2 | Челябинск    | False |
| 3 | Москва       | False |
+---+--------------+-------+
+---+--------------+-------+
| 1 | Екатеринбург | False |
| 3 | Москва       | False |
| 2 | Челябинск    | False |
+---+--------------+-------+
+---+---+--------------+
| 1 | 1 | Екатеринбург |
| 2 | 3 | Москва       |
| 3 | 2 | Челябинск    |
+---+---+--------------+

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


Входные значения

<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>

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

Значение <Array> в текст

<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.

Кстати, оператор StringJoin можно использовать для проверки значений DataConnection или массива, отображение которых не предусмотрено на форме, но необходимо проверить корректность промежуточных расчетов.

Для этого нужно в тэг <Hint> любого доступного графического элемент добавить <Array> с оператором StringJoin.

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

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

Join двух матриц

<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>.

Количество <Inner> и <Outer> индексов в тэге <Keys>должно совпадать.

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

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

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

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

Подстановка значений

<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.

Выражение

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

<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>

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

Group By Id

<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>
+---+-------------------------------------+
| 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>
  <Items>
    <Item>
      <Result>0</Result>
      <Expression>{Result} + [2] * [3]</Expression>
    </Item>
  </Items>
</Aggregate>

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

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

<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>, чтобы в ответе были фамилии клиентов. Откройте форму и проверьте ответ:

Первым выполнится оператор с типом Equal (по умолчанию), который отфильтрует строки матрицы по значению False в колонке Archive. Данные после фильтрации:

Затем оператор отсортирует значения по колонке Title по возрастанию (по умолчанию).

Последним оператором идет , который задает набор селекторов для формирования структуры результирующей матрицы. Первой колонкой идет селектор , который задает порядковый номер строки. Для второй и третьей колонок используется самый простой и распространенный вариант селекторов - - индекс колонки входной матрицы. Порядок описания селекторов задает порядок столбцов результирующей матрицы.

Дальше рассмотрим несколько задач, в которых познакомимся с другими операторами и возможностью их комбинировать. Работать будем с формой и запросами из раздела .

В предыдущем примере рассмотрели вариант, когда в качестве источника данных для <Array> используется загружающий . Матрицу можно получить и из таблицы через get-проперти . Но для получения данных из таблицы можно использовать get-проперти , чтобы получить массив словарей.

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

Чтобы значение тэга <Array> преобразовать в строку и отобразить в текстовом поле, следует использовать оператор .

Один из самых простых примеров использования массивов является соединение двух матриц. У нас на форме есть список клиентов с идентификаторами городов и список самих городов. Давайте соединим оба списка с помощью оператора , так чтобы в новом списке для каждого клиента было название его города.

Задачу из предыдущего примера можно решить с помощью селектора , который по ключу выбирает значение из таблицы подстановки и добавляет его в строку результирующей матрицы.

Селектор вычисляет выражение на основе элементов исходного массива (указываются в квадратных скобках []) и/или дополнительных значений (указываются в фигурных скобках {}), перечисленные в тэге <Items> вложенном в <Item Type="Expression">.

В этом примере рассмотрим, как подсчитать стоимость всех товаров для каждого клиента. Для этого будем использовать операторы и , а так же селектор .

Результатом выполнения оператора будет матрица вида:

Чтобы подсчитать сумму значений всех строк матрицы используется оператор , который для каждой строки вычисляет выражение из тэга <Expression> и суммирует полученное значение с суммой значений выражения для предыдущих строк.

Так как матрицы, для которых нужно подсчитать сумму, являются вложенными, то используем селектор , чтобы к матрице в каждой строке применить оператор <Aggregate> .

ссылке
<Filter>
<Order>
<Select>
Number
Index
DataConnection
DatabaseTable
ArrayData
DictionaryArrayData
Field
<StringJoin>
<Join>
Substitution
Expression
<Group>
<Aggregate>
Action
<Group>
<Aggregate>
Action
Подготовка