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

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

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

Метод 1: Выгрузка всей таблицы с последующим удалением лишних колонок

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

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


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

// 2. Обходим колонки с конца к началу, чтобы не сбить индексы при удалении
КоличествоКолонок = ТЗ.Колонки.Количество();
Для Индекс = 1 По КоличествоКолонок Цикл
    НомерКолонки = КоличествоКолонок - Индекс;
    ТекущаяКолонка = ТЗ.Колонки[НомерКолонки];
    
    // Проверяем итог по колонке. Метод Итог() работает быстро
    Попытка
        Если ТЗ.Итог(ТекущаяКолонка.Имя) <= 0 Тогда
            ТЗ.Колонки.Удалить(ТекущаяКолонка);
        КонецЕсли;
    Исключение
        // Если колонка не числовая, метод Итог() вызовет исключение
        // В этом случае решаем: оставить колонку или удалить
        ТЗ.Колонки.Удалить(ТекущаяКолонка);
    КонецПопытки;
КонецЦикла;

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

Метод 2: Формирование новой таблицы по условию

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

Разберем, как это сделать по шагам:

  1. Создаем пустую ТаблицаЗначений.
  2. В цикле обходим колонки исходной табличной части.
  3. Вычисляем сумму значений в каждой колонке.
  4. Если сумма больше нуля — добавляем колонку в новую ТЗ и заполняем ее данными.

Для заполнения данных можно использовать метод ВыгрузитьКолонку() и ЗагрузитьКолонку(). Проанализируем пример кода:


НоваяТЗ = Новый ТаблицаЗначений;
ИсходнаяТЗ = Объект.ИмяТабличнойЧасти.Выгрузить();

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

Проблема именования колонок: из Excel в 1С

Часто в Excel заголовки содержат пробелы, спецсимволы или начинаются с цифр (например, "2023 год" или "Сумма (руб.)"). Платформа 1С предъявляет строгие требования к свойству Имя колонки таблицы значений — оно должно быть идентификатором. Это значит: никаких пробелов, знаков препинания (кроме подчеркивания) и начинаться должно с буквы или подчеркивания.

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


Функция ПолучитьКорректноеИмяКолонки(Знач ЗаголовокИзЭксель)
    // Убираем лишние пробелы по краям
    Результат = СокрЛП(ЗаголовокИзЭксель);
    
    // Заменяем пробелы и дефисы на подчеркивания
    Результат = СтрЗаменить(Результат, " ", "_");
    Результат = СтрЗаменить(Результат, "-", "_");
    
    // Удаляем все недопустимые символы (упрощенно)
    ДопустимыеСимволы = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZабвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ0123456789_";
    ОчищеннаяСтрока = "";
    Для Поз = 1 По СтрДлина(Результат) Цикл
        Символ = Сред(Результат, Поз, 1);
        Если Найти(ДопустимыеСимволы, Символ) > 0 Тогда
            ОчищеннаяСтрока = ОчищеннаяСтрока + Символ;
        КонецЕсли;
    КонецЦикла;
    
    // Проверка на первый символ (не может быть цифрой)
    ПервыйСимвол = Лев(ОчищеннаяСтрока, 1);
    Если Найти("0123456789", ПервыйСимвол) > 0 Тогда
        ОчищеннаяСтрока = "п_" + ОчищеннаяСтрока;
    КонецЕсли;
    
    Возврат ОчищеннаяСтрока;
КонецФункции

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

Типизация данных при загрузке из Excel

Проанализируем еще одну проблему: Excel часто передает числа как строки или значения с плавающей запятой, которые 1С может интерпретировать неоднозначно. Чтобы метод Итог() не выдавал ошибку, при создании колонок в ТаблицаЗначений настоятельно рекомендуется явно указывать описание типов.

Посмотрим на пример правильного создания колонки:


МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("Число"));
КвалификаторыЧисла = Новый КвалификаторыЧисла(15, 2);
ОписаниеТипаЧисло = Новый ОписаниеТипов(МассивТипов, , , КвалификаторыЧисла);

ТЗ.Колонки.Добавить(ИмяИдентификатор, ОписаниеТипаЧисло, ОригинальныйЗаголовок);

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

Оптимизация при больших объемах данных

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

Разберем схему такого решения:

  1. Текст запроса формируется динамически (через СтрШаблон или конкатенацию), где перечисляются все колонки: СУММА(Колонка1) КАК К1, СУММА(Колонка2) КАК К2....
  2. Запрос выполняется к таблице значений.
  3. Из результата запроса (одна строка) считываются значения.
  4. Если значение в результате запроса равно 0, колонка удаляется из исходной ТЗ.

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

Таким образом, мы рассмотрели несколько стратегий фильтрации колонок. Выбор конкретного метода зависит от объема данных и необходимости сохранения исходной структуры. Главное — помнить про обратный порядок удаления и обязательную проверку имен на соответствие правилам идентификаторов 1С.

← На главную