Недавно пришлось в рамках одного отчета строить довольно большое количество диаграмм, в итоге я пришел к универсальному механизму формирования диаграммы на основе таблицы значений.

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

В 1С при построении диаграмм используются такие термины, как "серии" и "точки". Понятие серии в данном случае совпадает с "рядом данных" в Excel, ну а "точки" - это, скажем так, значения оси Х, или просто "значения" в терминах Excel. Так вот, чтобы механизм был более-менее универсальным, условимся, что таблица значений имеет следующую структуру: первая колонка - наименование серии, последующие колонки - это значения точек, причем заголовок колонки и будет являться наименованием точки. Ну а для заполнения таблицы значений существует множество методов, например, для реализации неких алгоритмов в цикле хорошо использовать метод УстановитьЗначение(<Строка>,<Колонка>,<Знач>). Однако формирование таблицы значений мы в рамках данной статьи оставим все же за кадром и сосредоточимся на выводе диаграммы. Допустим также, что перед диаграммой необходимо выводить таблицу, по которой эта самая диаграмма построена.

Начнем с "рисования" макета. Укажем ячейки с основным и дополнительным заголовками диаграммы (пусть для определенности это будут выражения ЗаголовокДиаграммы и ЗагДополн) и нарисуем таблицу из 4х ячеек. В первой ячейке можно написать, например, "Серия / Точка", во 2-м столбце первой строки - выражение НаименованиеТочки, во 2-й строке 1-го столбца - выражение НаименованиеСерии, и, наконец, в последней ячейке - выражение Значение. Определим горизонтальные секции: "Шапка", куда войдут заголовки и первая строка таблицы, и "Серия" - вторая строка таблицы. Определим вертикальные секции - "Боковик", куда войдет 1-й столбец таблицы, и "Точка", содержащая второй столбец таблицы.

Вставим в макет диаграмму. По умолчанию вставляется гистограмма с легендой, что лично меня устраивает, но, разумеется, можно выбрать и другое представление, а также поднастроить внешний вид. Заключим диаграмму в горизонтальную секцию "Гистограмма". В свойствах диаграммы (имеется в виду 1С-ное диалоговое окно "Свойства рисунка", а не всякого рода настройки диаграммы как OLE-объекта) на закладке текст в поле ввода введем:

СформироватьДиаграмму(Таб.ТекущийОбъект, Параметры)

Т.е. вызываем процедуру, которая будет непосредственно рисовать диаграмму. Второй параметр ("Параметры") как раз и будет представлять собой таблицу значений.

Примерный вид макета приведен на рисунке:

 

Что ж, переходим к коду. Первым делом напишем процедуру обратного вызова СформироватьДиаграмму. В ней мы в соответствии с размером таблицы значений устанавливаем количество серий и точек, и в цикле по строкам и столбцам таблицы значений заполняем диаграмму, учитывая, что в первой колонке таблицы значений содержится наименование серии, а наименование точки необходимо получить из заголовка колонки. Используем следующие методы объекта Диаграмма:

  • КоличествоСерий - устанавливаем количество серий;
  • КоличествоТочек - устанавливаем количество точек;
  • УстановитьИмяСерии - назначаем имя серии;
  • УстановитьИмяТочки - аналогично;
  • УстановитьЗначение - основной метод, собственно говоря, указываем, какое значение соответствует комбинации серия/точка.

Также мы используем следующие методы объекта ТаблицаЗначений:

  • КоличествоСтрок, КоличествоКолонок - получение размера таблицы;
  • ПолучитьЗначение - получение значения из таблицы значений по номеру строки и колонки;
  • ПолучитьПараметрыКолонки - с помощью этого метода мы в данном случае узнаем заголовок колонки, это один из необязательных параметров метода.
Процедура СформироватьДиаграмму(Диаграмма, Параметры)
  Диаграмма.Обновление(0);

  // Устанавливаем количество серий и точек
  КолСтрок = Параметры.КоличествоСтрок();
  КолКолонок = Параметры.КоличествоКолонок();
  Диаграмма.КоличествоСерий(КолСтрок);
  Диаграмма.КоличествоТочек(КолКолонок-1);

  // Цикл по значениям таблицы
  Для Сч = 1 По КолСтрок Цикл
    Диаграмма.УстановитьИмяСерии(Сч, СокрЛП(Параметры.ПолучитьЗначение(Сч, 1)));
    Для Сч2 = 2 По КолКолонок Цикл
      Если Сч = 1 Тогда
        НаименованиеТочки = "";
        // Наименование точки возьмем из заголовка колонки
        Параметры.ПолучитьПараметрыКолонки(Сч2, , , , НаименованиеТочки);
        Диаграмма.УстановитьИмяТочки(Сч2 - 1, НаименованиеТочки);
      КонецЕсли;
      Диаграмма.УстановитьЗначение(Сч2 - 1, Сч, Параметры.ПолучитьЗначение(Сч, Сч2));
    КонецЦикла;
  КонецЦикла;

  Диаграмма.Обновление(1);
