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