К статье
Практический материал

Разработка и Конфигурация · 11 мин

1С: как выгрузить табличную часть в таблицу значений

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

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

Задача возникает постоянно: нужно свернуть товары документа по номенклатуре, передать список строк в запрос с временной таблицей, заполнить движения регистра или просто вывести данные в отчёт на СКД. Во всех этих случаях первый шаг один и тот же — получить таблицу значений из табличной части объекта.

Методика одинакова для управляемых и обычных форм, для версий платформы 8.2 и 8.3. Отличаются лишь детали: какие колонки выгружать, как отобрать нужные строки и что делать, если объект ещё не записан в базу.

Базовый синтаксис метода Выгрузить()

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

ТаблицаТоваров = ДокументОбъект.Товары.Выгрузить();

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

Результат — полноценная таблица значений со всеми колонками табличной части, включая служебную колонку НомерСтроки. Типы колонок соответствуют типам реквизитов табличной части, описанным в конфигураторе.

bsl
ТаблицаТоваров = ДокументОбъект.Товары.Выгрузить();
Для Каждого СтрокаТЗ Из ТаблицаТоваров Цикл
	Сообщить(СтрокаТЗ.Номенклатура);
КонецЦикла;

Выгрузка только нужных колонок

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

ТЗ = ДокументОбъект.Товары.Выгрузить(, "Номенклатура, Количество, Сумма");

Первый параметр здесь пропущен (это отбор строк, о нём в следующем разделе), а второй — список колонок. Обратите внимание: если указать несуществующее имя колонки, платформа выдаст ошибку выполнения. Поэтому при универсальном коде, работающем с разными видами документов, состав колонок лучше формировать динамически или проверять через метаданные.

Выгрузка части колонок удобна ещё и тем, что сразу подготавливает таблицу к свёртке. Например, чтобы получить итоги по номенклатуре:

ТЗ = ДокументОбъект.Товары.Выгрузить(, "Номенклатура, Количество, Сумма");

ТЗ.Свернуть("Номенклатура", "Количество, Сумма");

Такой приём часто применяется при формировании движений по регистрам, когда в документе допустимы повторяющиеся позиции, а в регистр нужно писать агрегированные данные.

Отбор строк при выгрузке

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

Отбор = Новый Структура("Склад", СкладОтгрузки);

ТЗ = ДокументОбъект.Товары.Выгрузить(Отбор, "Номенклатура, Количество");

Отбор работает только на равенство. Условия вида «больше», «содержит», «в списке» через структуру задать нельзя. Если нужна сложная фильтрация, есть два пути: выгрузить всё и затем использовать методы таблицы значений (НайтиСтроки() с последующей обработкой или копирование через Скопировать() с отбором), либо получать данные запросом с произвольным условием ГДЕ.

Маршрут решения

Как выбрать способ получения данных

Объект уже открыт и изменён в памяти, нужны актуальные строкиИспользуйте Объект.ТабличнаяЧасть.Выгрузить() — запрос увидит только записанные данные
Есть только ссылка и нужен сложный отбор или соединенияИспользуйте запрос к табличной части через Документ.РеализацияТоваровУслуг.Товары
Нужны только строки с равенством по одному-двум реквизитамПередайте структуру отбора первым параметром Выгрузить()
Нужна свёртка или итогиВыгрузите минимум колонок и примените Свернуть()

Выгрузка через запрос к табличной части

Альтернатива методу Выгрузить() — запрос. Табличные части доступны в запросах как отдельные таблицы с составным именем: Документ.РеализацияТоваровУслуг.Товары. Результат запроса легко превратить в таблицу значений методом Выгрузить() у результата запроса:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Товары.Номенклатура КАК Номенклатура,

| СУММА(Товары.Количество) КАК Количество

|ИЗ

| Документ.РеализацияТоваровУслуг.Товары КАК Товары

|ГДЕ

| Товары.Ссылка = &Ссылка

|СГРУППИРОВАТЬ ПО

| Товары.Номенклатура";

Запрос.УстановитьПараметр("Ссылка", СсылкаНаДокумент);

ТЗ = Запрос.Выполнить().Выгрузить();

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

Выгрузка на управляемой форме и работа с ДанныеФормыКоллекция

В управляемых формах табличная часть объекта представлена не привычной коллекцией, а реквизитом формы типа ДанныеФормыКоллекция. У него нет метода Выгрузить(), и попытка вызвать его приведёт к ошибке. Правильный путь — преобразовать данные формы в объект и уже у объекта вызвать выгрузку:

&НаСервере

Функция ПолучитьТаблицуТоваров()

ДокументОбъект = РеквизитФормыВЗначение("Объект");

Возврат ДокументОбъект.Товары.Выгрузить();

