Как решить проблему, когда отчет на СКД в расширении 1С не видит реквизиты документа-регистратора?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет
← На главную

При работе с расширениями в системе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда Система Компоновки Данных (СКД) в отчетах не "видит" или не предоставляет доступ к некоторым реквизитам объектов, которые, казалось бы, доступны в основной конфигурации или даже добавлены в само расширение. Рассмотрим подробно проблему, когда отчет, созданный в расширении и использующий регистр бухгалтерии, не отображает поля документа-регистратора, такие как контрагент или договор.

Представьте следующую ситуацию: мы создали расширение для типовой конфигурации, например, "Бухгалтерия КОРП МСФО". В это расширение были добавлены существующий документ "Поступление (акты, накладные)" и регистр бухгалтерии "Хозрасчетный". Для нового отчета на СКД, который выбирает данные из виртуальной таблицы оборотов регистра бухгалтерии, нам необходимо вывести и использовать в отборах реквизиты документа-регистратора, такие как "Контрагент" и "Договор". Однако, несмотря на то что документ корректно открывается в тонком клиенте и позволяет фильтровать по этим полям в списках, в конструкторе запросов СКД они оказываются недоступными. Это достаточно распространенная проблема, и мы разберем её причины и способы решения.

Почему СКД не видит реквизиты регистратора в расширении?

Давайте выясним основные причины, по которым возникает эта сложность:

  1. Ограниченная видимость метаданных в расширениях: Конструктор запросов и СКД в конфигураторе имеют особенности при работе с метаданными, которые были добавлены или заимствованы в расширение. Объекты, внесенные в расширение конфигурации, не всегда полностью доступны во внешних отчетах или обработках на этапе разработки в конфигураторе. Это означает, что хотя объекты существуют и функционируют в режиме "1С:Предприятие", на этапе проектирования в конфигураторе их структура может быть видна не полностью.

  2. Проблемы с заимствованием: Хотя заимствование объектов (документов, регистров, справочников, их реквизитов, табличных частей, форм) из основной конфигурации в расширение является одним из способов решения проблем с видимостью, оно не всегда срабатывает для всех связанных метаданных или их глубоких связей. Более того, заимствование большого количества объектов может значительно усложнить процесс обновления и анализа изменений в расширении, что создает дополнительные трудности.

  3. Доступность стандартных реквизитов: Даже если сам объект заимствован, стандартные реквизиты (например, "ЭтоГруппа" у справочника или "Владелец" для подчиненного справочника) могут быть недоступны в конструкторе запросов в расширении. Для их корректного отображения иногда требуется явно указывать свойства как "контролируемые" в расширении, что требует ручной работы и внимания.

  4. Ошибки доступа: При обращении СКД отчета из расширения к несуществующему типу объектов или к полям, которые не были правильно определены, может возникать ошибка при получении информации из набора данных. Также проблемы могут быть связаны с правами доступа или функциональными опциями, которые скрывают определенные поля от пользователя или подсистемы.

Первые попытки решения и их ограничения

Когда мы сталкиваемся с такой проблемой, первое, что мы обычно пытаемся сделать, это убедиться, что все необходимые объекты добавлены в расширение. В нашем случае, автор уже попытался:

  1. Добавить сам документ "Поступление (акты, накладные)" в расширение. Это базовый шаг, чтобы СКД вообще могла оперировать этим типом документа.

  2. Добавить в расширение реквизиты документа, такие как "Контрагент", "Договор". Это должно обеспечить видимость этих конкретных полей.

  3. Добавить связанные справочники, например, "Контрагенты" и "Договоры контрагентов", в расширение. Часто СКД требует, чтобы не только сам реквизит, но и тип данных, на который он ссылается, был виден в контексте расширения.

Однако, как показала практика автора, даже выполнение всех этих шагов не всегда приносит желаемый результат. Он подтвердил, что все эти объекты были добавлены, но СКД по-прежнему не видела поля "Контрагент" и "Договор" из регистратора. Это указывает на более глубокую проблему в работе конструктора запросов СКД в контексте расширений.

Альтернативные подходы к разработке схемы СКД в расширениях

