Kategori arşivi: SAP Business Objects IDT

Sap BO IDT UDT Veri Tabanı Eşanlamlı Tablolar (Database Table Synonym)

Sap Business Objects Information Design Tool IDT (veya Universe Design Tool UDT) ile veritabanındaki eşanlamlı tabloları (synonym) universe e (platforma) eklerken karşılaşılan durum.

Örnek senaryo: Veri tabanı Oracle. T tablosu A şemasında (schema) yer alsın. S sinonimi de B şemasında yer alsın. Raporlama işlemleri B şemasından yapıldığı için B şemasındaki sinonimin kullanılması istensin. Universe ün veri tabanı bağlantı kullanıcısı B olsun.

Yukarıdaki gibi bir senaryoda B.S (B şemasındaki S sinonimi) universe e eklendiğinde universe e tablo eklenir ama sinonimin kolonları IDT veya UDT ile tespit edilemez. Çünkü IDT ve UDT de sinonim kolonları ALL_TAB_COLUMNS ta (oracle da tabloların kolon bilgilerinin tutulduğu oracle dahili tablosunda) arar.

select * from ALL_TAB_COLUMNS where OWNER=’B’ and table_name=’S’;

IDT veya UDT eklenen tablo kolonlarını almak için yukarıdaki gibi bir sorgu gönderir; ama eklenen obje tipi sinonim olduğu için (tablo olmadığı için) ALL_TAB_COLUMNS da yer almaz ve kolonlar bulunamaz.

Eklenen sinonim universe e kolonsuz bir şekilde eklenmiş olur. Çözüm için universe e sinonim eklememek her zaman gerçek tabloyu eklemek tercih edilebilir ya da önce gerçek tablo eklenip sonra universe te şema adı ve tablo adı değiştirilir (Change Qualifier/Owner, Edit and Rename Table). Bu sayede kolonların gerçek tablodan alınması sağlanmış ve sorgular da sinonimden oluşturulmuş olur.

universe design tool (unv universe) toplu obje güncelleme (bulk object update) – 3

Önceki iki yazıda (birinci yazı, ikinci yazı) paylaşılan kodun tam tersini, yani gizleme yerine gösterme, yapan kod. İlgili objeleri görünür hale getirip gerekiyorsa üst klasörlerini de görünür hale getiren VBA Script.

Kod indirme adresi:
UnhideWithParents.xlsm.zip


Option Explicit 'require variables to be declared before being used
Dim DesignerApp As Designer.Application
Dim Univ As Designer.Universe
Dim Cls As Designer.Class
Dim Obj As Designer.Object
Dim Pdc As Designer.PredefinedCondition
Dim Wksht As Excel.Worksheet
Dim Ssttrr As String
Dim Rn As Integer
Dim WorksheetRowCount As Integer
Dim StatusChangeFlag As Boolean
Dim CheckList(1 To 20000, 1 To 2) As String
Dim DeepHideList(1 To 20000, 1 To 6) As String
' 1:Level, 2:ObjectType, 3:ObjectName, 4:ObjectStatus, 5:ParentClass, 6:HideChangeFlag
Dim DeepHideIndex As Integer
Dim DeepHideLevel As Integer
Dim WkshtDoc As Excel.Worksheet
Dim WkshtRes As Excel.Worksheet



