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

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

При разработке алгоритмов обработки данных в 1С часто возникает задача разделить коллекцию строк на части, например, получить первые N записей или ровно половину таблицы значений во вторую независимую таблицу. Разберем особенности работы с коллекциями строк в платформе 1С:Предприятие 8, типичные ошибки при выборе методов и наиболее эффективные варианты решения этой задачи.

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

Способ 1. Использование метода Скопировать с массивом строк

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

Разберем по шагам, как скопировать первую половину строк:

  1. Определим общее количество строк в исходной таблице и рассчитаем границу выборки.
  2. Создадим массив и наполним его ссылками на объекты СтрокаТаблицыЗначений из первой половины исходной таблицы.
  3. Вызовем метод Скопировать, передав подготовленный массив.

Посмотрим на пример программного кода:


КоличествоВсего = ИсходнаяТЗ.Количество();
КоличествоПоловина = Цел(КоличествоВсего / 2);

МассивСтрок = Новый Массив;
Для Счетчик = 0 По КоличествоПоловина - 1 Цикл
    МассивСтрок.Добавить(ИсходнаяТЗ[Счетчик]);
КонецЦикла;

ВтораяТЗ = ИсходнаяТЗ.Скопировать(МассивСтрок);

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


// Для табличной части документа или справочника:
ВтораяТЗ = Объект.Товары.Выгрузить(МассивСтрок);

Способ 2. Копирование структуры колонок и заполнение через цикл

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

Посмотрим, как реализовать данный алгоритм:


ВтораяТЗ = ИсходнаяТЗ.СкопироватьКолонки();
КоличествоПоловина = Цел(ИсходнаяТЗ.Количество() / 2);

Для Счетчик = 0 По КоличествоПоловина - 1 Цикл
    НоваяСтрока = ВтораяТЗ.Добавить();
    ЗаполнитьЗначенияСвойств(НоваяСтрока, ИсходнаяТЗ[Счетчик]);
КонецЦикла;

Такой способ полностью переносит типы и наименования всех 15–20 колонок без ручного перечисления каждого поля, сохраняя исходную типизацию данных.

Способ 3. Использование механизма запросов (ВЫБРАТЬ ПЕРВЫЕ)

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 10
    |   *
    |ИЗ
    |   &ИсходнаяТЗ КАК ИсходнаяТЗ";

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

Обратим внимание на критические нюансы этого метода:

  1. Строгая типизация: Таблицу значений можно передать в запрос в качестве параметра только тогда, когда для абсолютно всех колонок явно задано ОписаниеТипов. Если хотя бы одна колонка создана без указания типа данных, запрос завершится аварийно с ошибкой типизации.
  2. Неопределенный порядок: Конструкция ВЫБРАТЬ ПЕРВЫЕ без явного указания директивы УПОРЯДОЧИТЬ ПО не гарантирует, что в выборку попадут именно первые строки в порядке их следования в таблице. Механизм СУБД рассматривает строки во временной таблице как неупорядоченное множество, поэтому без добавления колонки-индекса результат может отличаться от исходного порядка.

Способ 4. Усечение исходной таблицы (удаление лишних строк)

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

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


ВсегоСтрок = ИсходнаяТЗ.Количество();
ГраницаОтсечения = Цел(ВсегоСтрок / 2);

Для Счетчик = ВсегоСтрок - 1 По ГраницаОтсечения Убыв Цикл
    ИсходнаяТЗ.Удалить(Счетчик);
КонецЦикла;

Ограничения контекста исполнения

Напомним, что объект ТаблицаЗначений является чисто серверным типом данных и недоступен на тонком клиенте и веб-клиенте в управляемом приложении. Все манипуляции по расчету половины строк, заполнению массивов и копированию должны производиться в процедурах и функциях с директивами &НаСервере, &НаСервереБезКонтекста или в модулях объектов и общих модулях.

← На главную