Разработка и Конфигурация · 10 мин
Как скопировать таблицу значений (ТЗ) в 1С
Как скопировать таблицу значений (ТЗ) в 1С: метод Скопировать, копирование колонок и строк, выгрузка в новую ТЗ, типичные ошибки и примеры кода.
Под аббревиатурой ТЗ в среде разработчиков 1С почти всегда понимается таблица значений — универсальный объект для хранения и обработки данных в оперативной памяти. Задача скопировать ТЗ возникает постоянно: при фильтрации строк, передаче данных между процедурами, подготовке временных выборок и заполнении табличных частей документов. При этом у новичков копирование часто превращается в источник ошибок, потому что таблица значений — ссылочный тип, и простое присваивание переменной не создаёт копию.
Если написать ТЗ2 = ТЗ1;, обе переменные будут указывать на один и тот же объект. Любое изменение через вторую переменную отразится и в первой таблице. Чтобы получить независимую копию, нужно использовать специальные методы объекта «ТаблицаЗначений». Ниже разобраны все рабочие способы с примерами кода, ограничениями и проверкой результата.
Почему простое присваивание не копирует таблицу значений
Таблица значений в 1С относится к ссылочным (объектным) типам данных, как и запрос, дерево значений или COM-объект. Когда вы присваиваете одну переменную другой, платформа копирует не содержимое, а ссылку на область памяти, где хранится объект. В результате две переменные работают с одной таблицей.
Типичный симптом этой ошибки: вы очищаете «копию» таблицы методом Очистить(), а оригинал тоже оказывается пустым. Или добавляете строки в новую таблицу, и они появляются в старой. Такие ошибки трудно отловить, потому что код выполняется без сообщений об ошибках — просто данные ведут себя неожиданно.
// НЕПРАВИЛЬНО: обе переменные указывают на одну таблицу
ТЗКопия = ТЗИсходная;
ТЗКопия.Очистить(); // ТЗИсходная тоже станет пустой!
// ПРАВИЛЬНО: создаётся независимая копия
ТЗКопия = ТЗИсходная.Скопировать();
Полное копирование таблицы методом Скопировать()
Основной способ создать полную независимую копию таблицы значений — метод Скопировать() без параметров. Он создаёт новый объект с той же структурой колонок и тем же набором строк. Изменения в копии никак не влияют на исходную таблицу, и наоборот.
// Полное копирование таблицы значений
ТЗКопия = ТЗИсходная.Скопировать();
// Теперь можно безопасно менять копию
ТЗКопия.Сортировать("Номенклатура");
ТЗКопия.Свернуть("Номенклатура", "Количество, Сумма");
Метод копирует и структуру колонок, включая типы данных, и все строки с их значениями. Индексы таблицы при этом не переносятся — если они нужны в копии, их необходимо создать заново через ТЗКопия.Индексы.Добавить("ИмяКолонки").
Копирование части строк с отбором
Часто нужна не вся таблица, а только строки, удовлетворяющие условию. Метод Скопировать() принимает параметры: структуру отбора и список копируемых колонок. Это удобная замена связки «НайтиСтроки + цикл добавления».
// Копируем только строки по выбранному складу
Отбор = Новый Структура("Склад", ВыбранныйСклад);
ТЗПоСкладу = ТЗИсходная.Скопировать(Отбор);
// Копируем отобранные строки, но только две колонки
ТЗСокращенная = ТЗИсходная.Скопировать(Отбор, "Номенклатура, Количество");
Первый параметр — структура, где ключ совпадает с именем колонки, а значение — с искомым значением. Отбор работает только на равенство; для условий «больше», «содержит» и подобных придётся перебирать строки в цикле и добавлять их в новую таблицу вручную либо использовать запрос к таблице.
- 1Создайте пустую таблицу с той же структурой: ТЗНовая = ТЗИсходная.СкопироватьКолонки()
- 2Переберите строки исходной таблицы в цикле Для Каждого
- 3Внутри цикла проверьте условие оператором Если
- 4При выполнении условия добавьте строку: НоваяСтрока = ТЗНовая.Добавить() и заполните её через ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка)
- 5После цикла проверьте количество строк в результате
Копирование только структуры без данных
Когда нужна пустая таблица с такими же колонками, как у существующей, используйте метод СкопироватьКолонки(). Он переносит описание колонок (имена, типы, заголовки), но не переносит строки. Это стандартный приём для подготовки таблицы-результата перед циклом отбора.
// Пустая таблица с той же структурой
ТЗРезультат = ТЗИсходная.СкопироватьКолонки();
// Заполняем вручную по условию
Для Каждого Строка Из ТЗИсходная Цикл
Если Строка.Количество > 100 Тогда
НоваяСтрока = ТЗРезультат.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка);
КонецЕсли;
КонецЦикла;
Методу можно передать список имён колонок строкой через запятую, если нужна не вся структура, а её часть. Обратите внимание: ЗаполнитьЗначенияСвойств заполняет только совпадающие по именам свойства, поэтому колонки в обеих таблицах должны называться одинаково.
Копирование через выгрузку и загрузку
Альтернативный путь — выгрузить таблицу в значение и загрузить обратно. Метод Выгрузить() у таблицы значений отсутствует в том виде, в каком он есть у результата запроса, но сама таблица уже является «выгруженным» объектом. Поэтому на практике приём применяется в обратную сторону: результат запроса выгружают в ТЗ, а дальше копируют её методом Скопировать().
Запрос = Новый Запрос("ВЫБРАТЬ Номенклатура, Количество ИЗ ...");
ТЗИзЗапроса = Запрос.Выполнить().Выгрузить();
// Независимая копия для дальнейшей обработки
ТЗРабочая = ТЗИзЗапроса.Скопировать();
Для копирования отдельных колонок в виде массива есть метод ВыгрузитьКолонку("ИмяКолонки") — он возвращает массив значений. Обратная операция — ЗагрузитьКолонку(Массив, "ИмяКолонки"). Это удобно, когда нужно перенести данные одной колонки между таблицами с разной структурой.
Способы копирования ТЗ
Полная независимая копия со всеми строками. Подходит в большинстве случаев, но не переносит индексы
Копия части строк по отбору на равенство. Не подходит для условий «больше/меньше»
Только структура без строк. Используется перед ручным заполнением в цикле
Перенос одной колонки в виде массива между таблицами с разной структурой
Копирование табличной части документа в ТЗ и обратно
Отдельная частая задача — скопировать табличную часть документа или справочника в таблицу значений. Табличная часть — это не ТЗ, но у неё есть метод Выгрузить(), который возвращает именно таблицу значений. Для загрузки обратно используется Загрузить(ТЗ).
// Выгружаем табличную часть документа в ТЗ
ТЗТовары = ДокументОбъект.Товары.Выгрузить();
// Обрабатываем как обычную таблицу значений
ТЗОтбор = ТЗТовары.Скопировать(Новый Структура("Склад", ОсновнойСклад));
// Загружаем результат обратно в табличную часть
ДокументОбъект.Товары.Загрузить(ТЗОтбор);
Важное ограничение: метод Выгрузить() доступен у табличных частей только в серверном контексте. В управляемых формах на клиенте табличная часть представлена объектом «ДанныеФормыКоллекция», у которого есть метод Выгрузить(), но вызов серверных методов объекта документа недоступен. Для обработки на сервере данные формы преобразуют через РеквизитФормыВЗначение и ЗначениеВРеквизитФормы.
Проверка результата и производительность
После копирования полезно убедиться, что копия действительно независима и содержит ожидаемые данные. Минимальная проверка — сравнить количество строк и изменить одно значение в копии, убедившись, что оригинал не изменился. В отладчике это видно сразу: у двух переменных, указывающих на один объект, совпадают все изменения в реальном времени.
Как проверить результат
ТЗКопия.Количество() равно ожидаемому числу строк
Копия пустая или строк больше, чем в источнике
Изменение копии не влияет на оригинал
Обе таблицы меняются одновременно — скопирована ссылка
Все нужные колонки присутствуют с правильными типами
Колонок нет или тип значения стал строкой
Все строки копии соответствуют условию отбора
В копии есть лишние строки — ошибка в структуре отбора
По производительности: копирование большой таблицы (десятки тысяч строк) методом Скопировать() занимает заметное время и память, потому что создаётся полный дубликат данных. Если копия нужна только для чтения внутри одной процедуры, зачастую дешевле работать с исходной таблицей через НайтиСтроки() или скопировать только нужные колонки. Для тяжёлой обработки больших объёмов предпочтительнее запрос с пакетом временных таблиц.
Частые вопросы о копировании ТЗ в 1С
Чем отличается Скопировать() от СкопироватьКолонки()?
Метод Скопировать() переносит и структуру колонок, и все строки с данными. СкопироватьКолонки() создаёт пустую таблицу только с описанием колонок — её заполняют вручную в цикле, когда нужен отбор по сложному условию.
Почему после ТЗ2 = ТЗ1 изменения видны в обеих таблицах?
Таблица значений — ссылочный тип. Присваивание копирует ссылку на объект, а не данные. Обе переменные работают с одной таблицей в памяти. Для независимой копии используйте ТЗ2 = ТЗ1.Скопировать().
Как скопировать строки по условию «больше» или «содержит»?
Отбор в методе Скопировать() работает только на равенство. Для других условий создайте пустую таблицу через СкопироватьКолонки(), переберите строки в цикле с проверкой Если и добавляйте подходящие строки через Добавить() и ЗаполнитьЗначенияСвойств().
Как скопировать табличную часть документа в таблицу значений?
Вызовите у табличной части метод Выгрузить() на сервере: ТЗ = ДокументОбъект.Товары.Выгрузить(). Обратная загрузка выполняется методом Загрузить(ТЗ), который полностью замещает содержимое табличной части.
Переносятся ли индексы таблицы при копировании?
Нет, метод Скопировать() не переносит индексы. Если копия будет использоваться для поиска через Найти() или НайтиСтроки(), добавьте индексы заново: ТЗКопия.Индексы.Добавить("ИмяКолонки").
Как скопировать только одну колонку из таблицы?
Используйте ТЗ.ВыгрузитьКолонку("ИмяКолонки") — метод вернёт массив значений. Загрузить массив в колонку другой таблицы можно методом ЗагрузитьКолонку(Массив, "ИмяКолонки").
Что важно запомнить
Таблица значений — ссылочный тип, поэтому копию создают только методом Скопировать(), а не присваиванием. Для части строк используйте отбор в параметрах, для пустой структуры — СкопироватьКолонки(), для табличных частей — Выгрузить() и Загрузить(). После копирования проверяйте независимость объектов и количество строк.