Часто в процессе разработки возникает задача: перенести алгоритм заполнения документа, реализованный в стандартном событии ОбработкаЗаполнения модуля объекта, на кнопку формы. При этом начинающие разработчики нередко пытаются скопировать код из модуля объекта напрямую в обработчик команды формы и сталкиваются с ошибкой компиляции вида «Переменная не определена (ИмяТабличнойЧасти)». Разберем по шагам, почему возникает эта ошибка и как правильно реализовать заполнение документа по кнопке.
Проанализируем контекст выполнения кода в платформе 1С:Предприятие 8.3:
Стоимость.Добавить() или Дата = ТекущаяДата()).Объект). Прямое обращение по имени реквизита или табличной части без указания префикса Объект. приводит к тому, что платформа ищет локальную переменную модуля формы, не находит ее и выдает ошибку компиляции.Кроме того, перенос всего алгоритма заполнения внутрь формы нарушает принцип повторного использования кода. Если логика ввода на основании уже написана в модуле объекта, ее следует вызывать централизованно.
Рассмотрим правильный способ вызова логики ОбработкаЗаполнения из управляемой формы. В модуле объекта документа оставляем типовой обработчик заполнения. Посмотрим на пример кода в модуле объекта:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.уатЗаказГрузоотправителя") Тогда
// Очищаем табличную часть перед заполнением
Стоимость.Очистить();
Для Каждого ТекСтрокаУслуги Из ДанныеЗаполнения.Услуги Цикл
НоваяСтрока = Стоимость.Добавить();
НоваяСтрока.Номенклатура = ТекСтрокаУслуги.Номенклатура;
НоваяСтрока.НоменклатураУслуги = ТекСтрокаУслуги.Номенклатура;
НоваяСтрока.Количество = ТекСтрокаУслуги.Количество;
НоваяСтрока.Цена = ТекСтрокаУслуги.Цена;
НоваяСтрока.СтавкаНДС = ТекСтрокаУслуги.СтавкаНДС;
НоваяСтрока.Сумма = ТекСтрокаУслуги.Сумма;
НоваяСтрока.СуммаНДС = ТекСтрокаУслуги.СуммаНДС;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Чтобы запустить этот код по кнопке на форме, преобразуем реквизит формы в прикладной объект с помощью РеквизитФормыВЗначение, вызовем платформенный метод Заполнить() и вернем измененные данные обратно в форму через ЗначениеВРеквизитФормы. Обратите внимание, что эти методы работают исключительно в контексте &НаСервере.
Разберем код модуля управляемой формы:
&НаКлиенте
Процедура КомандаЗаполнитьПоЗаказу(Команда)
// В качестве параметра передаем ссылку на документ-основание
// Например, реквизит документа или выбранное пользователем значение
Если ЗначениеЗаполнено(Объект.ДокументОснование) Тогда
ЗаполнитьНаСервере(Объект.ДокументОснование);
Иначе
ПоказатьПредупреждение(, "Не указан документ-основание для заполнения!");
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьНаСервере(ДокументОснование)
// Получаем реальный объект из реквизита формы
ДокументОбъект = РеквизитФормыВЗначение("Объект");
// Вызываем обработку заполнения модуля объекта
ДокументОбъект.Заполнить(ДокументОснование);
// Помещаем измененный объект обратно в реквизит формы
ЗначениеВРеквизитФормы(ДокументОбъект, "Объект");
// Устанавливаем признак модифицированности формы
Модифицированность = Истина;
КонецПроцедуры
Если логика заполнения требуется исключительно для интерактивной работы в конкретной форме и нет необходимости дергать ОбработкаЗаполнения всего объекта, можно заполнить коллекцию формы напрямую на сервере. Это исключает накладные расходы на сериализацию всего объекта через РеквизитФормыВЗначение.
Рассмотрим пример реализации прямого заполнения на сервере:
&НаКлиенте
Процедура ЗаполнитьТабличнуюЧасть(Команда)
Если НЕ ЗначениеЗаполнено(Объект.ДокументОснование) Тогда
ПоказатьПредупреждение(, "Выберите документ-основание!");
Возврат;
КонецЕсли;
ЗаполнитьТабличнуюЧастьНаСервере(Объект.ДокументОснование);
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьТабличнуюЧастьНаСервере(СсылкаНаЗаказ)
// Очищаем табличную часть формы через реквизит Объект
Объект.Стоимость.Очистить();
// Считываем строки документа-основания
Для Каждого ТекСтрокаУслуги Из СсылкаНаЗаказ.Услуги Цикл
НоваяСтрока = Объект.Стоимость.Добавить();
НоваяСтрока.Номенклатура = ТекСтрокаУслуги.Номенклатура;
НоваяСтрока.НоменклатураУслуги = ТекСтрокаУслуги.Номенклатура;
НоваяСтрока.Количество = ТекСтрокаУслуги.Количество;
НоваяСтрока.Цена = ТекСтрокаУслуги.Цена;
НоваяСтрока.СтавкаНДС = ТекСтрокаУслуги.СтавкаНДС;
НоваяСтрока.Сумма = ТекСтрокаУслуги.Сумма;
НоваяСтрока.СуммаНДС = ТекСтрокаУслуги.СуммаНДС;
КонецЦикла;
Модифицированность = Истина;
КонецПроцедуры
Заполнить() платформы 1С самостоятельно не удаляет строки, которые уже были в табличной части. Обязательно вызывайте Очистить() перед циклом добавления строк, иначе при повторном нажатии на кнопку данные продублируются.СсылкаНаЗаказ.Услуги) происходит неявное чтение всего объекта из базы данных. Если в документе-основании много строк или реквизитов, предпочтительнее выбирать данные запросом к табличной части документа.Модифицированность = Истина, чтобы платформа предупредила пользователя о необходимости сохранения изменений при закрытии формы.