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