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

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

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

Анализ исходной ошибки: почему код не работал

Рассмотрим ситуацию, представленную в вопросе. Автор пытался выполнить цикл по результату запроса и вызвать метод Записать() или Выполнить() непосредственно у объекта ТабличнаяЧасть. Проанализируем, почему это приводит к ошибке. В системе 1С:Предприятие табличная часть документа является коллекцией строк (тип ДанныеФормыКоллекция на форме или ТабличнаяЧасть в объекте). У этой коллекции есть методы для управления составом строк, такие как Добавить(), Удалить() или Очистить(), но методов Записать() или Выполнить() у нее не существует.

Метод Записать() существует только у самого документа (объекта) или у набора записей регистра. Когда мы работаем в контексте формы с переменной Объект, мы манипулируем данными в оперативной памяти. Изменения в табличной части отобразятся на экране сразу после завершения серверного вызова, а физическая запись в базу данных произойдет только при сохранении всего документа пользователем или программным вызовом Объект.Записать().

Пошаговая инструкция по заполнению табличной части через выборку

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


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

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

Оптимизация: использование ЗаполнитьЗначенияСвойств

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

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


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

Максимальная производительность: метод Загрузить()

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

Рассмотрим, как это реализовать по шагам:

  1. Выполним запрос.
  2. Выгрузим результат запроса в таблицу значений методом Выгрузить().
  3. Применим метод Загрузить() к табличной части документа.

РезультатЗапроса = Запрос.Выполнить();
ТаблицаДанных = РезультатЗапроса.Выгрузить();

// Метод Загрузить автоматически очищает старые строки и добавляет новые из таблицы
Объект.ТабличнаяЧасть.Загрузить(ТаблицаДанных);

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

Нюансы работы с датами и параметрами в запросах

Проанализируем текст запроса из примера. В условии ГДЕ используется сравнение дат: СведенияОбОбзвоне.ДатаПерезвона = &ДатаПерезвона. В 1С тип Дата всегда содержит время. Если в регистре дата записана как "01.01.2023 14:30:00", а в параметр вы передаете начало дня "01.01.2023 00:00:00", запрос не найдет эту запись. Чтобы избежать этой проблемы, рекомендуется использовать функцию НАЧАЛОПЕРИОДА или сравнивать даты в диапазоне (от начала дня до конца дня).

Также важно убедиться, что параметр Менеджер действительно используется в блоке ГДЕ. В исходном сообщении автора параметр устанавливался в коде (УстановитьПараметр), но отсутствовал в тексте запроса. Это типичная ошибка, при которой фильтрация просто не срабатывает, и запрос возвращает избыточные данные.

Заключение

Подведем итог. Чтобы успешно выполнить результат запроса и добавить строки в документ, необходимо соблюдать следующие правила:

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

← На главную