К статье
Практический материал

Разработка и Конфигурация · 13 мин

1С: как загрузить одну таблицу значений в другую

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

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

Ключевой момент, который определяет выбор способа: совпадают ли структуры колонок у таблиц-источника и приёмника. Если состав и типы колонок одинаковы, работает прямая загрузка. Если структуры различаются — потребуется либо предварительно подготовить колонки приёмника, либо переносить данные построчно с явным сопоставлением полей.

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

Метод Загрузить(): когда структуры таблиц совпадают

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

ТаблицаПриемник.Загрузить(ТаблицаИсточник);

Важно понимать поведение метода: все строки, которые были в приёмнике до вызова, удаляются без предупреждения. Если в приёмнике уже есть данные, которые нужно сохранить, Загрузить() не подходит — используйте Вставить() или цикл.

Типы колонок должны быть совместимы. Если в источнике колонка имеет тип «Число», а в приёмнике та же колонка объявлена как «Строка», платформа попытается выполнить преобразование, но при невозможности (например, строка с буквами в числовую колонку) возникнет ошибка выполнения. Перед загрузкой стоит убедиться, что описания типов колонок совпадают или хотя бы не конфликтуют.

Типичный практический сценарий — перенос результата запроса в заранее созданную таблицу значений, которая затем передаётся в другую процедуру или выводится пользователю:

Запрос = Новый Запрос("ВЫБРАТЬ Номенклатура, Количество ИЗ РегистрНакопления.Остатки.Остатки");

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

ТаблицаДляОтчета.Загрузить(ТаблицаРезультат);

Метод Вставить(): добавление строк без очистки приёмника

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

// Добавить строки источника в конец приёмника

ТаблицаПриемник.Вставить(ТаблицаПриемник.Количество(), ТаблицаИсточник);

// Или в начало

ТаблицаПриемник.Вставить(0, ТаблицаИсточник);

Первый параметр — индекс позиции вставки (нумерация с нуля), второй — таблица-источник. Если индекс равен количеству строк приёмника, данные добавляются в конец. Указание индекса больше текущего размера таблицы вызовет ошибку.

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

Как и у Загрузить(), требование к совместимости колонок сохраняется. Колонки источника, которых нет в приёмнике, игнорируются; колонки приёмника, которых нет в источнике, останутся незаполненными в новых строках.

Сравнение способов переноса

Загрузить()

Полная замена содержимого приёмника. Быстро, но уничтожает имеющиеся строки.

Вставить()

Добавление строк в заданную позицию без очистки. Подходит для объединения данных.

Цикл с Добавить()

Полный контроль над каждой строкой: фильтрация, преобразование, сопоставление разных колонок. Медленнее на больших объёмах.

Построчное копирование в цикле

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

Для Каждого СтрокаИсточника Из ТаблицаИсточник Цикл

Если СтрокаИсточника.Количество > 0 Тогда

НоваяСтрока = ТаблицаПриемник.Добавить();

НоваяСтрока.Товар = СтрокаИсточника.Номенклатура;

НоваяСтрока.Количество = СтрокаИсточника.Количество;

НоваяСтрока.Сумма = СтрокаИсточника.Количество * СтрокаИсточника.Цена;

КонецЕсли;

КонецЦикла;

Этот подход даёт полный контроль: можно переименовать колонки «на лету», вычислять производные значения, пропускать ненужные строки и обрабатывать исключения для отдельных записей. Расплата — производительность: на таблицах в десятки тысяч строк цикл заметно медленнее Загрузить().

Копирование с помощью ЗаполнитьЗначенияСвойств

Если колонки частично совпадают по именам, но структуры не идентичны, удобно использовать ЗаполнитьЗначенияСвойств() — она перенесёт значения всех одноимённых колонок автоматически:

Для Каждого СтрокаИсточника Из ТаблицаИсточник Цикл

НоваяСтрока = ТаблицаПриемник.Добавить();

ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаИсточника);

КонецЦикла;

Функция сопоставляет свойства по именам, поэтому опечатка в имени колонки приведёт к тому, что поле просто не заполнится — без сообщения об ошибке. После такого переноса обязательно проверьте результат на тестовых данных.

Порядок построчного переноса
  1. 1
    Убедитесь, что в таблице-приёмнике созданы все нужные колонки с правильными типами
  2. 2
    Переберите строки источника в цикле Для Каждого
  3. 3
    Для каждой подходящей строки вызовите Приемник.Добавить() и заполните поля
  4. 4
    Проверьте количество строк в приёмнике и содержимое контрольных записей

Подготовка колонок приёмника: типичная причина пустого результата

Частая ситуация: разработчик создаёт пустую таблицу значений через Новый ТаблицаЗначений, вызывает Загрузить() — и получает пустую таблицу или потерю части данных. Причина в том, что колонки приёмника не созданы, а Загрузить() сам их не добавляет.

Колонки нужно объявить заранее с указанием типов:

ТаблицаПриемник = Новый ТаблицаЗначений;

ТаблицаПриемник.Колонки.Добавить("Номенклатура",

Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));

ТаблицаПриемник.Колонки.Добавить("Количество",

Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));

ТаблицаПриемник.Загрузить(ТаблицаИсточник);