' başlangıç metodu
Sub GetData()
    
    Set DesignerApp = New Designer.Application
    DesignerApp.Visible = True
    Call DesignerApp.LogonDialog
    Set Univ = DesignerApp.Universes.Open
    ''Set Univ = DesignerApp.Universes.Import("/Universes/ayhan_deneme", "base_unv_for_link")
    
    'DesignerApp.Visible = False
    
    Set Wksht = ThisWorkbook.Worksheets("Objects")
    Wksht.Unprotect
    
    WorksheetRowCount = Wksht.UsedRange.Rows.Count
    
    For Rn = 1 To WorksheetRowCount
        CheckList(Rn, 1) = Wksht.Cells(Rn, 1).Value
        CheckList(Rn, 2) = Wksht.Cells(Rn, 2).Value
    Next Rn
    
    Call GoClasses(Univ.Classes)
    
    DeepHideIndex = 1
    DeepHideLevel = 0
    Call DocumentDeepHideList(Univ.Classes, 0, DeepHideIndex, "Root")
    
    Set WkshtDoc = ThisWorkbook.Worksheets("Doc")
    For Rn = 1 To (DeepHideIndex - 1)
        If (DeepHideLevel < CInt(DeepHideList(Rn, 1))) Then
            DeepHideLevel = CInt(DeepHideList(Rn, 1))
        End If
        WkshtDoc.Cells(Rn, 1).Value = DeepHideList(Rn, 1)
        WkshtDoc.Cells(Rn, 2).Value = DeepHideList(Rn, 2)
        WkshtDoc.Cells(Rn, 3).Value = DeepHideList(Rn, 3)
        WkshtDoc.Cells(Rn, 4).Value = DeepHideList(Rn, 4)
        WkshtDoc.Cells(Rn, 5).Value = DeepHideList(Rn, 5)
        WkshtDoc.Cells(Rn, 6).Value = DeepHideList(Rn, 6)
    Next Rn
    WkshtDoc.Cells(Rn + 1, 1).Value = "Max Lvl"
    WkshtDoc.Cells(Rn + 1, 2).Value = CStr(DeepHideLevel)
    
    Call CalculateDeepUnhide(1)
    
    Set WkshtRes = ThisWorkbook.Worksheets("Res")
    For Rn = 1 To (DeepHideIndex - 1)
        WkshtRes.Cells(Rn, 1).Value = DeepHideList(Rn, 1)
        WkshtRes.Cells(Rn, 2).Value = DeepHideList(Rn, 2)
        WkshtRes.Cells(Rn, 3).Value = DeepHideList(Rn, 3)
        WkshtRes.Cells(Rn, 4).Value = DeepHideList(Rn, 4)
        WkshtRes.Cells(Rn, 5).Value = DeepHideList(Rn, 5)
        WkshtRes.Cells(Rn, 6).Value = DeepHideList(Rn, 6)
    Next Rn
    WkshtRes.Cells(Rn + 1, 1).Value = "Max Lvl"
    WkshtRes.Cells(Rn + 1, 2).Value = CStr(DeepHideLevel)
    
    Call FolderDeepUnhideClasses(Univ.Classes)
    
    Call FolderDeepUnhideObjects(Univ.Classes)
    
    'WkshtRes.Protect
    'WkshtDoc.Protect
    'Wksht.Protect
    
End Sub



' klasörler, objeler, filtreler üzerinde özyinelemeli gezilerek listedeki objeler görünür hale getiriliyor ve varsa açıklamasındaki kısım siliniyor
Sub GoClasses(Clss)
    
    Dim TempClsName As String
    Dim TempObjName As String
    Dim TempPdcName As String
    
    For Each Cls In Clss
        TempClsName = Cls.Name
        For Each Obj In Cls.Objects
            TempObjName = Obj.Name
            'Rn = Rn + 1
            'Wksht.Cells(Rn, 1).Value = Cls.Name
            'Wksht.Cells(Rn, 2).Value = Obj.Name
            StatusChangeFlag = False
            For Rn = 1 To WorksheetRowCount
                If (TempClsName = CheckList(Rn, 1)) And (TempObjName = CheckList(Rn, 2)) Then
                    StatusChangeFlag = True
                    Wksht.Cells(Rn, 3).Value = "done"
                End If
            Next Rn
            If (StatusChangeFlag = True) And (Obj.Show = False) Then
                Obj.Show = True
                Obj.Description = Replace(Replace(Replace(Obj.Description, " #hide_unused_object_201709#", ""), "#hide_unused_object_201709#", ""), "#Hide_Unused_Object_201709", "")
            End If
        Next Obj
        For Each Pdc In Cls.PredefinedConditions
            TempPdcName = Pdc.Name
            'Rn = Rn + 1
            'Wksht.Cells(Rn, 1).Value = Cls.Name
            'Wksht.Cells(Rn, 2).Value = Obj.Name
            StatusChangeFlag = False
            For Rn = 1 To WorksheetRowCount
                If (TempClsName = CheckList(Rn, 1)) And (TempPdcName = CheckList(Rn, 2)) Then
                    StatusChangeFlag = True
                    Wksht.Cells(Rn, 3).Value = "done"
                End If
            Next Rn
            If (StatusChangeFlag = True) And (Pdc.Show = False) Then
                Pdc.Show = True
                Pdc.Description = Replace(Replace(Replace(Pdc.Description, " #hide_unused_object_201709#", ""), "#hide_unused_object_201709#", ""), "#Hide_Unused_Object_201709", "")
            End If
        Next Pdc
        
        If Cls.Classes.Count > 0 Then
            Call GoClasses(Cls.Classes)
        End If
        
    Next Cls
    
End Sub



