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