В процессе разработки интерфейсов на платформе 1С:Предприятие 8.3 часто возникает задача автоматизации ввода данных. Типичный пример: пользователю необходимо, чтобы при заполнении одного поля («Реквизит1») данные автоматически дублировались в другое поле («Реквизит2»), но только в том случае, если установлена специальная «галочка» (флаг). Это позволяет избежать двойного ввода и минимизировать ошибки.
В данной статье мы подробно разберем, как реализовать такую механику на управляемых формах, рассмотрим программный код, нюансы клиент-серверного взаимодействия и вопросы удобства пользовательского интерфейса (UX).
Прежде всего, проанализируем структуру наших данных. Допустим, у нас есть объект (документ или справочник), в котором созданы три реквизита:
СправочникСсылка.Контрагенты).Булево, который будет выступать в роли той самой «галочки».Разберем важный момент: для того чтобы обращаться к этим данным в коде формы, мы должны использовать префикс Объект. Это связано с тем, что в управляемом приложении данные формы, связанные с основным объектом, помещаются в структуру Объект.
Основная логика должна срабатывать в тот момент, когда пользователь выбирает значение в первом поле. Рассмотрим, как это сделать. Для элемента формы, связанного с Реквизит1, необходимо создать обработчик события ПриИзменении.
Проанализируем программный код, который будет располагаться в модуле формы:
&НаКлиенте
Процедура Реквизит1ПриИзменении(Элемент)
// Проверяем, установлена ли галочка
Если Объект.ФлагКопирования Тогда
// Копируем значение из первого реквизита во второй
Объект.Реквизит2 = Объект.Реквизит1;
КонецЕсли;
КонецПроцедуры
В этом примере мы используем директиву &НаКлиенте. Это оптимально, так как для простого присваивания ссылочных значений или примитивных типов нам не требуется обращение к серверу. Это экономит ресурсы системы и обеспечивает мгновенный отклик интерфейса.
Многие начинающие разработчики забывают про важный сценарий: пользователь может сначала заполнить Реквизит1, а уже потом нажать на галочку «Копировать». В этом случае событие ПриИзменении для первого поля уже не отработает, и второе поле останется пустым.
Чтобы избежать этой ситуации, выясним причину и добавим аналогичную проверку в обработчик события ПриИзменении для самого флажка (ФлагКопирования):
&НаКлиенте
Процедура ФлагКопированияПриИзменении(Элемент)
Если Объект.ФлагКопирования Тогда
// Если галочку включили, сразу синхронизируем данные
Объект.Реквизит2 = Объект.Реквизит1;
КонецЕсли;
КонецПроцедуры
Таким образом, мы обеспечиваем корректное поведение системы независимо от последовательности действий пользователя.
Рассмотрим ситуацию с точки зрения пользователя. Если включена опция автоматического копирования, логично предположить, что ручное редактирование Реквизит2 должно быть запрещено, чтобы данные не рассинхронизировались. Для этого мы можем программно управлять свойством Доступность или ТолькоПросмотр элемента формы.
Дополним наш код в процедуре обработки флажка:
&НаКлиенте
Процедура ФлагКопированияПриИзменении(Элемент)
// Синхронизируем значение, если флаг установлен
Если Объект.ФлагКопирования Тогда
Объект.Реквизит2 = Объект.Реквизит1;
КонецЕсли;
// Управляем доступностью поля Реквизит2
// Если флаг установлен, поле недоступно для редактирования
Элементы.Реквизит2.Доступность = НЕ Объект.ФлагКопирования;
КонецПроцедуры
Обратите внимание: управление доступностью через свойство Элементы позволяет визуально «затенить» поле, давая пользователю понять, что оно заполняется автоматически.
В обсуждениях часто всплывает свойство метаданных Заполнять из данных заполнения. Разберем подробнее, подходит ли оно для нашей задачи. Это свойство эффективно работает только в момент создания нового объекта (например, при копировании или вводе на основании). Если вам нужно динамическое изменение значений в уже открытой форме существующего документа, данное свойство вам не поможет.
Для динамики (интерактива) всегда следует использовать обработчики событий элементов формы, как мы рассмотрели выше.
Посмотрим на ситуацию, когда пользователь очищает Реквизит1. Если галочка установлена, Реквизит2 также должен стать пустым. Наш код Объект.Реквизит2 = Объект.Реквизит1; справится с этим автоматически, так как в Реквизит2 запишется «Пустая ссылка» того же типа.
Однако, если вы используете сложные проверки с функцией ЗначениеЗаполнено(), убедитесь, что они не блокируют процесс очистки зависимого поля.
Если ваша задача подразумевает, что копирование должно происходить не только в интерактивном режиме (на форме), но и при загрузке данных из внешних источников (Excel, API), то код в модуле формы не сработает. В таком случае проанализируем возможность переноса логики в Модуль объекта.
Используем предопределенную процедуру ПередЗаписью:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Логика будет работать всегда, даже если форма не открыта
Если ФлагКопирования Тогда
Реквизит2 = Реквизит1;
КонецЕсли;
КонецПроцедуры
Важно: в модуле объекта мы обращаемся к реквизитам напрямую, без префикса Объект.
Мы проанализировали несколько подходов к решению задачи копирования значений. Оптимальный алгоритм действий для программиста 1С выглядит так:
ПриИзменении для исходного реквизита.ПриИзменении для флага (галочки) для моментальной синхронизации.&НаКлиенте для быстродействия.Доступность зависимого поля.ПередЗаписью.Соблюдение этих правил позволит создать надежный и интуитивно понятный механизм заполнения данных в ваших конфигурациях.