excelvba64-bitsap-guiregedit

How to change SAP Logon language using VBA code to update it directly in Registry Editor


I am trying to rework a code from another topic (HERE) and the answer from user Storax to suit my current needs. However, in the quoted example the values are in Boolean type (1 and 0) while in my case they should be String (i.e. text).

I would like to create a simple code where:

  1. to reach the path Computer\HKEY_CURRENT_USER\SOFTWARE\SAP\General (from the Registry Editor/regedit.exe), to read and to store the initial value of the file "Language" REG_SZ as a constant (e.g. DE - German language*) in Sub_1;
  2. to change the value from the initial constant to the variable EN (i.e. English) in Sub_2;
  3. to revert back the change to the original/initial state (i.e. DE or the variable to become equal to the constant) in Sub_3.

*Remark: The initial value of the language can be different than DE, e.g. ES, FR, etc. or even EN.

Why? Because in another sub routine, I would like to call (in its very beginning) Sub_1 and Sub_2, then the steps of the main routine to follow as usual, and finally (at the very end) to call Sub_3 which to restore the remembered value of the language (i.e. the constant stored in Sub_1).

Or with other words, I would like to set SAP Logon language to be English (no matter which other language is chosen currently) in order to execute some steps in SAP for data extraction and when it is done, to reset the SAP Logon language back to its initial value.

Class Module clsRegistry2

Option Explicit

Function ReadRegKey(RegKey As String) As Variant
Dim wsh As Object
    Set wsh = CreateObject("WScript.Shell")
    On Error GoTo NoRegkey
    ReadRegKey = wsh.regread(RegKey)
    Set wsh = Nothing
    Exit Function
NoRegkey:
    ReadRegKey = ""
End Function

Function DeleteRegKey(RegKey As String) As Boolean
Dim wsh As Object
   Set wsh = CreateObject("WScript.Shell")
   On Error GoTo NoRegkey
   wsh.RegDelete RegKey
   DeleteRegKey = True
   Set wsh = Nothing
   Exit Function
NoRegkey:
    DeleteRegKey = False
End Function


Function WriteRegKey(RegName As String, RegValue As Variant, RegType As String) As Boolean
Dim wsh As Object
   Set wsh = CreateObject("WScript.Shell")
   On Error GoTo NoRegkey
   wsh.RegWrite RegName, RegValue, RegType
   WriteRegKey = True
   Set wsh = Nothing
   Exit Function
NoRegkey:
    WriteRegKey = False
End Function

Class Module clsSapgui2

Option Explicit
Const mRegNameBase2 = "HKEY_CURRENT_USER\Software\SAP\General\"
Const mLanguage = "Language"

Dim mRegKey As New clsRegistry

Property Get Language() As String
    UserScripting = ReadRegKey(mLanguage)
End Property

Property Let Language(newVal As String)
    WriteRegKey mLanguage, CBoolToVal(newVal)
End Property

Private Function CBoolToVal(bVal As Boolean) As Byte
    If bVal Then
        CBoolToVal = 1
    Else
        CBoolToVal = 0
    End If
End Function

Private Function ReadRegKey(sRegValue As String) As String
    Dim sRegName As String
On Error GoTo NoRegkey
    sRegName = mRegNameBase2 & sRegValue
    ReadRegKey = mRegKey.ReadRegKey(sRegName)
    Exit Function
NoRegkey:
    ReadRegKey = 0
End Function

Private Function WriteRegKey(sRegKey As String, ByVal sRegValue As String) As Boolean
    Dim sRegName As String
On Error GoTo NoRegkey
    sRegName = mRegNameBase2 & sRegKey
    WriteRegKey = mRegKey.WriteRegKey(sRegName, sRegValue, "REG_SZ")
    Exit Function
NoRegkey:
    WriteRegKey = "EN"
End Function

Module Z_SAP_Options

Sub Sub_2 ()
    Dim mySapGui2 As New clsSapgui2

    With mySapGui2
        .Language = "EN"
    End With

End Sub