КонецФункции

Учтите, что таблица значений не может быть возвращена с сервера на клиент напрямую — она не сериализуется. Если результат нужен на клиенте или в форме, преобразуйте его в массив структур либо загрузите в реквизит формы типа «ТаблицаЗначений» через ЗначениеВРеквизитФормы().

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

Что можно делать с полученной таблицей значений

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

ДокументОбъект.Товары.Загрузить(ТаблицаТоваров);

Метод Загрузить() полностью заменяет содержимое табличной части строками таблицы значений. Состав колонок должен соответствовать реквизитам табличной части — лишние колонки игнорируются, а недостающие обязательные реквизиты останутся пустыми, что может привести к ошибкам при записи.

Типовые операции с выгруженной таблицей: сортировка методом Сортировать(), свёртка через Свернуть(), поиск строк через Найти() и НайтиСтроки(), передача в запрос как источник временной таблицы (параметром типа «ТаблицаЗначений» с конструкцией ПОМЕСТИТЬ), заполнение движений регистров в обработке проведения.

Типовой порядок работы
  1. 1
    Получите объект документа или справочника (не ссылку)
  2. 2
    Вызовите Выгрузить() у табличной части, указав отбор и колонки при необходимости
  3. 3
    Выполните обработку: свёртку, сортировку, расчёт итогов
  4. 4
    Если результат должен попасть обратно в документ — вызовите Загрузить() и запишите объект
  5. 5
    Проверьте результат: количество строк и итоговые суммы до и после обработки

Типичные ошибки и как их избежать

Самая частая ошибка — попытка вызвать Выгрузить() у ссылки. У объекта типа ДокументСсылка табличные части недоступны как коллекции, и код вида Ссылка.Товары.Выгрузить() завершится ошибкой. Решение: либо Ссылка.ПолучитьОбъект(), либо запрос к табличной части.

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

Третья типичная ситуация — потеря колонки НомерСтроки или неожиданное её поведение. При выгрузке без параметров колонка присутствует, но при свёртке или копировании структуры она может потеряться, и обратная загрузка пройдёт корректно (номера строк пересчитаются), однако ссылки на «номер строки» из других данных станут недействительными.

Типичные ошибки
01
Вызов Выгрузить() у ссылки вместо объекта — ошибка выполнения; получите объект или используйте запрос
02
Ожидание автоматической синхронизации таблицы значений с документом — изменения теряются без Загрузить() и Записать()
03
Запрос к табличной части в обработке проведения — читаются старые данные прошлого проведения
04
Передача таблицы значений с сервера на клиент в управляемой форме — тип не сериализуется, используйте массив структур
05
Вызов РеквизитФормыВЗначение в цикле — резкое падение производительности формы
Контрольные точки

Как проверить результат

Количество строк в таблице значений
Норма

Совпадает с числом строк табличной части (или с ожидаемым числом при отборе)

Тревожный признак

Строк меньше без видимой причины — проверьте отбор и то, записан ли документ

Итоговые суммы
Норма

Сумма по колонке в ТЗ равна итогу табличной части

Тревожный признак

Расхождение — вероятно, читаете записанные данные вместо текущих

Обратная загрузка
Норма

После Загрузить() и Записать() документ содержит обновлённые строки

Тревожный признак

Строки не изменились — забыли Записать() или изменяли другую таблицу

FAQ

Можно ли выгрузить табличную часть, не открывая объект документа?

Да, через запрос к таблице вида Документ.ИмяДокумента.ИмяТабличнойЧасти с отбором по ссылке. Это быстрее, чем ПолучитьОбъект(), и не блокирует объект. Ограничение: запрос видит только записанные данные.

Как выгрузить табличную часть справочника?

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

Как выгрузить только строки, где количество больше нуля?

Структура отбора в Выгрузить() поддерживает только равенство. Выгрузите все строки и отберите нужные через ТЗ.НайтиСтроки() с последующим копированием, либо используйте запрос с условием ГДЕ Количество > 0.

Сохраняются ли изменения в таблице значений в документе автоматически?

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

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

Установите таблицу значений как параметр запроса и используйте конструкцию «ВЫБРАТЬ ... ПОМЕСТИТЬ ВременнаяТаблица ИЗ &ТЗ КАК ТЗ». Далее временную таблицу можно соединять с другими данными в том же запросе.

Почему в управляемой форме нет метода Выгрузить() у табличной части?

В управляемой форме табличная часть представлена типом ДанныеФормыКоллекция, у которого этого метода нет. Преобразуйте реквизит формы в объект на сервере через РеквизитФормыВЗначение("Объект") и вызывайте Выгрузить() у полученного объекта.

Итог

Что важно запомнить

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