Как исправить ошибку "Переменная не определена (Документы)" в управляемой форме 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

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


Процедура Команда1(Команда)
    // Попытка прямого доступа к базе данных
    Выборка = Документы.СоставБригады.Выбрать();
    Пока Выборка.Следующий() Цикл 
        Сообщить(СтрШаблон("%1", Выборка.Водитель));
    КонецЦикла;
КонецПроцедуры

При выполнении этого кода платформа выдает ошибку: {Форма.Форма.Форма(2,12)}: Переменная не определена (Документы). Причина этой ошибки кроется в фундаментальных принципах архитектуры управляемых форм.

Причина ошибки: разделение кода на клиентский и серверный

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

Представим эту модель так:

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

Код в модуле формы выполняется по умолчанию на клиенте. Таким образом, когда вы пишете Документы.СоставБригады.Выбрать() в процедуре-обработчике команды без специальных указаний, вы пытаетесь выполнить серверную операцию в клиентском контексте, где объект Документы просто не существует. Отсюда и возникает ошибка «Переменная не определена».

Правильное решение: использование директив компиляции

Чтобы управлять тем, где будет выполняться код, в 1С используются специальные директивы компиляции. Рассмотрим основные из них:

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

Давайте исправим исходный код по этой схеме. Наша задача — получить список водителей из документов и вывести его пользователю.

  1. Создадим на клиенте процедуру-обработчик команды, которая будет вызывать серверную функцию.
  2. Создадим на сервере функцию, которая получит данные из базы, обработает их и вернет результат, пригодный для передачи на клиент (например, массив или структуру).
  3. Вернемся на клиент, получим результат от серверной функции и отобразим его пользователю.

Посмотрим на пример правильной реализации:


// 1. Клиентская процедура, которая запускает процесс
&НаКлиенте
Процедура Команда1(Команда)
    // Вызываем серверную функцию и получаем результат ее работы
    СписокВодителей = ПолучитьСписокВодителейНаСервере();
    
    // 3. Отображаем полученные с сервера данные на клиенте
    Для Каждого Водитель Из СписокВодителей Цикл
        Сообщить(Водитель);
    КонецЦикла;
КонецПроцедуры

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

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

Почему переключение на толстый клиент не помогло?

Часто возникает вопрос: "Я пробовал переключить тип клиента на толстый, но ошибка осталась. Почему?"

Здесь важно понимать, что толстый клиент может работать в двух режимах:

  1. Режим обычного приложения (для старых конфигураций на обычных формах).
  2. Режим управляемого приложения (для современных конфигураций на управляемых формах).

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

Таким образом, причина ошибки — архитектурная, и смена типа клиента ее не решает. Решение всегда одно — перенос кода, работающего с базой данных, в процедуры и функции с директивой &НаСервере или &НаСервереБезКонтекста.

← На главную