When I run the sub routine, I receive the following error message "Compile error: ByRef argument type mismatch", highlighting (newVal).

Property Let Language(newVal As String)
    WriteRegKey mLanguage, CBoolToVal(newVal)
End Property

Again, this is the preexisting code which I tried to adapt. I believe the type should be changed from Boolean to String (or other). I couldn't write Sub_1 and Sub_3 so far. Apologies from my side. The VBA coding for Registry Editor is brand new territory for me.

I would appreciate highly if it is possible someone to assist me in resolving the case of mine.


Solution

  • Take a look at the extended version of the class below. However, I am not certain if this will be of much help to you. The key point is that you always need to completely restart SAPGUI for the changes to the registry to take effect. This means you must close every session and restart SAPLOGON

    You can test it with the following code

    Sub testit()
        Dim myGuiReg As New GuiReg
        
        Debug.Print myGuiReg.Language
        
        Dim savedUserLang As String
        savedUserLang = myGuiReg.Language
        
        myGuiReg.Language = "EN"
        
        ' do whatever is needed
        ' ATTENTION
        ' Restart of SAPGUI is neccessary otherwise
        ' changes do not have any effect
        
        
        myGuiReg.Language = savedUserLang
        
        
    End Sub
    

    Classes needed (Sorry, I renamed them)

    Class GuiReg

    Option Explicit
    
    ' Enumeration for SecurityLevel
    Enum guiLevel
        Disabled = 0
        Customized = 1
        StrictDeny = 2
    End Enum
    
    ' Enumeration for DefaultAction
    Enum guiAction
        Allow = 0
        Ask = 1
        Deny = 2
    End Enum
    
    ' Only certain combinations with SecurtiyLevel are allowed resp. reasonable
    ' SecurityLevel DefaultAction
    ' 0 0 , 1 0, 1 1, 1 2, 2 2
    
    Const mRegNameSecurity = "HKEY_CURRENT_USER\Software\SAP\SAPGUI Front\SAP Frontend Server\Security\"
    Const mUserScripting = "UserScripting"
    Const mWarnOnAttach = "WarnOnAttach"
    Const mWarnOnConnection = "WarnOnConnection"
    
    ' 0 = Deactivated, 1 = Allow , 2 = rule based
    Const mSecurityLevel = "SecurityLevel"
    ' Deafult Action
    Const mDefaultAction = "DefaultAction"
    
    Const mRegNameScripting = "HKEY_CURRENT_USER\Software\SAP\SAPGUI Front\SAP Frontend Server\Scripting\"
    Const mShowNativeWinDlgs = "ShowNativeWinDlgs"
    
    Const mRegNameLang = "HKEY_CURRENT_USER\Software\SAP\General\"
    Const mLang = "Language"
    
    Dim mRegKey As Registry
    
    Property Get DefaultAction() As Byte
        DefaultAction = ReadKey(mRegNameSecurity, mDefaultAction)
    End Property
    
    Property Let DefaultAction(nVal As Byte)
        WriteKey mRegNameSecurity, mDefaultAction, nVal
    End Property
    
    Property Get ShowNativeWinDlgs() As Byte
        ShowNativeWinDlgs = ReadKey(mRegNameScripting, mShowNativeWinDlgs)
    End Property
    
    Property Let ShowNativeWinDlgs(newVal As Byte)
        WriteKey mRegNameScripting, mShowNativeWinDlgs, newVal
    End Property
    
    Property Get UserScripting() As Boolean
        UserScripting = ReadKey(mRegNameSecurity, mUserScripting)
    End Property
    
    Property Let UserScripting(newVal As Boolean)
        WriteKey mRegNameSecurity, mUserScripting, CBoolToVal(newVal)
    End Property
    
    Property Get WarnOnAttach() As Boolean
        WarnOnAttach = ReadKey(mRegNameSecurity, mWarnOnAttach)
    End Property
    
    Property Let WarnOnAttach(newVal As Boolean)
        WriteKey mRegNameSecurity, mWarnOnAttach, CBoolToVal(newVal)
    End Property
    
    Property Get WarnOnConnection() As Boolean
        WarnOnConnection = ReadKey(mRegNameSecurity, mWarnOnConnection)
    End Property
    
    Property Let WarnOnConnection(newVal As Boolean)
        WriteKey mRegNameSecurity, mWarnOnConnection, CBoolToVal(newVal)
    End Property
    
    Property Get SecurityLevel() As Byte
        SecurityLevel = ReadKey(mRegNameSecurity, mSecurityLevel)
    End Property
     
    Property Let SecurityLevel(ByVal newVal As Byte)
        WriteKey mRegNameSecurity, mSecurityLevel, newVal
    End Property
    
    Private Function CBoolToVal(bVal As Boolean) As Byte
        If bVal Then
            CBoolToVal = 1
        Else
            CBoolToVal = 0
        End If
    End Function
    
    Property Get Language() As String
        Language = ReadKey(mRegNameLang, mLang)
    End Property
    
    Property Let Language(nVal As String)
        WriteKey mRegNameLang, mLang, nVal, REG_SZ
    End Property
    
    Private Function ReadKey(regKey As String, regValue As String) As Variant
    
        Dim regName As String
        
        On Error GoTo EH
    
        regName = regKey & regValue
        ReadKey = mRegKey.ReadKey(regName)
        Exit Function
    
    EH:
        ReadKey = ""
    
    End Function
    
    Private Function WriteKey(keyPath As String, key As String, ByVal newValue As String, Optional ByVal inpType As regType = REG_DWORD) As Boolean
    
        Dim regName As String
    
    On Error GoTo EH
    
        regName = keyPath & key
        WriteKey = mRegKey.WriteKey(regName, newValue, inpType)
        Exit Function
    
    EH:
        WriteKey = False
    
    End Function
    
    Function isGuiRunning()
        
        Dim sapAppl As Object
        
        On Error Resume Next
        Set sapAppl = GetObject("SAPGUI")
        On Error GoTo 0
        
        If sapAppl Is Nothing Then
            isGuiRunning = False
        Else
            isGuiRunning = True
        End If
    
    End Function
    
    Private Sub Class_Initialize()
        Set mRegKey = New Registry
    End Sub
    

    This is the class Registry (I renamed the class)

    Option Explicit
    
    Private wsh As Object
    
    Enum regType
        REG_DWORD = 0
        REG_SZ = 1
        REG_EXPAND_SZ = 2
        REG_BINARY = 3
    End Enum
    
    Function ReadKey(key As String) As Variant
    
        On Error GoTo EH
            
        ReadKey = wsh.RegRead(key)
        Exit Function
    
    EH:
        ReadKey = vbNullChar
    
    End Function
    
    
    Function DeleteKey(key As String) As Boolean
    
        On Error GoTo EH
        
        wsh.RegDelete key
        DeleteKey = True
        
        Exit Function
       
    EH:
        DeleteKey = False
    
    End Function
    
    Function WriteKey(key As String, ByVal Value As Variant, Optional ByVal inpType As regType = REG_DWORD) As Boolean
        ' regType could be REG_SZ, REG_EXPAND_SZ, REG_DWORD, REG_BINARY
        
        On Error GoTo EH
       
        wsh.RegWrite key, Value, convRegType(inpType)
        WriteKey = True
       
        Exit Function
       
    EH:
        WriteKey = False
    
    End Function
    
    Private Function convRegType(inpType As regType) As String
    
        Select Case inpType
        
            Case REG_BINARY
                convRegType = "REG_BINARY"
            
            Case REG_DWORD
                convRegType = "REG_DWORD"
            
            Case REG_EXPAND_SZ
                convRegType = "REG_EXPAND_SZ"
        
            Case REG_SZ
                convRegType = "REG_SZ"
            
            Case Else
                convRegType = ""
        End Select
    
    End Function
    
    Private Sub Class_Initialize()
        Set wsh = CreateObject("WScript.Shell")
    End Sub