Как программно изменить тип значения реквизита формы и реализовать сортировку по цене

Программист 1С v8.3 (Управляемые формы) Управленческий учет Торговля и дистрибуция
← На главную

В процессе разработки интерфейсов на платформе 1С:Предприятие часто возникает задача динамического управления данными. Типичная ситуация: на форме расположен список номенклатуры, и пользователю требуется сортировка по полю, которое не является индексированным реквизитом справочника (например, по цене, рассчитанной «на лету» или полученной из регистра сведений). Рассмотрим, можно ли программно изменить тип реквизита формы с СправочникСписок на ТаблицаЗначений и какие альтернативные подходы существуют для решения этой задачи.

Анализ технической возможности смены типа реквизита

Для начала проанализируем архитектурные ограничения платформы. В 1С тип реквизита формы жестко задается в метаданных на этапе проектирования. Прямое переназначение типа существующего реквизита (например, попытка присвоить РеквизитФормы = Новый ТаблицаЗначений, если он был СправочникСписок) невозможно и вызовет ошибку времени выполнения.

В управляемых формах (платформа 8.2 и 8.3) существует метод ИзменитьРеквизиты(). Разберем, как он работает. Этот метод не меняет тип старого реквизита, а позволяет удалить существующий реквизит и добавить новый с тем же именем, но другим типом. Однако такой подход крайне трудозатратен, так как требует:

  1. Удаления программно созданных элементов формы, связанных со старым реквизитом.
  2. Перепривязки путей к данным (DataPath) для всех колонок таблицы.
  3. Переинициализации обработчиков событий.

Поэтому, если перед нами стоит задача обеспечить сортировку по произвольному полю, стоит рассмотреть более эффективные методы.

Решение №1: Использование динамического списка с произвольным запросом

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

Проанализируем ситуацию: стандартный СправочникСписок отображает только данные самой таблицы справочника. Чтобы добавить цену, нам нужно переключить список в режим произвольного запроса. Разберем по шагам:

  1. В свойствах динамического списка установим флаг Произвольный запрос.
  2. В тексте запроса выполним левое соединение справочника номенклатуры с регистром сведений (например, ЦеныНоменклатуры.СрезПоследних).
  3. Выведем поле Цена в список.

Пример текста запроса для динамического списка:


ВЫБРАТЬ
    СпрНоменклатура.Ссылка КАК Ссылка,
    СпрНоменклатура.Код КАК Код,
    СпрНоменклатура.Наименование КАК Наименование,
    ЕСТЬNULL(ЦеныСрезПоследних.Цена, 0) КАК Цена
ИЗ
    Справочник.Номенклатура КАК СпрНоменклатура
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ) КАК ЦеныСрезПоследних
        ПО СпрНоменклатура.Ссылка = ЦеныСрезПоследних.Номенклатура

Преимущество этого метода: платформа 1С автоматически позволяет пользователю выполнять сортировку, группировку и поиск по полю Цена, так как оно теперь является частью результирующей выборки запроса. При этом сохраняются все стандартные функции списка (иерархия, контекстное меню, отборы).

Решение №2: Использование Таблицы значений (для обычных форм)

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

Выясним, как правильно организовать работу в этом случае. Вместо смены типа существующего реквизита, мы изначально создаем на форме Табличное поле и связываем его с реквизитом типа ТаблицаЗначений. Рассмотрим алгоритм заполнения:

1. Создадим структуру таблицы значений с необходимыми колонками:


ТЗ_Товары = Новый ТаблицаЗначений;
ТЗ_Товары.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
ТЗ_Товары.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));
ТЗ_Товары.Колонки.Добавить("Группа", Новый ОписаниеТипов("Строка"));

2. После заполнения данных мы можем легко выполнить сортировку по любому полю одной командой:


// Сортировка по возрастанию цены
ТЗ_Товары.Сортировать("Цена Возр");

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

Решение №3: Программное изменение пути к данным

Рассмотрим вариант, предложенный в сообщении №1 — изменение пути к данным элемента формы. Этот метод применим, когда элементы управления создаются программно. Например, у нас есть одна таблица на форме, и мы хотим, чтобы она отображала то список справочника, то таблицу значений.

Для этого используется свойство ПутьКДанным. Однако, как справедливо замечено в дискуссии, для визуальных элементов, созданных в конфигураторе, это свойство ограничено в изменении. Если же элемент создан через Элементы.Добавить(), мы можем перенаправить его на другой реквизит формы:


// Пример для управляемых форм
НовыйЭлемент = Элементы.Добавить("ТаблицаРезультатов", Тип("ТаблицаФормы"));
НовыйЭлемент.ПутьКДанным = "Объект.ВременнаяТаблицаЗначений";

Проанализировав ситуацию, можно сделать вывод: если вам нужно просто сменить отображение данных, лучше иметь два разных элемента формы и управлять их видимостью (Элементы.ТаблицаСписка.Видимость = Ложь; Элементы.ТаблицаЗначений.Видимость = Истина;).

Сравнение подходов: что выбрать?

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

Динамический список:

Таблица значений:

Итоги и рекомендации

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

  1. Если это управляемая форма: переведите список номенклатуры в режим произвольного запроса и подключите таблицу цен через ЛЕВОЕ СОЕДИНЕНИЕ. Это сохранит быстродействие и даст желаемую сортировку.
  2. Если это обычная форма: используйте ТаблицуЗначений как промежуточный буфер. При открытии формы или изменении условий подбора заполняйте её данными из запроса и вызывайте метод Сортировать().
  3. Если требуется максимально гибкое управление: создайте два реквизита (список и таблицу) и переключайте видимость соответствующих элементов формы в зависимости от режима работы пользователя.

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

← На главную