Oracle Apex – компонент для разработки конечных приложений, входящий в состав поставки СУБД Oracle, позволяющий быстро «доставать» данные из базы и доставлять их через веб-интерфейс конечному пользователю. Как правило, данные для просмотра и редактирования выдаются в табличном виде и Apex предоставляет богатые возможности для настраивания отчета: можно накладывать фильтры, делать сортировку и группировку, скрывать имеющиеся столбцы и добавлять расчетные новые, делать сводные отчеты, выгружать данные в формате csv, pdf и даже Excel. Каждый пользователь может сохранить предпочитаемые им настройки каждого отчета как индивидуально, так и для совместного использования. В таком формате Apex функционирует у большинства наших заказчиков.

Однако мало кто использует довольно широкие возможности Apex’а для построения графиков. Эта тема, на наш взгляд, довольно интересна и мало освещена в интернете.

В этой статье будем предполагать, что читатель имеет представление о разработке приложений с помощью Oracle Apex.

В качестве примера рассмотрим гипотетический дашборд, показывающий переработки и недоработки сотрудников департамента за отчетный период, а также распределение трудозатрат по активностям.

С точки зрения разработки добавление графика на страницу приложения в Apex’е представляет собой добавление региона типа Chart. У него есть ряд обычных для региона свойств, которые можно заполнить значениями по умолчанию или не заполнять вообще.

В интерфейсе разработки Apex 5.1 часть свойств самого региона заполнялась через пункт меню Attributes, что вносило некую неразбериху: было интуитивно не всегда понятно, что и где лежит. Надеюсь, в новых версиях UI эту путаницу убрали. В частности, именно в «атрибутах» указывался тип графика, который мы хотим получить (Рисунок 1). Как видим, выбор достаточно большой и охватывает все основные визуальные представления, используемые аналитиками в большинстве случаев.

Рисунок 1 Выбор типа графика
Рисунок 1 Выбор типа графика

Здесь же мы указываем ориентацию столбцов гистограммы (вертикальная или горизонтальная), высоту панели, настройку всплывающих подсказок (показывать ли их вообще, а если показывать, то что именно выводить), настройку легенды, а также можем добавить код на JavaScript для тонкой «подгонки» графика под требования заказчика. Это нужно, например, в том случае, если каждому столбцу на диаграмме мы хотим задать цвет на наш выбор. Код можно добавить явно или указать наименование функции, реализацию которой мы можем привести где-то еще (Apex позволяет добавлять в приложение js-файлы для определения кода на «высшем» уровне или указывать код в рамках одной страницы веб-приложения).

В каждом графическом регионе может быть несколько графиков, если они объединены общей осью абсцисс (при этом по оси ординат может быть две шкалы). В таком случае мы добавляем их через пункт меню Series и указываем SQL-запрос, который будет возвращать нам значения по осям и – при желании – некоторую дополнительную информацию: наименование ряда, значения для всплывающих подсказки или даже ссылку для перехода на другую страницу приложения (Рисунок 2).  В нашем примере табличный тип данных, возвращаемый запросом, объявлен следующим образом:

type     t_graph_row          is record (
      link                          varchar2(255)
    , series                        varchar2(2000)
    , label                         varchar2(2000)
    , val                           number(23,8)
  );
Рисунок 2 Настройка графика
Рисунок 2 Настройка графика

Передача параметров (в нашем случае – даты отчета и идентификатора департамента или какого-либо из его подразделений) из формы ввода на сервер происходит стандартным для Apex образом: или через кнопку Submit, или путем создания DynamicAction, который реализует технологию Ajax и может обновить тот или иной регион, их совокупность (ограничения по числу обновляемых регионов нет) на странице динамически. Лично я предпочитаю второй вариант. Изменение графиков при этом происходит в режиме мультфильма: столбцы гистограмм, к примеру, при этом «вырастают» или «съеживаются», появляются стрелки-указатели динамики изменений – пользователь может немного развлечься.

Графики «из коробки» выглядят вполне прилично, но иногда требуется их подстройка под требования заказчика. Например, мой заказчик долгое время получал отчеты в Excel и уже привык к его цветовой гамме, маркерам и т.п. На помощь может прийти JavaScript. 

Например, этот код задает цвета для трех вхождений в круговой диаграмме:

options.dataFilter = function( data ) {
    if (data.series[0] !== undefined) data.series[0].color = "#A8A8A8";
    if (data.series[1] !== undefined) data.series[1].color = "#FF6200";
		if (data.series[2] !== undefined) data.series[2].color = "#525199";
    return data;
  };

Итоговый вид круговой диаграммы приведен на Рисунке 3.

Рисунок 3 Круговая диаграмма
Рисунок 3 Круговая диаграмма
Лирическое отступление про цвета

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

Рисунок 4 О цветовой дифференциации – распределение по активностям, в каждой из групп активностей – Co, Ho, Su, могут быть активности из списка над графиком
Рисунок 4 О цветовой дифференциации – распределение по активностям, в каждой из групп активностей – Co, Ho, Su, могут быть активности из списка над графиком

