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

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

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

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

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

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

Способ 1. Полное копирование методом Скопировать()

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

ТаблицаКопия = ИсходнаяТаблица.Скопировать();

После выполнения ТаблицаКопия содержит те же колонки и строки, но является самостоятельным объектом. Если нужно скопировать только часть строк, метод принимает параметр отбора:

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

Отбор = Новый Структура("Количество", 0);

ТаблицаПустых = ИсходнаяТаблица.Скопировать(Отбор);

// Отбор по нескольким условиям

Отбор = Новый Структура;

Отбор.Вставить("Склад", СкладОтгрузки);

Отбор.Вставить("Активна", Истина);

ТаблицаОтобранных = ИсходнаяТаблица.Скопировать(Отбор);

Обратите внимание: отбор сравнивает значения на строгое равенство. Условия «больше», «меньше», «содержит» через структуру отбора не задаются — для них используйте цикл или запрос.

Способ 2. Загрузка данных в существующую таблицу

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

ЦелеваяТаблица.Загрузить(ИсходнаяТаблица.Выгрузить());

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

ЦелеваяТаблица.Очистить();

ЦелеваяТаблица.Загрузить(ИсходнаяТаблица.Выгрузить());

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

Способ 3. Копирование строк в цикле

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

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

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

Продолжить;

КонецЕсли;

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

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

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

КонецЦикла;

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

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

Способ 4. Копирование только структуры колонок

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

ПустаяТаблица = ИсходнаяТаблица.СкопироватьКолонки();

Метод переносит имена, типы, заголовки и ширину колонок, но не строки. Если нужны не все колонки, передайте их список строкой через запятую:

ЧастичнаяСтруктура = ИсходнаяТаблица.СкопироватьКолонки("Номенклатура,Количество");

Такой же параметр есть и у Скопировать() — можно одновременно ограничить и колонки, и строки:

Копия = ИсходнаяТаблица.Скопировать(Отбор, "Номенклатура,Количество,Сумма");

Копирование табличной части документа в таблицу значений

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

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

// Обратно — из таблицы значений в табличную часть

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

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

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

Выбор метода зависит от исходной ситуации. Сводная таблица поможет быстро определить подходящий вариант.

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

Сравнение вариантов

Скопировать()

Быстрый полный клон таблицы. Не подходит, если целевая таблица уже существует как реквизит формы.

Загрузить(Выгрузить())

Заполняет существующую таблицу с готовой структурой. Требует предварительной очистки.

Цикл по строкам

Максимальная гибкость: отбор, пересчёт, преобразование типов. Проигрывает по скорости на больших таблицах.

Типичные ошибки и как их избежать

Первая распространённая ошибка — попытка скопировать таблицу простым присваиванием: Таблица2 = Таблица1;. В этом случае обе переменные ссылаются на один и тот же объект, и любое изменение «копии» меняет оригинал. Всегда используйте Скопировать().

Вторая ошибка — забыть Очистить() перед Загрузить(), из-за чего строки дублируются при повторном вызове процедуры. Третья — несовпадение типов колонок: если в целевой таблице колонка имеет другой тип, значение может быть обрезано или приведено к пустому. Проверяйте типы через Таблица.Колонки.Найти("ИмяКолонки").ТипЗначения.

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

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

Проверка результата копирования

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

Если ТаблицаКопия.Количество() <> ИсходнаяТаблица.Количество() Тогда

ВызватьИсключение "Количество строк не совпадает";

КонецЕсли;

СуммаИсточник = ИсходнаяТаблица.Итог("Сумма");

СуммаКопия = ТаблицаКопия.Итог("Сумма");

Если СуммаИсточник <> СуммаКопия Тогда

ВызватьИсключение "Итоги по колонке Сумма различаются";

КонецЕсли;

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

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

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

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

Значения совпадают (или равны числу отобранных строк)

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

Строк больше — забыли Очистить(); меньше — сработал лишний отбор

Итог по числовой колонке через Итог()
Норма

Суммы в обеих таблицах равны

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

Итоги различаются — потеряны строки или неверные типы колонок

Изменение строки в копии
Норма

Исходная таблица не меняется

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

Меняется и оригинал — использовано присваивание вместо Скопировать()

Часто задаваемые вопросы

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

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

Как скопировать таблицу значений на управляемой форме между клиентом и сервером?

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

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

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

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

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

Можно ли отобрать строки по условию «больше» или «содержит»?

Через структуру отбора — нет, она поддерживает только равенство. Используйте цикл с проверкой условия, метод НайтиСтроки() не поможет по той же причине. Для сложных условий эффективнее выполнить запрос к таблице значений через конструктор запроса с параметром-таблицей.

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

Если структуры совпадают, пройдите циклом по второй таблице и добавляйте строки в первую через ЗаполнитьЗначенияСвойств(). Для объединения с группировкой и суммированием дублей используйте запрос с ОБЪЕДИНИТЬ ВСЕ или метод Свернуть() после слияния строк.

Итог

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

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