Недавно пришлось в рамках одного отчета строить довольно большое количество диаграмм, в итоге я пришел к универсальному механизму формирования диаграммы на основе таблицы значений.
Суть проблемы заключается в том, что формирование диаграммы происходит в своего рода процедуре обратного вызова. Когда в одном отчете диаграмм может быть множество всяких разных, то эта самая процедура может весьма "разбухнуть", да и с получением данных могут возникнуть проблемы. К счастью, в 1С: Предприятии есть объект ТаблицаЗначений, который нас в данном случае и выручит, ведь большинство видов диаграмм строится на основе табличных данных.
В 1С при построении диаграмм используются такие термины, как "серии" и "точки". Понятие серии в данном случае совпадает с "рядом данных" в Excel, ну а "точки" - это, скажем так, значения оси Х, или просто "значения" в терминах Excel. Так вот, чтобы механизм был более-менее универсальным, условимся, что таблица значений имеет следующую структуру: первая колонка - наименование серии, последующие колонки - это значения точек, причем заголовок колонки и будет являться наименованием точки. Ну а для заполнения таблицы значений существует множество методов, например, для реализации неких алгоритмов в цикле хорошо использовать метод УстановитьЗначение(<Строка>,<Колонка>,<Знач>). Однако формирование таблицы значений мы в рамках данной статьи оставим все же за кадром и сосредоточимся на выводе диаграммы. Допустим также, что перед диаграммой необходимо выводить таблицу, по которой эта самая диаграмма построена.
Начнем с "рисования" макета. Укажем ячейки с основным и дополнительным заголовками диаграммы (пусть для определенности это будут выражения ЗаголовокДиаграммы и ЗагДополн) и нарисуем таблицу из 4х ячеек. В первой ячейке можно написать, например, "Серия / Точка", во 2-м столбце первой строки - выражение НаименованиеТочки, во 2-й строке 1-го столбца - выражение НаименованиеСерии, и, наконец, в последней ячейке - выражение Значение. Определим горизонтальные секции: "Шапка", куда войдут заголовки и первая строка таблицы, и "Серия" - вторая строка таблицы. Определим вертикальные секции - "Боковик", куда войдет 1-й столбец таблицы, и "Точка", содержащая второй столбец таблицы.
Вставим в макет диаграмму. По умолчанию вставляется гистограмма с легендой, что лично меня устраивает, но, разумеется, можно выбрать и другое представление, а также поднастроить внешний вид. Заключим диаграмму в горизонтальную секцию "Гистограмма". В свойствах диаграммы (имеется в виду 1С-ное диалоговое окно "Свойства рисунка", а не всякого рода настройки диаграммы как OLE-объекта) на закладке текст в поле ввода введем:
Code
СформироватьДиаграмму(Таб.ТекущийОбъект, Параметры)
Т.е. вызываем процедуру, которая будет непосредственно рисовать диаграмму. Второй параметр ("Параметры") как раз и будет представлять собой таблицу значений.
Примерный вид макета приведен на рисунке:
Что ж, переходим к коду. Первым делом напишем процедуру обратного вызова СформироватьДиаграмму. В ней мы в соответствии с размером таблицы значений устанавливаем количество серий и точек, и в цикле по строкам и столбцам таблицы значений заполняем диаграмму, учитывая, что в первой колонке таблицы значений содержится наименование серии, а наименование точки необходимо получить из заголовка колонки. Используем следующие методы объекта Диаграмма:
- КоличествоСерий - устанавливаем количество серий;
- КоличествоТочек - устанавливаем количество точек;
- УстановитьИмяСерии - назначаем имя серии;
- УстановитьИмяТочки - аналогично;
- УстановитьЗначение - основной метод, собственно говоря, указываем, какое значение соответствует комбинации серия/точка.
Также мы используем следующие методы объекта ТаблицаЗначений:
- КоличествоСтрок, КоличествоКолонок - получение размера таблицы;
- ПолучитьЗначение - получение значения из таблицы значений по номеру строки и колонки;
- ПолучитьПараметрыКолонки - с помощью этого метода мы в данном случае узнаем заголовок колонки, это один из необязательных параметров метода.
Code
Процедура СформироватьДиаграмму(Диаграмма, Параметры)
Диаграмма.Обновление(0);
// Устанавливаем количество серий и точек
КолСтрок = Параметры.КоличествоСтрок();
КолКолонок = Параметры.КоличествоКолонок();
Диаграмма.КоличествоСерий(КолСтрок);
Диаграмма.КоличествоТочек(КолКолонок-1);
// Цикл по значениям таблицы
Для Сч = 1 По КолСтрок Цикл
Диаграмма.УстановитьИмяСерии(Сч, СокрЛП(Параметры.ПолучитьЗначение(Сч, 1)));
Для Сч2 = 2 По КолКолонок Цикл
Если Сч = 1 Тогда
НаименованиеТочки = "";
// Наименование точки возьмем из заголовка колонки
Параметры.ПолучитьПараметрыКолонки(Сч2, , , , НаименованиеТочки);
Диаграмма.УстановитьИмяТочки(Сч2 - 1, НаименованиеТочки);
КонецЕсли;
Диаграмма.УстановитьЗначение(Сч2 - 1, Сч, Параметры.ПолучитьЗначение(Сч, Сч2));
КонецЦикла;
КонецЦикла;
Диаграмма.Обновление(1);
КонецПроцедуры
Далее напишем процедуру для вывода таблицы с "расшифровкой" диаграммы. Здесь аналогичным образом нам понадобится метод ПолучитьПараметрыКолонки объекта ТаблицаЗначений, цикл по ее строкам и столбцам и метод ПолучитьЗначение. Процедура выглядит следующим образом:
Code
Процедура ВывестиРасшифровкуДиаграммы(Таб, ЗаголовокДиаграммы, ЗагДополн, Параметры)
Таб.ВывестиСекцию("Шапка|Боковик");
Для Сч2 = 2 По Параметры.КоличествоКолонок() Цикл
НаименованиеТочки = "";
Параметры.ПолучитьПараметрыКолонки(Сч2, , , , НаименованиеТочки);
Таб.ПрисоединитьСекцию("Шапка|Точка");
КонецЦикла;
Для Сч = 1 По Параметры.КоличествоСтрок() Цикл
НаименованиеСерии = СокрЛП(Параметры.ПолучитьЗначение(Сч, 1));
Таб.ВывестиСекцию("Серия|Боковик");
Для Сч2 = 2 По Параметры.КоличествоКолонок() Цикл
Значение = Параметры.ПолучитьЗначение(Сч, Сч2);
Таб.ПрисоединитьСекцию("Серия|Точка");
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Параметры процедуры ЗаголовокДиаграммы и ЗагДополн в явном виде в ней не используются, но эти выражения используются в макете таблицы.
Собственно говоря, осталось всему этому делу "скормить" таблицу значений. Для примера я сделал поиск по картинкам (запрос "диаграмма"), и почти сразу же наткнулся на некую динамику стоимости жилья. Собственно, за май и июнь цифры я взял из статьи, а за июль "аппроксимировал".
Процедура Сформировать для нашего примера выглядит совсем уж простой. Как обычно, инициализируем табличный документ, создаем таблицу значений, вызываем процедуру вывода расшифровки диаграммы, выводим секцию с гистограммой и показываем табличный документ на экране.
Code
Процедура Сформировать()
Таб = СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("Таблица");
Таб.Опции(0,0,0,0);
Параметры = СоздатьОбъект("ТаблицаЗначений");
Параметры.НоваяКолонка("Серия", "Строка", 100);
Параметры.НоваяКолонка("Алмалинский", "Число", 10);
Параметры.НоваяКолонка("Бостандыкский", "Число", 10);
Параметры.НоваяКолонка("Жетысуский", "Число", 10);
Параметры.НоваяКолонка("Турксибский", "Число", 10);
Параметры.НоваяСтрока();
Параметры.Серия = "май";
Параметры.Алмалинский = 3739;
Параметры.Бостандыкский = 3922;
Параметры.Жетысуский = 3476;
Параметры.Турксибский = 2790;
Параметры.НоваяСтрока();
Параметры.Серия = "июнь";
Параметры.Алмалинский = 3805;
Параметры.Бостандыкский = 3852;
Параметры.Жетысуский = 3438;
Параметры.Турксибский = 2859;
Параметры.НоваяСтрока();
Параметры.Серия = "июль";
Параметры.Алмалинский = 3853;
Параметры.Бостандыкский = 3786;
Параметры.Жетысуский = 3398;
Параметры.Турксибский = 2927;
ВывестиРасшифровкуДиаграммы(Таб, "Динамика стоимости жилья по районам", "За период май - июль 2007 года", Параметры);
Таб.ВывестиСекцию("Гистограмма");
Таб.ТолькоПросмотр(1);
Таб.Показать("Динамика стоимости жилья");
КонецПроцедуры
Ну а результат показан на рисунке:
Вот, пожалуй, и все
Приложение к статье - внешняя обработка с построенной диаграммой.
Форум: построение диаграмм в 1С: Предприятии 7.7
Форум: разное по программированию в 1С