Как исправить ошибку Процедура или функция не определена (Предупреждение) при переходе на клиент-серверную версию 1С

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

Перевод базы данных 1С с файлового варианта на клиент-серверный (SQL) — это ответственный процесс, который часто вскрывает скрытые ошибки в программном коде, особенно в старых конфигурациях, таких как Управление торговлей 10.3. Одной из самых распространенных проблем является использование интерактивных методов в коде, который в серверном режиме должен выполняться без участия интерфейса пользователя. Разберем подробно, почему возникает ошибка Процедура или функция с указанным именем не определена (Предупреждение) и как её правильно исправить.

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

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

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

Способ 1. Использование универсального метода Сообщить

Рассмотрим самый простой и быстрый способ решения проблемы. Метод Сообщить является универсальным: он доступен и на клиенте, и на сервере. Если вызвать его на сервере, текст сообщения будет передан на клиентскую сторону и отображен в специальном окне сообщений внизу экрана.

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


Если Источник.Дата < Константы.ДатаЗапретаРедактирования.Получить() Тогда
    // Заменяем Предупреждение на Сообщить
    Сообщить("Документы в периоде ранее " + Константы.ДатаЗапретаРедактирования.Получить() + " изменять запрещено!");
    Отказ = Истина;
КонецЕсли;

Важный нюанс: метод Сообщить не останавливает выполнение кода и не требует от пользователя нажатия кнопки «ОК» немедленно. Это позволяет избежать ошибки компиляции, но пользователь может пропустить сообщение, если оно «утонет» среди других системных уведомлений. Однако, так как переменная Отказ устанавливается в значение Истина, запись документа все равно будет заблокирована.

Способ 2. Жесткая блокировка через ВызватьИсключение

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

Этот метод генерирует программную ошибку, которая прерывает текущую транзакцию. В клиент-серверном режиме это выглядит для пользователя как стандартное окно ошибки с вашим текстом.


Если Источник.Дата < Константы.ДатаЗапретаРедактирования.Получить() Тогда
    ТекстОшибки = "Документы в периоде ранее " + Константы.ДатаЗапретаРедактирования.Получить() + " изменять запрещено!";
    ВызватьИсключение ТекстОшибки;
КонецЕсли;

Преимущество этого подхода в том, что транзакция гарантированно откатывается, а текст сообщения невозможно проигнорировать. Недостатком является «аварийный» характер завершения — это может выглядеть для пользователя менее эстетично, чем аккуратное предупреждение.

Способ 3. Использование объекта СообщениеПользователю

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


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

Этот метод сочетает в себе стабильность серверного кода и информативность для конечного пользователя.

Способ 4. Директивы компиляции (Инструкции препроцессора)

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


#Если Клиент Тогда
    Предупреждение("Текст предупреждения...");
#Иначе
    Сообщить("Текст сообщения для сервера...");
#КонецЕсли

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

Глобальная проверка конфигурации

Как показывает практика, если подобная ошибка возникла в одном модуле, велика вероятность, что она встретится и в других местах. При переходе на SQL-вариант мы рекомендуем провести глобальный поиск по всей конфигурации (сочетание клавиш Ctrl+Shift+F).

Что искать:

  1. Текст Предупреждение(
  2. Текст Вопрос(
  3. Текст ВвестиЗначение(

Особое внимание следует уделить Общим модулям, у которых в свойствах установлена галочка Сервер и снята галочка Клиент. Все найденные интерактивные методы в таких модулях необходимо заменить на серверные аналоги (Сообщить или ВызватьИсключение). Это позволит избежать внезапных остановок работы системы в будущем, например, при выполнении регламентных заданий или обменов данными, где нет живого пользователя, способного нажать кнопку в окне предупреждения.

Подводя итог, отметим: для системного администратора наиболее безопасным и простым решением будет замена на Сообщить, так как это не ломает бизнес-логику и устраняет критическую ошибку. Однако для качественной поддержки базы в долгосрочной перспективе лучше использовать объект СообщениеПользователю или грамотное разделение кода директивами #Если Клиент Тогда.

← На главную