При разработке конфигураций на платформе 1С часто возникает задача автоматизации заполнения документов. Пользователям неудобно вводить данные по одной строке, особенно если информация уже содержится в другом документе или внешнем файле. В этой статье мы подробно разберем, какими способами можно реализовать множественное добавление строк в табличную часть (ТЧ), проанализируем программные методы и встроенные возможности платформы.
Это самый быстрый и эффективный способ программного копирования данных между табличными частями. Если нам нужно полностью заменить содержимое табличной части одного документа данными из другого, мы используем связку методов Выгрузить() и Загрузить(). Проанализируем, как это работает на практике.
Метод Выгрузить() создает объект ТаблицаЗначений, который содержит все колонки и данные исходной ТЧ. Метод Загрузить(), напротив, очищает целевую ТЧ и заполняет ее данными из переданной таблицы значений. Рассмотрим пример кода:
// Копируем все строки из СтарогоДокумента в НовыйДокумент
ТаблицаДанных = СтарыйДокументОбъект.Товары.Выгрузить();
НовыйДокументОбъект.Товары.Загрузить(ТаблицаДанных);
Важно помнить, что метод Загрузить() сопоставляет данные по именам колонок. Если в исходной и целевой табличных частях имена реквизитов совпадают, данные будут перенесены корректно. Если же нужно добавить строки к уже существующим в документе, алгоритм немного усложняется. Разберем ситуацию, когда в новом документе уже есть данные, которые нельзя удалять:
// Выгружаем текущие строки целевого документа
ТЗ_Цель = Объект.Товары.Выгрузить();
// Выгружаем строки из источника
ТЗ_Источник = ДокументИсточник.Товары.Выгрузить();
// Объединяем таблицы. Для этого перебираем источник и добавляем в цель
Для Каждого СтрокаИсточника Из ТЗ_Источник Цикл
НоваяСтрока = ТЗ_Цель.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаИсточника);
КонецЦикла;
// Загружаем объединенный результат обратно
Объект.Товары.Загрузить(ТЗ_Цель);
Преимущество этого метода: работа с объектом ТаблицаЗначений в памяти происходит значительно быстрее, чем прямое обращение к строкам табличной части документа на форме или в объекте при больших объемах данных.
Иногда требуется более тонкая настройка при добавлении строк — например, проверка условий или пересчет цен «на лету». В этом случае мы используем классический цикл. Посмотрим на пример реализации, который часто встречается в типовых конфигурациях:
Для Каждого СтрокаИзИсточника Из СписокСтрокДляДобавления Цикл
НоваяСтрока = Объект.Товары.Add();
// Копируем значения только тех реквизитов, имена которых совпадают
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаИзИсточника);
// Здесь можно добавить произвольную логику
Если НоваяСтрока.Количество > 100 Тогда
НоваяСтрока.Скидка = 5;
КонецЕсли;
КонецЦикла;
Рассмотрим подробнее функцию ЗаполнитьЗначенияСвойств(). Она является крайне полезным инструментом, так как избавляет программиста от необходимости прописывать копирование каждого поля вручную (например, НоваяСтрока.Номенклатура = СтрокаИзИсточника.Номенклатура). Это сокращает код и делает его более устойчивым к изменениям структуры метаданных.
Выясним, можно ли обойтись без программирования. Начиная с версии платформы 8.3.10, в 1С реализован штатный механизм копирования строк. Это именно та «магическая кнопка», о которой часто спрашивают пользователи.
Как это работает для пользователя:
Важный нюанс: для того чтобы этот механизм работал в «самописке», в свойствах табличного поля на форме должно быть разрешено выделение строк, а у пользователя должны быть соответствующие права. Платформа автоматически сопоставит колонки по именам. Если колонка «Номенклатура» есть в обоих документах, данные перенесутся.
Проанализируем ситуацию, когда нам нужно реализовать кнопки «Копировать строки» и «Вставить строки» на командной панели ТЧ. Это удобно, когда стандартный Ctrl+V по каким-то причинам не подходит или требуется сложная обработка данных при вставке.
Для реализации такого механизма мы можем использовать Временное хранилище. Рассмотрим алгоритм по шагам:
Пример кода для копирования:
// На клиенте получаем выделенные строки
ВыбранныеСтроки = Элементы.Товары.ВыделенныеСтроки;
МассивДанных = Новый Массив;
Для Каждого ИдентификаторСтроки Из ВыбранныеСтроки Цикл
СтрокаТЧ = Объект.Товары.НайтиПоИдентификатору(ИдентификаторСтроки);
СтруктураСтроки = Новый Структура("Номенклатура, Количество, Цена, Сумма");
ЗаполнитьЗначенияСвойств(СтруктураСтроки, СтрокаТЧ);
МассивДанных.Добавить(СтруктураСтроки);
КонецЦикла;
// Помещаем во временное хранилище
АдресХранилища = ПоместитьВоВременноеХранилище(МассивДанных, УникальныйИдентификатор);
Если ваша конфигурация построена на базе Библиотеки стандартных подсистем (БСП), вам доступен еще более мощный инструмент — подсистема «Заполнение из внешнего источника». Она позволяет не просто копировать строки между документами, но и загружать их из файлов Excel, CSV или просто из буфера обмена, в который скопирована область таблицы.
Разберем, почему это удобно. Система предоставляет готовое диалоговое окно, в котором пользователь может:
При реализации массового добавления строк программным способом (особенно методом Загрузить()), нужно помнить о нескольких критически важных моментах:
1. События формы: При программном изменении серверного объекта (документа) события интерфейса, такие как ПриИзменении для конкретной колонки, не вызываются. Если у вас в документе реализован сложный пересчет (например, при выборе номенклатуры подставляется цена), вам придется вызвать этот пересчет программно после загрузки строк.
2. Типы данных: Будьте осторожны при копировании данных между разными типами документов. Если в одном документе реквизит имеет тип СправочникСсылка.Номенклатура, а в другом — Строка, простое копирование через ЗаполнитьЗначенияСвойств может привести к потере данных или ошибкам.
3. Итоги документа: После массовой вставки всегда вызывайте процедуру пересчета итогов (сумма документа, сумма НДС), так как они могут не обновиться автоматически в зависимости от того, как написан ваш код.
Подводя итог, можно сказать: для простых задач «копипаста» пользователям достаточно стандартного механизма Ctrl+C / Ctrl+V. Для разработчика же наиболее изящным решением является использование методов Выгрузить() и Загрузить() для максимальной производительности системы.