вторник, 11 декабря 2018 г.

Экстратор, виртуальник на трансформации

BI

Inverse routine:

  C_TH_FIELDS_INBOUND = I_TH_FIELDS_OUTBOUND.
  C_R_SELSET_INBOUND = I_R_SELSET_OUTBOUND.
  C_EXACT = RS_C_TRUE.

https://archive.sap.com/kmuuid2/f05d0b81-076a-2c10-44ab-f00b0b90ce38/Writing%20Inverse%20Routine%20with%20Expert%20Routine.pdf

http://www.denisreis.com/how-to-sap-bi-inverse-routinen-invertierungsroutinen-in-sap-bw/ - тут попонятней, хоть и на немецком...


Но не помогло, где то до start inverse рутине терялись переданные параметры.
Сделал передачу параметров через глобальные переменные класса.

ERP:

Все поля могут быть переданны как параметры в источник, галки не важны, от слова совсем.

Полей было много... было лень перечислять их, поэтому

* Select ranges
 DATA:
    lt_where    TYPE STANDARD TABLE OF char200,
    lt_condtab  TYPE TABLE OF hrcond,
    ls_condtab  LIKE LINE OF lt_condtab.

"collect values of restrictions
    clear ls_condtab.
    LOOP AT s_s_if-t_select
      ASSIGNING FIELD-SYMBOL()
      WHERE sign   = 'I'.

      ls_condtab-field =  -fieldnm.
      ls_condtab-opera = -option.
      ls_condtab-high  = -high.
      ls_condtab-low   = -low.
      APPEND ls_condtab TO lt_condtab.
    ENDLOOP.

    "create WHERE clause
    CALL FUNCTION 'RH_DYNAMIC_WHERE_BUILD'
      EXPORTING
        dbtable         = SPACE
      TABLES
        condtab         = lt_condtab
        where_clause    = lt_where
      EXCEPTIONS
        empty_condtab   = 1
        no_db_field     = 2
        unknown_db      = 3
        wrong_condition = 4
        OTHERS          = 5.

      OPEN CURSOR WITH HOLD @s_cursor FOR
      SELECT *
      FROM ZVTETATET
        WHERE (lt_where).

The elements in the "SELECT LIST" list must be separated using commas.

Нужен был left outer join на курсоре

Пока было условие на 1й таблице всё было хорошо

OPEN CURSOR s_cursor FOR
      SELECT V~FORM V~ID D~DAT
      FROM Table1 as V
        LEFT OUTER JOIN Table2 as D
        ON  V~docnum = D~docnum
        WHERE V~FORM EQ 'LC'.

Но после добавления условия на 2й таблице, возникла ошибка

The elements in the "SELECT LIST" list must be separated using commas.

Вариант решения

OPEN CURSOR @s_cursor FOR
      SELECT V~FORM, V~ID, D~DAT
      FROM Table1 as V
        LEFT OUTER JOIN Table2 as D
        ON  V~docnum = D~docnum
        WHERE V~FORM EQ 'LC'
             AND  D~DAT GT '20180101'.

воскресенье, 9 декабря 2018 г.

MDX

SELECT
NON EMPTY
  { [00O2TOGA0GQMBY3GPSFLP5TIR].Members }
ON COLUMNS,
NON EMPTY
  {
    {FILTER([0COMP_CODE].MEMBERS,   "All" <> [0COMP_CODE].[20COMP_CODE])}
   *{FILTER([0CALYEAR].MEMBERS,"All" <> [0CALYEAR].[20CALYEAR])}
  }
DIMENSION PROPERTIES
   [0COMP_CODE].[20COMP_CODE]
  ,[0CALYEAR].[20CALYEAR]

ON ROWS
FROM
  [cube/query]

 SAP VARIABLES
[!V000001] INCLUDING [0CALDAY].[20180505]
[0CMPCODE] INCLUDING [0COMP_CODE].[0001]
[!V000003] INCLUDING [0CALYEAR].[2018]

Нашел более производительный вариант, использовать c Level01.Member

SELECT
  {[Measures].[00O2TOGA0GQMBWHEA5HWM60RN]}
ON COLUMNS,
NON EMPTY {
  {[ZDIM1].[LEVEL01].Members}
 *{[ZDIM2].[LEVEL01].Members}
 *{[ZDIM5].[LEVEL01].Members}
}
DIMENSION PROPERTIES
  [ZDIM1].[2ZATT1]
 ,[ZDIM1].[2ZATT2]
 ,[ZDIM1].[1ZATT3]
 ,[ZDIM5].[5ZITEM]
 ,[ZDIM5].[20CALDAY]
 ,[ZDIM5].[10COMP_CODE]

ON ROWS
FROM
  [cube/query]]

