Cognos开发一个基于DMR模型的同比环比报表

浏览: 3419

场景:现在存在一段时间的订单销售数据,我们需要根据日期查看不同时间段内的订单笔数的同比环比值

功能实现点:

1:同比环比实现

2:用户体验

3:实现效果

效果1:用户默认不用选择任何条件进入报表页面,默认显示从当前时间向前推一个月的数据

效果2:实现按照日期显示该天、该天前一天、该天后一天、去年该天的订单笔数

效果3:用户重新选择任意时间段,实现该时间段内该天、该天前一天、该天后一天、去年该天的订单笔数

下面就从报表开发来说一下具体的实现步骤:

【1】:模型开发与设计-建模过程不再阐述

 1.1:这里主要是开发一个雪花模型,由于时间有限,就创建一个维度和一个度量,结构如下

【2】:报表开发与设计

 2.1:创建提示页面1-目的是为了给报表运行中必要的参数赋初始值

 拖入一个提示页面,结构如下图所示

 html1处代码为:

<div style="display:none">
//隐藏提示页面中的对象

sbdate1,sedate1为日期提示控件,参数名为sbdate,sedate,名称为sbdate1,sedate1

bdate1,edate1为值提示控件,参数名为bdate,edate,名称为bdate1,edate1,值来自查询1,使用值都为[日]

html2处代码为:

复制代码

<script>
//得到昨天时间并格式化
function getyesterday()
{
var dtToday = new Date();
var dtYesterday = new Date( dtToday - 86400000 );
var strYesterday = [dtYesterday.getUTCFullYear(), dtYesterday.getMonth()+1, dtYesterday.getDate()].join("-");
return strYesterday;
}
//得到上一个月的昨天并格式化
function getyesterdaybeforeamonth()
{
var dtToday = new Date();
var dtYesterday = new Date( dtToday - 86400000 );
dtYesterday.setMonth(dtYesterday.getMonth()
-1);
var stryesterdaybeforeamonth= [dtYesterday.getUTCFullYear(), dtYesterday.getMonth()+1, dtYesterday.getDate()].join("-");
return stryesterdaybeforeamonth;
}
//得到日期提示的值并返回
function getsdate()
{
var sbdate=getFormWarpRequest().txtDatesbdate1.value;
var sedate=getFormWarpRequest().txtDatesedate1.value;
var returnstr=sbdate+'_'+sedate;
return returnstr;
}
//执行查询
function doquery(datastr)
{
//alert('来了');
//
alert(datastr);
//
接收日期提示来的值
var strarray= new Array();
strarray
=datastr.split("_");
var bdatestr=strarray[0];
var edatestr=strarray[1];
//接收2012-5-10这样的截取后的年月日
var barray=new Array();
var earray=new Array();
barray
=bdatestr.split("-");
earray
=edatestr.split("-");
//需要转换的格式:[订单数据分析].[日期维度].[日期维度].[日]->[all].[2013].[201310].[20131019]
//
处理已经从日期提示获取到的日期值的格式
var givebdate='[订单数据分析].[日期维度].[日期维度].[日]->[all].' + '['+barray[0]+'].' + '['+barray[0]+addzero(barray[1])+'].' + '['+barray[0]+addzero(barray[1])+addzero(barray[2])+']';
var giveedate='[订单数据分析].[日期维度].[日期维度].[日]->[all].' + '['+earray[0]+'].' + '['+earray[0]+addzero(earray[1])+'].' + '['+earray[0]+addzero(earray[1])+addzero(earray[2])+']';
//alert(givebdate);
//
alert(giveedate);

//为值提示赋值
var form=getFormWarpRequest();
var mylist1=form._oLstChoicesbdate1;//粗体部分为提示页面中值提示的名称,而不是参数名称。
var mylist2= form._oLstChoicesedate1;//粗体部分为提示页面中值提示的名称,而不是参数名称。

//alert(mylist1.length);
//
alert(mylist2.length);
//
给开始日期的值提示赋值
for(var i=0;i<mylist1.length;i++)
{
if(mylist1[i].value==givebdate)
{
mylist1[i].selected
="true";
}
}
//给结束日期的值提示赋值
for(var i=0;i<mylist2.length;i++)
{
if(mylist2[i].value==giveedate)
{
mylist2[i].selected
="true";
}
}
//提交form
promptButtonFinish();
}

