В процессе разработки интерфейсов на платформе 1С:Предприятие часто возникает задача динамического управления данными. Типичная ситуация: на форме расположен список номенклатуры, и пользователю требуется сортировка по полю, которое не является индексированным реквизитом справочника (например, по цене, рассчитанной «на лету» или полученной из регистра сведений). Рассмотрим, можно ли программно изменить тип реквизита формы с СправочникСписок на ТаблицаЗначений и какие альтернативные подходы существуют для решения этой задачи.
Для начала проанализируем архитектурные ограничения платформы. В 1С тип реквизита формы жестко задается в метаданных на этапе проектирования. Прямое переназначение типа существующего реквизита (например, попытка присвоить РеквизитФормы = Новый ТаблицаЗначений, если он был СправочникСписок) невозможно и вызовет ошибку времени выполнения.
В управляемых формах (платформа 8.2 и 8.3) существует метод ИзменитьРеквизиты(). Разберем, как он работает. Этот метод не меняет тип старого реквизита, а позволяет удалить существующий реквизит и добавить новый с тем же именем, но другим типом. Однако такой подход крайне трудозатратен, так как требует:
DataPath) для всех колонок таблицы.Поэтому, если перед нами стоит задача обеспечить сортировку по произвольному полю, стоит рассмотреть более эффективные методы.
Если вы работаете в управляемом приложении, наиболее правильным и производительным решением будет использование реквизита с типом ДинамическийСписок. Рассмотрим, как реализовать в нем сортировку по цене, даже если цена хранится в отдельном регистре.
Проанализируем ситуацию: стандартный СправочникСписок отображает только данные самой таблицы справочника. Чтобы добавить цену, нам нужно переключить список в режим произвольного запроса. Разберем по шагам:
ЦеныНоменклатуры.СрезПоследних).Цена в список.Пример текста запроса для динамического списка:
ВЫБРАТЬ
СпрНоменклатура.Ссылка КАК Ссылка,
СпрНоменклатура.Код КАК Код,
СпрНоменклатура.Наименование КАК Наименование,
ЕСТЬNULL(ЦеныСрезПоследних.Цена, 0) КАК Цена
ИЗ
Справочник.Номенклатура КАК СпрНоменклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ) КАК ЦеныСрезПоследних
ПО СпрНоменклатура.Ссылка = ЦеныСрезПоследних.Номенклатура
Преимущество этого метода: платформа 1С автоматически позволяет пользователю выполнять сортировку, группировку и поиск по полю Цена, так как оно теперь является частью результирующей выборки запроса. При этом сохраняются все стандартные функции списка (иерархия, контекстное меню, отборы).
Если ваша конфигурация использует обычные формы или специфические алгоритмы подбора, где данные должны рассчитываться программно, использование ТаблицыЗначений оправдано. Как отмечалось в обсуждении, это позволяет реализовать практически любую логику сортировки.
Выясним, как правильно организовать работу в этом случае. Вместо смены типа существующего реквизита, мы изначально создаем на форме Табличное поле и связываем его с реквизитом типа ТаблицаЗначений. Рассмотрим алгоритм заполнения:
1. Создадим структуру таблицы значений с необходимыми колонками:
ТЗ_Товары = Новый ТаблицаЗначений;
ТЗ_Товары.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
ТЗ_Товары.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));
ТЗ_Товары.Колонки.Добавить("Группа", Новый ОписаниеТипов("Строка"));
2. После заполнения данных мы можем легко выполнить сортировку по любому полю одной командой:
// Сортировка по возрастанию цены
ТЗ_Товары.Сортировать("Цена Возр");
3. Важно помнить, что при использовании ТаблицыЗначений вы берете на себя ответственность за обновление данных. Если в справочнике изменится цена или наименование, таблица на форме автоматически не обновится, в отличие от динамического списка.
Рассмотрим вариант, предложенный в сообщении №1 — изменение пути к данным элемента формы. Этот метод применим, когда элементы управления создаются программно. Например, у нас есть одна таблица на форме, и мы хотим, чтобы она отображала то список справочника, то таблицу значений.
Для этого используется свойство ПутьКДанным. Однако, как справедливо замечено в дискуссии, для визуальных элементов, созданных в конфигураторе, это свойство ограничено в изменении. Если же элемент создан через Элементы.Добавить(), мы можем перенаправить его на другой реквизит формы:
// Пример для управляемых форм
НовыйЭлемент = Элементы.Добавить("ТаблицаРезультатов", Тип("ТаблицаФормы"));
НовыйЭлемент.ПутьКДанным = "Объект.ВременнаяТаблицаЗначений";
Проанализировав ситуацию, можно сделать вывод: если вам нужно просто сменить отображение данных, лучше иметь два разных элемента формы и управлять их видимостью (Элементы.ТаблицаСписка.Видимость = Ложь; Элементы.ТаблицаЗначений.Видимость = Истина;).
Выясним сильные и слабые стороны каждого метода, чтобы выбрать оптимальный для вашей задачи.
Динамический список:
Таблица значений:
Подводя итог, можно сказать, что «менять тип реквизита» в буквальном смысле не нужно. Если ваша цель — сортировка по цене в окне регистрации продаж, рекомендуем следующий путь:
ЛЕВОЕ СОЕДИНЕНИЕ. Это сохранит быстродействие и даст желаемую сортировку.ТаблицуЗначений как промежуточный буфер. При открытии формы или изменении условий подбора заполняйте её данными из запроса и вызывайте метод Сортировать().Рассмотренные методы позволяют обойти жесткую типизацию платформы и предоставить пользователю удобный инструмент для работы с данными, сохраняя при этом стабильность и производительность системы.