結合AnyChart作報表:一個生成AnyChart圖形XML數據的工具類

今天頭有點痛,因此不能詳細地寫了,先把代碼貼上來,等身體情況稍微好一點,再繼續完善。 java

一、(主角)一個使用XML模板生成Anychart XML數據的工具類 ajax

/**
 * 
 */
package com.common.anychart;

import java.io.InputStream;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.NullArgumentException;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.common.reflect.ReflectUtils;

/**
 * XML數據處理工具類,服務於AnyChart報表
 * @author luolin
 *
 * @version $id:AnyChartXMLProcessor.java,v 0.1 2015年8月19日 上午10:15:57 luolin Exp $
 */
public class AnyChartXMLProcessor {

    private static final Logger LOGGER                         = Logger
                                                                   .getLogger(AnyChartXMLProcessor.class);

    /** 簡單線性曲線圖模板路徑 */
    private static final String SIMPLE_LINE_TEMPLATE_FILE      = "xmltemplate/simpleLine.xml";
    /** 簡單柱狀圖圖模板路徑 */
    private static final String SIMPLE_HISTOGRAM_TEMPLATE_FILE = "xmltemplate/simpleHistogram.xml";

    /**
     * 使用simpleLine.xml模板生成簡單的線性曲線圖XML數據
     * @param xName x軸標題,格式如:「X軸標題@feild」,feild表示從數據中取值的字段
     * @param yName y軸標題,格式如:「y軸標題@feild」,feild表示從數據中取值的字段
     * @param title 圖標標題
     * @param dataList 要展現的數據
     * @return 生成的XML數據
     * @throws Exception 
     */
    public static String simpleLine(String xName, String yName, String title, List<?> dataList)
                                                                                               throws Exception {
        LOGGER.info("【使用categorizedVertical.xml模板生成簡單的線性曲線圖XML數據】xName : " + xName + " , yName : "
                    + yName + " , title : " + title);
        // 基本參數校驗
        if (!baseDataValidate(xName, yName, title, dataList)) {
            return "";
        }
        String[] xData = xName.split("@");
        String[] yData = yName.split("@");
        // 座標軸數據校驗
        axisFormatValidate(xData, yData);

        InputStream inputStream = AnyChartXMLProcessor.class.getClassLoader().getResourceAsStream(
            SIMPLE_LINE_TEMPLATE_FILE);

        return templateProcessor(title, dataList, xData, yData, inputStream);
    }

    /**
     * 根據模板處理數據,生成修改後的XML數據
     * @param title 統計圖的標題
     * @param dataList 統計數據
     * @param xData X軸數據
     * @param yData Y軸數據
     * @param inputStream 讀入模板的流
     * @return 修改模板後獲得的XML數據
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    private static String templateProcessor(String title, List<?> dataList, String[] xData,
                                            String[] yData, InputStream inputStream)
                                                                                    throws Exception {
        SAXReader sax = new SAXReader();
        Document xmlDoc = sax.read(inputStream);
        Element root = xmlDoc.getRootElement();//根節點  
        // 取得text節點
        List<Element> titleElements = root.selectNodes("//text");
        // 獲得chart_settings下的第一個text節點,並修改它的值
        Element titleElement = titleElements.get(0);
        titleElement.setText(title);

        // 獲得X軸的第一個text座標,修改它的值
        Element xTitleElement = titleElements.get(1);
        xTitleElement.setText(xData[0]);

        // 獲得X軸的第一個text座標,修改它的值
        Element yTitleElement = titleElements.get(2);
        String yTitleTemplate = yTitleElement.getTextTrim();
        yTitleElement.setText(yTitleTemplate.replace("#YTitle#", yData[0]));

        // 替換format裏面的x、y的標題
        List<Element> formatElements = root.selectNodes("//format");
        if (CollectionUtils.isNotEmpty(formatElements)) {
            for (Element element : formatElements) {
                String formatText = element.getTextTrim();
                element.setText(formatText.replace("#YTitle#", yData[0]).replace("#XTitle#",
                    xData[0]));
            }
        }

        Element dataElement = (Element) root.selectSingleNode("//data");
        // 如何數據集裏存放的是更多數據集(表示須要多條線或者多柱),循環處理
        if (dataList.get(0) instanceof List) {
            for (Object element : dataList) {
                createSeriesElement(title, (List<?>) element, xData, yData, dataElement);
            }
            return xmlDoc.asXML();
        }
        createSeriesElement(title, dataList, xData, yData, dataElement);
        return xmlDoc.asXML();
    }

    /**
     * 生成series部分
     * @param title 標題
     * @param dataList 數據集合
     * @param xData X軸數據
     * @param yData Y軸數據
     * @param dataElement "data"節點
     * @throws Exception
     */
    private static void createSeriesElement(String title, List<?> dataList, String[] xData,
                                            String[] yData, Element dataElement) throws Exception {
        Element seriesElement = dataElement.addElement("series");
        seriesElement.addAttribute("name", title);
        for (Object item : dataList) {
            Element pointElement = seriesElement.addElement("point");
            pointElement.addAttribute("name",
                String.valueOf(ReflectUtils.getCellValue(item, xData[1])));
            pointElement.addAttribute("y",
                String.valueOf(ReflectUtils.getCellValue(item, yData[1])));
        }
    }

