Как реализовать вычисляемые формулы в табличном документе 1С на основе имен колонок

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

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

Метод подстановки через структуру и функцию Вычислить()

Рассмотрим основной подход, к которому пришел автор темы. Идея заключается в том, чтобы превратить пользовательскую формулу в исполняемый код на встроенном языке 1С. Для этого нам необходимо подготовить контекст выполнения, в котором будут определены все переменные, указанные в формуле.

Представим, что пользователь ввел формулу: Колонка1 + " " + Колонка3. Чтобы платформа поняла, что такое Колонка1, мы можем использовать объект Структура. Разберем этот процесс по шагам:

  1. Создаем структуру, ключами которой будут имена колонок (например, "Колонка1", "Колонка2"), а значениями — содержимое соответствующих ячеек текущей строки.
  2. В тексте формулы производим замену слова "Колонка" на обращение к свойству этой структуры.
  3. Используем метод Вычислить() для получения результата.

Проанализируем пример кода, реализующий этот алгоритм:


// Предположим, мы обходим строки табличного документа в цикле
Для НомерСтроки = НачалоДанных По ТабличныйДокумент.ВысотаТаблицы Цикл
    
    // 1. Собираем данные текущей строки в структуру
    ЗначенияВсехКолонок = Новый Структура();
    Для ИндексКолонки = 1 По ТабличныйДокумент.ШиринаТаблицы Цикл 
        ОбластьЗначения = ТабличныйДокумент.Область(НомерСтроки, ИндексКолонки);
        ЗначениеКолонки = ОбластьЗначения.Текст; // Или .Содержимое, если нужны типизированные данные
        ЗначенияВсехКолонок.Вставить("Колонка" + ИндексКолонки, ЗначениеКолонки);
    КонецЦикла;
    
    // 2. Подготавливаем текст алгоритма
    // Допустим, ТекстАлгоритма = "Колонка1 + Колонка2"
    ИсполняемыйКод = СтрЗаменить(ТекстАлгоритма, "Колонка", "ЗначенияВсехКолонок.Колонка");
    
    // 3. Вычисляем результат
    Попытка
        Результат = Вычислить(ИсполняемыйКод);
        // Записываем результат в нужную область
        ТабличныйДокумент.Область(НомерСтроки, КолонкаРезультата).Текст = Результат;
    Исключение
        Сообщить("Ошибка в формуле в строке " + НомерСтроки);
    КонецПопытки;

КонецЦикла;

Этот метод хорош своей простотой и гибкостью. Пользователь может писать практически любой код, включая стандартные функции встроенного языка. Однако при работе с десятками тысяч строк производительность метода Вычислить() может стать узким местом, так как интерпретация строки кода — это ресурсозатратная операция. Для оптимизации сложных расчетов данных можно использовать функцию для программного расчета таблиц через СКД.

Оптимизация чтения данных: использование Построителя отчета

Когда речь идет об «огромных данных» (сотни тысяч строк), цикличный обход каждой ячейки через ТабличныйДокумент.Область() становится крайне медленным. Выясним причину: каждое обращение к области ячейки требует обращения к объектной модели документа, что создает накладные расходы.

Для ускорения процесса мы можем воспользоваться Построителем отчета. Этот объект обладает уникальной способностью быстро считывать данные из области табличного документа и преобразовывать их в Таблицу Значений. Проанализируем, как это сделать:


Построитель = Новый ПостроительОтчета;
// Указываем область, которую нужно прочитать
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабличныйДокумент.Область());
Построитель.Выполнить();

// Получаем таблицу значений с данными из ТабДока
ТЗДанных = Построитель.Результат.Выгрузить();

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

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

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

Если нам нужно «соединить» данные из табличного документа с данными из базы данных (например, получить остатки товаров, артикулы которых указаны в ТабДоке), алгоритм должен быть следующим:

  1. Считать данные из Табличного документа в Таблицу Значений (используя описанный выше ПостроительОтчета для скорости).
  2. Передать полученную Таблицу Значений в запрос в качестве параметра.
  3. В тексте запроса создать временную таблицу из этого параметра.

Пример реализации передачи данных в запрос:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_ДанныеИзДокумента ИЗ &ВнешняяТЗ КАК ВнешняяТЗ;
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |    ВТ.Колонка1 КАК НоменклатураСсылка,
    |    ТоварыНаСкладахОстатки.ВНаличииОстаток
    |ИЗ
    |    ВТ_ДанныеИзДокумента КАК ВТ
    |ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК ТоварыНаСкладахОстатки
    |ПО ВТ.Колонка1 = ТоварыНаСкладахОстатки.Номенклатура";

Запрос.УстановитьПараметр("ВнешняяТЗ", ТЗДанных);
РезультатЗапроса = Запрос.Выполнить();

Проблема памяти и производительности при больших объемах

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

Если ваша задача подразумевает обработку 500 000 строк, рекомендуется придерживаться следующей стратегии:

В завершение отметим, что решение задачи «Excel в 1С» всегда балансирует между удобством пользователя и производительностью системы. Использование структуры для подстановки контекста — отличный вариант для небольших и средних отчетов, а связка ПостроительОтчета + Запрос — необходимый инструмент для профессиональной обработки больших массивов данных.

← На главную