Как исправить ошибку «Переменная не определена» при установке параметров запроса и заполнить таблицу на обычной форме 1С?

Программист 1С v8.3 (Обычные формы) Бухгалтерский учет IT и автоматизация бизнеса
← На главную

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

Выясняем причины возникновения ошибок

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

Рассмотрим подробнее, почему это произошло. Ошибка вызвана двумя фундаментальными причинами:

1. Нарушение областей видимости переменных. Функция ЗаполнитьТаблицуРасшифровкаСтатейРасходов() не «знает» о существовании реквизитов формы или объекта НачалоПериода и КонецПериода, если они не объявлены внутри самой функции или не переданы в нее в качестве входящих параметров. В отличие от управляемых форм, в обычных формах обращение к реквизитам объекта должно осуществляться явно (например, через ЭтотОбъект) или передаваться контекстно.

2. Неверный синтаксис метода УстановитьПараметр(). Конструкция вида Запрос.УстановитьПараметр("НачалоПериода,КонецПериода", НачалоПериода,КонецПериода); синтаксически ошибочна. Метод УстановитьПараметр у объекта Запрос принимает строго два параметра: имя параметра в виде строки (один параметр) и его значение.

Шаг 1. Передаем параметры в функцию

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


Функция ЗаполнитьТаблицуРасшифровкаСтатейРасходов(Знач НачалоПериода, Знач КонецПериода) 
    
    Запрос = Новый Запрос;
    // ... дальнейший код запроса
    
КонецФункции

Шаг 2. Корректно устанавливаем параметры запроса

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


Запрос.УстановитьПараметр("НачалоПериода", НачалоПериода);
Запрос.УстановитьПараметр("КонецПериода", КонецПериода);

Обратим внимание на то, что в самом тексте запроса используются параметры виртуальной таблицы оборотов: &Субконто и &Субконто1. Если их не инициализировать, запрос завершится аварийно при вызове метода Выполнить(). Нам необходимо передать в них корректные типы и значения аналитики. Добавим установку этих параметров:


// Определяем вид субконто, по которому получаем обороты
ВидСубконто = ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.СтатьиЗатрат; // Укажите ваш план видов характеристик
Запрос.УстановитьПараметр("Субконто", ВидСубконто);

// Задаем конкретную статью затрат для фильтрации (например, из реквизита документа)
Запрос.УстановитьПараметр("Субконто1", ЭтотОбъект.СтатьяЗатрат);

Шаг 3. Заполняем таблицу на форме результатом запроса

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

Сценарий А. Заполнение стандартной табличной части документа

Если на форме отображается табличная часть документа, созданная в конфигураторе (например, с именем РасшифровкаСтатей), имена колонок в запросе (псевдонимы) должны полностью совпадать с именами реквизитов табличной части. Для заполнения используем метод Загрузить():


Процедура КоманднаяПанель2Заполнить(Кнопка)
    
    // Получаем даты периода напрямую из реквизитов объекта
    ДатаНачала = ЭтотОбъект.НачалоПериода; 
    ДатаКонца  = ЭтотОбъект.КонецПериода;
    
    // Проверяем заполнение дат
    Если Не ЗначениеЗаполнено(ДатаНачала) Или Не ЗначениеЗаполнено(ДатаКонца) Тогда
        Предупреждение("Пожалуйста, заполните даты периода!");
        Возврат;
    КонецЕсли;
    
    // Вызываем функцию и получаем результат запроса
    РезультатЗапроса = ЗаполнитьТаблицуРасшифровкаСтатейРасходов(ДатаНачала, ДатаКонца);
    
    Если Не РезультатЗапроса.Пустой() Тогда
        // Очищаем существующие строки табличной части и загружаем новые данные
        ЭтотОбъект.РасшифровкаСтатей.Очистить();
        ЭтотОбъект.РасшифровкаСтатей.Загрузить(РезультатЗапроса.Выгрузить());
    Иначе
        Предупреждение("За указанный период обороты не найдены.");
    КонецЕсли;
    