' hata ayıklayabilmek ve yapılan işlemleri takip edebilmek için universe objeleri excel in Doc sheet ine yaılıyor
Sub DocumentDeepHideList(Clss, Lvl, DeepHideIndex, DeepHideParentClassName)
    
    Dim TempClsName As String
    Dim TempObjName As String
    Dim TempPdcName As String
    
    For Each Cls In Clss
        'If (Cls.Show = True) Then
            TempClsName = Cls.Name
            
            DeepHideList(DeepHideIndex, 1) = CStr(Lvl)
            DeepHideList(DeepHideIndex, 2) = "Class"
            DeepHideList(DeepHideIndex, 3) = TempClsName
            DeepHideList(DeepHideIndex, 4) = Cls.Show ' "True" ' object status
            DeepHideList(DeepHideIndex, 5) = DeepHideParentClassName ' parent class
            DeepHideList(DeepHideIndex, 6) = "False" ' hide change flag
            DeepHideIndex = DeepHideIndex + 1
            
            For Each Obj In Cls.Objects
                'If (Obj.Show = True) Then
                    DeepHideList(DeepHideIndex, 1) = CStr(Lvl + 1)
                    DeepHideList(DeepHideIndex, 2) = "Object"
                    DeepHideList(DeepHideIndex, 3) = Obj.Name
                    DeepHideList(DeepHideIndex, 4) = Obj.Show ' "True" ' object status
                    'If (Obj.Show = True) Then
                    '    DeepHideList(DeepHideIndex, 4) = "True"
                    'Else
                    '    DeepHideList(DeepHideIndex, 4) = "False"
                    'End If
                    DeepHideList(DeepHideIndex, 5) = TempClsName ' parent class
                    DeepHideList(DeepHideIndex, 6) = "False" ' hide change flag
                    DeepHideIndex = DeepHideIndex + 1
                'End If
            Next Obj
            For Each Pdc In Cls.PredefinedConditions
                'If (Pdc.Show = True) Then
                    DeepHideList(DeepHideIndex, 1) = CStr(Lvl + 1)
                    DeepHideList(DeepHideIndex, 2) = "Filter"
                    DeepHideList(DeepHideIndex, 3) = Pdc.Name
                    DeepHideList(DeepHideIndex, 4) = Pdc.Show ' "True" ' object status
                    DeepHideList(DeepHideIndex, 5) = TempClsName ' parent class
                    DeepHideList(DeepHideIndex, 6) = "False" ' hide change flag
                    DeepHideIndex = DeepHideIndex + 1
                'End If
            Next Pdc
            
        'End If
        
        If Cls.Classes.Count > 0 Then
            Call DocumentDeepHideList(Cls.Classes, Lvl + 1, DeepHideIndex, TempClsName)
        End If
        
    Next Cls
    
End Sub



' görünür hale getirilen objeler sebebiyle görünür yapılması gereken üst klasörler var mı diye hesaplanıyor
Sub CalculateDeepUnhide(abc)
    Dim DeepHideLevel_i As Integer
    Dim DeepHide_i As Integer
    Dim Change_i As Integer
    Dim DeepHide_ii As Integer
    
    For DeepHideLevel_i = DeepHideLevel To 0 Step -1
        ' MsgBox "" & DeepHideLevel_i
        For DeepHide_i = 1 To (DeepHideIndex - 1)
            If (DeepHideList(DeepHide_i, 2) = "Class") And (DeepHideList(DeepHide_i, 4) = "False") And (DeepHideLevel_i = DeepHideList(DeepHide_i, 1)) Then
                Change_i = 0
                For DeepHide_ii = 1 To (DeepHideIndex - 1)
                    If ((DeepHide_i <> DeepHide_ii) And (CStr(CInt(DeepHideList(DeepHide_i, 1)) + 1) = DeepHideList(DeepHide_ii, 1)) And (DeepHideList(DeepHide_i, 3) = DeepHideList(DeepHide_ii, 5)) And (DeepHideList(DeepHide_ii, 4) = "True")) Then
                        Change_i = 1
                        Exit For ' DeepHide_ii = (DeepHideIndex - 1) ' Exit For
                    End If
                Next DeepHide_ii
                If (Change_i = 1) Then
                    DeepHideList(DeepHide_i, 4) = "True" ' object status
                    DeepHideList(DeepHide_i, 6) = "True" ' hide change flag
                End If
            End If
        Next DeepHide_i
    Next DeepHideLevel_i
    
End Sub



' hesaplama sonucu görünürlüğü değiştirilecek objelerin görünürlüğü aktif hale getiriliyor
Sub FolderDeepUnhideClasses(Clss)
    ' 1:Level, 2:ObjectType, 3:ObjectName, 4:ObjectStatus, 5:ParentClass, 6:HideFlag
    
    Dim TempClsName As String
    Dim TempObjName As String
    Dim TempPdcName As String
    
    For Each Cls In Clss
        TempClsName = Cls.Name
        
        For Rn = 1 To (DeepHideIndex - 1)
            If ((DeepHideList(Rn, 6) = "True") And (TempClsName = DeepHideList(Rn, 3))) Then
                Cls.Show = True
                Cls.Description = Replace(Replace(Replace(Cls.Description, " #hide_unused_object_201709#", ""), "#hide_unused_object_201709#", ""), "#Hide_Unused_Object_201709", "")
                WkshtRes.Cells(Rn, 7).Value = "done"
            End If
        Next Rn
        
        If Cls.Classes.Count > 0 Then
            Call FolderDeepUnhideClasses(Cls.Classes)
        End If
        
    Next Cls
    
End Sub



