Как программно получить значения из табличных частей любого документа в 1С

Программист IT и автоматизация бизнеса
← На главную

Разработка универсальных механизмов выгрузки данных — одна из классических задач для программиста 1С. Часто возникает необходимость создать обработку, которая «умеет» читать любой документ, независимо от его структуры, и сохранять его данные в текстовый файл, JSON или XML. Основная сложность здесь заключается не в получении реквизитов шапки (с ними все достаточно просто), а в правильном обходе табличных частей. В этой статье мы подробно разберем, как, используя метаданные, программно извлечь значения из строк любой табличной части документа.

Проблема: Метаданные против Данных

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

Алгоритм универсального обхода табличных частей

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

Разберем пример кода, который решает эту задачу:


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

Нюансы работы со стандартными реквизитами

При анализе коллекции МетаТЧ.Реквизиты мы увидим только те колонки, которые были добавлены разработчиком вручную (например, Номенклатура, Количество). Однако в табличных частях существуют и стандартные реквизиты, такие как НомерСтроки. Если ваша цель — полная выгрузка данных для последующего восстановления документа, важно не забывать и про них. Выясним причину, почему это важно: без сохранения номера строки при загрузке данных обратно порядок позиций в документе может измениться, что критично для некоторых видов учета.

Чтобы включить их в обход, можно добавить аналогичный цикл по коллекции МетаТЧ.СтандартныеРеквизиты.

Оптимизация: Использование метода Выгрузить()

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

Посмотрим на пример реализации через выгрузку:


Для Каждого МетаТЧ Из ДокОбъект.Метаданные().ТабличныеЧасти Цикл
    
    // Выгружаем ТЧ документа в независимую таблицу значений
    ТЗ = ДокОбъект[МетаТЧ.Имя].Выгрузить();
    
    // Перебираем строки ТЗ
    Для Каждого СтрокаДанных Из ТЗ Цикл
        // Работаем с колонками ТЗ
        Для Каждого Колонка Из ТЗ.Колонки Цикл
            ИмяПоля = Колонка.Имя;
            ЗначениеПоля = СтрокаДанных[ИмяПоля];
            
            // Здесь можно добавить логику обработки типов (ссылки, числа, даты)
            Сообщить("Поле: " + ИмяПоля + " = " + ЗначениеПоля);
        КонецЦикла;
    КонецЦикла;
    
КонецЦикла;

Подготовка данных для выгрузки в текст (CSV)

Если вы планируете сохранять данные в текстовый формат (как предлагал автор темы на форуме), необходимо учитывать типы данных. Простое использование функции Строка(Значение) для ссылочных типов (например, для товара) вернет лишь его наименование. При загрузке в другую базу этого будет недостаточно, так как наименования могут дублироваться или отсутствовать.

Рекомендуемые подходы для универсальной выгрузки:

  1. Использование GUID: Для ссылочных типов лучше выгружать уникальный идентификатор: Значение.УникальныйИдентификатор().
  2. Сериализация в XML/JSON: Это наиболее надежный способ. Использование СериализаторXDTO позволяет одной командой превратить весь объект со всеми его табличными частями в структурированный текст, который 1С сможет прочитать обратно с полным сохранением типов данных.
  3. Экранирование символов: Если вы используете запятую как разделитель, убедитесь, что в самих данных (например, в наименовании товара "Диван, модель А") нет этого символа, иначе структура файла "поплывет". В таких случаях значения обычно заключают в кавычки.

Использование XDTO для универсальной выгрузки

Проанализируем совет из обсуждения на форуме по поводу использования XDTO. Это действительно профессиональный стандарт. Вместо написания сложных циклов обхода метаданных, мы можем использовать встроенные механизмы платформы.


// Пример упрощенной сериализации всего документа в XML
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();

// Используем СериализаторXDTO для записи объекта
СериализаторXDTO.ЗаписатьОбъект(ЗаписьXML, ДокОбъект);

ТекстXML = ЗаписьXML.Закрыть();
Сообщить(ТекстXML); // Здесь будет весь документ со всеми ТЧ в структурированном виде

Этот метод избавляет от необходимости вручную перебирать Метаданные.ТабличныеЧасти и гарантирует, что ни один реквизит не будет упущен. Однако, если задача стоит именно в создании собственного текстового формата для самообразования или специфических нужд интеграции, то ручной обход через СтрокаТЧ[ИмяРеквизита] остается базовым и необходимым навыком для любого разработчика 1С.

Подводя итог, можно сказать, что для получения значений табличной части нам всегда нужно связывать имя реквизита, полученное из Метаданные, с коллекцией строк самого Объекта. Понимание этой связи позволяет создавать гибкие и мощные инструменты для работы с данными в системе 1С:Предприятие.

← На главную