КонецПроцедуры

Далее напишем процедуру для вывода таблицы с "расшифровкой" диаграммы. Здесь аналогичным образом нам понадобится метод ПолучитьПараметрыКолонки объекта ТаблицаЗначений, цикл по ее строкам и столбцам и метод ПолучитьЗначение. Процедура выглядит следующим образом:

Процедура ВывестиРасшифровкуДиаграммы(Таб, ЗаголовокДиаграммы, ЗагДополн, Параметры)
  Таб.ВывестиСекцию("Шапка|Боковик");
  Для Сч2 = 2 По Параметры.КоличествоКолонок() Цикл
    НаименованиеТочки = "";
    Параметры.ПолучитьПараметрыКолонки(Сч2, , , , НаименованиеТочки);
    Таб.ПрисоединитьСекцию("Шапка|Точка");
  КонецЦикла;

  Для Сч = 1 По Параметры.КоличествоСтрок() Цикл
    НаименованиеСерии = СокрЛП(Параметры.ПолучитьЗначение(Сч, 1));
    Таб.ВывестиСекцию("Серия|Боковик");
    Для Сч2 = 2 По Параметры.КоличествоКолонок() Цикл
      Значение = Параметры.ПолучитьЗначение(Сч, Сч2);
      Таб.ПрисоединитьСекцию("Серия|Точка");
    КонецЦикла;
  КонецЦикла;
КонецПроцедуры

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

Собственно говоря, осталось всему этому делу "скормить" таблицу значений. Для примера я сделал поиск по картинкам (запрос "диаграмма"), и почти сразу же наткнулся на некую динамику стоимости жилья. Собственно, за май и июнь цифры я взял из статьи, а за июль "аппроксимировал". rolleyes

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

Процедура Сформировать()
  Таб = СоздатьОбъект("Таблица");
  Таб.ИсходнаяТаблица("Таблица");
  Таб.Опции(0,0,0,0);

  Параметры = СоздатьОбъект("ТаблицаЗначений");
  Параметры.НоваяКолонка("Серия", "Строка", 100);
  Параметры.НоваяКолонка("Алмалинский", "Число", 10);
  Параметры.НоваяКолонка("Бостандыкский", "Число", 10);
  Параметры.НоваяКолонка("Жетысуский", "Число", 10);
  Параметры.НоваяКолонка("Турксибский", "Число", 10);

  Параметры.НоваяСтрока();
  Параметры.Серия = "май";
  Параметры.Алмалинский = 3739;
  Параметры.Бостандыкский = 3922;
  Параметры.Жетысуский = 3476;
  Параметры.Турксибский = 2790;

  Параметры.НоваяСтрока();
  Параметры.Серия = "июнь";
  Параметры.Алмалинский = 3805;
  Параметры.Бостандыкский = 3852;
  Параметры.Жетысуский = 3438;
  Параметры.Турксибский = 2859;

  Параметры.НоваяСтрока();
  Параметры.Серия = "июль";
  Параметры.Алмалинский = 3853;
  Параметры.Бостандыкский = 3786;
  Параметры.Жетысуский = 3398;
  Параметры.Турксибский = 2927;

  ВывестиРасшифровкуДиаграммы(Таб,
    "Динамика стоимости жилья по районам",
    "За период май - июль 2007 года",
    Параметры);

  Таб.ВывестиСекцию("Гистограмма");

  Таб.ТолькоПросмотр(1);
  Таб.Показать("Динамика стоимости жилья");
КонецПроцедуры

Ну а результат показан на рисунке:

 

Вот, пожалуй, и все! smile

Приложение к статье - внешняя обработка с построенной диаграммой.


Категория: Программирование, 1С | Опубликовано 31.10.2010 | Редакция от 20.01.2017

Похожие материалы:


Комментарии, обсуждение

комментарии простроенны на платформе Disqus