Почему в запросе 1С 7.7 возникает ошибка «Неверно заданный путь» при обращении к реквизиту?

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

При доработке стандартных отчетов в платформе 1С:Предприятие 7.7 разработчики нередко сталкиваются с ситуацией, когда добавление нового поля через цепочку реквизитов приводит к аварийной остановке выполнения запроса с диагностическим сообщением вида: «Запрос : Неверно заданный путь 'ИмяРеквизита'».

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

Причина ошибки: ограничения механизма запросов 1С 7.7

Посмотрим на путь к данным, вызвавший сбой при формировании отчета:

Регистр.ПартииНаличие.ТекущийДокумент.Реализация.Контрагент.ЮрФизЛицо.ФактАдрес

На первый взгляд цепочка кажется логичной: от регистра через документ-регистратор мы переходим к контрагенту, затем к его юридическому или физическому лицу, а от него хотим получить фактический адрес. Однако транслятор запросов 1С 7.7 сообщает об ошибке на последнем элементе пути. Причина кроется в типизации реквизита ЮрФизЛицо в метаданных конфигурации (например, в конфигурации «Торговля и Склад 7.7»):

  1. Неопределенный вид справочника. Реквизит ЮрФизЛицо имеет базовый тип Справочник без жестко зафиксированного конкретного вида, так как может ссылаться либо на справочник ЮрЛица, либо на ФизЛица.
  2. Статический разбор метаданных. Механизм встроенных запросов («черный запрос») платформы 1С 7.7 строго типизирован на этапе компиляции. Он должен однозначно сопоставить каждое поле запроса с физической таблицей базы данных. Если тип или вид объекта не зафиксирован, транслятор запроса не может определить, из какой именно таблицы извлекать реквизит ФактАдрес.
  3. Отсутствие позднего связывания в запросах. В обычном коде модулей платформа 1С 7.7 поддерживает позднее связывание (Late Binding): если написать Контрагент.ЮрФизЛицо.ФактАдрес в процедуре, платформа во время выполнения определит реальный вид справочника и вернет значение. Внутри самого текста запроса в секциях объявления переменных и группировок это поведение платформой не поддерживается.

Способ 1. Постобработка результата через Таблицу Значений (рекомендуемый)

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

Разберем по шагам, как переписать логику отчета:

  1. Убираем из текста запроса проблемную переменную ФактАдрес и группировку по ней. Оставляем группировку по строго типизированному объекту — Покупатель (или Контрагент), а также по номенклатуре.
  2. Выгружаем результат запроса в таблицу значений методом Выгрузить().
  3. Добавляем в полученную таблицу новую колонку под фактический адрес.
  4. В цикле обходим строки таблицы значений, обращаясь к реквизиту ЮрФизЛицо.ФактАдрес через стандартный синтаксис языка 1С, где позднее связывание работает корректно.
  5. Используем метод Свернуть() для получения итоговых группировок по адресу и номенклатуре с суммированием числовых показателей.

Рассмотрим пример программной реализации:


Перем Запрос, ТЗ;

ТекстЗапроса = "
|Период с ДатаНачала по ДатаКонца;
|Фирма        = Регистр.ПартииНаличие.Фирма;
|Номенклатура = Регистр.ПартииНаличие.Номенклатура;
|Покупатель   = Регистр.ПартииНаличие.ТекущийДокумент.Реализация.Контрагент;
|Количество   = Регистр.ПартииНаличие.Количество;
|Сумма        = Регистр.ПартииНаличие.СуммаРуб;
|Функция РасходК = Расход(Количество);
|Функция РасходС = Расход(Сумма);
|Группировка Покупатель без групп;
|Группировка Номенклатура без групп;
|";

Запрос = СоздатьОбъект("Запрос");
Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
    ТЗ = СоздатьОбъект("ТаблицаЗначений");
    Запрос.Выгрузить(ТЗ, 1, 0);
    
    // Добавляем колонку для адреса
    ТЗ.НоваяКолонка("ФактАдрес", "Строка");
    
    // Заполняем адрес обычным обращением к объекту
    ТЗ.ВыбратьСтроки();
    Пока ТЗ.ПолучитьСтроку() = 1 Цикл
        Если ПустоеЗначение(ТЗ.Покупатель) = 0 Тогда
            Если ТЗ.Покупатель.ЮрФизЛицо.Выбран() = 1 Тогда
                ТЗ.ФактАдрес = СокрЛП(ТЗ.Покупатель.ЮрФизЛицо.ФактАдрес);
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    
    // Сворачиваем по требуемым группировкам отчета
    ТЗ.Свернуть("ФактАдрес,Номенклатура", "РасходК,РасходС");
    ТЗ.Сортировать("ФактАдрес+,Номенклатура+");
    
    // Выводим данные в печатную форму
    // ...
КонецЕсли;

Способ 2. Кэширование адреса в справочнике «Контрагенты»

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

  1. Добавляем в справочник Контрагенты строковый реквизит ФактАдрес.
  2. В модуле формы или в предопределенной процедуре ПриЗаписи() справочника Контрагенты реализуем автоматическое копирование фактического адреса из связанного элемента ЮрФизЛицо.
  3. Заполняем значение реквизита для существующих элементов справочника групповой обработкой.

После этого путь в тексте запроса сокращается и становится однозначно типизированным:

ФактАдрес = Регистр.ПартииНаличие.ТекущийДокумент.Реализация.Контрагент.ФактАдрес;

Такая конструкция успешно компилируется встроенным генератором запросов 1С 7.7 и позволяет использовать поле ФактАдрес в секции Группировка без необходимости дополнительной постобработки в памяти.

Способ 3. Использование прямого SQL-запроса (для баз на MS SQL Server)

Если информационная база работает под управлением MS SQL Server и в конфигурации подключен компонент прямого доступа (например, библиотека 1С++ через класс ODBCRecordset), ограничение платформы можно обойти на уровне базы данных:

  1. В прямом T-SQL запросе таблицы справочников Контрагенты, ЮрЛица и ФизЛица соединяются через операторы LEFT JOIN.
  2. Определение типа объекта выполняется через проверку префикса идентификатора или поля вида объекта.
  3. Агрегирование и группировка по фактическому адресу выполняются напрямую на стороне сервера СУБД, что обеспечивает максимальную скорость формирования отчета на больших объемах данных.
← На главную