Почему возникает ошибка «Переменная не определена (РегистрыСведений)» в общем модуле и как правильно организовать клиент-серверное взаимодействие?

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

Переход с обычного приложения на управляемые формы часто сопровождается трудностями в понимании того, где именно выполняется код. Одной из самых распространенных ошибок является попытка обращения к объектам базы данных (например, к регистрам сведений) из контекста, в котором они физически недоступны. В этой статье мы подробно разберем, почему возникают такие ошибки, как правильно настраивать общие модули и как организовать эффективную работу между клиентом и сервером.

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

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

Выясним причину. В управляемом приложении 1С реализовано жесткое разделение полномочий. Объекты метаданных, такие как менеджеры регистров, справочников и документов, существуют только на сервере (или в толстом клиенте). Когда вы помечаете общий модуль флагом Клиент (УФ), система компилирует копию этого модуля для исполнения на стороне тонкого клиента. На стороне клиента объект РегистрыСведений просто не существует в памяти, поэтому компилятор выдает ошибку.

Рассмотрим, какие объекты доступны исключительно на сервере:

  1. Все менеджеры типов (РегистрыСведений, Справочники, Документы и т.д.).
  2. Объекты данных (СправочникОбъект, ДокументОбъект).
  3. Запросы (Запрос) и схемы компоновки данных.

Как правильно настроить общий модуль

Разберем, что делать, если вам нужно, чтобы код работал и на клиенте, и на сервере. Самый простой и правильный путь — использование инструкций препроцессора. Это специальные команды, которые говорят системе, какую часть кода нужно компилировать для конкретного контекста.

Посмотрим на пример правильного оформления процедуры в общем модуле, у которого стоят галочки «Клиент» и «Сервер»:


Процедура ВыполнитьДействие(Данные) Экспорт
    
    #Если Сервер Тогда
        // Этот блок кода будет виден только серверу
        Набор = РегистрыСведений.МойРегистр.СоздатьНаборЗаписей();
        // ... логика работы с БД
    #КонецЕсли

    #Если Клиент Тогда
        // Этот блок кода выполнится только на стороне пользователя
        Сообщить("Действие выполнено на клиенте");
    #КонецЕсли

КонецПроцедуры

Однако, если ваша процедура на 90% состоит из работы с базой данных, лучше вообще снять флаг Клиент (УФ) и оставить только Сервер и Вызов сервера. Тогда вы сможете вызывать эту процедуру с клиента, и она будет гарантированно выполняться в серверном контексте, где доступны все таблицы базы.

Критическая ошибка: передача ЭтаФорма в общий модуль

Проанализируем еще одну проблему из примера автора: передачу объекта ЭтаФорма в процедуру общего модуля. В управляемом приложении так делать категорически нельзя по нескольким причинам:

  1. Контекстная зависимость: Объект «Форма» является визуальным объектом клиента. Если процедура выполняется на сервере (через «Вызов сервера»), передача всей формы приведет к огромным накладным расходам по трафику, а зачастую и к ошибке сериализации.
  2. Доступность элементов: На сервере вы не имеете доступа к элементам формы напрямую (например, к кнопкам или табличным полям).

Рассмотрим правильный подход. Вместо передачи всей формы, передавайте только необходимые данные в виде структуры или простых типов. Например:


// Код в модуле формы
ПараметрыДействия = Новый Структура;
ПараметрыДействия.Вставить("Контрагент", Объект.Контрагент);
ПараметрыДействия.Вставить("Дата", Объект.Дата);

ОбщийМодульСервер.ОбработатьДанные(ПараметрыДействия);

Работа с сообщениями пользователю на сервере

Часто возникает вопрос: «А как же Сообщить(), если модуль серверный?». Существует заблуждение, что для вывода сообщений обязательно нужен клиентский контекст. На самом деле, объект СообщениеПользователю отлично работает и на сервере.

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

Пример надежного вывода сообщения:


Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Не удалось найти параметры шаблона!";
Сообщение.Сообщить();

Асинхронность и модальные окна

Разберем важный нюанс, касающийся «вопросов пользователю». В современных управляемых формах (особенно в веб-клиенте) нельзя использовать модальные окна (функцию Вопрос()). Если вам нужно что-то спросить у пользователя перед выполнением серверного кода, это нужно делать строго до вызова серверной процедуры.

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


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

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

Выводы и рекомендации

Для эффективной работы в управляемом приложении 1С рекомендуем придерживаться следующих правил:

Соблюдение этих принципов позволит вам избежать ошибок инициализации модулей и сделает код вашей конфигурации стабильным и производительным.

← На главную