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