前端呈现olap表格二种实现方式:
后端拼接olap表格的html字符串,吐到前端,Hyperion应该就是采取这种方式实现的。
另外一种,就是前端vue/react/js方式实现。本文对第一种方式均进行阐述。
纯js实现方式:
1、绘制左顶第一个单元格
2、绘制列头区,判断单元格上是否有上卷、下钻图标、跨多少列colspan
3、判断是否有行维,如果没有行维度,仅仅根据结果输出一行factdata
4、如果有行维,则循环绘制每一行的标头、行数据
绘制左顶第一个单元格
一行行的绘制,先绘制表头部分(左顶部第一个单元格+后面的列表头)
按头部区占用的行数遍历
绘制左上角第一个单元格, 设置其rowspan、colspan,rowspan的值是行维区的列数,colspan的值是列维区占用的行数
if (i == 0 && axesCount > 1) {
html.append("<th style='border-top:solid 1px silver;' rowspan='")//第一行第一列添加顶部边框样式
.append(columnsSize) //列表头行数
.append("' colspan='")
.append(rowLength) //行表头列数
.append("' class='Locked1 scrollCR'>");
html.append(" </th>").append(Util.nl);
}
ps: viewGrid类中,有private int[][] colMembers = null; 第1[]表示行数,第2[]表示列,
colMembers.length 就是第一个单元格占用的跨行数。
生成列表头的总体过程:
viewGrid模型中 有属性:
// 行列维度成员
private int[][] rowMembers = null;
private int[][] colMembers = null;
这里对colMembers 进行遍历
按行循环遍历
按列循环遍历
获取该单元格是否需要加上上卷\下钻图标
while ((j + 1) < 本行最后的元素)
{
if(和上一个元素是一样的)
{j++;colspan++;} //确定colspan ,及需要跳过的列
}
根据上面的结果,拼接html字符串
绘制列头区,判断单元格上是否有上卷、下钻图标
(上卷、下钻图标)
对是否有上卷下钻图标的判断:
是否有子节点显示中:
是否有子节点处于显示中,返回1表示"+" , 返回 -1 表示"-", 返回0表示无上卷下钻符号
-1表示可上卷,1表示可下钻
判断逻辑如下:
- 从成员角度验证 如有无子代返回0,有 子代往下验证:dimMember.getHasChildren()==0
- 从表单角度验证 如果其子代不在表单中 返回0,其子代在表单中往下验证:
- 从组角度验证 如果其子代不在该组中 返回0, 其子代在组中往下验证,由于我们开始只搞一个组,所有这块可忽略?
- 从层级别验证? 我们的模型一般就一个层,级有多个。以列表头为例,我们以当前节点为起点,需要判断本行(本组?)后面节点上的数据,是否是本层的下一级元素。
从表单角度验证 如果其子代不在表单中 返回0,其子代在表单中往下验证的相关代码:
//index 是分组index ,这里遍历viewGrid中的List<List<List<DimMember>>> rowColDimMemberList
//进行遍历,判断是否要+-上卷、下钻标记
List<List<DimMember>> childList=rowColDimMemberList.get(index);
for(int j=0;j<childList.size();j++){
List<DimMember> dimMemberList=childList.get(j);
for(int k=0;k<dimMemberList.size();k++){
DimMember dimMemberInForm=dimMemberList.get(k);
if(dimMemberInForm.getParentId()==dimMember.getMemberId()){
flag=true; //flag=ture,表示存在下级成员,可能需要上卷、或者下钻
break;
}
}
if(flag){break;}
}
如果是列标题表头第一行元素,判断是否有“-”标志的代码如下:
member 就是当前遍历到元素,dimMember 当然是我们目标点位上的维度成员了,
if(member!=null && member.getParentId()==dimMember.getMemberId()){
childFlag=true; //可以有上卷标志
......;
}
不是第一行的判断,判断相对复杂?后面再补充。
一个头部单元格应该跨多少列?
这个好办,按列循环过程当中,判断下一个单元格是否和本单元格内容一致即可。即询问arr[i][j]!=arr[i][j+1],即可知道如何处理。
ps1:获取组号
/**
* 根据所给viewgrid的布局及布局上操作点位置的信息计算此操作点所在的布局分组号,返回分组号(从1开始)
*实现原理是:行、列组信息本来就有完整坐标,这个坐标信息在viewGrid对象中,把表格行列表头点位信息和这个坐*标数组比较即可得出每个点的组位置
* @param viewGrid 上卷或下钻的FormGrid
* @param mbrLayout 布局位置 (0 - 列 1 - 行)
* @param rowPoint (需要判断组号点位-行)
* @param colPoint (需要判断组号点位-列)
* @return
*/
public static int getGroupNumber(FormGrid viewGrid, int layout,
int rowPoint, int colPoint)
ps2:如果对于只有一组的情况,其实就是记录开始行、列号
记录展开 收缩位置的坐标
newDrillDownOrRollUpPoint(FormGrid viewGrid,int mbrLayout, int groupNumber, int rowPoint, int colPoint)
行维表头、事实数据区的绘制步骤,在这里就不展开描述,其过程和列表头的步骤类似。