' klasör görünür hale getirilince altındaki tüm objeler de görünür duruma dönüştüğü için fazladan dönüşen objeler ilk görünürlük hallerine çevriliyor
Sub FolderDeepUnhideObjects(Clss)
    ' 1:Level, 2:ObjectType, 3:ObjectName, 4:ObjectStatus, 5:ParentClass, 6:HideFlag
    
    Dim TempClsName As String
    Dim TempObjName As String
    Dim TempObjShow As String
    Dim TempPdcName As String
    Dim TempPdcShow As String
    Dim DeepHide_i As Integer
    Dim Change_i As Integer
    
    For Each Cls In Clss
        TempClsName = Cls.Name
        
        For Each Obj In Cls.Objects
            TempObjName = Obj.Name
            TempObjShow = Obj.Show
            For DeepHide_i = 1 To (DeepHideIndex - 1)
                Change_i = 0
                If (TempClsName = DeepHideList(DeepHide_i, 5) And TempObjName = DeepHideList(DeepHide_i, 3)) Then
                    If (TempObjShow = DeepHideList(DeepHide_i, 4)) Then
                        Change_i = 0
                    Else
                        Change_i = 1
                    End If
                    Exit For
                End If
            Next DeepHide_i
            If (Change_i = 1) Then
                Obj.Show = DeepHideList(DeepHide_i, 4)
                WkshtRes.Cells(DeepHide_i, 8).Value = "done"
            End If
        Next Obj
        For Each Pdc In Cls.PredefinedConditions
            TempPdcName = Pdc.Name
            TempPdcShow = Pdc.Show
            For DeepHide_i = 1 To (DeepHideIndex - 1)
                Change_i = 0
                If (TempClsName = DeepHideList(DeepHide_i, 5) And TempPdcName = DeepHideList(DeepHide_i, 3)) Then
                    If (TempPdcShow = DeepHideList(DeepHide_i, 4)) Then
                        Change_i = 0
                    Else
                        Change_i = 1
                    End If
                    Exit For
                End If
            Next DeepHide_i
            If (Change_i = 1) Then
                Pdc.Show = DeepHideList(DeepHide_i, 4)
                WkshtRes.Cells(DeepHide_i, 8).Value = "done"
            End If
        Next Pdc
        
        If Cls.Classes.Count > 0 Then
            Call FolderDeepUnhideObjects(Cls.Classes)
        End If
        
    Next Cls
    
End Sub

universe design tool (unv universe) toplu obje güncelleme (bulk object update) – 2

Önceki yazıda paylaşılan kodun performansı iyileştirilmiştir. Ayrıca toplu obje gizleme işlemi sonucunda boş kalan klasörleri de belirleyip gizleme yapmaktadır.


Option Explicit 'require variables to be declared before being used
Dim DesignerApp As Designer.Application
Dim Univ As Designer.Universe
Dim Cls As Designer.Class
Dim Obj As Designer.Object
Dim Pdc As Designer.PredefinedCondition
Dim Wksht As Excel.Worksheet
Dim Ssttrr As String
Dim Rn As Integer
Dim WorksheetRowCount As Integer
Dim StatusChangeFlag As Boolean
Dim CheckList(1 To 20000, 1 To 2) As String
Dim DeepHideList(1 To 20000, 1 To 6) As String
' 1:Level, 2:ObjectType, 3:ObjectName, 4:ObjectStatus, 5:ParentClass, 6:HideFlag
Dim DeepHideIndex As Integer
Dim DeepHideLevel As Integer
Dim WkshtDoc As Excel.Worksheet
Dim WkshtRes As Excel.Worksheet



