При разработке отчетов в Системе компоновки данных (СКД) на платформе 1С:Предприятие часто возникает задача программного управления визуальными свойствами диаграмм. Одной из наиболее популярных подзадач является динамическое определение минимального и максимального значений на оси значений диаграммы. Например, когда автоматическое масштабирование платформы делает мелкие колебания показателей визуально огромными или, наоборот, когда нужно жестко зафиксировать шкалу под бизнес-требования пользователя.
В этой статье мы подробно разберем, как пробиться сквозь сложную структуру настроек компоновки данных до параметров диаграммы, рассмотрим подводные камни стандартного подхода и предложим два альтернативных решения этой задачи: классический способ через модификацию схемы компоновки и более элегантный способ через постобработку готового табличного документа.
Прежде всего, проанализируем, где именно СКД хранит настройки диаграммы. В отличие от простых группировок или таблиц, параметры диаграммы находятся на более глубоком уровне иерархии объектов компоновки. Если мы обратимся к компоновщику настроек, то увидим, что диаграмма является элементом структуры отчета.
Многие разработчики совершают типичную ошибку, пытаясь обратиться к параметрам диаграммы напрямую через индекс, например: КомпоновщикНастроек.Настройки.Структура[0]. Настоятельно рекомендуем избегать подобного подхода в реальных задачах. Если пользователь в режиме предприятия изменит структуру отчета, добавит заголовок, другую таблицу или группировку выше диаграммы, индекс изменится. Это неминуемо приведет к ошибке выполнения кода или к тому, что настройки применятся не к тому объекту.
Давайте выясним, как правильно и безопасно найти элемент структуры настроек, отвечающий за диаграмму, и программно переопределить свойства её оси значений.
Рассмотрим пошагово первый способ. Нам потребуется обратиться к структуре настроек компоновки, найти нужную диаграмму, извлечь из её параметров вывода вложенные параметры оси значений и задать необходимые ограничения.
Для начала напишем функцию безопасного рекурсивного поиска диаграммы в структуре отчета, чтобы не зависеть от жестких индексов:
Функция НайтиВсеДиаграммы(КоллекцияЭлементов) Экспорт
МассивДиаграмм = Новый Массив;
Для Каждого Элемент Из КоллекцияЭлементов Цикл
Если ТипЗнч(Элемент) = Тип("ДиаграммаКомпоновкиДанных") Тогда
МассивДиаграмм.Добавить(Элемент);
КонецЕсли;
// Рекурсивно проверяем вложенные элементы структуры, если они есть
Если ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойство(Элемент, "Структура") Тогда
ВложенныеДиаграммы = НайтиВсеДиаграммы(Элемент.Структура);
Для Каждого Вложенная Из ВложенныеДиаграммы Цикл
МассивДиаграмм.Добавить(Вложенная);
КонецЦикла;
КонецЕсли;
КонецЦикла;
Возврат МассивДиаграмм;
КонецФункции
Теперь, когда у нас есть инструмент для безопасного поиска диаграмм, перейдем непосредственно к модификации параметров оси в модуле объекта отчета. Нам нужно переопределить обработчик события ПриКомпоновкеРезультата.
Обратите внимание на важный нюанс современных версий платформы "1С:Предприятие" (начиная с 8.3.13): свойства АвтоМаксимальноеЗначение и АвтоМинимальноеЗначение устарели. Вместо них следует использовать перечисление СпособОпределенияОграничивающегоЗначенияДиаграммы со значением ИспользоватьЗначение. Если этого не сделать, платформа проигнорирует ваши числовые настройки и продолжит рассчитывать масштаб автоматически.
Проанализируем пример кода программной настройки оси значений диаграммы:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
СхемаКомпоновкиДанных = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
// Безопасный поиск всех диаграмм в структуре текущих настроек
МассивДиаграмм = НайтиВсеДиаграммы(Настройки.Структура);
Если МассивДиаграмм.Количество() > 0 Тогда
// Берем первую найденную диаграмму для настройки
ДиаграммаСКД = МассивДиаграмм[0];
// Переходим к поиску параметра "Тип диаграммы"
ПараметрТипДиаграммы = ДиаграммаСКД.ПараметрыВывода.НайтиПараметр(Новый ПараметрКомпоновкиДанных("ТипДиаграммы"));
Если ПараметрТипДиаграммы <> Неопределено Тогда
ВложенныеПараметры = ПараметрТипДиаграммы.ЗначенияВложенныхПараметров;
ОсьЗначений = ВложенныеПараметры.Найти("ТипДиаграммы.ОсьЗначений");
Если ОсьЗначений <> Неопределено Тогда
// Задаем числовые границы оси (например, рассчитываем их на основе параметров отчета)
ОсьЗначений.Значение.МинимальноеЗначение = 60;
ОсьЗначений.Значение.МаксимальноеЗначение = 90;
// Обязательно отключаем автоопределение границ оси
ОсьЗначений.Значение.СпособОпределенияМинимальногоЗначения = СпособОпределенияОграничивающегоЗначенияДиаграммы.ИспользоватьЗначение;
ОсьЗначений.Значение.СпособОпределенияМаксимальногоЗначения = СпособОпределенияОграничивающегоЗначенияДиаграммы.ИспользоватьЗначение;
КонецЕсли;
КонецЕсли;
КонецЕсли;
// Стандартный процесс вывода отчета с измененными настройками
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки);
ДокументРезультат.Очистить();
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
КонецПроцедуры
Этот способ является методологически самым верным с точки зрения архитектуры СКД. Мы меняем настройки до момента генерации макета и вывода результата, поэтому система строит отчет сразу с нужными параметрами. Для упрощения работы с объектной моделью и сокращения кода компоновки можно использовать общий модуль-обёртку для программного создания и настройки СКД.
Разберем теперь альтернативный подход, который зачастую оказывается гораздо проще в реализации и поддержке. Вместо того чтобы пробиваться через глубоко вложенные XML-подобные структуры параметров вывода СКД, мы можем позволить платформе стандартно сформировать отчет.
В тот момент, когда отчет уже выведен в результирующий ТабличныйДокумент, диаграмма превращается в обычный объект рисования на листе. Мы можем легко перебрать коллекцию рисунков табличного документа, найти объект диаграммы и напрямую изменить свойства его шкалы.
Посмотрим на пример реализации данного метода:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// 1. Позволяем платформе сформировать отчет стандартным образом
// (Или выполняем программный вывод, если это необходимо для других задач)
// 2. После того как документ сформирован, выполняем обход коллекции рисунков
Для Каждого Рисунок Из ДокументРезультат.Рисунки Цикл
// Проверяем, является ли рисунок диаграммой
Если Рисунок.ТипРисунка = ТипРисункаТабличногоДокумента.Диаграмма Тогда
// Получаем непосредственный объект "Диаграмма"
ДиаграммаОбъект = Рисунок.Объект;
// Настраиваем шкалу оси значений напрямую
Шкала = ДиаграммаОбъект.ОсьЗначений;
Шкала.МинимальноеЗначение = 60;
Шкала.МаксимальноеЗначение = 90;
// Отключаем автоматический расчет масштаба
Шкала.СпособОпределенияМинимальногоЗначения = СпособОпределенияОграничивающегоЗначенияДиаграммы.ИспользоватьЗначение;
Шкала.СпособОпределенияМаксимальногоЗначения = СпособОпределенияОграничивающегоЗначенияДиаграммы.ИспользоватьЗначение;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Выясним преимущества и недостатки каждого из предложенных вариантов, чтобы вы могли сделать осознанный выбор для своего проекта:
Рекомендуем использовать первый способ в тиражных решениях и сложных отчетах, где важна чистота архитектуры СКД и корректная работа с пользовательскими вариантами отчетов. Второй способ отлично подойдет для простых внутренних отчетов предприятия, когда задачу нужно решить быстро, надежно и с минимальными затратами времени на написание кода.