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