' başlangıç metodu
Sub GetData()
   
    Set DesignerApp = New Designer.Application
    DesignerApp.Visible = True
    Call DesignerApp.LogonDialog
    Set Univ = DesignerApp.Universes.Open
    'Set Univ = DesignerApp.Universes.Import("/deneme_klasor", "deneme_unv")
   
    'DesignerApp.Visible = False
   
    Set Wksht = ThisWorkbook.Worksheets("Objects")
    'Wksht.Unprotect
   
    WorksheetRowCount = Wksht.UsedRange.Rows.Count
    'Rn = 0
   
    For Rn = 1 To WorksheetRowCount
        CheckList(Rn, 1) = Wksht.Cells(Rn, 1).Value
        CheckList(Rn, 2) = Wksht.Cells(Rn, 2).Value
    Next Rn
   
    Call GoClasses(Univ.Classes)
   
    DeepHideIndex = 1
    DeepHideLevel = 0
    Call DocumentDeepHideList(Univ.Classes, 0, DeepHideIndex, "Root")
   
    Set WkshtDoc = ThisWorkbook.Worksheets("Doc")
    For Rn = 1 To (DeepHideIndex - 1)
        If (DeepHideLevel < CInt(DeepHideList(Rn, 1))) Then
            DeepHideLevel = CInt(DeepHideList(Rn, 1))
        End If
        WkshtDoc.Cells(Rn, 1).Value = DeepHideList(Rn, 1)
        WkshtDoc.Cells(Rn, 2).Value = DeepHideList(Rn, 2)
        WkshtDoc.Cells(Rn, 3).Value = DeepHideList(Rn, 3)
        WkshtDoc.Cells(Rn, 4).Value = DeepHideList(Rn, 4)
        WkshtDoc.Cells(Rn, 5).Value = DeepHideList(Rn, 5)
        WkshtDoc.Cells(Rn, 6).Value = DeepHideList(Rn, 6)
    Next Rn
    WkshtDoc.Cells(Rn + 1, 1).Value = "Max Lvl"
    WkshtDoc.Cells(Rn + 1, 2).Value = CStr(DeepHideLevel)
   
    Call CalculateDeepHide(1)
   
    Set WkshtRes = ThisWorkbook.Worksheets("Res")
    For Rn = 1 To (DeepHideIndex - 1)
        WkshtRes.Cells(Rn, 1).Value = DeepHideList(Rn, 1)
        WkshtRes.Cells(Rn, 2).Value = DeepHideList(Rn, 2)
        WkshtRes.Cells(Rn, 3).Value = DeepHideList(Rn, 3)
        WkshtRes.Cells(Rn, 4).Value = DeepHideList(Rn, 4)
        WkshtRes.Cells(Rn, 5).Value = DeepHideList(Rn, 5)
        WkshtRes.Cells(Rn, 6).Value = DeepHideList(Rn, 6)
    Next Rn
    WkshtRes.Cells(Rn + 1, 1).Value = "Max Lvl"
    WkshtRes.Cells(Rn + 1, 2).Value = CStr(DeepHideLevel)
   
    Call FolderDeepHide(Univ.Classes)
   
    'WkshtRes.Protect
    'WkshtDoc.Protect
    'Wksht.Protect
   
End Sub



' excel listesindeki objeler, klasör ve objeler üzerinde özyinelemeli olarak gezilerek görünürlükleri devre dışı bırakılıyor
Sub GoClasses(Clss)
   
    Dim TempClsName As String
    Dim TempObjName As String
    Dim TempPdcName As String
   
    For Each Cls In Clss
        TempClsName = Cls.Name
        For Each Obj In Cls.Objects
            TempObjName = Obj.Name
            'Rn = Rn + 1
            'Wksht.Cells(Rn, 1).Value = Cls.Name
            'Wksht.Cells(Rn, 2).Value = Obj.Name
            StatusChangeFlag = False
            For Rn = 1 To WorksheetRowCount
                If (TempClsName = CheckList(Rn, 1)) And (TempObjName = CheckList(Rn, 2)) Then
                    StatusChangeFlag = True
                    Wksht.Cells(Rn, 3).Value = "done"
                End If
            Next Rn
            If (StatusChangeFlag = True) And (Obj.Show = True) Then
                Obj.Show = False
                Obj.Description = Obj.Description & " #hide_unused_object_201709#"
            End If
        Next Obj
        For Each Pdc In Cls.PredefinedConditions
            TempPdcName = Pdc.Name
            'Rn = Rn + 1
            'Wksht.Cells(Rn, 1).Value = Cls.Name
            'Wksht.Cells(Rn, 2).Value = Obj.Name
            StatusChangeFlag = False
            For Rn = 1 To WorksheetRowCount
                If (TempClsName = CheckList(Rn, 1)) And (TempPdcName = CheckList(Rn, 2)) Then
                    StatusChangeFlag = True
                    Wksht.Cells(Rn, 3).Value = "done"
                End If
            Next Rn
            If (StatusChangeFlag = True) And (Pdc.Show = True) Then
                Pdc.Show = False
                Pdc.Description = Pdc.Description & " #hide_unused_object_201709#"
            End If
        Next Pdc
       
        If Cls.Classes.Count > 0 Then
            Call GoClasses(Cls.Classes)
        End If
       
    Next Cls
   
End Sub



