Как реализовать автоматическое заполнение данных сотрудника при его выборе на форме документа?

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

В процессе разработки на платформе 1С:Предприятие часто возникает задача повышения эргономики интерфейса. Один из самых популярных сценариев — автоматическое заполнение связанных полей при выборе ключевого объекта. Например, когда пользователь выбирает сотрудника в документе, система должна мгновенно «подтянуть» его должность, табельный номер или подразделение. В этой статье мы подробно разберем, как реализовать этот механизм правильно, учитывая архитектуру управляемых форм и требования производительности.

Разберем причину ошибки ПолучитьОбъект()

Часто начинающие разработчики сталкиваются с ошибкой «Метод не найден» при попытке написать Объект.Сотрудник.ПолучитьОбъект(). Проанализируем ситуацию: в управляемом приложении код на клиенте работает с типом СправочникСсылка. Метод ПолучитьОбъект() предназначен для получения тяжелого серверного объекта типа СправочникОбъект, который обладает методами записи, удаления и работы с табличными частями. Этот метод доступен только на сервере.

Однако, даже если вы перейдете на сервер, использовать ПолучитьОбъект() для простого чтения реквизитов — это плохая практика. Рассмотрим почему: данный метод считывает из базы данных все поля объекта, включая все табличные части и двоичные данные (например, фото сотрудника). Если вам нужна только «Должность», считывать мегабайты лишней информации — крайне неэффективно для памяти и сети.

Шаг 1: Создание обработчика события ПриИзменении

Прежде всего, нам нужно определить момент, когда данные должны быть заполнены. Для этого мы будем использовать событие элемента формы. Рассмотрим последовательность действий:

  1. Откроем форму документа в конфигураторе.
  2. Выберем поле ввода, где выбирается Сотрудник.
  3. В панели свойств найдем событие ПриИзменении (OnChange) и нажмем на лупу.
  4. Система создаст клиентскую процедуру.

В этой процедуре мы вызовем серверную функцию, которая вернет нам необходимые данные. Проанализируем пример кода:


&НаКлиенте
Процедура СотрудникПриИзменении(Элемент)
    
    // Если сотрудник очищен, очищаем и зависимые поля
    Если Объект.Сотрудник.Пустая() Тогда
        Объект.Должность = Неопределено;
        Возврат;
    КонецЕсли;
    
    // Получаем данные с сервера
    ДанныеСотрудника = ПолучитьДанныеСотрудникаНаСервере(Объект.Сотрудник);
    
    // Заполняем реквизиты объекта
    Если ДанныеСотрудника <> Неопределено Тогда
        Объект.Должность = ДанныеСотрудника.Должность;
        Объект.Подразделение = ДанныеСотрудника.Подразделение;
    КонецЕсли;
    
КонецПроцедуры

Шаг 2: Получение данных через запрос (Лучшая практика)

Теперь рассмотрим, как максимально быстро получить данные на сервере. Использование запроса — это профессиональный стандарт. Запрос позволяет извлечь из базы данных только те поля, которые нам действительно нужны. Выясним, как это выглядит в коде:


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

Обратите внимание на использование директивы &НаСервереБезКонтекста. Это критически важный момент для оптимизации. В этом режиме на сервер не передаются данные всей формы (весь Объект), а передается только ссылка на сотрудника. Это значительно ускоряет работу интерфейса, особенно при работе через медленный интернет.

Шаг 3: Получение данных «через точку»

Если вам нужно получить всего один реквизит и вы не хотите писать сложный запрос, можно воспользоваться обращением «через точку». Посмотрим на пример:


&НаСервере
Функция ПолучитьДолжностьПросто(СсылкаНаСотрудника)
    // Простое обращение к реквизиту ссылки
    Возврат СсылкаНаСотрудника.Должность; 
КонецФункции

Важно: этот метод допустим только на сервере. Платформа 1С при таком обращении неявно выполняет запрос к базе данных. Если вы напишете пять таких строк для пяти разных реквизитов, система может выполнить пять отдельных обращений к БД. Именно поэтому запрос (рассмотренный в предыдущем шаге) предпочтительнее — он делает одно обращение за всеми данными сразу.

Шаг 4: Использование функций общего назначения (БСП)

Если вы работаете в типовой конфигурации (например, БП 3.0, ЗУП 3.1 или УТ 11), проанализируем наличие готовых инструментов. В составе Библиотеки Стандартных Подсистем (БСП) есть отличная функция, которая позволяет получить данные объекта одной строкой кода. Это избавляет от необходимости писать свои запросы в каждом модуле.

Пример использования функции из общего модуля ОбщегоНазначения:


&НаСервереБезКонтекста
Функция ПолучитьДанныеБСП(СсылкаНаСотрудника)
    
    НужныеПоля = "Должность, Подразделение, ТабельныйНомер";
    Возврат ОбщегоНазначения.ЗначенияРеквизитовОбъекта(СсылкаНаСотрудника, НужныеПоля);
    
КонецФункции

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

Особенности работы с регистрами сведений

Иногда нужные данные (например, текущий оклад сотрудника или его паспортные данные) хранятся не в реквизитах самого справочника Сотрудники, а в Регистрах сведений. В таком случае обращение через точку не сработает в принципе.

Проанализируем ситуацию: данные в регистрах зависят от времени (периодические регистры). Чтобы получить актуальные данные на дату документа, нам необходимо использовать метод СрезПоследних. Рассмотрим пример получения данных о паспорте:


&НаСервереБезКонтекста
Функция ПолучитьПаспортныеДанные(Сотрудник, ДатаДокумента)
    
    Менеджер = РегистрыСведений.ПаспортныеДанныеФизЛиц;
    
    // Получаем структуру данных на конкретную дату
    Отбор = Новый Структура("ФизЛицо", Сотрудник.ФизическоеЛицо);
    Данные = Менеджер.СрезПоследних(ДатаДокумента, Отбор);
    
    Если Данные.Количество() > 0 Тогда
        Возврат "Серия: " + Данные[0].Серия + " Номер: " + Данные[0].Номер;
    КонецЕсли;
    
    Возврат "";
КонецФункции

Подведем итоги

Мы рассмотрели несколько способов автоматизации заполнения данных. Подведем краткий итог нашей совместной работы:

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

← На главную