Как исправить ошибки «Переменная не определена» и «Поле агрегатного объекта не обнаружено» в 1С 7.7?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

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

1. Разбор ошибки «Переменная не определена»: контекст и неявное объявление

В языке 1С 7.7 поддерживается неявное объявление локальных переменных: переменная создается в момент первого присваивания ей значения. Однако если переменная впервые передается в метод в качестве выходного параметра или используется в выражении до инициализации, платформа выдаст ошибку.

Рассмотрим классический пример ошибочного кода:


Функция ТестВыбораИзСписка()
    Список = СоздатьОбъект("СписокЗначений");
    Список.ДобавитьЗначение("Первое значение");
    Список.ДобавитьЗначение("Второе значение");
    Список.ДобавитьЗначение("Третье значение");
    
    // Ошибка: переменная ВыбранноеЗначение еще не объявлена и не инициализирована
    Если Список.ВыбратьЗначение(ВыбранноеЗначение, "Тест",,, 1) = 1 Тогда
        Возврат ВыбранноеЗначение;
    КонецЕсли;
    Возврат 0;
КонецФункции

Метод ВыбратьЗначение() ожидает переменную в первом параметре для записи выбранного элемента. Так как переменная ВыбранноеЗначение ранее не встречалась в левой части оператора присваивания, компилятор не знает о ее существовании. Чтобы исправить такую ситуацию, достаточно предварительно объявить переменную или присвоить ей начальное значение:


Функция ТестВыбораИзСписка()
    Перем ВыбранноеЗначение; // Явное объявление переменной
    Список = СоздатьОбъект("СписокЗначений");
    Список.ДобавитьЗначение("Первое значение");
    
    Если Список.ВыбратьЗначение(ВыбранноеЗначение, "Тест",,, 1) = 1 Тогда
        Возврат ВыбранноеЗначение;
    КонецЕсли;
    Возврат 0;
КонецФункции

2. Ошибки в выражениях ячеек печатной таблицы

Частая причина ошибки «Переменная не определена» при формировании отчетов — обращение к несуществующим переменным внутри ячеек макета (табличного документа).

Когда выполняется метод Таб.ВывестиСекцию("Секция"), платформа 1С 7.7 вычисляет выражения во всех ячейках выводимой секции. Если в свойствах ячейки указан тип «Выражение» и написано, например, Спр.ИстФин.ТекущийЭлемент(), система ищет переменную модуля с именем Спр. Если такой переменной в модуле отчета нет, возникает ошибка компиляции шаблона ячейки.

Проанализируем правила привязки данных макета к коду:

  1. Прямая связь с переменными модуля: В ячейке макета можно использовать только те переменные и объекты, которые объявлены в модуле (или на уровне модуля через Перем) и доступны в момент вызова ВывестиСекцию().
  2. Контекст цикла: Если вывод строк выполняется в цикле по таблице значений (например, ТабОбъект), в ячейках секции строки должны использоваться поля текущей строки этой таблицы (ТабОбъект.с1, ТабОбъект.ИстФин и т. д.), а не переменные временных запросов.
  3. Отсутствие лишних методов: Если поле уже содержит ссылку на справочник, метод ТекущийЭлемент() вызывать не нужно — достаточно указать само поле или его реквизит (например, ТабОбъект.ИстФин.Наименование).

3. Причины ошибки «Поле агрегатного объекта не обнаружено»

