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

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

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

Метод Скопировать: самый простой и эффективный способ

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

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

Скопировать(<Строки>, <Колонки>)

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

  1. Параметр «Строки»: Если нам нужно скопировать данные всех строк, мы передаем сюда значение Неопределено или просто пропускаем этот параметр.
  2. Параметр «Колонки»: Здесь мы указываем строку с именами нужных колонок, разделяя их запятыми.

Давайте посмотрим на пример кода, который решает задачу автора:


// Предположим, ИсходнаяТЗ содержит колонки: Товар, Количество, Цена, Сумма, Склад
// Нам нужно скопировать только "Товар" и "Количество"

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

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

Работа с табличными частями: метод Выгрузить

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

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


// Выгружаем данные из табличной части документа
// Параметры: МассивСтрок (Неопределено - все), СписокКолонок
СписокПолей = "Номенклатура, Количество";
ТаблицаРезультат = Объект.Товары.Выгрузить(, СписокПолей);

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

Метод «от обратного»: удаление лишних колонок

Рассмотрим ситуацию, когда в исходной таблице 50 колонок, а вам нужно получить 45 из них. Перечислять 45 имен в строке через запятую — трудоемкая и чреватая ошибками работа. В таком случае эффективнее пойти путем исключения.

Разберем алгоритм действий:

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

Посмотрим на пример реализации:


// Делаем полную копию
НоваяТЗ = ИсходнаяТЗ.Скопировать();

// Удаляем ненужные колонки по именам
НоваяТЗ.Колонки.Удалить("СлужебнаяИнформатция");
НоваяТЗ.Колонки.Удалить("ВременныйРасчет");

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

Использование механизмов запроса для копирования ТЗ

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

Проанализируем, как это сделать:

  1. Передаем исходную ТЗ в запрос как параметр.
  2. В тексте запроса выбираем только нужные поля.
  3. Выгружаем результат обратно в новую ТЗ.

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ВТ.Товар КАК Товар,
    |   ВТ.Количество КАК Количество
    |ПОМЕСТИТЬ ВТ_Данные
    |ИЗ
    |   &ВнешняяТЗ КАК ВТ
    |;
    |
    |ВЫБРАТЬ * ИЗ ВТ_Данные";

Запрос.УстановитьПараметр("ВнешняяТЗ", ИсходнаяТЗ);
НоваяТЗ = Запрос.Выполнить().Выгрузить();

Этот способ позволяет гибко управлять типами данных. Например, в запросе можно сразу привести типы или заменить NULL на 0, что невозможно сделать простым методом Скопировать().

Ручной обход и ЗаполнитьЗначенияСвойств

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

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


// 1. Создаем структуру новой ТЗ вручную
НоваяТЗ = Новый ТаблицаЗначений;
НоваяТЗ.Колонки.Добавить("Номенклатура"); // имя совпадает
НоваяТЗ.Колонки.Добавить("Всего");        // имя НЕ совпадает (в исходной - "Количество")

// 2. Обходим исходную таблицу
Для Каждого СтрокаИсточкик Из ИсходнаяТЗ Цикл
    НоваяСтрока = НоваяТЗ.Добавить();
    
    // Копируем то, что совпадает по именам (Номенклатура)
    ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаИсточкик);
    
    // Дозаполняем то, что не совпало, вручную
    НоваяСтрока.Всего = СтрокаИсточкик.Количество;
КонецЦикла;

Этот метод самый медленный, но он дает разработчику абсолютный контроль над процессом переноса данных.

Важные нюансы: типы данных и индексы

При копировании колонок важно помнить о двух технических моментах, которые часто упускают из виду:

1. Типизация: Метод Скопировать() полностью наследует описание типов колонок. Если в исходной таблице колонка была составного типа (например, «СправочникСсылка.Товары» и «СправочникСсылка.Услуги»), то и в новой таблице она останется такой же. Если вам нужно "сузить" тип данных, используйте метод запроса или ручной обход.

2. Индексы: Это критически важный момент. Индексы при копировании не сохраняются! Если ваша исходная таблица была проиндексирована для быстрого поиска методами Найти() или НайтиСтроки(), в новой таблице индексы будут отсутствовать. Если вы планируете выполнять частый поиск по новой таблице, не забудьте создать их заново:


// После копирования создаем индекс для ускорения поиска
НоваяТЗ.Индексы.Добавить("Товар");

Подводя итог, можно сказать: для простого копирования данных двух колонок используйте ИсходнаяТЗ.Скопировать(, "Колонка1, Колонка2"). Это самый быстрый, надежный и рекомендуемый стандарт разработки в среде 1С.

← На главную