В процессе разработки в среде 1С:Предприятие часто возникает задача автоматизации ввода данных. Типичный сценарий: при выборе определенного значения в одном поле (например, «Вид ремонта») система должна автоматически заполнить другое текстовое поле (например, «Рекомендация») заранее определенным шаблоном. Однако на практике программисты сталкиваются с проблемой — как сделать так, чтобы автоматика не затирала текст, который пользователь ввел вручную, и не создавала хаос при случайном переключении значений.
В этой статье мы подробно разберем несколько стратегий решения этой задачи, ориентируясь на Обычные формы (платформа 8.3), проанализируем типичные ошибки и выработаем наиболее надежный алгоритм.
Рассмотрим самый очевидный подход, с которого начинают многие разработчики. Мы используем событие ПриИзменении для реквизита, который служит триггером (в нашем случае это ВидРемонта).
Проанализируем базовый код:
Процедура ВидРемонтаПриИзменении(Элемент)
Если ВидРемонта.Код = "ТО" Тогда
Рекомендация = "Проверенные в рамках ТО параметры: ...";
КонецЕсли;
КонецПроцедуры
В чем здесь кроется проблема? Если пользователь сначала ввел свой уникальный текст в поле Рекомендация, а затем решил изменить ВидРемонта на «ТО», его авторский текст будет безвозвратно удален и заменен шаблоном. Чтобы этого избежать, добавим проверку на пустоту строки.
Процедура ВидРемонтаПриИзменении(Элемент)
// Заполняем только если поле еще не заполнено пользователем
Если ВидРемонта.Код = "ТО" И ПустаяСтрока(Рекомендация) Тогда
Рекомендация = "Проверенные в рамках ТО параметры: ...";
КонецЕсли;
КонецПроцедуры
Этот вариант лучше, но он не решает ситуацию, когда пользователь ошибочно выбрал «ТО», текст заполнился автоматически, а затем пользователь передумал и выбрал другой вид ремонта. Шаблон «ТО» останется в поле Рекомендация.
Чтобы обеспечить максимальную гибкость и не «пугать» пользователя внезапными изменениями данных, рекомендуется использовать функцию Вопрос(). Это стандарт вежливости в интерфейсах 1С.
Разберем логику по шагам:
ВидРемонта нашему условию.Рекомендация уже содержит какой-то текст, спрашиваем пользователя, нужно ли его заменить.
Процедура ВидРемонтаПриИзменении(Элемент)
Если ВидРемонта.Код = "ТО" Тогда
ТекстШаблона = "Проверенные в рамках ТО параметры: ...";
Если НЕ ПустаяСтрока(Рекомендация) И Рекомендация <> ТекстШаблона Тогда
Ответ = Вопрос("Поле 'Рекомендация' уже заполнено. Перезаполнить его стандартным текстом ТО?", РежимДиалогаВопрос.ДаНет);
Если Ответ = КодВозвратаДиалога.Нет Тогда
Возврат;
КонецЕсли;
КонецЕсли;
Рекомендация = ТекстШаблона;
КонецЕсли;
КонецПроцедуры
Ситуация усложняется, если нам нужно возвращать старый текст, если пользователь «передумал». В Обычных формах для этого удобно использовать переменные модуля.
Выясним причину, почему это работает лучше: переменная модуля формы живет все время, пока открыто окно документа. Мы можем запомнить состояние реквизита в момент открытия или в момент активации поля.
Перем СтараяРекомендация;
Процедура ПриОткрытии()
СтараяРекомендация = Рекомендация;
КонецПроцедуры
Процедура ВидРемонтаПриИзменении(Элемент)
Если ВидРемонта.Код = "ТО" Тогда
// Сохраняем текущее состояние перед автозаполнением
Если Рекомендация <> "Текст для ТО..." Тогда
СтараяРекомендация = Рекомендация;
КонецЕсли;
Рекомендация = "Текст для ТО...";
Иначе
// Если вид ремонта сменили с ТО на другой, возвращаем то, что было
Рекомендация = СтараяРекомендация;
КонецЕсли;
КонецПроцедуры
Хардкодинг (прописывание текста прямо в программном коде) — это плохая практика. Проанализируем ситуацию: сегодня текст ТО один, завтра он изменится. Если он зашит в код, вам придется обновлять конфигурацию. Правильнее хранить шаблоны в справочнике ВидыРемонтов.
Рассмотрим, как это реализовать:
ВидыРемонтов реквизит ТекстРекомендации (тип Строка).
Процедура ВидРемонтаПриИзменении(Элемент)
Если ЗначениеЗаполнено(ВидРемонта) И ЗначениеЗаполнено(ВидРемонта.ТекстРекомендации) Тогда
// Проверяем, не заполнено ли уже поле чем-то другим
Если ПустаяСтрока(Рекомендация) ИЛИ Рекомендация = "ПредыдущийШаблон" Тогда
Рекомендация = ВидРемонта.ТекстРекомендации;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Если мы хотим дополнять текст пользователя, а не заменять его, можно использовать функцию Найти(). Это позволит системе понять, содержится ли уже шаблон в поле, чтобы не дублировать его при многократном изменении реквизита.
Процедура ВидРемонтаПриИзменении(Элемент)
ШаблонТО = "Параметры проверены.";
Если ВидРемонта.Код = "ТО" Тогда
Если Найти(Рекомендация, ШаблонТО) = 0 Тогда
// Добавляем шаблон к существующему тексту
Рекомендация = Рекомендация + ?(ПустаяСтрока(Рекомендация), "", Символы.ПС) + ШаблонТО;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
При реализации подобных механизмов важно учитывать контекст выполнения кода:
Модифицированность = Истина. Это значит, что при закрытии формы система предложит сохранить изменения, даже если пользователь просто «посмотрел» на разные виды ремонта. Чтобы этого избежать, можно анализировать изменения и сбрасывать флаг, если это допустимо бизнес-логикой.ЭтотОбъект или реквизитами формы, связанными с данными. В отличие от Управляемых форм, здесь нет разделения на клиентский и серверный контекст внутри модуля формы в явном виде, что упрощает написание кода, но требует внимательности при работе с объектами базы данных.Для надежной работы системы автоматического заполнения лучше всего комбинировать хранение шаблонов в справочнике и диалоговое окно подтверждения. Это защитит данные пользователя от случайной потери и сделает поведение программы предсказуемым. Если же задача требует полной автоматизации без участия пользователя, используйте метод с переменными модуля для временного хранения предыдущих значений текста, чтобы иметь возможность «отката» при смене условий.