При изучении разработки в среде 1С:Предприятие 8.3 на управляемых формах начинающие программисты часто сталкиваются с ситуацией, когда написанная процедура отказывается вызываться, а синтаксическая проверка сообщает об ошибках вида Процедура или функция с указанным именем не определена или Переменная не определена. Кроме того, нередко возникают сложности с отображением окна сообщений при открытии обработки.
Разберем подробно, почему возникают эти ошибки, в чем заключается разница между директивами компиляции и инструкциями препроцессора, а также как правильно организовать выполнение алгоритмов в управляемом приложении.
Проанализируем базовый пример процедуры расчета налога, в котором объявляются входные параметры:
Процедура ПоказНалога(Сотрудник, Стаж, Оклад)
Налог = СтажРаботы * Оклад / 100 * 13;
ТекстСообщения = Сотрудник + " Оклад:" + Оклад + " руб. Стаж:" + Стаж + " мес. Налог=" + Налог + " руб.";
Сообщить(ТекстСообщения);
КонецПроцедуры
Обратим внимание на вычисление переменной Налог: в формуле используется идентификатор СтажРаботы, тогда как в заголовке процедуры параметр объявлен как Стаж. В платформе 1С переменные внутри процедур требуют точного совпадения имен. Если имя переменной не совпадает с объявленным параметром и ранее не определялось, система выдает ошибку Переменная не определена (СтажРаботы).
Исправленный вариант строки расчета выглядит следующим образом:
Налог = Стаж * Оклад / 100 * 13;
Часто разработчики пытаются ограничить контекст исполнения с помощью препроцессора #Если Клиент Тогда ... #КонецЕсли, считая, что это делает все вложенные процедуры клиентскими. Однако в управляемых формах этот механизм работает иначе:
#Если Клиент Тогда) управляют только включением или исключением исходного текста на этапе предварительной обработки. Они определяют, попадет ли фрагмент кода в сборку для клиента или сервера, но не задают контекст исполнения конкретной процедуры формы.&НаКлиенте, &НаСервере, &НаСервереБезКонтекста, &НаКлиентеНаСервереБезКонтекста) указывают платформе, где именно должен выполняться метод формы.&НаСервере).Если серверная процедура без директивы пытается вызываться из клиентского контекста или наоборот, платформа выдает ошибку о том, что метод не определен. Чтобы процедура стала доступна на стороне клиента, перед ней обязательно нужно указать директиву &НаКлиенте:
&НаКлиенте
Процедура ПоказНалога(Сотрудник, Стаж, Оклад)
Налог = Стаж * Оклад / 100 * 13;
ТекстСообщения = Сотрудник + " Оклад:" + Оклад + " руб. Стаж:" + Стаж + " мес. Налог=" + Налог + " руб.";
Сообщить(ТекстСообщения);
КонецПроцедуры
В обычных формах прошлых версий платформы код в конце модуля (вне процедур и функций) выполнялся как раздел инициализации. В управляемых формах раздел основной программы компилируется на сервере в момент инициализации контекста формы. Попытка вызвать из этого раздела клиентскую процедуру с директивой &НаКлиенте приводит к синтаксической ошибке.
Кроме того, если вызывать функцию Сообщить() в процессе инициализации формы до завершения ее отрисовки, окно сообщений может закрыться или очиститься сразу после завершения загрузки интерфейса.
Рассмотрим два корректных подхода к реализации интерактивных алгоритмов в управляемом интерфейсе.
Это наиболее наглядный и рекомендуемый способ для интерактивных обработок:
РассчитатьНалог.
&НаКлиенте
Процедура ПоказНалога(Сотрудник, Стаж, Оклад)
Налог = Стаж * Оклад / 100 * 13;
ТекстСообщения = Сотрудник + " Оклад:" + Оклад + " руб. Стаж:" + Стаж + " мес. Налог=" + Налог + " руб.";
Сообщить(ТекстСообщения);
КонецПроцедуры
&НаКлиенте
Процедура РассчитатьНалог(Команда)
Сотрудник1 = "Иванов";
СтажРаботы1 = 10;
Оклад1 = 10000;
ПоказНалога(Сотрудник1, СтажРаботы1, Оклад1);
КонецПроцедуры
Если расчет должен выполняться автоматически сразу при запуске обработки, используем предопределенный обработчик события ПриОткрытии:
ПриОткрытии и создадим процедуру-обработчик.
&НаКлиенте
Процедура ПоказНалога(Сотрудник, Стаж, Оклад)
Налог = Стаж * Оклад / 100 * 13;
ТекстСообщения = Сотрудник + " Оклад:" + Оклад + " руб. Стаж:" + Стаж + " мес. Налог=" + Налог + " руб.";
// Вывод сообщения пользователю
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = ТекстСообщения;
Сообщение.Сообщить();
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Сотрудник1 = "Иванов";
СтажРаботы1 = 10;
Оклад1 = 10000;
ПоказНалога(Сотрудник1, СтажРаботы1, Оклад1);
Сотрудник2 = "Петров";
СтажРаботы2 = 5;
Оклад2 = 12000;
ПоказНалога(Сотрудник2, СтажРаботы2, Оклад2);
КонецПроцедуры
Использование объекта СообщениеПользователю вместо базового метода Сообщить() гарантирует корректную доставку информационных сообщений в пользовательский интерфейс управляемого приложения.