При разработке дополнительных отчетов и обработок на базе Библиотеки Стандартных Подсистем (БСП) часто возникает задача заполнить табличную часть документа, который пользователь только что создал и еще не успел записать в базу данных. В этой ситуации стандартный вызов серверного метода не сработает, так как объект еще не существует в информационной базе как ссылка. Разберем, как правильно реализовать команду заполнения формы, как передать данные в табличную часть и почему могут появляться пустые строки.
Для работы с новым, незаписанным объектом прямо на клиенте или через контекст формы необходимо использовать специальный тип команды БСП — ТипКомандыЗаполнениеФормы. Рассмотрим регистрационную функцию модуля объекта внешней обработки:
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиЗаполнениеОбъекта();
ПараметрыРегистрации.Версия = "1.0";
ПараметрыРегистрации.Назначение.Добавить("Документ.ПриобретениеТоваровУслуг"); // Указываем целевой документ
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
НоваяКоманда.Представление = НСтр("ru = 'Заполнить по остаткам'");
НоваяКоманда.Идентификатор = "ЗаполнитьТЧ";
// Критически важный параметр для незаписанных объектов:
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыЗаполнениеФормы();
Возврат ПараметрыРегистрации;
КонецФункции
Выбор значения ТипКомандыЗаполнениеФормы указывает БСП, что обработка должна передавать в процедуру выполнения контекст управляемой формы документа.
Когда пользователь нажимает кнопку заполнения, БСП вызывает в модуле объекта обработки экспортную процедуру ВыполнитьКоманду. В структуру ПараметрыВыполнения передается свойство ЭтаФорма, через которое мы получаем прямой доступ к реквизитам формы документа.
Посмотрим на базовый пример реализации:
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения, ПараметрыВыполнения) Экспорт
Если ИдентификаторКоманды = "ЗаполнитьТЧ" Тогда
ЗаполнитьТабличнуюЧасть(ПараметрыВыполнения.ЭтаФорма);
КонецЕсли;
КонецПроцедуры
Процедура ЗаполнитьТабличнуюЧасть(ФормаДокумента)
// Получаем реквизиты из формы для формирования запроса
Организация = ФормаДокумента.Объект.Организация;
Склад = ФормаДокумента.Объект.Склад;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Остатки.Номенклатура КАК Номенклатура,
| Остатки.Характеристика КАК Характеристика,
| Остатки.КоличествоОстаток КАК Количество
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Организация = &Организация И Склад = &Склад) КАК Остатки";
Запрос.УстановитьПараметр("Период", ТекущаяДатаСеанса());
Запрос.УстановитьПараметр("Организация", Организация);
Запрос.УстановитьПараметр("Склад", Склад);
ТаблицаДанных = Запрос.Выполнить().Выгрузить();
// Загружаем данные в коллекцию формы
ФормаДокумента.Объект.Товары.Загрузить(ТаблицаДанных);
// Устанавливаем признак модифицированности, чтобы форма предложила сохранить изменения
ФормаДокумента.Модифицированность = Истина;
КонецПроцедуры
Частая проблема при заполнении табличной части: строки в документе добавляются, их количество совпадает с выборкой, но ячейки (например, Номенклатура) остаются пустыми. Проанализируем, почему это происходит:
Загрузить() сопоставляет колонки таблицы значений и табличной части исключительно по именам. Если запрос формировался через конструктор без явных псевдонимов, поля составных регистров могут получить автоматические имена (например, АналитикаУчетаНоменклатурыНоменклатура вместо Номенклатура). Всегда проверяйте псевдонимы колонок (КАК ИмяКолонкиТЧ).Неопределено вместо ссылки/числа, значение не отобразится.КлючСвязи или служебные реквизиты строк. При прямой загрузке таблицы они могут остаться пустыми, что нарушит работу связанных механизмов.Метод Форма.Объект.Товары.Загрузить() работает напрямую с объектом ДанныеФормыКоллекция. При этом не срабатывают типовые обработчики пересчета сумм, цен и налогов. Чтобы применить объектную логику конфигурации, можно преобразовать данные формы в полноценный прикладной объект, заполнить его и вернуть назад:
Процедура ЗаполнитьЧерезОбъект(ФормаДокумента)
// 1. Преобразуем данные формы в ДокументОбъект
ДокументОбъект = ДанныеФормыВЗначение(ФормаДокумента.Объект, Тип("ДокументОбъект.ПриобретениеТоваровУслуг"));
// 2. Заполняем табличную часть объекта
// ТаблицаДанных = ... (получение данных запросом)
ДокументОбъект.Товары.Загрузить(ТаблицаДанных);
// 3. Вызываем встроенные методы документа (если применимо)
// ДокументОбъект.РассчитатьСуммы();
// 4. Помещаем измененный объект обратно в форму
ЗначениеВДанныеФормы(ДокументОбъект, ФормаДокумента.Объект);
ФормаДокумента.Модифицированность = Истина;
КонецПроцедуры
Этот способ гарантирует корректную инициализацию всех служебных структур документа перед отображением пользователю.