El otro día me hicieron una consulta sobre cómo poder cambiar los colores de las columnas de un gráfico, dependiendo de una condición. Investigando en Internet, encontré un ejemplo perfecto que se puede utilizar para cubrir esta consulta. Este ejemplo ha sido desarrollado por Hilary Farrell en su demo llamado“Sample Charts, Maps, Gantts and Trees Application Express Demo Application”.
Los thresholds se utilizan para definir el color de los elementos del gráfico de acuerdo a algunas condiciones predefinidas. Por ejemplo, podemos crear un thresholds que muestre el color rojo por todos los valores de la serie que cumplan un máximo, o mostrar color verde por todos los valores negativos que se muestran en el gráfico original.
1. Para ilustrar lo ante dicho vamos a crear una applicación en Oracle Apex con una página de tipo Gráfico Columna de 2D e ingresamos la siguiente consulta SQL:
select null link, ename LABEL, sal VALUE from EMP order by ename
2. Editamos los atributos del gráfico y configuramos el Eje Y: Prefijo en $, colocamos los títulos y mostramos la leyenda en la parte inferior del gráfico y hacemos clic en Guardar.
3. Agregar un nuevo Elemento Oculto en la Página del Gráfico llamado PX_DATA (donde X es el número de página)
4. Creamos un Proceso de Aplicaciónpara manejar la creación de los datos del gráfico. El proceso debe generar el XML de datos utilizando la consulta SQL de la gráfica.
Ingresamos a Componentes Compartidos, en la sección Lógica de la Aplicación, hacemos clic en Procesos de la Aplicación y luego hacemos clic en el botón Crear para lanzar el asistente
En Punto de Proceso: En Carga Antes de Cabecera (cabecera de plantilla de página)
En Tipo: Bloque Anónimo PL/SQL
Origen: ingresamos el siguiente código PL/SQL:
declare
l_data clob;
l_chart_data_xml varchar2(32767);
begin
dbms_lob.createtemporary( l_data, FALSE, dbms_lob.session );
dbms_lob.open( l_data, dbms_lob.lob_readwrite );
l_chart_data_xml := '
<data threshold="salary_thresholds">'||chr(10);
dbms_lob.writeappend( l_data, length(l_chart_data_xml), l_chart_data_xml);
-- Series 1
l_chart_data_xml := '
<series name="Salary Thresholds">'||chr(10);
dbms_lob.writeappend( l_data, length(l_chart_data_xml), l_chart_data_xml);
-- Loop through series data
for c1 in (select ENAME LABEL,
SAL VALUE
from EMP
order by ENAME)
loop
l_chart_data_xml := '
<point name="'||c1.LABEL||'" ';
l_chart_data_xml := l_chart_data_xml||' y="'||c1.VALUE||'" ></point>'||chr(10);
dbms_lob.writeappend( l_data, length(l_chart_data_xml), l_chart_data_xml);
end loop;
l_chart_data_xml := ' </series>'||chr(10)||' </data>';
dbms_lob.writeappend( l_data, length(l_chart_data_xml), l_chart_data_xml);
l_chart_data_xml := wwv_flow.do_substitutions(wwv_flow_utilities.clob_to_varchar2(l_data));
dbms_lob.close( l_data );
if l_data is not null then
dbms_lob.freetemporary(l_data);
end if;
:P2_DATA := l_chart_data_xml;
end;
Nota: La etiqueta <data> contiene el atributo threshold con el nombre salary_thresholds (resaltado en Amarillo), es importante verificar cuando se haga el paso 7 que el nombre del threshold en el XML personalizado del gráfico corresponde con el nombre especificado dentro de la etiqueta <data>. El elemento P2_DATA contendrá el XML del gráfico. Cambiamos el nombre de la serie a: Salary Thresholds.
5. Editar la Página del Gráfico para incluir la siguiente función Javascript en la sección “Declaración de Función y Variable Global” que llama al Procedimiento On Demand:
function getdata() {
var get = new htmldb_Get(null,$x('pFlowId').value,'APPLICATION_PROCESS=CHART_DATA',0);
gReturn = get.get('XML');
get = null;}
6. Editar los atributos del Gráfico y configurar Personalización XML en Sí y actualizamos el XML cambiando el string #DATA# por el elemento &PX_DATA. (en este ejemplo uso &P2_DATA. - recordar de colocar el punto al final del elemento)
Por defecto, el esquema de color seleccionado mediante el asistente Crear Gráfico o en los Atributos de la página del gráfico se aplica a la serie del gráfico. Para definir los thresholds de un gráfico y asociar esos thresholds con los datos de la serie, se necesita modificar el XML del gráfico para personalizar e incluir las nuevas etiquetas <thresholds>, y también se necesita cambiar el String #DATOS# para que haga referencia a los thresholds.
7. En la región de Personalización XML añadimos las siguientes etiquetas justo arriba de la etiqueta de apertura <chart_settings>, luego hacemos clic en el botón Guardar.
<thresholds>
<threshold name="salary_thresholds">
<condition name="Low" type="lessThan" value_1="{%Value}" value_2="1500" color="orange"/>
<condition name="Average" type="between" value_1="{%Value}" value_2="1500" value_3="3000" color="Green"/>
<condition name="High" type="greaterThan" value_1="{%Value}" value_2="3000" color="Red"/>
</threshold>
</thresholds>
En la documentacion de AnyChart, se puede ver las diferentes condiciones:
Al ejecutar la página podemos ver el resultado de la gráfica, que representa 3 diferentes thresholds de Niveles de Salarios de Empleados, pero no muestra las leyendas, ni valores, ni los títulos.
Para mostrar las leyendas y valores vamos a modificar el XML del gráfico:
Reemplazamos el siguiente código XML desde la apertura de la etiqueta <chart_settings> hasta el cierre de la etiqueta </anychart>. Tener en cuenta que al final del código se encuentra el elemento Oculto, que en este ejemplo es P2_DATA, cambiar por el que corresponda en su proyecto.
<chart_settings>
<title text_align="Center" position="Top" >
<text>Gráfico Nivel de Salario de Empleados</text>
<font family="Tahoma" size="14" color="0x000000" />
</title>
<chart_background>
<fill type="Solid" color="0xffffff" opacity="0" />
<border enabled="false"/>
<corners type="Square"/>
</chart_background>
<data_plot_background>
</data_plot_background>
<axes>
<y_axis position="Opposite"><scale mode="Normal" />
<title>
<text>Salario</text>
<font family="Tahoma" size="10" color="0x000000" />
</title>
<labels enabled="true" position="Outside">
<font family="Tahoma" size="10" color="0x000000" />
<format><![CDATA[${%Value}{numDecimals:0,decimalSeparator:.,thousandsSeparator:\,}]]></format>
</labels>
<major_grid enabled="False"/><minor_grid enabled="False"/>
</y_axis>
<x_axis>
<scale mode="Normal" />
<title>
<text>Empleados</text>
<font family="Tahoma" size="10" color="0x000000" />
</title>
<labels enabled="true" position="Outside">
<font family="Tahoma" size="10" color="0x000000" />
<format><![CDATA[{%Value}{numDecimals:0,decimalSeparator:.,thousandsSeparator:\,}]]></format>
</labels>
<major_grid enabled="True" interlaced="false">
<line color="Black" />
</major_grid>
<minor_grid enabled="True">
</minor_grid>
</x_axis>
</axes>
<legend enabled="true" position="Bottom" align="Near" elements_layout="Horizontal">
<title enabled="true"><text>Leyenda</text>
<font family="Tahoma" size="10" color="0x000000" />
</title>
<icon><marker enabled="true" /></icon>
<font family="Tahoma" size="10" color="0x000000" />
</legend>
</chart_settings>
<data_plot_settings enable_3d_mode="false" >
<bar_series style='Default'>
<tooltip_settings enabled="true">
<format><![CDATA[{%Name}{enabled:False} - ${%Value}{numDecimals:0,decimalSeparator:.,thousandsSeparator:\,}]]></format>
<font family="Tahoma" size="10" color="0x000000" />
<position anchor="Float" valign="Top" padding="10" />
</tooltip_settings>
<label_settings enabled="true" mode="Outside" multi_line_align="Center">
<format><![CDATA[${%Value}{numDecimals:0,decimalSeparator:.,thousandsSeparator:\,}]]></format>
<background enabled="false"/><font family="Tahoma" size="10" color="0x000000" />
</label_settings>
<bar_style></bar_style>
<marker_settings enabled="True" >
<marker type="None" />
</marker_settings>
</bar_series>
</data_plot_settings>&P2_DATA.</chart>
</charts>
</anychart>
Ejecutamos la página y podemos ver que ya se muestran los títulos, etiquetas, valores y leyendas.
8. Por último para llamar a la función de JavaScript, necesitamos crear una nueva acción dinámica de página con las siguientes configuraciones:
Acción Verdadera 1
- Nombre Acción Dinámica: Llamar a JS
- Cuando - Evento: Carga de Página
- Verdadero
- Acción: Ejecutar Código JavaScript
- Código: getdata();
- Arrancar cuando el Resultado del Evento sea: Verdadero
- Arrancar al Cargar Página: Sí
Acción Verdadera 2
- Nombre Acción Dinámica: Refrescar Gráfico
- Verdadero
- Acción: Refrescar
- Tipo de Selección: Región
- Región: Gráfico 2D
- Arrancar cuando el Resultado del Evento sea: Verdadero
Bueno, será hasta pronto con más de Oracle Apex 5.0!