//转换格式2014-3-9为2014-03-09
function addzero(str)
{
var returnstr;
if(str>0&&str<10)
{
returnstr
=0+str;
}
else
{
returnstr
=str;
}
return returnstr;
}

//初始化页面的方法
function init()
{
pickerControlsbdate1.setValue( getyesterdaybeforeamonth());
//给开始日期赋值
doquery(getsdate());//提交查询

}
</script>

<body onload="init()">
</body>

</div>

复制代码

 2.2:进入报表页面1,拖一个交叉表,在查询1中新建如下数据项

对应表达式分别为:

当前时间

currentMember([订单数据分析].[日期维度].[日期维度])

前一个时间

prevMember ([当前时间])

后一个时间

nextMember ([当前时间])

去年当前时间

parallelPeriod ([订单数据分析].[日期维度].[日期维度].[年],1,[当前时间])

环比前一个时间

value (tuple ([前一个时间],[订单笔数]))

环比后一个时间

value (tuple ([后一个时间],[订单笔数]))

同比去年当前时间

value (tuple ([去年当前时间],[订单笔数]))

日期

except (lastPeriods (-9000,[订单数据分析].[日期维度].[日期维度].[日]->?bdate?),lastPeriods (-9000,nextMember ([订单数据分析].[日期维度].[日期维度].[日]->?edate?)))

过滤

total([订单笔数] for [日期])

从图上可以看出,需要把过滤>0放入明细过滤器中,不显示无订单笔数的日期数据.

2.3设计报表页面,在交叉表拖入结构如下,使用查询为查询1

sbdate,sedate为日期提示控件,参数名为sbdate,sedate,名称为sbdate,sedate

bdate,edate为值提示控件,参数名为bdate,edate,名称为bdate,edate,值来自查询1,使用值都为[日]

html1出代码为:

复制代码

<div class="clsPromptComponent" pt="btn">

<script>
//得到来自日期提示的值并返回
function getsdate()
{
var sbdate=getFormWarpRequest().txtDatesbdate.value;
var sedate=getFormWarpRequest().txtDatesedate.value;
var returnstr=sbdate+'_'+sedate;
return returnstr;
}
//执行查询,主查询
function doquery(datastr)
{
//alert('来了');
//
alert(datastr);
//
接收日期提示来的值
var strarray= new Array();
strarray
=datastr.split("_");
var bdatestr=strarray[0];
var edatestr=strarray[1];
//接收2012-5-10这样的截取后的年月日
var barray=new Array();
var earray=new Array();
barray
=bdatestr.split("-");
earray
=edatestr.split("-");
//需要转换的格式:[订单数据分析].[日期维度].[日期维度].[日]->[all].[2013].[201310].[20131019]
//
处理已经从日期提示获取到的日期值的格式
var givebdate='[订单数据分析].[日期维度].[日期维度].[日]->[all].' + '['+barray[0]+'].' + '['+barray[0]+addzero(barray[1])+'].' + '['+barray[0]+addzero(barray[1])+addzero(barray[2])+']';
var giveedate='[订单数据分析].[日期维度].[日期维度].[日]->[all].' + '['+earray[0]+'].' + '['+earray[0]+addzero(earray[1])+'].' + '['+earray[0]+addzero(earray[1])+addzero(earray[2])+']';
//alert(givebdate);
//
alert(giveedate);

//为值提示赋值
var form=getFormWarpRequest();
var mylist1=form._oLstChoicesbdate;//粗体部分为提示页面中值提示的名称,而不是参数名称。
var mylist2= form._oLstChoicesedate;//粗体部分为提示页面中值提示的名称,而不是参数名称。

//alert(mylist1.length);
//
alert(mylist2.length);
//
给开始日期的值提示赋值
for(var i=0;i<mylist1.length;i++)
{
if(mylist1[i].value==givebdate)
{
mylist1[i].selected
="true";
}
}
//给结束日期的值提示赋值
for(var i=0;i<mylist2.length;i++)
{
if(mylist2[i].value==giveedate)
{
mylist2[i].selected
="true";
}
}

//提交form
promptButtonFinish();
}

