自定義Report 變數儲存功能

leniz發表於2010-08-12
  自定義Report 變數儲存功能
   
      如果已經使用EP並且完成了BI Integrated Into EP的使用者,可能對這個功能很熟悉,就是在顯示Report之前輸入變數之時,報表的上方有輸入變數值的儲存功能。
如果以上都沒做到,下文值得看下去,當然整體思路絕對可以用到其他地方,因為它提供了一個互動切入點。
        碰到使用者需要儲存Report的變數,這還是第一遭。
在顯示報表之前,系統會自動生成變數輸入介面,這個介面乃系統生成無法定製(或不知道如何做到)。這個介面在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 --&gt

 

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

初始化組裝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 = "";
//採用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 = "";
         $(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的規則,比如說單值

***signopt的欄位都是空的,所以要結合lowhighsignopt進行值的設定

***,有空值的情況,也要把optsign清空。
    
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/,如需轉載,請註明出處,否則將追究法律責任。

相關文章