Как реализовать автоматическое заполнение колонок при выборе значения в табличной части 1С (Обычные формы)

Программист Управленческий учет IT и автоматизация бизнеса
← На главную

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

Разберем механику события «При изменении»

Для реализации нашей задачи мы будем использовать обработчик события ПриИзменении. Это событие возникает в тот момент, когда пользователь выбрал значение в поле или ввел его вручную и нажал Enter (или переключил фокус). В контексте табличной части это событие должно быть привязано не к самой таблице, а к конкретной колонке — в нашем случае к колонке «Сотрудник».

Важно понимать разницу между управляемыми и обычными формами. В обычных формах работа с данными строки происходит через обращение к текущим данным элемента управления формы. Чтобы создать обработчик, нам нужно зайти в свойства колонки табличной части и нажать на лупу рядом с событием ПриИзменении. Платформа создаст процедуру в модуле формы, с которой мы и будем работать.

Шаг 1. Получение доступа к текущей строке

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


Процедура ИмяВашейТабличнойЧастиСотрудникПриИзменении(Элемент)
    // Получаем текущую строку табличной части
    СтрокаТЧ = ЭлементыФормы.ИмяВашейТабличнойЧасти.ТекущиеДанные;
    
    // Проверим, не очистил ли пользователь поле Сотрудник
    Если СтрокаТЧ.Сотрудник.Пустая() Тогда
        СтрокаТЧ.Должность = "";
        СтрокаТЧ.Оклад = 0;
        Возврат;
    КонецЕсли;
КонецПроцедуры

Здесь ЭлементыФормы.ИмяВашейТабличнойЧасти — это программное имя элемента управления на форме, а не имя самой таблицы в метаданных. Переменная СтрокаТЧ теперь содержит ссылку на текущую строку, и мы можем обращаться к её реквизитам напрямую.

Шаг 2. Автозаполнение должности через обращение «через точку»

Если в вашей конфигурации должность закреплена непосредственно в справочнике СотрудникиОрганизаций, то получить её значение проще всего простым обращением к реквизиту ссылки. Однако, как было отмечено в исходной задаче, реквизиты «Должность» и «Оклад» имеют тип Строка. Нам необходимо привести ссылку к строковому представлению.

Рассмотрим код для заполнения должности:


// Должность получаем напрямую из данных сотрудника
// Используем функцию Строка(), если реквизит в справочнике — ссылка, 
// а в табличной части — текст.
СтрокаТЧ.Должность = Строка(СтрокаТЧ.Сотрудник.Должность);

Обратите внимание: если должность в справочнике сотрудника является периодическим значением (хранится в регистре сведений), такой способ не подойдет. В этом случае нам потребуется использовать метод СрезПоследних регистра сведений, чтобы получить актуальную должность на дату документа.

Шаг 3. Получение оклада из Плана видов расчета и регистров

Ситуация с окладом сложнее. Как указано в описании, ОкладТариф связан с планом видов расчета. Обычно в 1С сами планы видов расчета (ПВР) хранят только виды начислений, а конкретные суммы (размеры окладов) фиксируются в регистрах сведений (например, «Плановые начисления» или аналогичные).

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


// Подготовим структуру отбора для получения данных из регистра
Отбор = Новый Структура;
Отбор.Вставить("Сотрудник", СтрокаТЧ.Сотрудник);

// Получаем актуальную запись из регистра на дату документа
// Предположим, регистр называется "ПлановыеНачисления"
ЗаписиОклада = РегистрыСведений.ПлановыеНачисления.СрезПоследних(Дата, Отбор);

Если ЗаписиОклада.Количество() > 0 Тогда
    // Если запись найдена, записываем значение ресурса "Размер" в нашу строку
    // Приводим к строке, если в ТЧ реквизит строковый (хотя лучше использовать Число)
    СтрокаТЧ.Оклад = Строка(ЗаписиОклада[0].Размер);
Иначе
    СтрокаТЧ.Оклад = "0"; // Если данных нет
КонецЕсли;

Оптимизация типов данных

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

  1. Невозможность расчетов: Если «Оклад» — это строка, вы не сможете быстро просуммировать итог по колонке или использовать значение в формулах без преобразования Число().
  2. Ошибки аналитики: Если «Должность» — это строка, то при опечатке (например, «Бухгалтер » с пробелом и «Бухгалтер» без пробела) отчеты будут воспринимать их как разные должности.

Рекомендуем изменить тип реквизита Оклад на Число (15, 2), а реквизита Должность — на СправочникСсылка.Должности. Это существенно упростит написание кода и дальнейшую эксплуатацию системы.

Полный пример реализации

Сведем все вышеперечисленное в единый алгоритм, который можно вставить в модуль обычной формы документа:


Процедура ТабельнаяЧастьСотрудникПриИзменении(Элемент)
    
    // 1. Получаем доступ к строке
    СтрокаТЧ = ЭлементыФормы.ТабельнаяЧасть.ТекущиеДанные;
    
    // 2. Проверка на заполнение
    Если СтрокаТЧ = Неопределено Или СтрокаТЧ.Сотрудник.Пустая() Тогда
        Возврат;
    КонецЕсли;
    
    // 3. Заполняем должность (из реквизита справочника)
    СтрокаТЧ.Должность = Строка(СтрокаТЧ.Сотрудник.Должность);
    
    // 4. Поиск оклада в регистре сведений
    // Используем дату документа для получения актуального значения
    Отбор = Новый Структура("Сотрудник", СтрокаТЧ.Сотрудник);
    
    // Здесь указываем имя вашего регистра, где хранятся суммы начислений
    ДанныеОкладов = РегистрыСведений.НачисленияСотрудников.СрезПоследних(Дата, Отбор);
    
    Если ДанныеОкладов.Количество() > 0 Тогда
        // Заполняем реквизит из регистра
        СтрокаТЧ.Оклад = Строка(ДанныеОкладов[0].Размер);
    Иначе
        СтрокаТЧ.Оклад = "0";
    КонецЕсли;
    
КонецПроцедуры

Дополнительные рекомендации

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

Также стоит помнить, что в обычных формах при заполнении реквизитов через программный код визуальное обновление ячеек происходит автоматически, в отличие от некоторых сценариев управляемых форм. Однако, если вы хотите гарантировать перерисовку, можно использовать метод ЭлементыФормы.ИмяВашейТабличнойЧасти.ОбновитьСтроки().

Таким образом, мы проанализировали основные этапы решения задачи: от перехвата события изменения до получения данных из регистров. Использование этих методов позволит сделать ваш документ «Табель смены» удобным и защищенным от ошибок ручного ввода.

← На главную