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