При работе с отчетами, формируемыми Системой Компоновки Данных (СКД) в 1С, мы часто сталкиваемся с проблемой избыточно большого заголовка. Этот заголовок может включать в себя название отчета, период формирования, детализированные параметры отбора, информацию об организации и другие общие данные. В некоторых случаях такой объемный заголовок занимает значительную часть первого экрана, вынуждая пользователя постоянно прокручивать отчет вниз, чтобы увидеть основную информацию. Это ухудшает юзабилити и снижает оперативность работы с отчетом.
Для решения этой проблемы возникает необходимость обеспечить возможность сворачивания или группировки заголовка. Цель состоит в том, чтобы предоставить пользователю интерактивный механизм, позволяющий в любой момент скрыть или показать детали заголовка, тем самым освобождая полезное пространство экрана и делая отчет более компактным. Давайте рассмотрим два основных подхода к реализации этой функциональности в 1С:СКД, выделив их преимущества и особенности.
Наиболее надежный и проверенный на практике способ, который успешно применил автор исходного вопроса, заключается в манипулировании табличным документом уже после того, как он сформирован и отображен на форме отчета. Этот подход позволяет создать стандартные интерактивные маркеры группировки («плюсики» и «минусики»), которые пользователи привыкли видеть в табличных документах 1С.
Для того чтобы получить полный контроль над отображением отчета и иметь возможность программно воздействовать на него, нам потребуется собственная форма отчета. Если ваш отчет СКД использует стандартную форму, вы можете ее скопировать в конфигурации и модифицировать. Если у отчета уже есть своя форма, просто откройте ее в конфигураторе и перейдите в модуль формы.
Почему это важно: Работа с формой позволяет нам взаимодействовать с элементом управления ПолеТабличногоДокумента (который обычно содержит результат отчета) и вызывать для него специфические методы, доступные только после полной отрисовки документа.
Ключевым аспектом этого подхода является выбор правильного момента для вызова метода группировки. Операция должна быть выполнена после того, как:
ТабличныйДокумент) выведен в элемент формы типа ПолеТабличногоДокумента.Как правило, мы можем разместить код в обработчике события, которое срабатывает после формирования или отображения отчета. Например, это может быть процедура, вызываемая после нажатия кнопки «Сформировать», или в процедуре ПриОткрытии формы, если отчет формируется сразу при открытии.
Следующий критически важный шаг — это точное определение диапазона строк, которые составляют ваш заголовок и которые мы хотим сгруппировать. Заголовок может включать в себя несколько элементов: название отчета, параметры отбора, информацию о периоде, данные о компании и т.д.
Рассмотрим несколько способов идентификации этой области:
"R2:R11", как было сделано в решении из темы.
Важно: Этот метод менее гибок. Если в будущем структура заголовка изменится (например, добавятся новые параметры), вам придется корректировать код.
ТабличныйДокумент.Найти() или перебирать строки табличного документа, анализируя их содержимое.
Пример логики поиска:
// Предположим, что ОтчетТабличныйДокумент - это наш элемент формы
НачальнаяСтрокаЗаголовка = 1; // Обычно отчеты начинаются с первой строки
КонечнаяСтрокаЗаголовка = 0;
// Пример: Ищем первую строку с данными, чтобы определить конец заголовка
// Это очень условный пример, так как универсального способа определить "начало данных" нет.
// Возможно, есть строка-разделитель или всегда есть пустая строка перед данными.
Для НомерСтроки = ОтчетТабличныйДокумент.ФиксацияСверху По ОтчетТабличныйДокумент.ВысотаТаблицы Цикл
ОбластьЯчеек = ОтчетТабличныйДокумент.Область("R" + НомерСтроки);
Если ОбластьЯчеек.Уровень = 0 И ОбластьЯчеек.Параметр = Неопределено Тогда
// Это очень грубая эвристика: если у строки нет уровня группировки (0)
// и она не является строкой параметра СКД, то это может быть началом данных.
// В реальных отчетах нужно более точное определение, возможно, по содержимому.
Если ОбластьЯчеек.Текст <> "" И ОбластьЯчеек.Область(НомерСтроки, 1, НомерСтроки, ОтчетТабличныйДокумент.ШиринаТаблицы).Текст <> "" Тогда
КонечнаяСтрокаЗаголовка = НомерСтроки - 1; // Заголовок заканчивается перед этой строкой
Прервать;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если КонечнаяСтрокаЗаголовка = 0 Тогда
// Если не нашли конец данных, то, возможно, весь отчет - это заголовок
// или же данных нет. Или же это первая строка отчета
КонечнаяСтрокаЗаголовка = ОтчетТабличныйДокумент.ВысотаТаблицы;
КонецЕсли;
Если НачальнаяСтрокаЗаголовка <= КонечнаяСтрокаЗаголовка Тогда
ДиапазонЗаголовка = "R" + НачальнаяСтрокаЗаголовка + ":R" + КонечнаяСтрокаЗаголовка;
// ... далее вызов Сгруппировать
КонецЕсли;
Обратите внимание: Для точного определения конца заголовка вам потребуется провести анализ структуры вашего конкретного отчета.
ДокументРезультат.НайтиОбласть("ИмяОбласти") и использовать их для группировки.Сгруппировать()
После того как мы определили нужную область, мы вызываем для нее метод Сгруппировать(). Это действие добавит к этой области интерактивные маркеры группировки.
// Предположим, что "ОтчетТабличныйДокумент" - это имя элемента формы типа "ПолеТабличногоДокумента"
// или переменная, содержащая ссылку на табличный документ.
// Этот код размещаем в модуле формы отчета, например, после вызова процедуры,
// которая формирует отчет и выводит его в ТабличныйДокумент.
// Пример вызова после формирования отчета:
// ОтчетОбъект.СкомпоноватьРезультат(ОтчетТабличныйДокумент, ДанныеРасшифровки);
// Или после других действий, которые заполняют ОтчетТабличныйДокумент.
Если ОтчетТабличныйДокумент.ВысотаТаблицы > 0 Тогда // Убедимся, что документ не пуст
// В данном примере используем фиксированный диапазон, как в оригинальном решении.
// В реальном проекте, используйте динамическое определение диапазона.
ОтчетТабличныйДокумент.Область("R2:R11").Сгруппировать();
// Если мы хотим, чтобы заголовок был свернут по умолчанию сразу после открытия отчета:
// Используем ПоказатьУровеньГруппировокСтрок. Уровень 0 обычно означает полное сворачивание,
// уровень 1 – показ только первого уровня группировок (свернутые заголовки).
// Точное значение может зависеть от внутренней структуры отчета.
// Если сгруппировали только заголовок, то уровень 1 или 0 будет работать как "показать/скрыть" его.
// ОтчетТабличныйДокумент.ПоказатьУровеньГруппировокСтрок(1);
КонецЕсли;
После выполнения этого кода пользователи увидят рядом со строками 2-11 стандартный маркер со знаком "минус" (или "плюс", если уже свернуто), позволяющий им свернуть или развернуть эту область.
Преимущества этого подхода:
Процедура ПриКомпоновкеРезультата, расположенная в модуле объекта отчета, вызывается платформой непосредственно в процессе формирования отчета, перед тем как скомпонованный табличный документ будет окончательно передан для отображения. В этой процедуре мы получаем прямой доступ к объекту ДокументРезультат, который представляет собой "сырой" табличный документ.
ДокументРезультат
Процедура ПриКомпоновкеРезультата имеет следующую сигнатуру:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Здесь мы можем выполнять манипуляции с ДокументРезультат
КонецПроцедуры
ДокументРезультат — это объект типа ТабличныйДокумент, который мы можем изменять.
СтандартнаяОбработка = Ложь;
Если мы собираемся вносить существенные изменения в ДокументРезультат, которые должны быть сохранены и учтены при последующем выводе, нам почти всегда потребуется установить параметр СтандартнаяОбработка в значение Ложь. Это очень важный момент, так как без этого платформа может проигнорировать или перезаписать наши изменения после завершения процедуры ПриКомпоновкеРезультата, применяя свои стандартные механизмы вывода СКД.
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь; // Устанавливаем, чтобы взять контроль на себя
// ... далее код для работы с ДокументРезультат
// ... и возможно, ручной вызов вывода результата
КонецПроцедуры
В этой процедуре можно попробовать различные подходы, но важно понимать их ограничения в контексте интерактивного сворачивания заголовка:
ДокументРезультат.ПоказатьУровеньГруппировокСтрок(0);:
Метод ПоказатьУровеньГруппировокСтрок(0), предложенный в одном из сообщений, действительно позволяет управлять видимостью уровней группировок. Однако он воздействует на все группировки в отчете, сворачивая их до определенного уровня. Как было верно отмечено, этот метод предназначен для управления стандартными иерархическими группировками данных в отчете, а не для создания интерактивного маркера сворачивания для произвольной, несвязанной с данными области заголовка. Если ваш заголовок не является частью иерархической группировки данных СКД, то этот метод не создаст желаемые кнопки +/- для заголовка.
Сгруппировать():
Возникает естественный вопрос: можно ли применить метод Сгруппировать() к области ДокументРезультат прямо здесь? Опыт показывает, что это не приведет к появлению интерактивных кнопок сворачивания/разворачивания на форме отчета (как указано в сообщении 8). Это связано с тем, что ПриКомпоновкеРезультата работает с объектом ТабличныйДокумент до его фактического вывода на форму как элемент управления ПолеТабличногоДокумента. Интерактивная функциональность группировки добавляется на этапе отрисовки элемента формы.
Несмотря на ограничения в создании интерактивной группировки, ПриКомпоновкеРезультата является мощным инструментом для:
Уровень, то теоретически сможем управлять их видимостью с помощью ПоказатьУровеньГруппировокСтрок, но опять же, без интерактивных кнопок для этой конкретной области.Пример кода из сообщения 9 демонстрирует возможность манипуляции с содержимым и структурой ДокументРезультат (очистка или удаление строк), что подтверждает широкие возможности этой процедуры, но не для интерактивного сворачивания заголовка:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Устанавливаем СтандартнаяОбработка = Ложь, чтобы полностью контролировать вывод
// В реальном коде, после этого нужно самостоятельно вызвать вывод результата на форму.
СтандартнаяОбработка = Ложь;
// Пример: поиск и очистка определенных строк заголовка
// Предположим, что мы ищем строки, содержащие "лишнюю" информацию в заголовке
Для счСтрок = ДокументРезультат.ФиксацияСверху По ДокументРезультат.ВысотаТаблицы Цикл
// Пример: если в первой колонке находится текст "УдалитьЗаголовокДеталей"
Если ДокументРезультат.Область(счСтрок, 1).Текст = "УдалитьЗаголовокДеталей" Тогда
// Мы можем удалить эту строку
ДокументРезультат.УдалитьОбласть(ДокументРезультат.Область("R" + счСтрок), ТипСмещенияТабличногоДокумента.ПоГоризонтали);
счСтрок = счСтрок - 1; // Корректируем счетчик после удаления строки
Продолжить;
КонецЕсли;
// Другие варианты модификации, например, очистка области
Если ДокументРезультат.Область(счСтрок, 1).Текст = "ОчиститьЭтотБлок" Тогда
// Очищаем область от текста, но оставляем строки
ДокументРезультат.Область(счСтрок,1,счСтрок,ДокументРезультат.ШиринаТаблицы).Очистить(Истина,Ложь,Ложь);
КонецЕсли;
КонецЦикла;
// После всех манипуляций, если СтандартнаяОбработка = Ложь,
// необходимо самостоятельно вывести измененный ДокументРезультат на форму.
// Например, через метод объекта отчета, если он поддерживает вывод:
// ЭтотОбъект.ВывестиРезультат(ДокументРезультат, ДанныеРасшифровки);
// Или передать его дальше в пользовательскую функцию вывода, как в сообщении 12:
// КФ_Сервер.СКДПриКомпоновкеРезультата(ЭтотОбъект, ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка, ОриентацияСтраницы.Портрет);
КонецПроцедуры
Таким образом, хотя процедура ПриКомпоновкеРезультата дает огромные возможности для тонкой настройки содержимого табличного документа, для создания интерактивных элементов сворачивания/разворачивания конкретной области заголовка она является менее подходящей. Для этой задачи мы настоятельно рекомендуем использовать подход, описанный в первом разделе, с работой в модуле формы отчета.
Независимо от выбранного подхода, существуют общие рекомендации, которые помогут вам достичь наилучшего результата:
Всегда стремитесь к динамическому определению границ заголовка, а не к жестко заданным номерам строк. Это значительно повысит устойчивость вашего решения к изменениям в макете отчета или добавлению новых параметров. Как мы обсуждали, используйте поиск по уникальному тексту, по именам областей макета СКД или по другим характерным признакам строк заголовка.
После реализации функциональности группировки обязательно проведите всестороннее тестирование. Сформируйте отчет с различными комбинациями параметров, с большим и малым количеством данных, чтобы убедиться, что заголовок всегда корректно определяется и группируется, не затрагивая основные данные отчета и не вызывая ошибок.
Цель группировки — улучшить удобство работы пользователя. Убедитесь, что механизм сворачивания и разворачивания заголовка интуитивно понятен. Возможно, стоит предусмотреть, чтобы по умолчанию заголовок был свернут, если он действительно большой (это можно сделать с помощью ОтчетТабличныйДокумент.ПоказатьУровеньГруппировокСтрок(1) после вызова Сгруппировать(), где 1 — уровень, до которого останутся видимыми группы). Для заголовка без внутренних группировок, уровень 1 будет означать "свернут", а уровень 0 — "развернут" (или наоборот, в зависимости от контекста).
Если отчет очень большой и имеет сложную структуру, чрезмерные программные манипуляции с каждой строкой в цикле (особенно в ПриКомпоновкеРезультата без оптимизации) могут негативно сказаться на производительности формирования отчета. Старайтесь оптимизировать алгоритмы поиска и обработки областей.
Любые доработки в коде, особенно связанные с созданием собственных форм или перехватом стандартной логики компоновки, требуют внимания при обновлении платформы или конфигурации. Будьте готовы к тому, что при изменениях в типовых механизмах могут потребоваться адаптации вашего кода.
В итоге, для достижения интерактивного сворачивания заголовка отчета в 1С:СКД наиболее эффективным и рекомендуемым методом является программное применение метода Сгруппировать() к нужной области элемента ПолеТабличногоДокумента, расположенного на форме отчета, после того как отчет уже сформирован и отображен. Этот подход обеспечивает наилучший пользовательский опыт и является относительно простым в реализации.