//处理2014-3-9 格式为2014-03-09
function addzero(str)
{
var returnstr;
if(str>0&&str<10)
{
returnstr
=0+str;
}
else
{
returnstr
=str;
}
return returnstr;
}
//自写button按钮,样式可以拖一个自带按钮然后借鉴

</script>
<button type="button" name="tijiao" id="tijiao" class="bp" onmouseover="this.className = 'bp bph'" onmouseout="this.className = 'bp'" onclick="doquery(getsdate())" style="padding-left:10px;padding-right:10px;">查询</button>

<body onload="">

</body>

</div>

复制代码

html2处代码为

<div style="display:none">

html3处代码为

</div>

PS:html1为主要代码,html2与3的作用技术用一个层放入值提示,但是不显示。

【3】:查看效果

 3.1:用户第一次运行报表

 

3.2:选择从2013-01-01开始

     通过3.1和3.2可以看出数据显示正确

【4】:要点难点解析

 3.1:没有过滤为什么可以实现显示所选时间段的值?同比环比公式需要注意的是什么

 答:主要在于日期数据项的设计,里面用传参的方式实现了时间段的显示和同比环比

        

except (lastPeriods (-9000,[订单数据分析].[日期维度].[日期维度].[日]->?bdate?),lastPeriods (-9000,nextMember ([订单数据分析].[日期维度].[日期维度].[日]->?edate?)))

3.2:为什么要在提示页面即使用日期提示又使用值提示?同理为什么在报表页面即使用日期提示又使用值提示?

答:

第一问:由于之前已经写好了为日期提示赋值的代码,所以先给日期提示赋值,其实提示页面可以直接给值提示赋初始值,也可以不用日期提示,这里时间有限直接拿之前日期提示赋初始值的代码来用。

第二问:由于日期字段的特殊性,类似MemberUnique类型的格式'[订单数据分析].[日期维度].[日期维度].[日]->'必须用值提示的格式给’日期‘数据项传参,但是由于日这个层次的维度较多,选择不便,所以在用户选择方便使用日期提示选择,然后再点击查询的时候触犯onclick时间把日期提示的值赋给值提示,然后用值提示给'日期'数据项里面的参数传参,换一种思路解决日期提示参数格式不符合’日期‘传参的问题。

 3.3:同比环比通用公式

可以通用的公式

currentMember([订单数据分析].[日期维度].[日期维度])
prevMember ([当前时间])
nextMember ([当前时间])
value (tuple ([前一个时间],[订单笔数]))
value (tuple ([后一个时间],[订单笔数]))
value (tuple ([去年当前时间],[订单笔数]))

可以举一反三扩展的公式

parallelPeriod ([订单数据分析].[日期维度].[日期维度].[年],1,[当前时间])

通过上面的公式我们也可以向前一季度,前一月,前一周的同一天修改

except (lastPeriods (-9000,[订单数据分析].[日期维度].[日期维度].[日]->?bdate?),lastPeriods (-9000,nextMember ([订单数据分析].[日期维度].[日期维度].[日]->?edate?)))

通过上面的公式我们也可以根据[年]、[季度]、[月]等来作为同比环比的粒度。

文终于此     2014-5-21

推荐 4
本文由 kingwang 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

2 个评论

写的很清晰,一目了然。
写的很好,学习下

要回复文章请先登录注册