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