Разработка универсальных механизмов выгрузки данных — одна из классических задач для программиста 1С. Часто возникает необходимость создать обработку, которая «умеет» читать любой документ, независимо от его структуры, и сохранять его данные в текстовый файл, JSON или XML. Основная сложность здесь заключается не в получении реквизитов шапки (с ними все достаточно просто), а в правильном обходе табличных частей. В этой статье мы подробно разберем, как, используя метаданные, программно извлечь значения из строк любой табличной части документа.
Проанализируем типичную ошибку начинающих разработчиков. При использовании коллекции Метаданные мы получаем описание объекта: какие у него есть таблицы, как называются колонки, какой у них тип данных. Однако сами значения (например, цена конкретного товара в конкретной строке) хранятся в объекте данных (ссылке или самом объекте документа). Нам нужно научиться совмещать знание об имени реквизита из метаданных с обращением к конкретной строке документа.
Рассмотрим пошагово, как реализовать вывод значений табличной части Товары (или любой другой) для документа Реализация товаров и услуг. Нам потребуется вложенный цикл: внешний будет перебирать строки таблицы, а внутренний — колонки этой таблицы, имена которых мы возьмем из метаданных.
Разберем пример кода, который решает эту задачу:
// Предположим, ДокОбъект — это полученный объект документа (например, через Ссылка.ПолучитьОбъект())
// Проходим по всем описаниям табличных частей в метаданных документа
Для Каждого МетаТЧ Из ДокОбъект.Метаданные().ТабличныеЧасти Цикл
Сообщить("Обработка табличной части: " + МетаТЧ.Имя);
// Получаем саму таблицу данных из документа по ее имени
ТаблицаДанных = ДокОбъект[МетаТЧ.Имя];
// Перебираем строки этой табличной части
Для Каждого СтрокаТЧ Из ТаблицаДанных Цикл
СтрокаДляВывода = "";
// Теперь перебираем реквизиты (колонки) этой ТЧ, описанные в метаданных
Для Каждого МетаРеквизитТЧ Из МетаТЧ.Реквизиты Цикл
// Ключевой момент: получаем значение через индексное обращение к строке
// Имя реквизита берем из метаданных
Значение = СтрокаТЧ[МетаРеквизитТЧ.Имя];
// Формируем строку для вывода (например, через запятую)
СтрокаДляВывода = СтрокаДляВывода + Строка(Значение) + ", ";
КонецЦикла;
Сообщить(СтрокаДляВывода);
КонецЦикла;
КонецЦикла;
При анализе коллекции МетаТЧ.Реквизиты мы увидим только те колонки, которые были добавлены разработчиком вручную (например, Номенклатура, Количество). Однако в табличных частях существуют и стандартные реквизиты, такие как НомерСтроки. Если ваша цель — полная выгрузка данных для последующего восстановления документа, важно не забывать и про них. Выясним причину, почему это важно: без сохранения номера строки при загрузке данных обратно порядок позиций в документе может измениться, что критично для некоторых видов учета.
Чтобы включить их в обход, можно добавить аналогичный цикл по коллекции МетаТЧ.СтандартныеРеквизиты.
Рассмотрим более производительный способ получения данных. Вместо того чтобы обращаться к каждой ячейке через индекс во вложенном цикле, мы можем выгрузить всю табличную часть в Таблицу Значений. Это дает нам дополнительные возможности для манипуляции данными (сортировка, поиск, сворачивание).
Посмотрим на пример реализации через выгрузку:
Для Каждого МетаТЧ Из ДокОбъект.Метаданные().ТабличныеЧасти Цикл
// Выгружаем ТЧ документа в независимую таблицу значений
ТЗ = ДокОбъект[МетаТЧ.Имя].Выгрузить();
// Перебираем строки ТЗ
Для Каждого СтрокаДанных Из ТЗ Цикл
// Работаем с колонками ТЗ
Для Каждого Колонка Из ТЗ.Колонки Цикл
ИмяПоля = Колонка.Имя;
ЗначениеПоля = СтрокаДанных[ИмяПоля];
// Здесь можно добавить логику обработки типов (ссылки, числа, даты)
Сообщить("Поле: " + ИмяПоля + " = " + ЗначениеПоля);
КонецЦикла;
КонецЦикла;
КонецЦикла;
Если вы планируете сохранять данные в текстовый формат (как предлагал автор темы на форуме), необходимо учитывать типы данных. Простое использование функции Строка(Значение) для ссылочных типов (например, для товара) вернет лишь его наименование. При загрузке в другую базу этого будет недостаточно, так как наименования могут дублироваться или отсутствовать.
Рекомендуемые подходы для универсальной выгрузки:
Значение.УникальныйИдентификатор().СериализаторXDTO позволяет одной командой превратить весь объект со всеми его табличными частями в структурированный текст, который 1С сможет прочитать обратно с полным сохранением типов данных.Проанализируем совет из обсуждения на форуме по поводу использования XDTO. Это действительно профессиональный стандарт. Вместо написания сложных циклов обхода метаданных, мы можем использовать встроенные механизмы платформы.
// Пример упрощенной сериализации всего документа в XML
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
// Используем СериализаторXDTO для записи объекта
СериализаторXDTO.ЗаписатьОбъект(ЗаписьXML, ДокОбъект);
ТекстXML = ЗаписьXML.Закрыть();
Сообщить(ТекстXML); // Здесь будет весь документ со всеми ТЧ в структурированном виде
Этот метод избавляет от необходимости вручную перебирать Метаданные.ТабличныеЧасти и гарантирует, что ни один реквизит не будет упущен. Однако, если задача стоит именно в создании собственного текстового формата для самообразования или специфических нужд интеграции, то ручной обход через СтрокаТЧ[ИмяРеквизита] остается базовым и необходимым навыком для любого разработчика 1С.
Подводя итог, можно сказать, что для получения значений табличной части нам всегда нужно связывать имя реквизита, полученное из Метаданные, с коллекцией строк самого Объекта. Понимание этой связи позволяет создавать гибкие и мощные инструменты для работы с данными в системе 1С:Предприятие.