在显示报表之前,系统会自动生成变量输入界面,这个界面乃系统生成无法定制(或不知道如何做到)。这个界面在SAP 提供的基于Excel 的Bex Analysis是可以保存输入的变量的,用户接触之后希望能够移植到Web上,甚至说添加一个button来保存自己输入的变量值即可。需求简单明确,IT 捶胸顿足。
开始试图去发现,是否系统本身有这个功能,只是没人发扬光大而已,不过没有结果。以此同时,用户提到是否可以显示打开用户保存的View,还真在Web Application Designer发现相关控件,是一个Dropdown List。系统提供Save View的Button,这个一点我开始忽视了,这时突然觉得两者的相同之处,都是保存值到BW,无非都是提交Form给server处理,是否可以借鉴?答案是肯定的。
首先分析Save View Button的代码,通过WAD打开标准模板0ADHOC_TABLE
<!-- Save View -->
title=" "
href="JavaScript.:SAPBWOpenWindow(SAP_BW_URL_Get() + '&CMD=PROCESS_HELP_WINDOW&HELP_SERVICE=HW_SAVE_VIEW&item=QueryName', 'SaveView',500,250);">
看上去比较长,不过分析之后会发现关键是这里执行了一段Javascript,所以可以把关键部分拿出来分析。SAPBWOpenWindow 为Function 名,传入几个参数,第一个是URL,其它可以不用管它。用过BW的人对里面的某些关键字一定熟悉了,比如CMD,HELP_SERVICE,ITEM。对,这里用到了SAP Command URLs(即传说中的WebAPI)。所以这次的突破点就是:如果定制SAP Command URLs。
我们先来看看Save View是如何实现的:
前提:为了使用这个命令,必须将help service 注册到某个Web Item。就是将下述属性加入到web Item 中。
Attribute | Description |
HELP_SERVICE | Name of the help service (SAVE_VIEW) |
HELP_SERVICE_CLASS | Technical name of the help service class (CL_RSR_WWW_HWIND_SAVE_VIEW) |
以上我们可以获知,需要用到类,需要Register。
首先我们通过CL_RSR_WWW_HWIND_SAVE_VIEW认识一下这个类的定义和使用。
1. 继承CL_RSR_WWW_HELP_WINDOW
2. 通过Method PROCESS_CMD处理接受到的参数及参数值
3. 通过i_r_parameter获取参数及参数值
上述三步算是吧Class的框架立了起来。另外涉及到如何传参数,以及如何保存参数的问题,随后一一道来。
要把变量值整批的传递,自然考虑用Form以及Form的Submit功能。到这里会想到几个问题。
1. 传什么
2. 变量的类型决定用户会输入不同的数据,或单值或区间或通配符等等
3. 输入框的数量是变化的,比如Multiple Selection,Select-Option
4. 如何把Save Button嵌入到标准的界面
Rsrrepdir - Directory of all reports
Rsrvarianttxt - Texts for Variants
Rsrvariantdir - Directory of Variants for Queries and Selection Objects
RSRVARIANT - Variant Values
看完这三个表,并结合之前存的一些变量值,可以发现内部存值采用的都是Option的方式,即:queryId、variantName、POS、SIGN,OPT,LOW,HIGH.这些都是很熟悉的东西。所以要保存的值就是变量的名称以及各种各样的值。
第二、三个问题其实斗可以通过第一个问题获得答案,因为SAP的存值无法采用Option的方式。
第四个问题比较麻烦,因为我们很清楚标准的变量输入界面我们是无法插足的,可是我们需要动态去取输入界面的参数值。最终选择采用的方式是Iframe,当然内嵌网页的技术都可以实现,只是Iframe用的方便些。
src="/sap/bw/BEx?sap-language=EN&bsplanguage=EN&CMD=LDOC&TEMPLATE_ID=ZWAD_SALES_BUDGET_DATA&VARIABLE_SCREEN=X" frameBorder=0 width="100%" name=if01
marginWidth=0>
采用Iframe还有一个原因是后面需要动态去改变Iframe的内容,用Javascript去改变SRC的值即可实现。
用户不单单需要保存,同时还需要选择各种已保存的变量组合,甚至可能要修改已保存的变量,这些都是需要考虑而用户不一定会说的。最终的样式如下:
我用了一个下拉框来显示系统已保存变量,以及用户新增的变量。因为没有现成的Dropdown List可以显示保存变量,所以我对表RSRVARIANT 建了一个Remote Cube,直接拉一个query显示变量列表,然后通过JS把值组装到Dropdown List。
Dropdown List的HTML
default
初始化组装Dropdown List的代码
$(document).ready(function(){
var arr = new Array();
//输出的是一个两列的表,第一列是技术名,第二列是描述,所以直接写谈不上逻辑
$("table[name='TABLE_1']").find("tr").each(function(i){
arr[i] = new Array();
$(this).find("td").each(function(j){
arr[i][j] = $(this).text();
});
});
var i ,opt_str;
for( i = 0; i < arr.length ; i ++){
opt_str = "" + arr[i][1] + "";
//采用JQuery把可能值写入下拉框 sel01是Dropdown List的ID
$(opt_str).appendTo($("#sel01"));
}
})
Dropdown List值变化的处理函数
function fs(vari){
var iframe1 = document.getElementById("if01");
var if_src = iframe1.src;
iframe1.src = if_src + "&variant=" + vari;
$("#DESCRIPTION").val( $("#sel01 option:selected").text() ); //添加到编辑框
$("#TECH_NAME").val( $("#sel01 option:selected ").val() ); //添加到编辑框
}
变量值名称保存form
action=
target=show>
……..
保存发送代码
function pre_submit(){
var flag = check_val();
if(flag == 'N'){return ;}
//以下代码实现将Iframe. 的页面的变量存放的Form的值存到当前Form
$("#selection").empty();
input_txt = $(window.frames["if01"].document).find("form[name='VARI']").html() ;
$("#selection").append(input_txt);
//提交表单
$("form[0]").submit();
$("#frm01").css("display", "none")
}
开始的时候我还在考虑变量值怎么取,后来干脆把这个变量Form都拷贝出来,一起传,到Process_CMD里面去处理。
为了简洁,我还特意把保存框,在不用的时候隐藏起来,可以通过下述Funtion去切换。
function show( ){
var flag;
flag = $("#frm01").css("display");
if( flag == 'none'){
$("#frm01").css("display", "block");
}else{
$("#frm01").css("display", "none")
}
}
之前我们有提到,要把Class注册到Web Item,所以我们就把Class注册到Table上,注意最后两个参数设定。
ITEM: TABLE_1
还有一个函数是用来判断值是否存在的
function check_val(){
var flag;
var is_ort;
var desc,tech_name;
var size;
var opt_txt;
flag = 'Y';
desc = $("#DESCRIPTION").val();
tech_name = $("#TECH_NAME").attr("value");
is_ort = $("#OVERWRITE").attr("checked");
if (is_ort != true){
size = $("#sel01").find("option[value='"+ tech_name +"']").size()
if(size > 0){
alert("The technical name is exist");
flag = 'N';
return flag;
}
size = $("option:contains('"+desc+"')").size();
if(size > 0){
alert("The description is exist");
flag = 'N'; return flag;
}
}
size = $("#sel01").find("option[value='"+ tech_name +"']").size()
if(size > 0){
$("#sel01").find("option[value='"+ tech_name
+"']").text(desc).attr("selected","selected");
}else{
opt_txt = "" + desc + "";
$(opt_txt).appendTo("#sel01").attr("selected","selected");
}
}
以上部分把页面处理的过程以及代码都做了交代,应该可以参照完成了。
第三部分是关于如何存储值,这里还需要好好看看输入些什么。如何看输入的值呢?第一到输入变量的界面,看Web的源代码,就可以很清楚的看到相应的input的内容,里面一大串的input就是变量值的内容。另外可以在class的接收部分去传递过来的值的规律。
处理代码如下:
***Get The Parameters List
CALL METHOD i_r_parameter->get_table
RECEIVING
r_th_parameter = para_itab.
***Get Technical Name & Descript
l_view_id = i_r_parameter->get_upper_case( i_id = 'TECH_NAME' ).
……
***Get Query COMPUID
SELECT SINGLE compuid INTO l_compuid
FROM rsrrepdir
WHERE compid = l_queryname.
***Get Variant Name List
SORT para_itab BY id index.
LOOP AT para_itab INTO para_wa WHERE id EQ 'VAR_ID'.
***Set the sign
LOOP AT para_itab INTO para_wa WHERE id EQ 'VAR_SIGN'.
***Set the operation
LOOP AT para_itab INTO para_wa WHERE id EQ 'VAR_OPERATOR'.
***Set the low value
LOOP AT para_itab INTO para_wa WHERE id EQ 'VAR_VALUE_EXT'.
***Set the Low value
LOOP AT para_itab INTO para_wa WHERE id EQ 'VAR_VALUE_LOW_EXT'.
***Set the HIGH value
LOOP AT para_itab INTO para_wa WHERE id EQ 'VAR_VALUE_HIGH_EXT'.
DATA: moff TYPE i,mlen TYPE i.
LOOP AT itab_dat INTO wa_dat.
***这里主要是处理时间格式的问题
IF wa_dat-low NE ''.
MOVE wa_dat TO str.
FIND REGEX '\d{2}[\.\\]\d{4}' IN str.
IF sy-subrc EQ 0.
CONCATENATE wa_dat-low+3(4) wa_dat-low+0(2)
INTO wa_dat-low.
ENDIF.
ENDIF.
***这里比较麻烦,因为后来发现传过来的值没有严格的遵从Option的规则,比如说单值
***sign和opt的栏位都是空的,所以要结合low和high对sign和opt进行值的设定
***,有空值的情况,也要把opt,sign清空。
IF wa_dat-sign EQ ''.
IF wa_dat-high NE '' .
wa_dat-sign = 'I'.
wa_dat-opt = 'BT'.
ELSEIF wa_dat-low ne ''.
wa_dat-sign = 'I'.
wa_dat-opt = 'EQ'.
ENDIF.
ELSE.
IF wa_dat-low EQ ''.
CLEAR: wa_dat-sign , wa_dat-opt .
ENDIF.
ENDIF.
MODIFY itab_dat FROM wa_dat INDEX l_index.
ENDLOOP.
***先删除后保存值
DELETE FROM rsrvariant WHERE compuid = l_compuid AND
vari = l_view_id.
MODIFY rsrvariant FROM TABLE itab_dat.
***Set variant dir
MODIFY rsrvariantdir FROM wa_dir.
***Set Variant Text
MODIFY rsrvarianttxt FROM wa_txt.
IF sy-subrc EQ 0.
COMMIT WORK.
ELSE.
ROLLBACK WORK.
ENDIF.
完毕!
完整文档下载
http://space.itpub.net/batch.download.php?aid=23978
//雷国海 2010.08.12
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/554557/viewspace-670861/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/554557/viewspace-670861/