КонецПроцедуры

Сценарий Б. Заполнение произвольной таблицы значений на форме

Если данные выводятся в динамически создаваемое табличное поле, связанное с реквизитом формы типа ТаблицаЗначений (например, ТаблицаОборотов), алгоритм будет немного отличаться. Нам потребуется очистить старую таблицу, выгрузить результат запроса и принудительно обновить колонки элемента формы:


// Выгружаем результат в реквизит формы типа ТаблицаЗначений
ТаблицаОборотов = РезультатЗапроса.Выгрузить();

// Заставляем табличное поле на форме перерисовать колонки в соответствии с ТЗ
ЭлементыФормы.ТаблицаОборотов.СоздатьКолонки();

Если же структура колонок в табличном поле на форме была жестко настроена вами заранее в конфигураторе, метод СоздатьКолонки() вызывать не нужно, иначе ручные настройки собьются. Вместо этого используйте стандартный метод Загрузить() для обновления строк:


ТаблицаОборотов.Очистить();
ТаблицаОборотов.Загрузить(РезультатЗапроса.Выгрузить());

Полный корректный пример кода для модуля формы

Объединим все наши исправления в единое готовое решение, которое можно перенести в модуль обычной формы документа:


Функция ЗаполнитьТаблицуРасшифровкаСтатейРасходов(Знач НачалоПериода, Знач КонецПериода) 
     
    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ
    |    ТиповойОбороты.Субконто1 КАК СтатьяЗатрат,
    |    ТиповойОбороты.Субконто2 КАК Подразделение,
    |    ТиповойОбороты.СуммаОборотКт КАК СуммаОборота
    |ИЗ                                 
    |    РегистрБухгалтерии.Типовой.Обороты(&НачалоПериода, &КонецПериода, Месяц, , &Субконто, Субконто1 = &Субконто1, , ) КАК ТиповойОбороты";
     
    // Безопасная установка параметров периода
    Запрос.УстановитьПараметр("НачалоПериода", НачалоПериода);
    Запрос.УстановитьПараметр("КонецПериода", КонецПериода);
     
    // Установка параметров субконто (аналитики)
    ВидАналитики = ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.СтатьиЗатрат; 
    Запрос.УстановитьПараметр("Субконто", ВидАналитики);
    
    // В качестве фильтра передаем значение реквизита шапки документа
    Запрос.УстановитьПараметр("Субконто1", ЭтотОбъект.СтатьяЗатратОтбор); 
     
    Результат = Запрос.Выполнить();
    Возврат Результат;
     
КонецФункции

Процедура КоманднаяПанель2Заполнить(Кнопка)
    
    // Получаем значения реквизитов периода с формы документа
    ВыбНачалоПериода = ЭтотОбъект.НачалоПериода;
    ВыбКонецПериода  = ЭтотОбъект.КонецПериода;
    
    // Обязательная проверка на заполненность ключевых полей
    Если Не ЗначениеЗаполнено(ВыбНачалоПериода) Или Не ЗначениеЗаполнено(ВыбКонецПериода) Тогда
        Предупреждение("Необходимо заполнить даты начала и окончания периода!");
        Возврат;
    КонецЕсли;
    
    // Получаем данные из запроса
    РезультатЗапроса = ЗаполнитьТаблицуРасшифровкаСтатейРасходов(ВыбНачалоПериода, ВыбКонецПериода);
    
    // Заполняем табличную часть "РасшифровкаСтатей" на форме
    ЭтотОбъект.РасшифровкаСтатей.Очистить();
    ЭтотОбъект.РасшифровкаСтатей.Загрузить(РезультатЗапроса.Выгрузить());
    
КонецПроцедуры

Используя данный подход, вы полностью исключите ошибки компиляции, связанные с областями видимости, обеспечите корректную передачу параметров в СУБД для виртуальных таблиц и гарантируете стабильную работу интерфейса обычной формы.

← На главную