' ilgili excel verisine göre obje gizleme işinden sonra boş klasörleri tespit etmek için obje ve klasör envanteri çıkarılıyor
Sub DocumentDeepHideList(Clss, Lvl, DeepHideIndex, DeepHideParentClassName)
   
    Dim TempClsName As String
    Dim TempObjName As String
    Dim TempPdcName As String
   
    For Each Cls In Clss
        If (Cls.Show = True) Then
            TempClsName = Cls.Name
           
            DeepHideList(DeepHideIndex, 1) = CStr(Lvl)
            DeepHideList(DeepHideIndex, 2) = "Class"
            DeepHideList(DeepHideIndex, 3) = TempClsName
            DeepHideList(DeepHideIndex, 4) = "True" ' object status
            DeepHideList(DeepHideIndex, 5) = DeepHideParentClassName ' parent class
            DeepHideList(DeepHideIndex, 6) = "False"
            DeepHideIndex = DeepHideIndex + 1 ' hide flag
           
            For Each Obj In Cls.Objects
                If (Obj.Show = True) Then
                    DeepHideList(DeepHideIndex, 1) = CStr(Lvl + 1)
                    DeepHideList(DeepHideIndex, 2) = "Object"
                    DeepHideList(DeepHideIndex, 3) = Obj.Name
                    DeepHideList(DeepHideIndex, 4) = "True" ' object status
                    'If (Obj.Show = True) Then
                    '    DeepHideList(DeepHideIndex, 4) = "True"
                    'Else
                    '    DeepHideList(DeepHideIndex, 4) = "False"
                    'End If
                    DeepHideList(DeepHideIndex, 5) = TempClsName ' parent class
                    DeepHideList(DeepHideIndex, 6) = "False" ' hide flag
                    DeepHideIndex = DeepHideIndex + 1
                End If
            Next Obj
            For Each Pdc In Cls.PredefinedConditions
                If (Pdc.Show = True) Then
                    DeepHideList(DeepHideIndex, 1) = CStr(Lvl + 1)
                    DeepHideList(DeepHideIndex, 2) = "Filter"
                    DeepHideList(DeepHideIndex, 3) = Pdc.Name
                    DeepHideList(DeepHideIndex, 4) = "True" ' object status
                    DeepHideList(DeepHideIndex, 5) = TempClsName ' parent class
                    DeepHideList(DeepHideIndex, 6) = "False" ' hide flag
                    DeepHideIndex = DeepHideIndex + 1
                End If
            Next Pdc
           
        End If
       
        If Cls.Classes.Count > 0 Then
            Call DocumentDeepHideList(Cls.Classes, Lvl + 1, DeepHideIndex, TempClsName)
        End If
       
    Next Cls
   
End Sub



' en derin seviyeden en üst seviyeye doğru tümseviyelerde alt seviyesinde görünür obje olup olmadığına göre hesaplama yapılıyor
Sub CalculateDeepHide(abc)
    Dim DeepHideLevel_i As Integer
    Dim DeepHide_i As Integer
    Dim change_i As Integer
    Dim DeepHide_ii As Integer
   
    For DeepHideLevel_i = DeepHideLevel To 0 Step -1
        ' MsgBox "" & DeepHideLevel_i
        For DeepHide_i = 1 To (DeepHideIndex - 1)
            If (DeepHideList(DeepHide_i, 2) = "Class") And (DeepHideLevel_i = DeepHideList(DeepHide_i, 1)) Then
                change_i = 0
                For DeepHide_ii = 1 To (DeepHideIndex - 1)
                    If ((DeepHide_i <> DeepHide_ii) And (CStr(CInt(DeepHideList(DeepHide_i, 1)) + 1) = DeepHideList(DeepHide_ii, 1)) And (DeepHideList(DeepHide_i, 3) = DeepHideList(DeepHide_ii, 5)) And (DeepHideList(DeepHide_ii, 4) = "True")) Then
                        change_i = 1
                        Exit For ' DeepHide_ii = (DeepHideIndex - 1) ' Exit For
                    End If
                Next DeepHide_ii
                If (change_i = 0) Then
                    DeepHideList(DeepHide_i, 4) = "False" ' object status
                    DeepHideList(DeepHide_i, 6) = "True" ' hide flag
                End If
            End If
        Next DeepHide_i
    Next DeepHideLevel_i
   
End Sub



' gizlenecek olarak belirlenen klasörler gizleniyor
Sub FolderDeepHide(Clss)
    ' 1:Level, 2:ObjectType, 3:ObjectName, 4:ObjectStatus, 5:ParentClass, 6:HideFlag
   
    Dim TempClsName As String
    Dim TempObjName As String
    Dim TempPdcName As String
   
    For Each Cls In Clss
        TempClsName = Cls.Name
       
        For Rn = 1 To (DeepHideIndex - 1)
            If ((DeepHideList(Rn, 6) = "True") And (TempClsName = DeepHideList(Rn, 3))) Then
                Cls.Show = False
                Cls.Description = Cls.Description & " #hide_unused_object_201709#"
                WkshtRes.Cells(Rn, 7).Value = "done"
            End If
        Next Rn
       
        If Cls.Classes.Count > 0 Then
            Call FolderDeepHide(Cls.Classes)
        End If
       
    Next Cls
   
End Sub

universe design tool (unv universe) toplu obje güncelleme (bulk object update)

Sap Business Objects ortamında universelerin metadata sına ilgili sdk (software development kit) ile erişilebilir. Unv universe lere .net sdk ile unx lere java sdk ile erişilebilir.

VBA (Visual Basic Application) Scripts ile ilgili .net kütüphanesi kurulu olan ortamda, yani bizim durumumuzda Sap Business Objects Client Tools kurulu olan bir bilgisayarda VBA kodu ile Universe Design Tool uygulaması kod ile yönetilebilir (toplu işlemler otomatize edilebilir). VBA kodu excel üzerinde yazılıp çalıştırılabilir.