    /**
     * 座標軸數據校驗
     * @param xData X軸信息
     * @param yData Y軸信息
     */
    private static void axisFormatValidate(String[] xData, String[] yData) {
        if (xData.length < 2) {
            LOGGER.warn("【xName參數不正確】xData : " + xData);
            throw new IllegalArgumentException("xName");
        }
        if (yData.length < 2) {
            LOGGER.warn("【yName參數不正確】yData : " + yData);
            throw new IllegalArgumentException("yName");
        }
    }

    /**
     * 基本數據校驗
     * @param xName x軸標題,格式如:「X軸標題@feild」,feild表示從數據中取值的字段
     * @param yName y軸標題,格式如:「y軸標題@feild」,feild表示從數據中取值的字段
     * @param title 圖標標題
     * @param dataList 要展現的數據
     */
    private static boolean baseDataValidate(String xName, String yName, String title,
                                            List<?> dataList) {
        if (CollectionUtils.isEmpty(dataList)) {
            LOGGER.warn("【數據dataList爲空】");
            return false;
        }
        if (StringUtils.isBlank(xName)) {
            LOGGER.warn("【xName爲空】");
            throw new NullArgumentException("xName");
        }
        if (StringUtils.isBlank(yName)) {
            LOGGER.warn("【yName爲空】");
            throw new NullArgumentException("yName");
        }
        if (StringUtils.isBlank(title)) {
            LOGGER.warn("【title爲空】");
            throw new NullArgumentException("title");
        }
        return true;
    }

    /**
     * 使用simpleHistogram.xml模板生成簡單的柱狀圖的XML數據
     * @param xName x軸標題,格式如:「X軸標題@feild」,feild表示從數據中取值的字段
     * @param yName y軸標題,格式如:「y軸標題@feild」,feild表示從數據中取值的字段
     * @param title 圖標標題
     * @param dataList 要展現的數據
     * @return 生成的XML數據
     * @throws Exception 
     */
    public static String simpleHistogram(String xName, String yName, String title, List<?> dataList)
                                                                                                    throws Exception {

        LOGGER.info("【使用simpleHistogram.xml模板生成簡單的柱狀圖的XML數據】xName : " + xName + " , yName : "
                    + yName + " , title : " + title);
        // 基本參數校驗
        if (!baseDataValidate(xName, yName, title, dataList)) {
            return "";
        }
        String[] xData = xName.split("@");
        String[] yData = yName.split("@");
        // 座標軸數據校驗
        axisFormatValidate(xData, yData);

        InputStream inputStream = AnyChartXMLProcessor.class.getClassLoader().getResourceAsStream(
            SIMPLE_HISTOGRAM_TEMPLATE_FILE);

        return templateProcessor(title, dataList, xData, yData, inputStream);
    }

    /**
     * 使用simpleHistogram.xml模板生成簡單的多柱柱狀圖的XML數據
     * @param xName x軸標題,格式如:「X軸標題@feild」,feild表示從數據中取值的字段
     * @param yName y軸標題,格式如:「y軸標題@feild」,feild表示從數據中取值的字段
     * @param title 圖標標題
     * @param dataList 要展現的數據
     * @return 生成的XML數據
     * @throws Exception
     */
    public static String compareHistogram(String xName, String yName, String title,
                                          List<List<?>> dataList) throws Exception {
        LOGGER.info("【使用simpleHistogram.xml模板生成簡單的多柱柱狀圖的XML數據】xName : " + xName + " , yName : "
                    + yName + " , title : " + title);
        // 基本參數校驗
        if (!baseDataValidate(xName, yName, title, dataList)) {
            return "";
        }
        String[] xData = xName.split("@");
        String[] yData = yName.split("@");
        // 座標軸數據校驗
        axisFormatValidate(xData, yData);

        InputStream inputStream = AnyChartXMLProcessor.class.getClassLoader().getResourceAsStream(
            SIMPLE_HISTOGRAM_TEMPLATE_FILE);
        return templateProcessor(title, dataList, xData, yData, inputStream);
    }

}


2015-8-27 09:26:11更新:昨天忘記添加其中用到的一個反射工具類的代碼,今天補上: apache

ReflectUtils.java dom

/**
 * 
 */
package com.common.reflect;

import java.lang.reflect.Field;

/**
 * 反射工具類
 * @author luolin
 *
 * @version $id:ReflectUtils.java,v 0.1 2015年8月19日 下午1:46:54 luolin Exp $
 */
public class ReflectUtils {

    /**
     * 經過字段名從對象中獲得字段的值
     * @param object 對象
     * @param fieldName 字段名
     * @return 字段對應的值
     * @throws Exception
     */
    public static Object getCellValue(Object object, String fieldName) throws Exception {
        Field[] fields = object.getClass().getDeclaredFields();
        Object value = null;
        for (Field field : fields) {
            field.setAccessible(true);
            if (field.getName().equals(fieldName)) {
                value = field.get(object);
                break;
            }
        }
        return value;
    }

}