WHERE {
  {[ZDIM1__ZATTR1].[valA],[ZDIM1__ZATTR1].[valB],[ZDIM1__ZATTR1].[valG]}
 *{[0INFOPROV].[cubeA],[0INFOPROV].[cubeB],[0INFOPROV].[cubeC]}
 *{[ZDIM2__ZATTR1].[#]}
}

SAP VARIABLES
  [!V000001] INCLUDING [ZDIM2__ZATTR1].[D]
 ,[!V000002] INCLUDING [ZDIM2].[USD]
 ,[!V000012] INCLUDING [0CALDAY].[20200101] : [0CALDAY].[20200421]


воскресенье, 20 мая 2018 г.

Hierarchy

После обновления ERP, часть иерархий из наборов перестала грузится. Система просто не видет части иерархий в ERP, а часть видит.

Есть немного пространственная нота на эту тему - 2162245
Но суть в следующем...

В функции GSBH_HIERARCHY_CATALOG_SETS происходит исключение наборов входящих в другой набор, если родительский набор(супернабор) имеет тип S - Одномерный набор

В качестве решения загружаю "отброшенные" иерархии уже из родительской иерархии. Т.е. сделал трансформацию самого объекта на себя. В принцинципе все работает четко, есть только пару ньюансов...

1. В фильтре DTP надо обязательно указывать тип объекта - там так устроен поиск.


2. Было лениво делать для каждой иерархии свою трансформацию.
Сделал одну, а имя иерархии беру из ограничений DTP

DATAlt_filter TYPE RSBK_TH_RANGE.
DATAl_HIENM   TYPE RSHIENM.
FIELD-SYMBOLS LIKE LINE OF lt_filter.
"get DTP filter

p_r_request
->GET_TH_RANGERECEIVING R_TH_RANGE lt_filter ).
"get node name
READ TABLE lt_filter
  
WITH KEY FIELDNM 'NODENAME'
  
ASSIGNING .
IF sy-subrc 0.

  l_HIENM 
-LOW.
  
TRANSLATE l_HIENM TO UPPER CASE.

  
"dummy hier - Don't let the word make your hard
  
IF l_HIENM SPACE.

    l_HIENM 
'ZTEST1'.
  
ENDIF.

  
LOOP AT SOURCE_PACKAGE_1
    
ASSIGNING .

    
-H_HIENM l_HIENM.
  
ENDLOOP.
ENDIF.

воскресенье, 14 января 2018 г.

Afe macroses

in ThisWorkbook

Public Sub Workbook_SAP_Initialize()

' register callbacks
Call Application.Run("SAPExecuteCommand", "RegisterCallback", "AfterRedisplay", "Callback_AfterRedisplay")
'Call Application.Run("SAPExecuteCommand", "RegisterCallback", "BeforePlanDataSave", "Callback_BeforePlanDataSave")
'Call Application.Run("SAPExecuteCommand", "RegisterCallback", "BeforePlanDataReset", "Callback_BeforePlanDataReset")
'Call Application.Run("SAPExecuteCommand", "RegisterCallback", "BeforeMessageDisplay", "Callback_BeforeMessageDisplay")
'Call Application.Run("SAPExecuteCommand", "RegisterCallback", "BeforeFirstPromptsDisplay", "Callback_BeforeFirstPromptsDisplay")

End Sub


Sub Callback_AfterRedisplay()

 'just do it sometning :)
End Sub


Bex 7

Sub CallBack(ParamArray varname())

  Application.Interactive = False
  Application.EnableEvents = False
  Application.DisplayAlerts = False
  Application.ScreenUpdating = False

On Error Resume Next: Err

Dim lData_Provider As String
lData_Provider = Right(varname(2), 11)
Set lRange = varname(1)

....

Err:
  Application.Interactive = True
  Application.EnableEvents = True
  Application.DisplayAlerts = True
  Application.ScreenUpdating = True
End Sub


User function (should be defined in module)

'Join dimension
Function JoinDim(DimName As String, Optional delimiter As String = ";")
    JoinDim = ""
 
    'SAPListOfMembers returns unique list values of dimension
    'But result depends of characteristic setting
    'so you can receive one-dimensional or multi-dimensional array as result
    Dim Dimension As Variant
    Dimension = Application.Run("SAPListOfMembers", "DS_1", "FILTER", DimName)
 
    Dim l As Integer
    m = UBound(Dimension)

    For Each a In Dimension
 
    i = i + 1
    If i = m + 1 Then        'take only 2nd values
      'Exit For              'if you would like to take 1ts values
      JoinDim = ""
    ElseIf i = m + m + 1 Then
      Exit For
    End If
 
    If a <> "#" And a <> "#/#" Then
   
      If InStr(1, JoinDim, a, vbTextCompare) = 0 Then
     
        If Len(JoinDim) > 0 Then
        JoinDim = JoinDim & delimiter
        End If
     
        JoinDim = JoinDim & a
      End If
    End If
    Next a
End Function
'ZL_PORT

https://www.reyemsaibot.com/2016/07/25/analysis-office-infofields-formulas-dashboard-functions/


RIBBON
https://www.reyemsaibot.com/2016/12/01/analysis-office-2-4-customize-user-interface/
https://answers.sap.com/questions/223594/sap-analysis-25-custom-ribbon-macro.html
https://help.sap.com/viewer/5dd171bef6df457d9172164f7fd7dd7c/2.5.2.0/en-US/a4dcdbabddad45c085c8179f3fe28f0b.html
https://www.youtube.com/watch?v=X1jXGF8NiFs


Sub Button1_Click()
  Dim lResult As Long
  lResult = Application.Run("SAPExecuteCommand", "PlanDataSave")
End Sub