Прежде чем перейти к окончательному решению, которое нашел автор, рассмотрим несколько других методов, которые могут быть полезны в схожих ситуациях:

  1. Разработка схемы СКД через консоль СКД в режиме "1С:Предприятие": Консоль СКД, запущенная в пользовательском режиме, способна видеть таблицы из всех активных расширений при наличии соответствующих прав. Мы можем использовать этот подход для создания или отладки запроса. Для этого:

    1. Запускаем базу в режиме "1С:Предприятие".
    2. Открываем внешнюю обработку "Консоль СКД" (или аналогичную).
    3. Создаем запрос, в котором указываем все необходимые поля, включая те, что СКД не "видит" в конфигураторе, например, `Регистратор.Контрагент`.
    4. Настраиваем все нужные параметры, отборы, поля в СКД в консоли.
    5. Сохраняем схему компоновки данных в файл (XML).
    6. Загружаем этот файл в макет внешнего отчета в конфигураторе. При загрузке могут возникать предупреждения или ошибки в конфигураторе, но их часто можно игнорировать, и отчет при этом будет корректно работать в режиме "1С:Предприятие". Возможно, потребуется предварительно создать "пустой" запрос в схеме СКД отчета для возможности настройки структуры, отборов и т.п.
  2. Прямое редактирование текста запроса: Если конструктор запросов не справляется с задачей, мы можем вручную написать или скорректировать текст запроса. Этот текст затем можно вставить в схему компоновки данных напрямую, минуя конструктор. Этот метод требует хорошего знания языка запросов 1С и внимательности, поскольку ошибки в запросе не будут подсвечены конструктором.

  3. Использование расширения языка запросов для СКД: В СКД есть возможность использовать расширения языка запросов, которые позволяют, например, подключать характеристики объектов через конструкции типа `ХАРАКТЕРИСТИКИ`. Это может быть полезно для более сложных сценариев, когда нужно получить данные, связанные с дополнительными свойствами объектов.

  4. Виртуальные таблицы: При работе с виртуальными таблицами в запросах (как в нашем случае, таблица оборотов регистра бухгалтерии) рекомендуется передавать в параметры таблиц все относящиеся к ним условия (например, период, отбор по счету). Это помогает оптимизировать запрос и обеспечивает более точное получение данных. Следует учитывать, что СКД может автоматически вставлять дополнительные отборы в виртуальные таблицы, что иногда нежелательно и требует контроля.

Эффективное решение: программная подмена запроса в "ПриКомпоновкеРезультата"

В случае, когда никакие из вышеперечисленных методов не дали результата, или когда требуется особая гибкость и динамичность в формировании запроса, мы можем воспользоваться мощным механизмом — процедурой обработчика события ПриКомпоновкеРезультата. Именно этот метод помог автору решить его проблему.

Процедура ПриКомпоновкеРезультата вызывается при формировании отчета, непосредственно перед выполнением запроса, и позволяет нам переопределить или дополнить стандартное поведение генерации отчета. Это идеальное место для динамической модификации запроса, когда декларативный подход СКД не позволяет достичь нужной гибкости или обойти ограничения конфигуратора в расширении.

Разберем по шагам, как применить это решение:

  1. Создаем "пустую" выборку в СКД с нужными колонками и типами данных: В конфигураторе, в схеме компоновки данных нашего отчета, мы создаем набор данных типа "Запрос". В нем мы можем указать простейший запрос, который служит лишь "заглушкой", чтобы СКД могла сформировать структуру полей, их типы и заголовки. Главное, чтобы имена полей соответствовали тем, которые мы хотим получить в итоговом запросе. Например:

    
    ВЫБРАТЬ
        0 КАК СуммаОборот,
        NULL КАК Контрагент,
        NULL КАК Договор
    ИЗ
        РегистрБухгалтерии.Хозрасчетный.Обороты(, , , , , , , ) КАК ХозрасчетныйОбороты
    ГДЕ ЛОЖЬ
    

    Здесь мы указываем поля, которые нам нужны, и их примерные типы данных. Условие `ГДЕ ЛОЖЬ` гарантирует, что этот "заглушечный" запрос никогда не вернет реальных данных, но позволит СКД "увидеть" метаданные.

  2. Переопределяем текст запроса в процедуре ПриКомпоновкеРезультата: В модуле отчета мы находим или создаем обработчик события ПриКомпоновкеРезультата для нашего набора данных. В этой процедуре мы получаем доступ к объекту схемы компоновки данных и можем динамически изменить текст запроса для нашего набора данных.

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

    Таким образом, мы сначала создаем в СКД структуру, которая "обманывает" конфигуратор, сообщая ему о наличии нужных полей. А затем, в режиме "1С:Предприятие", в обработчике события ПриКомпоновкеРезультата, мы программно подменяем запрос на тот, который корректно обращается ко всем необходимым полям документа-регистратора. Этот подход позволяет обойти ограничения конструктора запросов в конфигураторе и использовать всю мощь СКД и языка запросов 1С.

Этот метод, а именно динамическое изменение текста запроса в процедуре ПриКомпоновкеРезультата, является признанным и эффективным для обхода ограничений СКД в сложных сценариях, особенно при работе с расширениями. Установив СтандартнаяОбработка = Ложь, мы полностью берем на себя контроль над процессом формирования отчета, включая модификацию запроса схемы компоновки данных перед его выполнением. Это позволяет нам адаптировать запрос под любые условия и получать доступ к данным, которые не видны на этапе проектирования.

← На главную