Как настроить взаимное автозаполнение реквизитов в табличной части 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При разработке интерфейсов в платформах 1С часто возникает необходимость автоматизировать ввод контактных данных. Например, в табличной части документа или обработки есть колонки Автор, Телефон и Почта. Требуется реализовать логику, при которой заполнение любого из этих полей автоматически подтягивает оставшиеся два из справочника Пользователи (или Сотрудники), а очистка поля обнуляет связанные значения.

Рассмотрим, как правильно написать код обработчиков событий для обычных форм, избежав частых ошибок, связанных с директивами компиляции и производительностью.

Анализ задачи и особенности обычных форм

Сформулируем основные требования к логике автозаполнения:

  1. При изменении автора ищутся его почта и внутренний телефон.
  2. При вводе или изменении почты находится соответствующий автор и его телефон.
  3. При изменении телефона находится автор и его адрес электронной почты.
  4. Если поле очищается, сбросить остальные заполненные реквизиты в строке.

При реализации этого функционала в обычных формах важно помнить ключевое отличие от управляемых форм: в обычных формах не используются директивы компиляции вроде &НаСервере или &НаСервереБезКонтекста. Их использование приводит к ошибкам компиляции вида «Процедура или функция с указанным именем не определена».

Шаг 1. Написание функций поиска данных через запрос

Обращение к реквизитам через точку (например, ст.Автор.ЭлектроннаяПочта) не всегда оптимально, так как платформа считывает объект полностью в кэш. Для повышения скорости работы и снижения нагрузки на память рекомендуется использовать язык запросов 1С.

Создадим три вспомогательные функции для поиска нужных данных в справочнике Пользователи:


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

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

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

Шаг 2. Настройка обработчиков событий на форме

Теперь назначим обработчики событий ПриИзменении для соответствующих колонок табличной части в модуле формы. Получаем текущую строку табличной части через свойство ЭлементыФормы.Задачи.ТекущиеДанные и заполняем её с помощью функции ЗаполнитьЗначенияСвойств().


Процедура ЗадачиАвторПриИзменении(Элемент)
    ТекущиеДанные = ЭлементыФормы.Задачи.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    Если ЗначениеЗаполнено(ТекущиеДанные.Автор) Тогда
        ДанныеСтроки = КонтактныеДанныеАвтора(ТекущиеДанные.Автор);
        ЗаполнитьЗначенияСвойств(ТекущиеДанные, ДанныеСтроки);
    Иначе
        ТекущиеДанные.Почта = "";
        ТекущиеДанные.Телефон = "";
    КонецЕсли;
КонецПроцедуры

Процедура ЗадачиПочтаПриИзменении(Элемент)
    ТекущиеДанные = ЭлементыФормы.Задачи.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    Если ЗначениеЗаполнено(ТекущиеДанные.Почта) Тогда
        ДанныеСтроки = АвторПоЭлектроннаяПочта(ТекущиеДанные.Почта);
        ЗаполнитьЗначенияСвойств(ТекущиеДанные, ДанныеСтроки);
    Иначе
        ТекущиеДанные.Автор = Справочники.Пользователи.ПустаяСсылка();
        ТекущиеДанные.Телефон = "";
    КонецЕсли;
КонецПроцедуры

Процедура ЗадачиТелефонПриИзменении(Элемент)
    ТекущиеДанные = ЭлементыФормы.Задачи.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    Если ЗначениеЗаполнено(ТекущиеДанные.Телефон) Тогда
        ДанныеСтроки = АвторПоТелефону(ТекущиеДанные.Телефон);
        ЗаполнитьЗначенияСвойств(ТекущиеДанные, ДанныеСтроки);
    Иначе
        ТекущиеДанные.Автор = Справочники.Пользователи.ПустаяСсылка();
        ТекущиеДанные.Почта = "";
    КонецЕсли;
КонецПроцедуры

Альтернативный способ: использование метода НайтиПоРеквизиту

Если требуется максимально сократить объем кода и не писать явные запросы, можно воспользоваться встроенным методом менеджера справочника НайтиПоРеквизиту().


// Пример быстрого поиска пользователя по электронной почте
НайденныйПользователь = Справочники.Пользователи.НайтиПоРеквизиту("ЭлектроннаяПочта", СокрЛП(ТекущиеДанные.Почта));

Если ЗначениеЗаполнено(НайденныйПользователь) Тогда
    ТекущиеДанные.Автор = НайденныйПользователь;
    ТекущиеДанные.Телефон = СокрЛП(НайденныйПользователь.ВнутрТел);
КонецЕсли;

Важные рекомендации по производительности и надежности

  1. Индексирование реквизитов: Чтобы поиск по реквизитам ЭлектроннаяПочта и ВнутрТел работал быстро даже в крупных базах данных, проверьте в Конфигураторе, чтобы у этих реквизитов справочника Пользователи было установлено свойство «Индексировать».
  2. Обработка дубликатов: Если в справочнике окажется несколько сотрудников с одинаковым телефоном или почтой, запрос вернет первую попавшуюся запись. В критически важных системах стоит дополнительно проверять количество найденных совпадений.
  3. Очистка пробелов: Всегда применяйте функцию СокрЛП() к текстовым строкам перед поиском, чтобы случайные пробелы в начале или конце строки не мешали точному совпадению.
← На главную