Переход со старых обычных форм на современные управляемые формы в платформе 1С:Предприятие 8.3 часто вызывает трудности у начинающих разработчиков. Основная сложность заключается в кардинальном изменении парадигмы: теперь код строго разделен на выполняемый на клиенте (в браузере или тонком клиенте) и выполняемый на сервере (где есть прямой доступ к базе данных).
В этой статье мы подробно разберем типичную задачу, с которой часто сталкиваются при разработке: автоматическое заполнение поля МФО (или БИК) при выборе банка в справочнике банковских счетов. Мы проанализируем ошибки, которые допускают новички, рассмотрим правильную реализацию через программный код, а также разберем передовые практики оптимизации контекстных вызовов и полностью декларативный метод решения задачи вообще без написания кода.
Начинающие разработчики часто пытаются написать код по аналогии с обычными формами, обращаясь к реквизитам связанных справочников напрямую на клиенте. Рассмотрим пример ошибочного кода:
&НаКлиенте
Процедура БанкПриИзменении(Элемент)
// Попытка получить Код банка напрямую через точку на клиенте
Объект.МФО = СокрЛП(Объект.Банк.Код);
КонецПроцедуры
Почему этот код не работает или приводит к ошибкам? Дело в том, что на клиенте переменная Объект.Банк хранит в себе только ссылку на элемент справочника (его уникальный идентификатор GUID) и его текстовое представление (наименование). Самих данных (таких как Код, БИК, ИНН, адрес и т.д.) на клиенте нет. Попытка обратиться к реквизитам ссылки "через точку" на тонком или веб-клиенте вызывает неявный и неконтролируемый серверный вызов, что существенно снижает производительность системы, а в некоторых случаях просто блокируется платформой.
Для безопасного и быстрого получения любых данных из базы мы всегда должны обращаться к серверу. Выясним, как сделать это правильно.
Просто написать процедуру с именем БанкПриИзменении в модуле формы недостаточно. Платформа должна знать, что эта процедура связана с конкретным полем на форме. Выполним привязку по шагам:
Объект.Банк.ПриИзменении и нажмем на кнопку с изображением лупы.Платформа автоматически сгенерирует заготовки процедур в модуле и свяжет их с элементом управления на форме. Теперь при изменении банка пользователем управление будет передаваться в созданный обработчик.
Рассмотрим классический способ решения задачи с использованием контекстного серверного вызова. В этом случае мы передаем управление на сервер, где у нас есть полный доступ к базе данных и объектам.
&НаКлиенте
Процедура БанкПриИзменении(Элемент)
// Вызываем серверную процедуру для заполнения данных
БанкПриИзмененииНаСервере();
КонецПроцедуры
&НаСервере
Процедура БанкПриИзмененииНаСервере()
// На сервере мы можем безопасно обращаться к реквизитам ссылки через точку
Если ЗначениеЗаполнено(Объект.Bank) Тогда
Объект.МФО = СокрЛП(Объект.Банк.Код);
Иначе
Объект.МФО = "";
КонецЕсли;
КонецПроцедуры
В этой схеме на клиенте срабатывает обработчик БанкПриИзменении, который перенаправляет выполнение на сервер в процедуру БанкПриИзмененииНаСервере. На сервере платформа считывает код выбранного банка и записывает его в реквизит формы Объект.МФО. По окончании работы процедуры данные формы возвращаются на клиент, и поле МФО обновляется на экране у пользователя.
Часто при копировании кода из интернета или ручном редактировании разработчики сталкиваются с ошибкой компиляции:
Процедура или функция с указанным именем уже определена (БанкПриИзменении)
Проанализируем причину этой ошибки. Она означает, что в модуле формы написаны две процедуры с абсолютно одинаковым именем. Это может произойти, если вы сначала автоматически создали обработчик через свойства элемента, а затем вручную скопировали готовый шаблон кода из интернета, не заметив дублирования. Чтобы исправить эту ошибку, найдите дублирующую процедуру и удалите ее, оставив только одну корректную реализацию.
Также будьте внимательны с синтаксисом. Случайные опечатки, такие как открывающая скобка вместо точки или запятой в имени вызова (например, БанкПриИзменении(НаСервере; вместо БанкПриИзмененииНаСервере();), сделают код неработоспособным.
Использование директивы &НаСервере передает на сервер весь контекст формы — все реквизиты, таблицы, списки и настройки. Если форма "тяжелая", это приводит к избыточной нагрузке на сеть и сервер. Лучшей практикой (Best Practice) в 1С является использование внеконтекстных вызовов с директивой &НаСервереБезКонтекста. При таком вызове на сервер передаются только явно указанные параметры, что работает значительно быстрее.
Разберем пример реализации этого метода:
&НаКлиенте
Процедура БанкПриИзменении(Элемент)
Если ЗначениеЗаполнено(Объект.Банк) Тогда
// Передаем на сервер только ссылку на банк, а возвращаем полученный код
Объект.МФО = ПолучитьКодБанкаНаСервере(Объект.Банк);
Иначе
Объект.МФО = "";
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьКодБанкаНаСервере(Знач СсылкаНаБанк)
// Извлекаем код (МФО/БИК) напрямую из базы данных по ссылке
Возврат СокрЛП(СсылкаНаБанк.Код);
КонецФункции
В этом примере функция ПолучитьКодБанкаНаСервере не имеет доступа к данным формы (реквизиту Объект), она получает только ссылку на банк в качестве параметра СсылкаНаБанк, быстро считывает его Код из базы данных и возвращает его обратно на клиент. Это максимально производительный способ получения данных на управляемых формах.
Если поле "МФО" на вашей форме предназначено только для вывода информации и просмотра (то есть пользователю не требуется редактировать его вручную отдельно от банка), то писать программный код вообще не нужно! Платформа 1С поддерживает мощный декларативный механизм вывода связанных реквизитов.
Рассмотрим, как вывести код банка на форму в несколько кликов:
Объект.Банк (который ссылается на справочник банков) и развернем его, нажав на значок "плюс".Код (или БИК).Код с помощью мыши в левое окно — в структуру элементов формы.Платформа автоматически создаст на форме новый элемент управления. Путь к данным у него будет прописан как Объект.Банк.Код. При запуске в режиме "1С:Предприятие" платформа сама, без единой строчки программного кода, будет считывать и показывать актуальный код банка каждый раз, когда пользователь выбирает или меняет банк. Поле автоматически станет доступным только для чтения, что исключит ошибки ручного ввода.
Если вы ведете разработку в типовой конфигурации (например, 1С:Бухгалтерия, 1С:УНФ, 1С:Управление торговлей и др.), в вашу базу уже встроена Библиотека стандартных подсистем (БСП). Разработчики БСП создали готовые общие модули для быстрого получения реквизитов без необходимости писать собственные серверные вызовы.
Посмотрим на пример кода с использованием БСП:
&НаКлиенте
Процедура БанкПриИзменении(Элемент)
Если ЗначениеЗаполнено(Объект.Банк) Тогда
// Функция БСП сама выполнит легкий запрос на сервер и вернет значение
Объект.МФО = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Объект.Банк, "Код");
Иначе
Объект.МФО = "";
КонецЕсли;
КонецПроцедуры
Этот подход делает код модуля формы лаконичным, чистым и простым для понимания. Функция ОбщегоНазначения.ЗначениеРеквизитаОбъекта самостоятельно выполнит быстрый внеконтекстный запрос к базе данных.
Часто перед разработчиком встает и обратная задача: сделать так, чтобы при вводе цифр МФО (БИК) в текстовое поле платформа автоматически находила нужный банк в справочнике и подставляла его. Писать для этого сложный программный поиск не требуется. В 1С для этого существует встроенный платформенный механизм "Ввод по строке".
Разберем, как его быстро настроить:
Банки (или аналогичный справочник, хранящий информацию о банках).Наименование и Код (или БИК).Теперь в режиме пользователя, когда человек начнет вводить цифры МФО прямо в поле выбора банка, платформа автоматически осуществит поиск по коду в базе данных и предложит подходящие варианты в выпадающем списке. Это избавляет от необходимости создавать дополнительное поле ввода для поиска.
Если при тестировании написанного кода вы ставите точку останова в процедуре БанкПриИзмененииНаСервере, но отладчик просто игнорирует её и "пролетает" мимо, не нужно отчаиваться. Это частая проблема, связанная с настройками выполнения процессов в управляемом приложении.
Проанализируем основные причины и способы их устранения:
&НаСервере или &НаСервереБезКонтекста), служба сервера должна запускаться с ключом -debug.Чтобы включить отладку на сервере 1С под управлением Windows, выполните следующие шаги:
services.msc).regedit).HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\1C:Enterprise 8.3... (имя ветки зависит от версии платформы).ImagePath и добавьте в конец строки запуска ключ -debug (через пробел после основных параметров).После выполнения этих действий сервер перезапустится в режиме отладки, и ваши точки останова в любых серверных модулях и общих модулях начнут стабильно срабатывать, позволяя легко анализировать состояние переменных в процессе разработки.