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