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