1 报表(理解)
1.1 报表是什么?
报表:向上级报告情况的表格(更加直观的来看数据表格)
1.2 为什么要有报表,学来有什么用?–实际应用场景?
老板想看一下 强经理 这个月的采购情况 --> 老板采取的决策,去做一些事情
使用场景:
(1)老板想看一下 强经理 这个月的采购情况
(2)看一下 航航 销售情况
(3)整年(整季度 整月)的营业额 利润 --财务人员
1.3 怎么去使用?
报表的种类:
(1) 数据表格 – excel表格
(2)图形表格 --各种各样的图形表格
3w
what 是什么
why 为什么
how 怎么
数据表格 报表 – easyui-datagrid-groupview
步骤:
(1) 创建一个类报表对象 PurchasebillitemVo(页面要展示的数据字段此类不交给jpa管理)
groupField – 分组字段
添加一个构造方法用来给PurchasebillitemVo这个字段赋值
当我们需要进行一个多表查询进行一个页面展示的时候
此时可以使用两种方式
方式一 在数据库里面创建视图我们直接查询视图就好了
方式二 当我们查询出所有的数据之后呢 将我们需要展示再前台的数据进行封装重新赋值(写一个类设定需要展示的字段赋值),这样我们后台只需要将这个类传到前台就可以进行页面渲染了
今天我们使用的第二种方式
package cn.itsource.aisell.domain;
import org.apache.commons.lang3.time.DateUtils;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
// 这个类不交给jpa管理我们自己维护
public class PurchasebillitemVo {
private Long id; //编号
private String supplier; //供应商名称
private String buyer; //采购员名称
private String product; //产品名称
private String productType; //产品分类名称
private Date vdate; //交易时间
private BigDecimal num; //采购数量
private BigDecimal price; //价格
private BigDecimal amount; //小计 = 价格*数量
private Integer status; //采购单据状态
private String groupField = ""; //分组字段
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getSupplier() {
return supplier;
}
public void setSupplier(String supplier) {
this.supplier = supplier;
}
public String getBuyer() {
return buyer;
}
public void setBuyer(String buyer) {
this.buyer = buyer;
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
public String getProductType() {
return productType;
}
public void setProductType(String productType) {
this.productType = productType;
}
public Date getVdate() {
return vdate;
}
public void setVdate(Date vdate) {
this.vdate = vdate;
}
public BigDecimal getNum() {
return num;
}
public void setNum(BigDecimal num) {
this.num = num;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getGroupField() {
return groupField;
}
public void setGroupField(String groupField) {
this.groupField = groupField;
}
// 创建一个无参数的构造方法
public PurchasebillitemVo (){}
//purchasebillitem 查询出来所有的值
//groupBy 通过什么来分组
// 就是将查询出来的数据通过这个构造方法封装好就能直接传到前台进行页面炫染
public PurchasebillitemVo(Purchasebillitem purchasebillitem, String groupBy){
System.out.println("purchasebillitem"+purchasebillitem.getBill());
this.id = purchasebillitem.getId(); // 赋值操作
System.out.println("bill:"+purchasebillitem.getBill().getBuyer());
this.buyer = purchasebillitem.getBill().getBuyer().getUsername();
this.supplier = purchasebillitem.getBill().getSupplier().getName();// 供应商的名字
this.product = purchasebillitem.getProduct().getName();// 产品名字
this.amount = purchasebillitem.getAmount();// 总数量
this.num = purchasebillitem.getNum();
this.price = purchasebillitem.getPrice();//价格
this.productType = purchasebillitem.getProduct().getTypes().getName();// 产品类型的名字
this.status = purchasebillitem.getBill().getStatus();// 状态
this.vdate = purchasebillitem.getBill().getVdate();//交易时间赋值
//分组字段 默认按照供应商分组
this.groupField = this.supplier;
// 前台传什么分组字段就使用什么分组字段分组 默认按照供应商分组 (equal放在字段的后面防止字段为null的情况)
if(("o.bill.buyer.username").equals(groupBy)){
this.groupField = this.buyer;
}else if(("MONTH(o.bill.vdate)").equals(groupBy)){
//取到月份 若是按照月份分组则月份加1 他们的月份从0开始(所以这里的月份就是要使用int类型若是使用string类型则类型转换异常很麻烦)
int month = (DateUtils.toCalendar(vdate).get(Calendar.MONTH)+1);
this.groupField = month+"月";
}
}
purchasebillitemQuery 类 高级查询
package cn.itsource.aisell.query;
import cn.itsource.aisell.domain.Purchasebillitem;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.github.wenhao.jpa.Specifications;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
// 视图模型查询 做报表的时候使用
public class PurchasebillitemQuery extends BaseQuery {
//自身条件 前台传这几个字段来后台通过字段进行分组查询
private Date beginDate ;//开始时间
private Date endDate;//结束时间
private Integer status;//审核状态
//分组字段 前台传过来的字段通过什么来分组
private String groupBy;
//前台参数的值
private List params = new ArrayList<>();
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")// 设置格式什么格式
public Date getBeginDate() {
return beginDate;
}
// 注意此时返回json格式的时候只设置到了月份这一拦
@DateTimeFormat(pattern = "yyyy-MM-dd")
public void setBeginDate(Date beginDate) {
this.beginDate = beginDate;
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
public Date getEndDate() {
return endDate;
}
@DateTimeFormat(pattern = "yyyy-MM-dd")
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getGroupBy() {
return groupBy;
}
public void setGroupBy(String groupBy) {
this.groupBy = groupBy;
}
public List getParams() {
return params;
}
public void setParams(List params) {
this.params = params;
}
@Override
public Specification createSpecification() {
//处理结束时间
Date tempDate=null;
if(this.getEndDate() != null){
//若是不为空则添加一天 月份是从0开始的老外只有到11月 addDays 追加日期的方法
tempDate = DateUtils.addDays(this.getEndDate(), 1);
}
//ge 大于等 vdate>= beginDate and vdate< endDate+1 it小于 eq等于 自动发sql去根据条件查询
Specification<Purchasebillitem> specification = Specifications.<Purchasebillitem>and()
/* 开始时间查询的时间大于等于
结束时间为000所以需要加一天但是必须小于否则将查询到不属于这个时间的数据
*/
.ge(this.beginDate != null,"bill.vdate", this.getBeginDate())
.lt(this.endDate!=null, "bill.vdate",tempDate)
.eq(this.status != null ,"bill.status",this.getStatus())
.build();
return specification;
}
// 动态拼接sql的方法(做图形报表的时候使用)
public String getWhereSql(){
StringBuffer whereSql = new StringBuffer();
// 判断开始的事件不等于空 并且不等于空字符串 动态拼接
if(this.beginDate!=null && "".equals(this.beginDate)){
whereSql.append("and").append("o.bill.vdate >=?");
// 前台传过来的参数追加一个
params.add(this.beginDate);
}
if(this.endDate!=null && "".equals(this.endDate)){
Date tempDate=null;
if(this.getEndDate() != null){
tempDate = DateUtils.addDays(this.getEndDate(), 1);
}
whereSql.append("and").append(" o.bill.vdate < ?");
params.add(tempDate);
}
if(this.status != null && !"".equals(this.status)){
whereSql.append("and").append(" o.bill.status = ?");
params.add(this.status);
}
return whereSql.toString().replaceFirst("and", "where");
}
}
再service层将数据封装好:
//返回PurchasebillitemVo
@Override
public List<PurchasebillitemVo> findItems(PurchasebillitemQuery purchasebillitemQuery) {
List<PurchasebillitemVo> itemVos = new ArrayList<>();
//查询采购明细 通过传入高级查询来进行查询到所有的数据不分页
List<Purchasebillitem> items = purchasebillitemRepository.findByQuery(purchasebillitemQuery);
for (Purchasebillitem item : items) {
// 查询到所有的采购明细数据和分组条件 传入自定义的视图类进行封装
PurchasebillitemVo purchasebillitemVo = new PurchasebillitemVo(item, purchasebillitemQuery.getGroupBy());
// 将封装好的数据 再次封装进去一个list集合里面返回到前台
itemVos.add(purchasebillitemVo);
}
return itemVos;
}
(2)写了方法 findItems
先查询出purchsebillitem
在构造出 PurchasebillitemVo对象
(3)返回前台 --表格里面就进行展示
//查询数据 /purchasebill/page
//{total:111,rows:[{},{}]}
@RequestMapping("/findItems")
@ResponseBody
public Map findItems(PurchasebillitemQuery purchasebillitemQuery){
Map mp = new HashMap();
List<PurchasebillitemVo> items = iPurchasebillitemService.
findItems(purchasebillitemQuery);
mp.put("total", items.size());
mp.put("rows", items);
//存进去map封装成这种格式
return mp;
}
前台:
(1) 准备一个页面purchasebillitem.jsp -->(查询工具栏 分组的下拉)–》查询功能
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<%--引入头信息--%>
<%@include file="/WEB-INF/head.jsp" %>
<%--引入分组表格报表--%>
<script type="text/javascript" src="/easyui/plugin/groupview/datagrid-groupview.js"></script>
<%-- 组件 报表的框架 --%>
<script src="/highcharts/code/highcharts.js"></script>
<script src="/highcharts/code/highcharts-3d.js"></script>
<script src="/highcharts/code/modules/exporting.js"></script>
<script src="/highcharts/code/modules/export-data.js"></script>
<!-- 引入js-->
<script type="text/javascript" src="/js/purchasebillitem.js"></script>
</head>
<body>
<%--
easyui的时候,查看默认属性与事件
$.fn.{plugin}.defaults
弹出框html代码
--%>
<div id="dlg" class="easyui-dialog" data-options="width:800,height:500,buttons:'#bb',closed:true">
<form id="purchasebillForm" class="easyui-form" method="post" data-options="">
<input type="hidden" id="purchasebillid" name="id" >
<table cellpadding="5">
<tr>
<td>交易时间:</td>
<td><input class="easyui-datebox" name="vdate" data-options="required:true"></input></td>
</tr>
<tr>
<td>供应商:</td>
<td>
<input class="easyui-combobox" name="supplier.id"
data-options="valueField:'id',textField:'name',panelHeight:'auto',url:'/util/findAllSupplier'">
</td>
</tr>
<tr>
<td>采购员:</td>
<td>
<input class="easyui-combobox" name="buyer.id"
data-options="valueField:'id',textField:'username',url:'/util/getBuyer'">
</td>
</tr>
</table>
<!-- 采购单明细的按钮准备 -->
<div id="itemBtns">
<a href="javascript:;" id="btnInsert" class="easyui-linkbutton"
data-options="iconCls:'icon-add',plain:true">添加</a>
<a href="javascript:;" id="btnRemove" class="easyui-linkbutton"
data-options="iconCls:'icon-remove',plain:true">删除</a>
</div>
</form>
</div>
<%--查询工具栏 选择查询条件的三个框--%>
<div id="tb" style="padding:10px;height:auto">
<div>
<div id="cc" class="easyui-calendar"></div>
<form id="searchForm" action="/purchaseBill/download" method="post">
日期 : <input name="beginDate" class="easyui-datebox" style="height:32px" sharedCalendar="#cc">
- <input name="endDate" class="easyui-datebox" style="height:32px" sharedCalendar="#cc">
状态 :<select class="easyui-combobox" name="status"
data-options="panelHeight:'auto'">
<option value="">--请选择--</option>
<option value="0">待审</option>
<option value="-1">作废</option>
<option value="1">已审</option>
</select>
分组类型 :<select class="easyui-combobox" name="groupBy"
data-options="panelHeight:'auto'" style="width:100px">
<option value="o.bill.supplier.name">供应商</option>
<option value="o.bill.buyer.username">采购员</option>
<option value="MONTH(o.bill.vdate)">月份</option>
</select>
<a href="#" data-method="search" class="easyui-linkbutton" iconCls="icon-search">查找</a>
<a href="#" data-method="charts2D" class="easyui-linkbutton" iconCls="icon-search">2D图</a>
<a href="#" data-method="charts3D" class="easyui-linkbutton" iconCls="icon-search">3D图</a>
</form>
</div>
</div>
<!-- 采购订单的表格-->
<table id="purchasebillitemGrid"></table>
<div id="purchaseBillItemDialog" class="easyui-dialog" data-options="closed:true,modal:true" title="功能操作" style="width:600px;height:300px; ">
</body>
</html>
(2) puchasebillitem.js 写了一个查询数据的方法 已经
表格的初始化设置的方法
$(function () {
//表格
var purchasebillitemGrid = $("#purchasebillitemGrid");
//给所有a标签都注册一个事件
$("a").on("click", function () {
//动态获取data-method属性对应的值
var method = $(this).data("method");
//method不能为空
if(method){
//动态触发事件
itsource[method]();
}
});
//编辑明细表格
var purchasebillitemGrid = $('#purchasebillitemGrid');
itsource = {
//高级查询
"search": function () {
//把form表单元素,直接封装成一个json对象
var jsonObj = $("#searchForm").serializeObject();
//加载datagrid
purchasebillitemGrid.datagrid('load', jsonObj);
},
"charts2D": function () {
//获取查询表单的参数
var params = $("#searchForm").serializeObject();
//发送ajax请求 到后台查询
//$.post()
$("#purchaseBillItemDialog").dialog("center").dialog("open");
$.post("/purchaseBillitem/findCharts", params, function (result) {
//数据表格
Highcharts.chart('purchaseBillItemDialog', {
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie'
},
title: {
text: '采购订单的数据情况'
},
tooltip: {
pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '<b>{point.name}</b>: {point.percentage:.1f} %',
style: {
color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
}
}
}
},
series: [{
name: '总金额比例',
colorByPoint: true,
data: result
}]
});
});
},
"charts3D": function () {
//获取查询表单的参数
var params = $("#searchForm").serializeObject();
//发送ajax请求 到后台查询
//$.post()
$("#purchaseBillItemDialog").dialog("center").dialog("open");
$.post("/purchaseBillitem/findCharts", params, function (result) {
Highcharts.chart('purchaseBillItemDialog', {
chart: {
type: 'pie',
options3d: {
/* enabled 是否启用3dalpha: 45,
beta: 0 分别代表深度和倾斜度*/
enabled: true,
alpha: 45,
beta: 0
}
},
title: {
// 抬头标题
text: '我是不是你最疼爱的人'
},
tooltip: {
//pointFormat 鼠标上移的时候展示的数据
pointFormat: ' {series.name}: <b>{point.percentage:.1f}%</b>'
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
depth: 70,
dataLabels: {
enabled: true,
format: '{point.name}'
}
}
},
series: [{
type: 'pie',
name: '总金额比例',
data: result
}]
});
});
}
}
$('#purchasebillitemGrid').datagrid({
title:'分组表格',
fit:true,
fixed:true,
fitColumns:true,
toolbar:'#tb',
remoteSort:false,
singleSelect:true,
fitColumns:true,
url:'/purchaseBillitem/findItems',
columns:[[
{field:'id',title:'编号',width:100},
{field:'supplier',title:'供应商',width:100},
{field:'buyer',title:'采购员',width:100},
{field:'product',title:'产品',width:100},
{field:'productType',title:'产品类型',width:100},
{field:'vdate',title:'日期',width:100},
{field:'num',title:'数量',width:100},
{field:'price',title:'单价',width:100},
{field:'amount',title:'小计',width:100},
{field:'status',title:'状态',width:100,formatter:function (action) {
var data = {
0:"<div style='color:red;'>待审</div>",
1:"<div style='color: green'>已审</div>",
"-1":"<div><s>作废</s></div>"
};
return data[action];
}}
]],
groupField:'groupField',
view: groupview,
groupFormatter:function(value, rows){
//总数据量
var totalNum = 0;
//总金额
var totalAmount = 0;
for(var i=0;i<rows.length;i++){
var row = rows[i];
totalNum += row.num;
totalAmount += row.amount;
}
return value + ' - ' + rows.length + ' 条数据 '+ totalNum+' 件商品,总金额:'+totalAmount+"元";
}
});
});
排除错误:打印法
百度法
2 图形报表
数据展示的形式,看到不爽,如果图形展示,看到要舒服
做图形报表的框架–echarts highcharts 只需要传递数据
flash – 兼容性不是很好 容易崩溃 actionscript/javascript (flex)
html5 – canvas
不管是哪一个款报表,其实他的用法都差不多
思路:
(1) 下载
(2)引入
(3)看例子 --把我们需要的数据传递给组件 --它就会自动渲染图表
highcharts – 下载
2.1 有哪些图形表格
饼图
柱状图
线图…
任务 今日通关目标
第一关:数据表格
(1)datagrid-groupview
步骤:
后台:(1)创建PurchasebillitemVo
(2)构造方法用来封装数据
(3)多添加一个groupField分组字段
this.groupField = this.supplier;
if(("o.bill.buyer.username").equals(groupBy)){
this.groupField = this.buyer;
}else if(("MONTH(o.bill.vdate)").equals(groupBy)){
//取到月份
int month = (DateUtils.toCalendar(vdate).get(Calendar.MONTH)+1);
this.groupField = month+"月";
}
(4) service写了方法查询数据
第二关:图形表格
(2)2D 3D饼图
核心–:拼接sql
public List<Object[]> findCharts(PurchasebillitemQuery purchasebillitemQuery ){
//拼接jpql的语句 where group
String jpql = "select "+purchasebillitemQuery.getGroupBy()+",sum(o.bill.totalAmount) from Purchasebillitem o " + purchasebillitemQuery.getWhereSql()+
" group by "+purchasebillitemQuery.getGroupBy();
System.out.println("jpql---------:"+jpql);
List<Object[]> result = purchasebillitemRepository.findByJpql(jpql, purchasebillitemQuery.getParams().toArray());
return result;
}
前台就拷贝完事儿了