Ошибка «Поле агрегатного объекта не обнаружено» означает попытку обратиться к свойству, реквизиту или колонке, которых нет у данного объекта. Выясним основные причины этой проблемы в отчетах 1С 7.7:

  1. Отсутствие колонки в ТаблицеЗначений: Если создана промежуточная таблица и в ней объявлены колонки с1, с2, с3, с4, то попытка присвоить значение в ТабОбъект.ИстФин = ... вызовет исключение, так как колонка ИстФин не была добавлена методом НоваяКолонка().
  2. Непозиционированная таблица: Обращение к полям таблицы значений ТабОбъект.с1 вне цикла Пока ТабОбъект.ПолучитьСтроку() = 1 Цикл или без предварительного вызова ТабОбъект.ТекущаяСтрока(НомерСтроки) приводит к ошибке, так как текущая строка не выбрана.
  3. Периодические реквизиты справочников: В 1С 7.7 периодические реквизиты нельзя получать через стандартное обращение через точку (Объект.ИстФин). Для периодических реквизитов требуется использовать метод Получить() с указанием даты или устанавливать дату выборки через метод ИспользоватьДату().
  4. Прямые SQL-запросы (1C++): При использовании компоненты 1С++ периодические реквизиты хранятся в отдельной таблице _1SCONST. Прямое обращение вида $Спр.ИстФин к периодическому полю внутри SQL-запроса не сработает корректно. Для таких полей следует применять мета-функцию $ПоследнееЗначение.Объект.ИстФин(Спр.ID, :Дата).

4. Пошаговое исправление и оптимизация алгоритма отчета

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

  1. Отказ от запросов в цикле: Выполнение SQL-запросов (RS.ВыполнитьИнструкцию()) внутри вложенных циклов по справочникам приводит к критическому замедлению системы (проблема N+1). Следует выполнять один общий запрос с группировками ко всей базе данных.
  2. Явное добавление всех колонок в таблицу значений: Все поля, которые планируется выводить в макет или сворачивать, должны быть объявлены при инициализации таблицы.
  3. Удаление холостых циклов: Бессмысленный перебор справочников перед выводом секций без сохранения значений не несет функциональной нагрузки и должен быть удален.

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


// 1. Инициализация колонок таблицы значений
ТабОбъект = СоздатьОбъект("ТаблицаЗначений");
ТабОбъект.НоваяКолонка("Объект");
ТабОбъект.НоваяКолонка("ИстФин");
ТабОбъект.НоваяКолонка("СуммаНеПодпис", "Число");
ТабОбъект.НоваяКолонка("СуммаПодпис", "Число");
ТабОбъект.НоваяКолонка("ДолгЭкспертизы", "Число");

// 2. Обработка строк результата запроса
ТЗ = RS.ВыполнитьИнструкцию(ТекстЗапроса);
ТЗ.ВыбратьСтроки();
Пока ТЗ.ПолучитьСтроку() = 1 Цикл
    ТабОбъект.НоваяСтрока();
    ТабОбъект.Объект = ТЗ.Объект;
    ТабОбъект.ИстФин = ТЗ.ИстФин;
    
    Если Число(ТЗ.ВидАкта.Код) = 4 Тогда
        ТабОбъект.ДолгЭкспертизы = ТЗ.ДолгПоОплате;
    Иначе
        Если ТЗ.ПризнакПодпис = Перечисление.Признак.Нет Тогда
            ТабОбъект.СуммаНеПодпис = ТЗ.ДолгПоОплате;
        ИначеЕсли ТЗ.ПризнакПодпис = Перечисление.Признак.Да Тогда
            ТабОбъект.СуммаПодпис = ТЗ.ДолгПоОплате;
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

// 3. Сворачивание и группировка данных
ТабОбъект.Свернуть("Объект,ИстФин", "СуммаНеПодпис,СуммаПодпис,ДолгЭкспертизы");

// 4. Обход и вывод в печатную форму
ТабОбъект.ВыбратьСтроки();
Пока ТабОбъект.ПолучитьСтроку() = 1 Цикл
    // В ячейках секции "Объект" в макете указываем:
    // ТабОбъект.Объект, ТабОбъект.ИстФин, ТабОбъект.СуммаНеПодпис и т.д.
    Таб.ВывестиСекцию("Объект");
КонецЦикла;

Следуя этим правилам, мы гарантируем, что все переменные объявлены в нужной области видимости, реквизиты доступны для платформы, а отчет формируется быстро и без ошибок.

← На главную