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

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

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

Выясняем причину: почему возникает ошибка «Неверные параметры»?

Проанализируем ситуацию, с которой столкнулся автор темы. Исходный код выглядел следующим образом:


СсылкаНаОтчет = ОтчетОРозничныхПродажах.Ссылка;
ДокПеремещение = Документы.ПеремещениеТоваров.СоздатьДокумент();
ДокПеремещение.Товары.Загрузить(СсылкаНаОтчет.Товары);

При выполнении этого кода система выдает ошибку «Неверные параметры». Давайте разберемся, почему так происходит.

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

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

Решение 1: Быстрое исправление через метод Выгрузить()

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


СсылкаНаОтчет = ОтчетОРозничныхПродажах.Ссылка;
ДокПеремещение = Документы.ПеремещениеТоваров.СоздатьДокумент();

// Выгружаем табличную часть документа-источника в Таблицу Значений
ТаблицаТоваров = СсылкаНаОтчет.Товары.Выгрузить();

// Загружаем полученную таблицу значений в новый документ
ДокПеремещение.Товары.Загрузить(ТаблицаТоваров);

Этот способ прост в реализации и отлично работает в тех случаях, когда структура колонок в документе-источнике и документе-приемнике полностью совпадает. Метод Загрузить() автоматически сопоставит колонки с одинаковыми именами и перенесет данные.

Решение 2: Использование запроса — лучшая практика разработки

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

  1. Производительность (избыточное чтение данных): Обращаясь к табличной части через точку от ссылки (СсылкаНаОтчет.Товары), мы заставляем платформу неявно считывать из базы данных весь документ-источник целиком (включая все реквизиты шапки и другие табличные части, если они есть), чтобы поместить этот массив в оперативную память.
  2. Несовпадение структуры данных: Документы ОтчетОРозничныхПродажах и ПеремещениеТоваров имеют разное назначение. В отчете о продажах присутствуют специфические колонки (например, «Цена», «Сумма», «СтавкаНДС»), которые совершенно не нужны в документе перемещения. Загружая ТЧ напрямую, мы тащим в память лишние данные.
  3. Различие в именах колонок: Если в источнике колонка называется, например, «Количество», а в приемнике — «КоличествоУпаковок», метод Загрузить() не сможет перенести эти данные автоматически.

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


// 1. Создаем запрос для получения только нужных данных
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ОтчетТовары.Номенклатура КАК Номенклатура,
    |	ОтчетТовары.Количество КАК Количество,
    |	ОтчетТовары.Характеристика КАК Характеристика
    |ИЗ
    |	Документ.ОтчетОРозничныхПродажах.Товары КАК ОтчетТовары
    |ГДЕ
    |	ОтчетТовары.Ссылка = &СсылкаНаОтчет";

Запрос.УстановитьПараметр("СсылкаНаОтчет", СсылкаНаОтчет);

// 2. Выгружаем результат запроса в Таблицу Значений
ТаблицаДляЗагрузки = Запрос.Выполнить().Выгрузить();

// 3. Создаем документ и загружаем очищенные данные
ДокПеремещение = Документы.ПеремещениеТоваров.СоздатьДокумент();
ДокПеремещение.Товары.Загрузить(ТаблицаДляЗагрузки);

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

Решение 3: Реализация буфера обмена для переноса строк (для Обычных форм)

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

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

1. Обработка «ВБуфер» (копирование данных):


Процедура Инициализировать(Объект, ИмяТабличнойЧасти, ТабличноеПолеОбъекта) Экспорт
    // Получаем ТЧ текущего документа
    тч = Объект[ИмяТабличнойЧасти];
    // Сохраняем выгруженную Таблицу Значений в системный буфер настроек пользователя
    СохранитьЗначение("БуферТаблиц_ИмениКозлова", тч.Выгрузить());
    Сообщить("Данные успешно скопированы в буфер!");
КонецПроцедуры

2. Обработка «ИзБуфера» (вставка данных):


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

Использование метода ЗаполнитьЗначенияСвойств() в цикле добавления строк — это очень важный прием. Он позволяет скопировать только те реквизиты, которые совпадают по типу и имени в исходном документе и документе-приемнике, предотвращая любые ошибки несовместимости структуры табличных частей.

Современная альтернатива для Управляемых форм (УФ)

Стоит отметить, что методы СохранитьЗначение() и ВосстановитьЗначение() являются устаревшими и не поддерживаются на тонком клиенте в управляемом приложении. Если вы работаете в современных конфигурациях (таких как ERP, КА, УТ 11, Бухгалтерия 3.0), для обмена данными между формами следует использовать другие механизмы:

Таким образом, мы разобрали все аспекты работы с табличными частями: от исправления простейших ошибок приведения типов до проектирования оптимальных алгоритмов работы с СУБД и создания пользовательских интерактивных инструментов.

← На главную