При переходе к разработке на управляемом интерфейсе платформы «1С:Предприятие 8» одной из самых частых трудностей для начинающих программистов становится понимание концепции разделения данных и их визуального отображения. В обычных формах (версия 8.2 и более ранние) разработчик мог напрямую манипулировать табличным полем на форме. В управляемых формах архитектура изменилась кардинально.
В этой статье мы подробно разберем, почему возникает популярная ошибка «Обращение к процедуре как к функции» при попытке добавить строку в таблицу, выясним разницу между элементами и реквизитами формы, а также рассмотрим полезные практические приемы работы со строками динамических коллекций.
Рассмотрим ситуацию, с которой столкнулся автор темы. На форме расположена таблица значений, и разработчик пытается добавить в нее строку следующим кодом:
НоваяСтрокаКом = Элементы.ТзНоменклатураДокумнетовДляПодбора.ДобавитьСтроку();
При компиляции или выполнении этого кода система выдает ошибку. Проанализируем, почему это происходит:
Элементы.ТзНоменклатураДокумнетовДляПодбора представляет собой визуальный элемент управления на форме. Его тип в контексте управляемой формы — ТаблицаФормы.ТаблицаФормы действительно существует метод ДобавитьСтроку(). Однако этот метод является процедурой, а не функцией.ДобавитьСтроку() предназначен исключительно для интерактивной имитации действий пользователя. Когда программа вызывает этот метод, на клиенте визуально создается новая строка и курсор позиционируется в ней для ввода данных (как если бы пользователь нажал кнопку «Добавить» на клавиатуре или панели инструментов).НоваяСтрокаКом = ...) вызывает закономерный сбой компилятора: система не может записать пустоту в переменную.Для успешного решения задачи нам необходимо четко разделять два понятия:
ДанныеФормыКоллекция (или ДанныеФормыДерево для иерархических списков). Именно сюда записываются все значения, которые затем сохраняются в базу данных.ТаблицаФормы. Через него настраивается оформление таблицы, видимость колонок, шрифты и доступность для редактирования.Золотое правило управляемых форм: любые изменения информации (добавление строк, удаление строк, заполнение колонок) всегда должны производиться в данных (реквизите), а не в визуальном элементе.
Чтобы успешно добавить строку и сразу же заполнить ее нужными значениями, нам необходимо обратиться напрямую к реквизиту формы, минуя коллекцию Элементы. Работающий код выглядит следующим образом:
НоваяСтрокаКом = ТзНоменклатураДокумнетовДляПодбора.Добавить();
Давайте проанализируем, почему этот вариант работает безошибочно:
ТзНоменклатураДокумнетовДляПодбора.ДанныеФормыКоллекция.Добавить() у этого объекта является функцией. Он физически добавляет новую строку в оперативную память и возвращает ссылку на эту строку в виде объекта типа ДанныеФормыЭлементКоллекции.НоваяСтрокаКом, мы можем обращаться к любым ее колонкам напрямую и заполнять их данными.Рассмотрим пример полноценного заполнения новой строки программным путем:
// Добавляем строку непосредственно в коллекцию данных формы
НоваяСтрокаКом = ТзНоменклатураДокумнетовДляПодбора.Добавить();
// Заполняем реквизиты добавленной строки
НоваяСтрокаКом.Номенклатура = Справочники.Номенклатура.НайтиПоРеквизиту("Код", "000001");
НоваяСтрокаКом.Количество = 10;
НоваяСтрокаКом.Цена = 1500;
НоваяСтрокаКом.Сумма = НоваяСтрокаКом.Количество * НоваяСтрокаКом.Цена;
При этом визуальный элемент таблицы на экране автоматически обновится и мгновенно покажет пользователю новую строку с заполненными реквизитами.
При решении задач автоматизации программисты часто сталкиваются с сопутствующими требованиями со стороны пользователей. Рассмотрим три важных сценария, которые сделают работу с таблицей максимально удобной.
Когда мы добавляем строку через данные (Реквизит.Добавить()), она тихо появляется в таблице, но фокус (активная строка, выделенная синим цветом) остается там, где и был. Чтобы перенести фокус на только что созданную строку, нужно связать данные и отображение с помощью уникального идентификатора строки:
// 1. Добавляем строку в данные
НоваяСтрокаКом = ТзНоменклатураДокумнетовДляПодбора.Добавить();
// 2. Получаем уникальный идентификатор этой строки в контексте формы
ИдентификаторСтроки = НоваяСтрокаКом.ПолучитьИдентификатор();
// 3. Устанавливаем фокус на эту строку в визуальном элементе управления
Элементы.ТзНоменклатураДокумнетовДляПодбора.ТекущаяСтрока = ИдентификаторСтроки;
Представим сценарий: пользователь нажимает кнопку «Добавить товар», программа добавляет строку, заполняет номенклатуру по умолчанию и сразу же открывает режим ввода в колонке «Количество», чтобы пользователю не приходилось лишний раз кликать мышкой. Для этого используется метод ИзменитьСтроку() у визуального элемента формы:
// Добавляем строку и фокусируемся на ней
НоваяСтрокаКом = ТзНоменклатураДокумнетовДляПодбора.Добавить();
ИдентификаторСтроки = НоваяСтрокаКом.ПолучитьИдентификатор();
Элементы.ТзНоменклатураДокумнетовДляПодбора.ТекущаяСтрока = ИдентификаторСтроки;
// Назначаем активной ту колонку таблицы, которую пользователь должен заполнить (например, Количество)
Элементы.ТзНоменклатураДокумнетовДляПодбора.ТекущийЭлемент = Элементы.ТзНоменклатураДокумнетовДляПодбораКоличество;
// Принудительно открываем режим интерактивного редактирования ячейки
Элементы.ТзНоменклатураДокумнетовДляПодбора.ИзменитьСтроку();
Важно всегда контролировать, в каком контексте выполняется ваш программный код:
&НаКлиенте) классический универсальный объект ТаблицаЗначений существовать не может. Вместо него платформа оперирует типом ДанныеФормыКоллекция. Его метод Добавить() работает быстро и не требует обращений к серверу.&НаСервере или &НаСервереБезКонтекста) у вас есть возможность работать как с типами ДанныеФормыКоллекция, так и переводить их в полноценные объекты ТаблицаЗначений с помощью методов РеквизитФормыВЗначение() и ЗначениеВРеквизитФормы().Объект:
&НаСервере
Процедура ЗаполнитьТабличнуюЧастьНаСервере()
// Добавление строки в табличную часть документа на сервере
НоваяСтрока = Объект.Товары.Добавить();
НоваяСтрока.Номенклатура = Справочники.Номенклатура.НайтиПоКоду("00012");
КонецПроцедуры
При программной работе с таблицами в управляемых формах 1С всегда задавайте себе вопрос: я сейчас работаю с данными или с картинкой на экране?
Если вам нужно добавить строку, удалить ее, изменить количество или цену — работайте напрямую с реквизитом формы (ТзНоменклатураДокумнетовДляПодбора.Добавить()). Если же вам нужно выделить строку цветом, установить фокус ввода или скрыть какую-то колонку — используйте визуальный элемент из коллекции элементов формы (Элементы.ТзНоменклатураДокумнетовДляПодбора).