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

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

Как заполнить таблицу значений из таблицы значений в 1С

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

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

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

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

Способ 1. Загрузить() — полное копирование таблицы

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

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

// колонки приемника должны совпадать с колонками источника

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

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

ТЗПриемник.Колонки.Добавить("Сумма");

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

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

ТЗПриемник.Загрузить(ТЗИсточник, "Номенклатура, Количество");

Обратите внимание: Загрузить() не добавляет строки, а полностью замещает содержимое таблицы-приемника. Если в приемнике уже есть нужные строки, они будут удалены.

Способ 2. Выгрузить() и комбинация методов

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

// полная копия

ТЗКопия = ТЗИсточник.Выгрузить();

// копия только с нужными колонками

ТЗКопия = ТЗИсточник.Выгрузить(, "Номенклатура, Сумма");

// копия только отобранных строк

Отбор = Новый Структура("Склад", СкладОсновной);

ТЗКопия = ТЗИсточник.Выгрузить(ТЗИсточник.НайтиСтроки(Отбор));

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

Способ 3. Построчное копирование через ЗаполнитьЗначенияСвойств

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

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

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

Продолжить; // пропускаем нулевые строки

КонецЕсли;

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

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

// ручное преобразование отдельных полей

НоваяСтрока.СуммаСНДС = СтрокаИсточника.Сумма * 1.2;

КонецЦикла;

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

Порядок действий при построчном копировании
  1. 1
    Убедитесь, что в приемнике созданы все нужные колонки с корректными типами
  2. 2
    Очистите приемник методом Очистить(), если это повторное заполнение
  3. 3
    Пройдите циклом по строкам источника, добавляя строки через Добавить()
  4. 4
    Переносите совпадающие поля через ЗаполнитьЗначенияСвойств(), остальные — вручную
  5. 5
    Проверьте Количество() строк в приемнике и контрольные итоги по суммовым колонкам

Способ 4. Заполнение через запрос

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Товары.Номенклатура КАК Номенклатура,

| СУММА(Товары.Количество) КАК Количество

|ИЗ

| Документ.РеализацияТоваровУслуг.Товары КАК Товары

|ГДЕ

| Товары.Ссылка = &Ссылка

|СГРУППИРОВАТЬ ПО

| Товары.Номенклатура";

ТЗПриемник = Запрос.Выполнить().Выгрузить();

Можно пойти дальше и поместить существующую таблицу значений во временную таблицу запроса через параметр, чтобы отфильтровать, сгруппировать или соединить её с данными базы. Для этого таблицу передают как параметр и используют конструкцию ПОМЕСТИТЬ:

Запрос.УстановитьПараметр("ТЗ", ТЗИсточник);

Запрос.Текст =

"ВЫБРАТЬ ТЗ.Номенклатура, ТЗ.Количество

|ПОМЕСТИТЬ ВТ ИЗ &ТЗ КАК ТЗ

|;

|ВЫБРАТЬ ВТ.Номенклатура, СУММА(ВТ.Количество)

|ИЗ ВТ КАК ВТ

|СГРУППИРОВАТЬ ПО ВТ.Номенклатура";

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

Сравнение способов заполнения

Загрузить()

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

Выгрузить()

Приемник еще не создан, нужна копия целиком, по колонкам или по отобранным строкам. Возвращает новую таблицу.

Цикл + ЗаполнитьЗначенияСвойств

Структуры различаются, нужен отбор строк или вычисление полей. Гибко, но медленно на больших объемах.

Запрос

Нужна группировка, соединение с данными базы или обработка большого объема. Требует написания текста запроса.

Как выбрать способ под свою задачу

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

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

Маршрут решения

Как выбрать действие

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

Проверка результата и типичные ошибки

После заполнения убедитесь, что данные перенеслись корректно. Минимальная проверка — сравнение количества строк и контрольных сумм по числовым колонкам источника и приемника. Для таблиц с итогами удобно использовать метод Итог("Сумма").

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

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

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

ТЗПриемник.Количество() равно ожидаемому числу строк

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

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

Итоги по суммовым колонкам
Норма

Итог("Сумма") источника и приемника совпадают

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

Итоги расходятся — проверяйте отбор и преобразования

Типы значений в колонках
Норма

Значения соответствуют типу колонки приемника

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

Пустые или нулевые значения там, где в источнике были данные

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

Все нужные колонки заполнены

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

Колонка пуста — вероятно, имя в приемнике отличается от источника

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

Третья группа ошибок связана с типами: если колонка приемника создана с узким типом (например, только Число), а из источника приходит Неопределено или строка, значение может быть приведено к пустому. Создавайте колонки с составным типом через ОписаниеТипов, если заранее не уверены в содержимом.

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

Производительность и ограничения

Таблицы значений целиком хранятся в оперативной памяти сервера или клиента. Копирование таблицы на сотни тысяч строк создаёт вторую полную копию данных в памяти — на слабом оборудовании это может привести к замедлению или нехватке памяти. В таких случаях лучше не копировать таблицу, а работать с исходной через отборы и индексы.

Для ускорения поиска строк в большой таблице добавляйте индексы: ТЗ.Индексы.Добавить("Номенклатура"). Это заметно ускоряет Найти() и НайтиСтроки(), которые часто используются при построчном переносе с сопоставлением.

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

При отладке переноса удобно вывести обе таблицы в табличный документ или сообщить количество строк и итоги до и после копирования. Расхождение видно сразу, а искать причину проще на маленьком тестовом наборе из 3-5 строк.
ПЗ
Практическое замечание

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

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

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

Почему после Загрузить() часть колонок осталась пустой?

Метод сопоставляет колонки по именам. Если имя в приемнике отличается хотя бы регистром не считается — но отличается само написание, данные по этой колонке не переносятся, и ошибка не выводится. Сравните списки колонок обеих таблиц через цикл по Колонки.

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

Используйте цикл: Для Каждого Строка Из ТЗИсточник Цикл … ТЗПриемник.Добавить() с ЗаполнитьЗначенияСвойств(). Метод Загрузить() для этого не подходит — он всегда полностью замещает содержимое приемника.

Можно ли заполнить табличную часть документа из таблицы значений?

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

Что быстрее: Загрузить() или цикл по строкам?

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

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

Используйте ТЗКопия = ТЗОригинал.Выгрузить() — создаётся полностью независимая таблица. Простое присваивание переменной (ТЗ2 = ТЗ1) копию не создаёт: обе переменные будут указывать на один и тот же объект.

Итог

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

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