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

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

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);
    }

}

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

大家一起学习进步。

时间: 2024-11-03 05:19:55

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

用于对项目中密码生成MD5摘要和加盐的工具类

import java.security.MessageDigest; /** * 用于对项目中密码生成MD5摘要和加盐的工具类 * @author 彭锋 */ public final class MD5Util { private static final char[] hexadecimal = {'0','1','2','3','4','5','6', '7','8','9','a','b','c','d','e','f'}; /** * 根据指定的字符串,返回对应的MD5摘要结果 *

Android Button Maker(在线生成android shape xml文件的工具),真方便!

直接上地址:http://angrytools.com/android/button/ 使用起来超简单,如图: Android Button Maker is online tool to generate buttons code for Android Apps. Android API provide Drawable Resources where XML file defines geometric shape, including colors, border and gradien

使用POI做的一个生成Excel的工具类。包含了导出Excel和解析Excel方法

PoiExcelUtils.java /** * */ package com.common.office; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.List;

高仿webqq做的一个webos桌面效果和web聊天工具,桌面效果完好,功能强大

QQ技术交流群:159995692 /--------   暂时开放的測试       帐号/password:[88888888/1;666666/1]    ---------/ 正如大家所知的ExtJs在Ajax效果方面的强大效果.加上可自己定义扩展组件.是吸引企业和开发者的一个非常重要的部分. 脚本语言要写好,特别是ExtJs,是一个非常不easy的过程的. 本人从ExtJs2一路走来,心酸自知. ExtJs2以来版本号一直不稳定,即使是最原始的类库也是一直在改动的. 为了加强兼容性.可

Java使用Zxing生成、解析二维码工具类

Zxing是Google提供的关于条码(一维码.二维码)的解析工具,提供了二维码的生成与解析的方法. 1.二维码的生成 (1).将Zxing-core.jar 包加入到classpath下. (2).二维码的生成需要借助MatrixToImageWriter类,该类是由Google提供的; package com.qlwb.business.util; //导入省略... /** * 二维码工具类 * */ public class MatrixToLogoImageWriter { priva

浅析Android Camera开发中的三个尺寸和三种变形 (贡献一个自适配Picturesize和Previewsize的工具类)

转至 (http://blog.csdn.net/yanzi1225627/article/details/17652643) 经常听人问Camera开发中,各种变形问题,今天有空就在此梳理总结下. 三个尺寸: 1.Surfaceview的尺寸 Surfaceview是用来预览Camera的,当它全屏时就是Screen的大小. 2.Picturesize的尺寸 这是拍照后的PictureSize尺寸. 3.Previewsize的尺寸 这是预览时帧数据的尺寸. 三种变形: 1.预览画面的物体长宽

翻车现场:我用pytorch和GAN做了一个生成神奇宝贝的失败模型

前言 神奇宝贝已经是一个家喻户晓的动画了,我们今天来确认是否可以使用深度学习为他自动创建新的Pokemon.我最终成功地使用了生成对抗网络(GAN)生成了类似Pokemon的图像,但是这个图像看起来并不像神奇宝贝.虽然这个尝试失败了,但是我认为其他人可能会喜欢这个过程,现在把他分享出来. GAN生成对抗网络 这里不想花很多时间讨论GAN是什么,但是上面的图片只是一个非常简单的解释过程.训练了两个网络-鉴别器和生成器. 生成器学习如何吸收随机噪声并从训练数据生成看起来像图像的图像. 它通过将其生成

用java打造一个生成cookies和headers字典的工具

先上效果图: 经常抓包时出来的数据是这样的: 每次模拟的话都需要手动构建这些数据的键值对 这个操作很繁琐而且很容易出错所以我准备做一个这种小工具 分析文本发现可以直接搜索替换 java源代码: package com.mycompany.myapp2; import android.app.*; import android.os.*; import android.view.*; import android.widget.*; public class MainActivity extend

一个加速产生 Spring JDBC RowMapper 的工具类

在使用Spring JdbcTemplate 时,编写 RowMapper 实在是一件累人的工作.于是我写了一个根据实体类产生 RowMapper 的工厂类 RowMapperFactory,来避免直接编写 RowMapper.RowMapperFactory 暂不支持枚举. 下面就是 RowMapperFactory: import org.springframework.jdbc.core.RowMapper; import java.lang.reflect.Method; import