При разработке аналитических отчетов в 1С 7.7 часто возникает задача формирования кросс-таблицы (шахматки), когда строки группируются по аналитике (контрагенты, номенклатура), а колонки динамически разворачиваются по периодам (месяцам, дням, кварталам). Разберем, какие подводные камни возникают при попытке написать универсальный разворот через стандартную ТаблицаЗначений, почему строковый поиск ломает учетные данные и какими способами эту задачу решать правильно и быстро.
Рассмотрим типовой вариант, когда результат запроса выгружается в ТаблицаЗначений, после чего в цикле формируется составной строковый ключ и выполняется поиск строк через НайтиЗначение(). Проанализируем критические уязвимости такого подхода:
ЗначениеВСтрокуВнутр().НайтиЗначение() в объекте ТаблицаЗначений выполняет линейный перебор строк. При росте объема выборки до тысяч строк алгоритм с ручным поиском приводит к полной заморозке сеанса 1С.НоваяКолонка(,"Число") без строкового идентификатора заставляет обращаться к колонкам по их номерам со сдвигом, что делает алгоритм хрупким при малейшем изменении структуры колонок.Платформа 1С 7.7 содержит оптимизированный на уровне ядра C++ метод Свернуть(), который выполняет группировку и суммирование в десятки раз быстрее ручных циклов. Разберем по шагам, как построить кросс-таблицу с его помощью:
Период_1, Период_2 или М_2026_01).Свернуть(), передавая список измерений и список колонок-периодов.Посмотрим на пример кода:
// Подготовим список измерений и список суммируемых колонок-периодов
СписГруппировок = "Покупатель,Номенклатура";
СписПериодов = "";
// Создаем колонки периодов в ТЗ
ТЗПериоды.ВыбратьСтроки();
Пока ТЗПериоды.ПолучитьСтроку() = 1 Цикл
ИмяКол = "П_" + СтрЗаменить(Строка(ТЗПериоды.Месяц), ".", "_");
ТЗ.НоваяКолонка(ИмяКол, "Число", 15, 2);
СписПериодов = СписПериодов + ?(СписПериодов = "", "", ",") + ИмяКол;
КонецЦикла;
// Переносим показатели в соответствующие колонки периодов
ТЗ.ВыбратьСтроки();
Пока ТЗ.ПолучитьСтроку() = 1 Цикл
ИмяКол = "П_" + СтрЗаменить(Строка(ТЗ.Месяц), ".", "_");
ТЗ.УстановитьЗначение(ТЗ.НомерСтроки, ИмяКол, ТЗ.ПродСтоимостьСумма);
КонецЦикла;
// Однократное платформенное сворачивание всей таблицы
ТЗ.Свернуть(СписГруппировок, СписПериодов);
Если конечной целью является вывод шахматки в печатную форму отчета (объект Таблица), создавать промежуточные таблицы значений вовсе не обязательно. Объект Запрос в 1С 7.7 умеет строить прямоугольные выборки с помощью конструкции Все ВошедшиеВЗапрос и метода прямого позиционирования Получить().
Разберем последовательность действий:
Все ВошедшиеВЗапрос.Группировка().Получить() по текущему периоду и выводим секции методом ПрисоединитьСекцию().Рассмотрим пример запроса и обхода выборки:
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|Период с (НачДата) по (КонДата);
|Покупатель = Регистр.Продажи.Покупатель;
|Номенклатура = Регистр.Продажи.Номенклатура;
|ПродСтоимость = Регистр.Продажи.ПродСтоимость;
|Функция СуммаПрод = Сумма(ПродСтоимость);
|Группировка Покупатель без групп;
|Группировка Номенклатура без групп;
|Группировка Месяц Все ВошедшиеВЗапрос;
|";
Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
Таб.ВывестиСекцию("Шапка");
// Формируем горизонтальную шапку периодов
Пока Запрос.Группировка("Месяц") = 1 Цикл
Таб.ПрисоединитьСекцию("ШапкаПериод");
КонецЦикла;
// Обход строк аналитики
Пока Запрос.Группировка("Покупатель") = 1 Цикл
Пока Запрос.Группировка("Номенклатура") = 1 Цикл
Таб.ВывестиСекцию("СтрокаАналитика");
// Вывод колонок периодов прямым позиционированием
Запрос.Группировка("Месяц", 1);
Пока Запрос.Группировка("Месяц") = 1 Цикл
// Значение ячейки доступно напрямую из запроса
Таб.ПрисоединитьСекцию("СтрокаПериод");
КонецЦикла;
КонецЦикла;
КонецЦикла;
КонецЕсли;
Когда требуется выполнять сложную обработку больших массивов данных вне запроса (например, при чтении информации из внешних файлов или Excel), стандартная ТаблицаЗначений платформы 1С 7.7 упирается в ограничения по скорости поиска. В таких задачах применяются специализированные классы и объекты:
ТаблицаЗначений. Поиск по составным ключам выполняется мгновенно (сложность O(log N) вместо O(N)).CASE WHEN или агрегатных функций, что исключает передачу лишних данных по сети и разгружает клиентскую станцию.