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

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

В процессе работы с документами в 1С часто возникает необходимость автоматизировать заполнение данных. Одной из распространённых задач является автозаполнение полей табличной части документа, когда изменение одного поля в строке должно инициировать заполнение других полей в той же строке — для этого подойдёт конструктор автозаполнения реквизитов и контроля данных без программирования. Для реализации таких задач разработчикам часто приходится программно изменять формы, чтобы стандартизировать и ускорить процесс разработки.

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

Основы работы с табличными частями и событиями формы

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

Ключевым для нашей задачи будет событие ПриИзменении для поля табличной части, которое является "инициатором" автозаполнения. Это событие возникает, когда пользователь изменяет значение в соответствующем поле и покидает его. Обработчик этого события позволяет нам выполнить необходимую логику по заполнению других полей.

Решение 1: Автозаполнение полей при изменении колонки в управляемой форме

Рассмотрим сценарий, когда у нас есть табличная часть, например, "Товары", и при выборе номенклатуры нам нужно автоматически подтянуть её цену и единицу измерения.

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

Допустим, у нас есть табличная часть Товары и колонки Номенклатура, ЕдиницаИзмерения, Цена. При изменении колонки Номенклатура нам нужно заполнить ЕдиницаИзмерения и Цена.

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

Мы создадим обработчик события НоменклатураПриИзменении для поля Номенклатура в табличной части Товары. Этот обработчик будет вызываться на клиенте.


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

Шаг 2: Реализация серверной процедуры для получения данных

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


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

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

Решение 2: Использование дополнительного реквизита формы для временного хранения и автозаполнения

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

Предположим, у нас есть поле КодВидаНоменклатуры, которое не хранится в табличной части, но нужно для вывода сообщения или дополнительной проверки при выборе номенклатуры.

Шаг 1: Добавление реквизита формы

Добавим реквизит формы, например, ВспомогательныйКодВида, типа Строка. Этот реквизит будет использоваться для временного хранения данных.

Шаг 2: Изменение обработчика ПриИзменении

В обработчике НоменклатураПриИзменении мы будем не только заполнять поля строки, но и обновлять наш вспомогательный реквизит.


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

Решение 3: Автозаполнение из другой табличной части или объекта данных

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

Допустим, у нас есть табличная часть СоставыРабот с полем ЭлементРаботы. При его изменении нужно заполнить данные в табличной части Ресурсы.


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

Решение 4: Работа с коллекцией Элементы.ИмяТабличнойЧасти.ТекущиеДанные

В управляемых формах 1С текущие данные строки доступны через свойство ТекущиеДанные. Это позволяет нам не только изменять значения, но и выполнять сложные проверки. Для получения связанных данных объекта на сервере мы можем использовать ссылку из текущей строки и функции получения реквизитов на любом уровне вложенности, что значительно упрощает код по сравнению с написанием запросов для каждого отдельного поля.


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

Советы и лучшие практики

  1. Оптимизация серверных вызовов: Каждый вызов сервера добавляет задержку. Стремитесь минимизировать их количество, собирая все необходимые данные за один раз.
  2. Обработка пустых значений: Всегда предусматривайте логику на случай, если пользователь очистил поле-инициатор.
  3. Интеллектуальное заполнение: Для заполнения текстовых описаний или сложных комментариев можно внедрить современные механизмы заполнения текстовых полей на базе DeepSeek, что значительно ускорит работу пользователя — для этого подойдёт модуль автоматического заполнения реквизитов с помощью нейросетей.
  4. Использование общих модулей: Сложную логику заполнения лучше выносить в общие модули для повышения переиспользуемости кода.
  5. Пользовательский опыт: Если заполнение занимает заметное время, используйте оповещения, чтобы пользователь понимал, что система выполняет расчеты.

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

← На главную