Как программно обойти заполненные колонки в строке таблицы значений документа

Программист 1С v8.3 (Управляемые формы) Управленческий учет Торговля и дистрибуция
← На главную

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

В этой статье мы подробно разберем, как эффективно решить эту задачу, начиная от простого перебора строк и заканчивая профессиональными методами работы с метаданными и запросами.

Способ 1: Использование вложенного цикла по коллекции колонок

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

Разберем пример кода, который позволяет вывести информацию о заполненных колонках в окно сообщений:


// Сначала выгружаем табличную часть документа в таблицу значений
ТаблЗначений = Объект.ПланПродаж.Выгрузить();

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

Важный нюанс: при работе с числовыми данными (планами) функция ЗначениеЗаполнено() возвращает Ложь для значения 0. Если в вашей логике нулевой план — это тоже важная информация, лучше использовать прямое сравнение ТекущееЗначение <> 0 или проверку на тип данных.

Способ 2: Универсальный обход через метаданные объекта

Проанализируем ситуацию, когда нам нужно обрабатывать не все колонки подряд, а только те, которые отвечают за «дни» (например, «День1», «День2» и т.д.). Хардкодить имена колонок — плохая практика. Вместо этого мы можем использовать объектную модель метаданных.

Давайте выясним, как программно отобрать нужные реквизиты табличной части:


// Получаем доступ к метаданным табличной части документа
МетаданныеТЧ = Метаданные.Документы.ПланПродаж.ТабличныеЧасти.СоставПлана;

Для Каждого СтрокаДокумента Из Объект.СоставПлана Цикл
    
    // Перебираем только те реквизиты, которые описаны в конфигураторе для этой ТЧ
    Для Каждого РеквизитТЧ Из МетаданныеТЧ.Реквизиты Цикл
        
        // Проверяем имя реквизита на соответствие шаблону (например, начинается на "День")
        Если Найти(РеквизитТЧ.Имя, "День") > 0 Тогда
            
            ЗначениеДня = СтрокаДокумента[РеквизитТЧ.Имя];
            
            Если ЗначениеДня > 0 Тогда
                // Здесь логика добавления точки на график
                ОбработатьДанныеДляГрафика(СтрокаДокумента.Сотрудник, РеквизитТЧ.Имя, ЗначениеДня);
            КонецЕсли;
            
        КонецЕсли;
        
    КонецЦикла;
    
КонецЦикла;

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

Способ 3: Трансформация данных через запрос (UNPIVOT на языке 1С)

Если ваша конечная цель — построение графика или диаграммы, то наиболее эффективным методом будет перевод «горизонтальных» данных в «вертикальные» еще на этапе получения данных из базы. В языке запросов 1С нет оператора UNPIVOT, но мы можем реализовать его через ОБЪЕДИНИТЬ ВСЕ.

Посмотрим на пример структуры такого запроса. Это позволит избежать сложных циклов в коде 1С:Предприятие и сразу получить готовую таблицу для серии графика:


ВЫБРАТЬ
    ПланПродаж.Сотрудник КАК Сотрудник,
    "День 1" КАК ПериодДень,
    ПланПродаж.День1 КАК Значение
ИЗ
    Документ.ПланПродаж.СоставПлана КАК ПланПродаж
ГДЕ
    ПланПродаж.Ссылка = &Ссылка И ПланПродаж.День1 > 0

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    ПланПродаж.Сотрудник,
    "День 2",
    ПланПродаж.День2
ИЗ
    Документ.ПланПродаж.СоставПлана КАК ПланПродаж
ГДЕ
    ПланПродаж.Ссылка = &Ссылка И ПланПродаж.День2 > 0

Преимущества этого подхода:

  1. Скорость: Платформа оптимизирует выполнение запросов на уровне СУБД.
  2. Готовые данные: Результат запроса можно сразу передать в объект Диаграмма или использовать как источник данных для системы компоновки данных (СКД).
  3. Фильтрация: Мы отсекаем пустые значения прямо в условии ГДЕ, не нагружая память сервера лишними данными.

Способ 4: Оптимизация работы с Таблицей Значений (ТЗ)

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


// Создаем структуру отбора
ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("Сотрудник", ВыбранныйСотрудник);

// Получаем массив только нужных строк
НайденныеСтроки = ТаблЗначений.НайтиСтроки(ПараметрыОтбора);

Для Каждого Строка Из НайденныеСтроки Цикл
    // Обход колонок выполняется только для целевого сотрудника
    Для Каждого Колонка Из ТаблЗначений.Колонки Цикл
        // Логика обработки...
    КонецЦикла;
КонецЦикла;

Подготовка данных для объекта «Диаграмма»

При построении графиков важно помнить о терминологии 1С. Точка диаграммы — это обычно ваше измерение времени (в данном случае — день, который мы вытянули из названия колонки). Серия — это разрез данных (например, «План» или «Факт»).

Проанализируем процесс заполнения программно созданной диаграммы:

  1. Очищаем диаграмму методом Диаграмма.Очистить().
  2. Устанавливаем количество серий (например, одна серия «План продаж»).
  3. В цикле обхода колонок (который мы разобрали выше) добавляем точки.
  4. Используем метод Диаграмма.УстановитьЗначение(Точка, Серия, Значение) для отрисовки графика.

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

← На главную