При разработке в системе 1С часто возникает задача автоматического заполнения полей документа при его создании. Например, в конфигурации «1С:Управление торговлей 11» при создании документа CRM_Интерес может потребоваться, чтобы поле Тип услуги сразу принимало значение «Товары». При этом важно сохранить возможность ручного изменения этого поля пользователем в дальнейшем. Рассмотрим подробнее, как реализовать эту задачу правильно, избегая типичных ошибок начинающих разработчиков.
Разберем ситуацию, с которой столкнулся автор темы. Основная ошибка заключалась в попытке использовать обработчик события элемента формы вместо события самой формы. Проанализируем, почему это важно. Когда мы открываем форму нового документа, система инициализирует данные объекта. Если мы хотим, чтобы значение подставилось один раз в момент создания, нам нужно использовать события жизненного цикла формы или объекта.
В управляемом приложении наиболее подходящим местом для этого в модуле формы является процедура ПриСозданииНаСервере. Она выполняется на стороне сервера до того, как форма будет передана на клиент, что позволяет нам эффективно работать с данными информационной базы и метаданными.
Посмотрим на пример кода, который решает поставленную задачу. Для того чтобы значение подставлялось только в новые документы и не перезаписывало уже выбранные значения в существующих документах, обязательно нужно добавить проверку на «новость» объекта. Выясним причину: если мы уберем эту проверку, то каждый раз при открытии уже сохраненного документа значение будет сбрасываться на «Товары», даже если менеджер ранее выбрал «Услуги».
Рассмотрим по шагам правильную реализацию:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверяем, является ли объект новым
Если Объект.Ссылка.Пустая() Тогда
// Используем функцию ПредопределенноеЗначение для получения ссылки на элемент справочника
Объект.ТипУслуги = ПредопределенноеЗначение("Справочник.CRM_ТипыУслуг.Товары");
КонецЕсли;
КонецПроцедуры
В этом коде мы обращаемся к свойству Объект, которое представляет собой данные документа на форме. Функция ПредопределенноеЗначение принимает строковый путь к элементу. Обратите внимание на синтаксис: "Справочник.ИмяСправочника.ИмяПредопределенногоЭлемента". Ошибка в одной букве приведет к тому, что система вернет Неопределено, и поле останется пустым.
Многие программисты ошибочно полагают, что к предопределенным данным можно обращаться только на сервере через менеджер справочника (например, Справочники.CRM_ТипыУслуг.Товары). Однако платформа 1С предоставляет мощный инструмент — функцию ПредопределенноеЗначение, которая доступна и в контексте &НаКлиенте. Это позволяет оптимизировать код, если вам нужно заполнить поле в ходе какой-то клиентской логики без лишнего вызова сервера.
Проанализируем ситуацию: клиент-серверный вызов (переход с &НаКлиенте на &НаСервере) — это ресурсозатратная операция. Если ваша логика позволяет избежать этого, производительность системы повысится. Однако в случае инициализации формы при открытии, мы и так находимся на сервере в процедуре ПриСозданииНаСервере, поэтому использование этой функции там наиболее оправдано.
Хотя решение через модуль формы работает, «лучшей практикой» (best practice) в 1С считается вынос логики заполнения значений по умолчанию в Модуль объекта. Рассмотрим подробнее преимущества этого подхода:
Разберем пример кода в модуле объекта документа:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
// Устанавливаем значение только при создании нового документа
ТипУслуги = Справочники.CRM_ТипыУслуг.Товары;
КонецПроцедуры
Эта процедура вызывается платформой автоматически при создании нового объекта. В этом контексте нам даже не нужно проверять Ссылка.Пустая(), так как процедура ОбработкаЗаполнения предназначена именно для инициализации новых данных.
Выясним, можно ли решить задачу вообще без программирования. В конфигураторе 1С у каждого реквизита есть свойство «Значение заполнения». Если в этом свойстве указать конкретный элемент справочника, платформа будет автоматически подставлять его во все новые документы.
Однако у этого метода есть ограничения. Если предопределенный элемент еще не создан в базе или если логика подстановки должна зависеть от каких-то условий (например, от организации или текущего пользователя), то программный метод в ОбработкаЗаполнения будет гораздо гибче.
Проанализируем основные причины, по которым код может «не срабатывать», как это было у автора вопроса на форуме:
Справочник.CRM_ТипУслуги вместо Справочники.CRM_ТипыУслуг (множественное число) — классическая ошибка. Проверяйте точное имя метаданных в конфигураторе.&После или &Вместо, если используете механизм расширений.Если вы модифицируете 1С:Управление торговлей 11, крайне рекомендуется использовать Расширения конфигурации. Это позволит вам обновлять основную программу без проблем. В расширении вы можете создать процедуру-обработчик, которая будет дополнять стандартную логику заполнения:
&После("ПриСозданииНаСервере")
Процедура ИмяПрефикс_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Объект.Ссылка.Пустая() Тогда
Объект.ТипУслуги = ПредопределенноеЗначение("Справочник.CRM_ТипыУслуг.Товары");
КонецЕсли;
КонецПроцедуры
Использование аннотации &После гарантирует, что сначала выполнится типовой код конфигурации, а затем ваш код установит нужное значение по умолчанию, не нарушая работу стандартных механизмов.
Таким образом, мы рассмотрели несколько способов решения задачи: от простых свойств метаданных до гибкого программирования в модулях формы и объекта. Выбор метода зависит от ваших требований к гибкости и архитектуре решения.