文档章节

结合AnyChart做报表:一个生成AnyChart图形XML数据的工具类

十月阳光
 十月阳光
发布于 2015/08/26 16:37
字数 1876
阅读 430
收藏 4

今天头有点痛,所以不能详细地写了,先把代码贴上来,等身体状况稍微好一点,再继续完善。

1、(主角)一个使用XML模板生成Anychart XML数据的工具类

/**
 * 
 */
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更新:昨天忘记添加其中用到的一个反射工具类的代码,今天补上:

ReflectUtils.java

/**
 * 
 */
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;
    }

}




2、模板文件:目前我使用了两个简单的模板文件。朋友们在使用的时候,注意模板相对工程的路径需要根据实际情况修改。

折线图模板(simpleLine.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="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>



3、如何使用?

我是使用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的,效果其实觉得还不错。

大家一起学习进步。




© 著作权归作者所有

十月阳光

十月阳光

粉丝 34
博文 94
码字总数 54658
作品 0
成都
程序员
私信 提问
在.Net开发中使用AnyChart的简单例子(上)

1.AnyChart控件相关 显示效果 2.AnyChart的简单原理 AnyChart是一个Flash做的控件,原理图在安装了AnyChart后的说明文档里面有,这里贴一下 其实很好理解,就是想办法生成一个符合AnyChart解...

咲晚杍
2013/08/29
411
0
在.Net开发中使用AnyChart的简单例子(上)

1.AnyChart控件相关 显示效果 2.AnyChart的简单原理 AnyChart是一个Flash做的控件,原理图在安装了AnyChart后的说明文档里面有,这里贴一下 其实很好理解,就是想办法生成一个符合AnyChart解...

牛奶哎营养
2013/09/16
154
0
在.Net开发中使用AnyChart的简单例子(下)

在上文《在.Net开发中使用AnyChart的简单例子(上)》中我分析了AnyChart所需要的XML数据格式,这里就说说实现。 获取了DataSet后,我通过下面的简单算法写出需要的XML格式。 /// <summary> ...

咲晚杍
2013/09/02
791
0
flash图表AnyChart应用教程汇总

基于Flash/JavaScript (HTML5) 的图表控件AnyChart,是跨多浏览器和多平台的。Anychart 图表目前已被很多知名大公司所使用,广泛应用于仪表盘的创建、报表、统计学和金融等领域。下面是本人翻...

百mumu
2012/12/14
214
2
AnyMap免费下载破解转换器价格AnyChart Flash图表功能介绍

AnyMap是AnyChart Flash图表的扩展 AnyMap互动地图是一个独特的功能。它可以使地理信息相关数据可视化。 下面是AnyMap的一些解决方案 1, 可用于创建Drilldown Maps 2, 创建相关的地理组合图...

yidongkaifa
2014/04/26
315
0

没有更多内容

加载失败,请刷新页面

加载更多

Redis集群搭建

服务器资源 ip 账号 配置 操作系统 xxx.70 root/xxx 磁盘50G(/)+150G(/home)、内存16G、CPU 16core CentOS Linux release 7.2.1511 (Core) xxx.74 root/xxx 磁盘50G(/)+150G(/home)、......

jxlgzwh
17分钟前
2
0
avro

一、 ```我们已经接触过很多序列化框架(或者集成系统),比如protobuf、hessian、thrift等,它们各有优缺点以及各自的实用场景,Avro也是一个序列化框架,它的设计思想、编程模式都和thi...

hexiaoming123
18分钟前
4
0
QML TextInput的字体超出控件范围

本文链接:https://blog.csdn.net/chyuanrufeng/article/details/54691998 问题描述 :QML TextInput输入内容超过TextInput的大小 当输入过多的字符串时,会出现内容超过TextInput的大小,字...

shzwork
20分钟前
2
0
《Java 8 in Action》Chapter 10:用Optional取代null

1965年,英国一位名为Tony Hoare的计算机科学家在设计ALGOL W语言时提出了null引用的想法。ALGOL W是第一批在堆上分配记录的类型语言之一。Hoare选择null引用这种方式,“只是因为这种方法实...

HelloDeveloper
21分钟前
2
0
进击的 Java ,云原生时代的蜕变

作者| 易立 阿里云资深技术专家<br /> <br />导读:云原生时代的来临,与Java 开发者到底有什么联系?有人说,云原生压根不是为了 Java 存在的。然而,本文的作者却认为云原生时代,Java 依然...

阿里巴巴云原生
23分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部