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