Как заполнить табличную часть документа данными из справочника в 1С

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

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

Вариант 1: Программное заполнение через кнопку на форме документа

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

Рассмотрим ситуацию, когда у нас есть документ ИнвентаризацияТоваровНаСкладе с табличной частью ЧекЛист, и мы хотим загрузить в нее данные из справочника ЧекЛист. Разберем по шагам создание обработчика команды:


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

КонецПроцедуры

В данном примере мы использовали псевдонимы в запросе (КАК Пункт), чтобы имена колонок в результате запроса в точности совпадали с именами реквизитов табличной части документа. Это критически важно для корректной работы метода Загрузить().

Вариант 2: Использование внешней обработки (без изменения конфигурации)

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

Для этого в обработке создается реквизит с типом ДокументСсылка.ИнвентаризацияТоваровНаСкладе. Код для заполнения будет выглядеть следующим образом:


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

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

Вариант 3: Обработка иерархии и сохранение структуры справочника

Если наш справочник ЧекЛист является иерархическим (содержит папки и подпапки), обычный запрос выгрузит все элементы "плоским" списком. Выясним, как сделать заполнение более структурированным.

Если мы хотим, чтобы в табличной части сохранялась информация о том, в какой папке находится пункт, нам следует добавить в ТЧ документа реквизит Группа (тип СправочникСсылка.ЧекЛист). Тогда запрос и логика изменятся:

  1. Фильтрация групп: В условии запроса мы должны указать ГДЕ ЭтоГруппа = ЛОЖЬ, чтобы сами папки не попадали в строки таблицы как отдельные элементы.
  2. Получение родителя: Мы выберем поле Родитель, которое и будет указывать на папку элемента.
  3. Сортировка: Чтобы пункты в документе шли в том же порядке, что и в справочнике, используем конструкцию УПОРЯДОЧИТЬ ПО Наименование ИЕРАРХИЯ.

Посмотрим на пример такого запроса:


Запрос.Текст = 
    "ВЫБРАТЬ
    |   ЧекЛист.Ссылка КАК Пункт,
    |   ЧекЛист.Балл КАК Балл,
    |   ЧекЛист.Родитель КАК Группа
    |ИЗ
    |   Справочник.ЧекЛист КАК ЧекЛист
    |ГДЕ
    |   ЧекЛист.ЭтоГруппа = ЛОЖЬ
    |УПОРЯДОЧИТЬ ПО
    |   ЧекЛист.Наименование ИЕРАРХИЯ";

Метод Загрузить() против Добавить(): когда что использовать?

Проанализируем разницу в подходах заполнения. Программисты часто используют два основных способа:

1. Метод Загрузить()

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

2. Метод Добавить() в цикле

Если нам нужно дозаполнить таблицу (например, добавить новые пункты к тем, что пользователь уже ввел вручную), следует использовать перебор результата запроса в цикле:


Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();

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

Рекомендации по использованию Расширений

Чтобы реализовать функционал "внутри документа", не снимая его с поддержки, рекомендуем использовать Расширения конфигурации. Рассмотрим преимущества этого метода:

При использовании расширения процедура на форме будет иметь аннотацию &НаСервере или &НаКлиенте в зависимости от логики, а доступ к данным будет осуществляться через заимствованные объекты.

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

← На главную