Альтернатива — скопировать структуру колонок с источника методом СкопироватьКолонки(). Он создаёт новую таблицу с такими же колонками, но без строк:

ТаблицаПриемник = ТаблицаИсточник.СкопироватьКолонки();

ТаблицаПриемник.Загрузить(ТаблицаИсточник);

Если нужна полная копия таблицы (и колонки, и строки) в новую переменную, проще всего вызвать ТаблицаИсточник.Скопировать() — это однострочная замена связки «скопировать колонки + загрузить».

Типичные ошибки
01
Вызов Загрузить() в пустую таблицу без колонок — данные теряются без ошибки
02
Ожидание, что Загрузить() добавит строки к существующим — метод полностью очищает приёмник
03
Несовпадение типов колонок — ошибка преобразования значения во время выполнения
04
Опечатка в имени колонки при ЗаполнитьЗначенияСвойств — поле остаётся пустым без предупреждения

Загрузка таблицы значений в табличную часть документа

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

ДокументОбъект.Товары.Загрузить(ТаблицаТоваров);

ДокументОбъект.Записать();

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

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

Для управляемых форм при работе с данными формы табличная часть представлена как ДанныеФормыКоллекция, и прямой вызов Загрузить() недоступен. Используется цикл с Добавить() либо преобразование через РеквизитФормыВЗначение().

Производительность и большие объёмы данных

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

Если построчная обработка неизбежна на большом объёме, рассмотрите варианты оптимизации: вынести фильтрацию и соединение данных в запрос (пусть СУБД делает тяжёлую работу), а в таблицу значений выгружать уже готовый результат. Часто вся задача «загрузить одну таблицу в другую с преобразованием» решается одним запросом с соединением и последующим Выгрузить().

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

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

Проверка результата и отладка

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

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

// Быстрая проверка количества строк

Сообщить("Загружено строк: " + ТаблицаПриемник.Количество());

// Проверка итога по числовой колонке

Сообщить("Итоговая сумма: " + ТаблицаПриемник.Итог("Сумма"));

Если строки загрузились, но часть полей пустая — первым делом сверьте имена колонок источника и приёмника. Это самая частая причина «тихой» потери данных, которую сложно заметить без явной проверки.

Контрольные точки

Как проверить результат

Количество строк в приёмнике
Норма

Совпадает с количеством строк источника (или с числом отфильтрованных)

Тревожный признак

Строк меньше или приёмник пуст — проверяйте колонки и условия фильтрации

Значения контрольных полей
Норма

Данные в ключевых колонках заполнены и совпадают с источником

Тревожный признак

Поля пустые — расходятся имена колонок или типы

Поведение приёмника
Норма

При Загрузить() старые строки удалены, при Вставить() — сохранены

Тревожный признак

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

Частые вопросы

Чем Загрузить() отличается от Скопировать()?

Загрузить() переносит строки в уже существующую таблицу, заменяя её содержимое, и не трогает структуру колонок. Скопировать() создаёт новую таблицу значений — полную копию источника вместе с колонками и строками — и возвращает её как результат. Если нужна независимая копия в новую переменную, используйте Скопировать(); если заполнить существующую таблицу — Загрузить().

Почему после Загрузить() таблица пустая, хотя в источнике есть строки?

Чаще всего у таблицы-приёмника не созданы колонки. Метод Загрузить() не добавляет колонки автоматически — он работает только с теми, что уже объявлены. Создайте колонки через Колонки.Добавить() или сформируйте приёмник вызовом Источник.СкопироватьКолонки(). Вторая возможная причина — источник на самом деле пуст, проверьте его через Количество().

Как объединить две таблицы значений в одну?

Используйте метод Вставить(): Приемник.Вставить(Приемник.Количество(), ВтораяТаблица) — строки второй таблицы добавятся в конец первой. Если после объединения нужно убрать дубли, вызовите Свернуть() с перечнем колонок группировки. Для сложного объединения по ключу (как JOIN) лучше использовать запрос с соединением таблиц, помещённых во временные таблицы.

Можно ли загрузить таблицу значений в табличную часть документа, не открывая его?

Да, но работать нужно с объектом, а не со ссылкой: получите объект через Ссылка.ПолучитьОбъект(), вызовите Объект.ТабличнаяЧасть.Загрузить(Таблица) и затем Объект.Записать(). Учтите, что загрузка полностью заменяет строки табличной части, а запись проведённого документа может потребовать отмены проведения.

Как перенести только часть строк по условию?

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

Что делать, если типы колонок источника и приёмника не совпадают?

Приведите типы при объявлении колонок приёмника к совместимым значениям через ОписаниеТипов, либо преобразуйте значения явно в цикле (Строка(), Число(), Дата()). Для сложных преобразований надёжнее построчный перенос с обработкой каждого значения — так вы контролируете поведение при некорректных данных и можете записать проблемные строки в журнал.

Итог

Что важно запомнить

Совпадающие структуры — Загрузить() с полной заменой содержимого, добавление строк — Вставить(), разные колонки или фильтрация — цикл с Добавить() или ЗаполнитьЗначенияСвойств. Колонки приёмника создавайте заранее, а результат всегда проверяйте по количеству строк и контрольным значениям.