二、模板文件:目前我使用了兩個簡單的模板文件。朋友們在使用的時候,注意模板相對工程的路徑須要根據實際狀況修改。

折線圖模板(simpleLine.xml): ide

<anychart>
	<settings>
		<animation enabled="True"/>
	</settings>
	<charts>
		<chart plot_type="CategorizedVertical">
			<chart_settings>
				<title enabled="true">
					<text>標題未初始化</text>
				</title>
				<axes>
					<x_axis tickmarks_placement="Center">
						<labels enabled="true"  rotation="60" display_mode="rotated" align="Inside">  
						</labels>  
						<title enabled="true">
							<text>#XTitle#</text>
						</title>
					</x_axis>
					<y_axis>
						<title enabled="true">
							<text>#YTitle#:  {%Min} - {%Max}</text>
						</title>
					</y_axis>
				</axes>
			</chart_settings>
			<data_plot_settings default_series_type="Line">
				<line_series point_padding="0.2" group_padding="1">
					<label_settings enabled="true">
						<background enabled="false"/>
						<font color="Rgb(45,45,45)" bold="true" size="9">
							<effects enabled="true">
								<glow enabled="true" color="White" opacity="1" blur_x="1.5" blur_y="1.5" strength="3"/>
							</effects>
						</font>
						<format>{%YValue}{numDecimals:0}</format>
					</label_settings>
					<tooltip_settings enabled="true">
						<format>
							#YTitle#: {%YValue}{numDecimals:2}  
							#XTitle#: {%Name}
						</format>
						<background>
							<border type="Solid" color="DarkColor(%Color)"/>
						</background>
						<font color="DarkColor(%Color)"/>
					</tooltip_settings>
					<marker_settings enabled="true"/>
					<line_style>
						<line thickness="3"/>
					</line_style>
				</line_series>

			</data_plot_settings>
			<data>
			
			</data>
		</chart>
	</charts>
</anychart>



柱狀圖模板(simpleHistogram.xml):
<anychart>
	<settings>
		<animation enabled="True"/>
	</settings>
	<charts>
		<chart plot_type="CategorizedVertical">
			<chart_settings>
				<title enabled="true">
					<text>標題未初始化</text>
				</title>
				<axes>
					<x_axis tickmarks_placement="Center">
						<labels enabled="true"  rotation="60" display_mode="rotated" align="Inside">  
						</labels>  
						<title enabled="true">
							<text>#XTitle#</text>
						</title>
					</x_axis>
					<y_axis>
						
						<title enabled="true">
							<text>#YTitle#:  {%Min} - {%Max}</text>
						</title>
					</y_axis>
				</axes>
			</chart_settings>
			<data_plot_settings default_series_type="Bar">
				<bar_series group_padding="0.2">
					<tooltip_settings enabled="true">
						<format>
							#YTitle#: {%YValue}{numDecimals:2}  
							#XTitle#: {%Name}
						</format>
						<background>
							<border type="Solid" color="DarkColor(%Color)"/>
						</background>
						<font color="DarkColor(%Color)"/>
					</tooltip_settings>
				</bar_series>
			</data_plot_settings>
			<data>
				
			</data>
		</chart>
	</charts>
</anychart>



三、如何使用?

我是使用AJAX的方式獲取XML數據並交給anychart的。 工具

/**
 * 建立圖表
 * @param chartDivId 顯示圖表的DIV的ID
 * @param xmlData 圖表須要的XML數據
 */
function createChart(chartDivId,xmlData){
	AnyChart.swfFile = "../js/anychart/AnyChart.swf";
	AnyChart.initText = "初始化中,請稍後...";
	AnyChart.xmlLoadingText = "數據加載中,請稍後...";
	AnyChart.noDataText = "沒有數據顯示,換個查詢條件試試!";
	
	var g_dxzr_chart = new AnyChart();
	g_dxzr_chart.width = '100%';
	g_dxzr_chart.height = '100%';
	g_dxzr_chart.bgColor = "#ffffff";
	g_dxzr_chart.setData(xmlData);
	g_dxzr_chart.write(chartDivId);
}

/**
 * 獲取數據
 * @param top3FormId 查詢參數的form的ID
 */
function executeAnalyzeTop3(top3FormId,chartDivId){
	var $form = $('#'+top3FormId); 
	$.ajax({
		url:$form.attr('action'),
		data:$form.serialize(),
		dataType:'text',
		type:'post',
		success:function(data){
			// 建立圖表
			createChart(chartDivId,data);
		},
		error:function(){
			alert('系統異常,請聯繫管理員!');
		}
	})
}



你們若是有什麼問題的話,能夠給我留言,我也是最近才接觸到anychart的,效果其實以爲還不錯。

你們一塊兒學習進步。 post

相關文章
相關標籤/搜索