Bu yazıdaki amaç Unv universe lerdeki objeleri toplu olarak güncellemek (gizlemek, bulk object hide in unv).

.net sdk ile yazılmış örnek kodlar için Business Objects Board (BOB) un 2. kaynaktaki sayfasına göz atılabilir.

Windows XP sonrası (Windows 7, 10, …) işletim sistemlerinde, benim durumumda Windows 8.1, Excel üzerindeki VBA kodu çalıştırabilmek için C:\Program Files (x86)\SAP BusinessObjects\SAP BusinessObjects Enterprise XI 4.0\win32_x86\designer.exe yi uyumluluk ayarlarından yönetici olarak çalıştır işaretlemek gerekliydi. (designer.exe right click compatibility “run this program as administrator”) Ayrıca UAC den (Kullanıcı Hesap Kontrolü Ayarlarından, User Account Control Settings) bildirim seviyesini en düşüğe çekmek gerekiyordu. Ve sonra da Excel uygulamasının da yönetici olarak çalıştırılması gerekiyordu. (Run Excel as Administrator) Kaynak 3

Universe design tool ile universe obje yapısına erişim için 1. kaynaktaki Business Objects Object Model Diagram (OMD) dokümanına başvurulabilir. Kaynak 4 ve 5 teki iki örnekte de universe objelerine (sınıflarına) erişim kodu yer alıyor.


' Objects named excel sheet must include "class name" and "object name" information at column 1 and column 2 without any header line
' Objects isimli excel sayfası "klasör ismi" ve "obje ismi" bilgisini 1. ve 2. kolonlarda tumalıdır ve başlık satırı kullanılmamalıdır

Option Explicit 'require variables to be declared before being used
Dim DesignerApp As Designer.Application
Dim Univ As Designer.Universe
Dim Cls As Designer.Class
Dim Obj As Designer.Object
Dim Pdc As Designer.PredefinedCondition
Dim Wksht As Excel.Worksheet
Dim Ssttrr As String
Dim Rn As Integer
Dim WorksheetRowCount As Integer
Dim StatusChangeFlag As Boolean
Dim CheckList(1 To 10000, 1 To 2) As String


Sub GetData()
    
    Set DesignerApp = New Designer.Application
    DesignerApp.Visible = True
    Call DesignerApp.LogonDialog
    Set Univ = DesignerApp.Universes.Open
    
    'Set Univ = DesignerApp.Universes.Import("/deneme_klasor", "deneme_unv")
    'DesignerApp.Visible = False
    
    Set Wksht = ThisWorkbook.Worksheets("Objects")
    Wksht.Unprotect
    
    WorksheetRowCount = Wksht.UsedRange.Rows.Count
    
    For Rn = 1 To WorksheetRowCount
        CheckList(Rn, 1) = Wksht.Cells(Rn, 1).Value
        CheckList(Rn, 2) = Wksht.Cells(Rn, 2).Value
    Next Rn
    
    Call GoClasses(Univ.Classes)
    
    Wksht.Protect
    
End Sub


Sub GoClasses(Clss)
    
    For Each Cls In Clss
        For Each Obj In Cls.Objects
            StatusChangeFlag = False
            For Rn = 1 To WorksheetRowCount
                If (Cls.Name = CheckList(Rn, 1)) And (Obj.Name = CheckList(Rn, 2)) Then
                    StatusChangeFlag = True
                    Wksht.Cells(Rn, 3).Value = "done"
                End If
            Next Rn
            If (StatusChangeFlag = True) And (Obj.Show = True) Then
                Obj.Show = False
                Obj.Description = Obj.Description & " #hide_unused_object_201709#"
            End If
        Next Obj
        For Each Pdc In Cls.PredefinedConditions
            StatusChangeFlag = False
            For Rn = 1 To WorksheetRowCount
                If (Cls.Name = CheckList(Rn, 1)) And (Pdc.Name = CheckList(Rn, 2)) Then
                    StatusChangeFlag = True
                    Wksht.Cells(Rn, 3).Value = "done"
                End If
            Next Rn
            If (StatusChangeFlag = True) And (Pdc.Show = True) Then
                Pdc.Show = False
                Pdc.Description = Pdc.Description & " #hide_unused_object_201709#"
            End If
        Next Pdc
        
        If Cls.Classes.Count > 0 Then
            Call GoClasses(Cls.Classes)
        End If
        
    Next Cls
    
End Sub

Kod indirme adresi:
unv_bulk_update_objects.xlsm.zip

Sonraki yazı

Kaynaklar:
1) BO OMD (Object Model Diagram) dokümanı, alternatif adres
2) Business Objects Board SDK (VBA/ASP/JSP)
3) Excel VBA problems’ solutions
4) Document a universe using Excel and the Designer SDK
5) Mass update to object names / descriptions