Почитав пару обсуждений на stackoverflow.com, я решил изобрести свой велосипед следующим образом. Взял таблицу цветов с сайта material design, отсортировал, чтобы близкие группы оттенков (например, «розовый» и «фиолетовый» или «лимонный» и «светло-зеленый») не оказались соседними, какие-то группы цветов исключил и взял только оттенки, которые в css имеют индекс 300, 500, 700 или 900.

В результате получил вот такой список из заведомо избыточных 76 цветов, который и используется в графике (Рисунок 4).

"#e57373","#ba68c8","#7986cb","#4fc3f7","#4db6ac","#aed581","#fff176","#ffb74d","#a1887f","#90a4ae","#f06292","#9575cd","#64b5f6","#4dd0e1","#81c784","#dce775","#ffd54f","#ff8a65","#e0e0e0",
"#f44336","#9c27b0","#3f51b5","#03a9f4","#009688","#8bc34a","#ffeb3b","#ff9800","#795548","#607d8b","#e91e63","#673ab7","#2196f3","#00bcd4","#4caf50","#cddc39","#ffc107","#ff5722","#9e9e9e",
"#d32f2f","#7b1fa2","#303f9f","#0288d1","#00796b","#689f38","#fbc02d","#f57c00","#5d4037","#455a64","#c2185b","#512da8","#1976d2","#0097a7","#388e3c","#afb42b","#ffa000","#e64a19","#616161",
"#b71c1c","#4a148c","#1a237e","#01579b","#004d40","#33691e","#f57f17","#e65100","#3e2723","#263238","#880e4f","#311b92","#0d47a1","#006064","#1b5e20","#827717","#ff6f00","#bf360c","#212121"

Тех, кому интересна эта тема, могу отправить в обсуждения вот здесь, здесь или здесь.

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

Рисунок 5 Переработка сотрудников какого-то подразделения в феврале какого-то года
Рисунок 5 Переработка сотрудников какого-то подразделения в феврале какого-то года

Например, для того, чтобы отобразить цифры в кружках на левом графике (см. Рисунок 5), потребовалось сделать настройки для каждого элемента в отдельности:

options.dataFilter = function( data ) {     
    if (data.series[1] !== undefined) {
        data.series[1].markerSize = 25; 
        // Didn't find the property for labelStyle for all series, only by points
        for(i = 0; i < data.series[1].items.length;i++)
            data.series[1].items[i].labelStyle = 'font-weight:bold;font-size:14px;color:#FFFFFF';
    }
      
    return data;
};

А референсная линия «0» на правом графике настраивается вот таким кодом:

// Define Reference Object line on Y Axis of chart
var constantLineX = [ {text:"Reference Object", type: "line", value: " ", color: "#FF6200", displayInLegend: "off", lineWidth: 4, location: "back", lineStyle: "dashed", shortDesc: "Zero line:\n<- undertime | overtime ->"}];
    
// Set the referenceObjects option as part of the chart initialization
options.xAxis.referenceObjects = constantLineX;

Мне всё-таки кажется, что подобное вмешательство в установленную функциональность инструмента напоминает костыли. Надеюсь, что в новых версиях Oracle Apex этих «костылей» потребуется меньше. Справедливости ради надо отметить, что в моей практике был случай, когда мне пришлось «допиливать» какие-то настройки BI-отчета с помощью JavaScript в «профессиональном» Oracle BI EE версии 12. На мой взгляд, это говорит о том, что каким бы ни продвинутым инструмент ни был, найдется требование заказчика, выходящее за рамки его штатной функциональности.

В качестве заключения можно сказать, что возможности Oracle Apex как инструмента графического представления данных, конечно, несопоставимы с профессиональными BI-инструментами, особенно если вам потребуется выводить на дашборд что-нибудь вроде линий тренда. Но если вы уже используете БД Oracle, то этими возможностями пренебрегать не стоит. Опять же, с учетом весьма низкого порога входа в эту технологию, она кажется весьма заслуживающей внимания.

Автор статьи: Вадим Бояркин, ведущий консультант группы разработки Big Data Solutions в компании Neoflex

Комментарии (2)


  1. MiIs
    26.11.2021 13:41

    Надеюсь, что в новых версиях Oracle Apex этих «костылей» потребуется меньше.

    При этом в статье обсуждаются возможности Oracle APEX версии 5.1, вышедшего в 2017 году, при том что сейчас, в конце 2021 года, текущий Oracle APEX имеет версию 21.2 и в нем есть разные как положительные, так и не очень изменения по сравнению с версией 5.1.

    А так, смысл статьи правилен - что-то набросать по-быстрому, сделать и показать макет заказчику на данных из Oracle DB можно и на бесплатном Oracle APEX, но потом нужно брать профессиональный BI инструмент, и даже не Oracle BIEE 12, а что-то посовременнее (рекламировать не буду - кому надо сам разберется).


    1. neoflex Автор
      26.11.2021 13:48

      При этом в статье обсуждаются возможности Oracle APEX версии 5.1, вышедшего в 2017 году, при том что сейчас, в конце 2021 года, текущий Oracle APEX имеет версию 21.2 и в нем есть разные как положительные, так и не очень изменения по сравнению с версией 5.1.

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

      Ну и Oracle BIEE 12 (с ним последний раз работал ещё раньше) упомянут в контексте, что он дорогой, профессиональный, а по факту - тоже не всемогущий :)