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