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