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