sap bo universe ve oracle birlikte kullanımı en iyi pratikleri (best practices)

Veri ambarında Sap BO universe lerinin bağlandığı veri tabanı (database) Oracle tercih edilmiş ise tabloların partition larını kullanmak sorgu performansları için çok kritik önemdedir. Partition lı tablolar çoğunlukla işlem (fact) tablolarıdır. İşlem tablolarınında hem günlük aktarım ile (etl ile) veri ambarına alınma hem de hatalı günler için tekrar çalıştıralabilme hem de sorgularken performanslı sorgulayabilmek için işlem tarihine göre günlük partiton ile oluşturmak çok faydalı olacaktır. (Veri miktarı çok fazla ise günlük range partition + hash sub partition da kullanılabilir.) Burada partition ı diğer tablolar ile join lerken de verimli kullanabilmek için tarih bilgisinin saat detayı olmadan partition lanması önemlidir.

Veri ambarlarında (data warehouse, dwh) genellikle takvim (calendar) tablosu bulunur. Takvim tablosunda her bir gün için bir kayıt bulunur ve o günün çeşitli özellikleri tabloda yer alır. Örneğin: Tarih, Yıl, Ay Numarası, HaftaiçiMi, HaftasonuMu, ResmiTatilMi gibi.

Bir universe te birden fazla işlem (fact) tablosu context ler yardımıyla kullanılabilir. İşlem tablolarının da partition larını günlük (saat detaysız bir kolon ile) yaptığımız için takvim tablosunun tarih kolonuyla (inner) join leyerek universe e koyarsak. Takvim tablosu üzerinden bir obje ile filtrelemeyi yaptığımızda işlem (fact) tablosunun sadece ilgili partition larına erişim sağlanmış olur. Böylece sorgularımız hızlı sonuç döndürür. BO kullanıcıları raporlarını hızlı bir şekilde alabilirler.

Ek olarak işlem (fact) tablosu üzerindeki işlem tarihi doğrudan filtrede kullanıldığında oracle tabloya partition kullanarak erişmeyebilir. Sebebi Sap BO tarih alanlar üzerinde filtreleme yapıldığında sorgunun where ifadesine tarih tipinde değil de string olarak yollamasındandır. Örneğin yukarıdaki tablolarımız için:

select count(islem_1_no)
from islem_1
where islem_tarihi between ‘16.01.2017 00:00:00’ and ‘28.02.2017 00:00:00’

Yukarıdaki gibi sql sorgusu üretildiği için Oracle string i tarih tipine (ya da islem_tarihi ni string e) çevirdiği için partition kullanarak tablo erişimi yapmaz. Doğrudan islem_tarihi üzerinde filtreleme yapılması için hazır filtre (predefined filter) oluşturulabilir.

islem_1.islem_tarihi between to_date( @Prompt(‘İşlem 1 Baş. Tarihi’,’D’,,Mono,Free,Not_Persistent,) ,’DD.MM.YYYY HH24:MI:SS’) and to_date( @Prompt(‘İşlem 1 Bit. Tarihi’,’D’,,Mono,Free,Not_Persistent,) ,’DD.MM.YYYY HH24:MI:SS’)

Hazır filtre ile istemlerden (prompt) gelen değerler tarih tipine yukarıdaki gibi çevirilerek islem tablosuna partition kullanılarak erişim yapılmış olur.

maskeli alanları fonksiyon ile maskelemek

Sap BO universe lerinde (platform, evren) görüntülenmesi kritik öneme sahip alanlar (örneğin: kart no, gsm no, vb.) sadece yetkili kişiler tarafından görüntülenmesi gerekir. Böyle bir durumda genel yaklaşım bu önemli alanların bir kısmının görüntülenebildiği maskeli obje ve sadece yetkililerin görebildiği maskesiz obje oluşturulur.

Örnek olarak gsm numarasının ilk ve son 4 hanesinin gösterilmesini sağlayan “Gsm No Maskeli” ve Gsm Numarasının tamamının görüntülenebildiği “Gsm No Maskesiz” alanı oluşturulabilir. Sonra da maskesiz alan sadece yetkili kullanıcılara Business Security Profile (veya Access Restriction) ile yetki yerilir.

Bu yöntemden daha sade, kolay ve basit olarak şöyle bir yöntem kullanılabilir. İlgili obje için yetkili personeller (siciller) bir tabloda tutulur. Sadece bir tane Gsm No alanı oluşturulur. Alanın içinde bir veritabanı fonksiyonuna @Variable(“BOUSER”) değişkeni gönderilerek eğer yetkili ise maskesiz hali eğer yetkisiz ise maskeli hali gösterilir.

case when obje_yetkisi(‘@Variable(‘BOUSER’)’) = ‘var’ then gsm_no else substr(gsm_no,1,4)||’***’||substr(gsm_no,8,4) end