Tip: How to Find an SAP Label by its Text

In a few cases the result of an SAP report are a collection labels on the screen. You see in the object hierarchy the lbl for label and their column and row. lbl[53,0] means a label which starts at column 53 in row 0. In this example open fields,.

image

UiPath use the ID of the element to identify it.

image

But the ID could change, if more or less entries are visible. That’s where a search for a descriptive attribute would be helpful. Here an approach how to realize this with SAP GUI Scripting.

This approach uses the detection of the connection and session number from here. I added a tiny function to detect an Id of an UI element via its text (Function FindIdByText). This function loops over the area and compares each text of an element with the searched. If the text was found, the Id is returned.

'-Begin-----------------------------------------------------------------

'-Directives------------------------------------------------------------
Option Explicit

'-Function FindIdByText-------------------------------------------------
Function FindIdByText(oArea, strText)

  Dim cntObj, i, Child, Id

  On Error Resume Next
  cntObj = oArea.Children.Count()
  If cntObj > 0 Then
    For i = 0 To cntObj - 1
      Set Child = oArea.Children.Item(CLng(i))
      If InStr(UCase(Child.Text), UCase(strText)) Then
        Id = Child.Id
        Exit For
      End If
    Next
  End If
  On Error Goto 0
  FindIdByText = Id

End Function

'-Function FindSAPWindowsByHandle---------------------------------------
Function FindSAPWindowByHandle(hSAPWnd)

  Dim SapGuiAuto, app, CollCon, oCon, CollSes, oSes, hWnd, i, j

  Set SapGuiAuto = GetObject("SAPGUI")
  If Not IsObject(SapGuiAuto) Then
    Exit Function
  End If

  Set app = SapGuiAuto.GetScriptingEngine
  If Not IsObject(app) Then
    Exit Function
  End If

  '-Get all connections-------------------------------------------------
  Set CollCon = app.Connections()
  If Not IsObject(CollCon) Then
    Exit Function
  End If

  '-Loop over connections-----------------------------------------------
  For i = 0 To CollCon.Count() - 1

    Set oCon = app.Children(CLng(i))
    If Not IsObject(oCon) Then
      Exit Function
    End If

    '-Get all sessions of a connection----------------------------------
    Set CollSes = oCon.Sessions()
    If Not IsObject(CollSes) Then
      Exit Function
    End If

    '-Loop over sessions------------------------------------------------
    For j = 0 To CollSes.Count() - 1

      Set oSes = oCon.Children(CLng(j))
      If Not IsObject(oSes) Then
        Exit Function
      End If 

      If oSes.Busy() = vbFalse Then

        hWnd = oSes.findById("wnd[0]").Handle
        
        If hSAPWnd = hWnd Then
          FindSAPWindowByHandle = oSes.ID
        End If

      End If

    Next

  Next

End Function

'-Sub Main--------------------------------------------------------------
Sub Main()

  Dim HandleSAPWindow
  Dim sessionId, connectionNumber, sessionNumber
  Dim pos, Len

  HandleSAPWindow = CLng(WScript.Arguments.Item(0))

  sessionId = CStr(FindSAPWindowByHandle(HandleSAPWindow))

  pos = InStr(sessionId, "con[") + 4
  Len = InStr(pos, sessionId, "]") - pos
  connectionNumber = CLng(Mid(sessionId, pos, Len))

  pos = InStr(sessionId, "ses[") + 4
  Len = InStr(pos, sessionId, "]") - pos
  sessionNumber = CLng(Mid(sessionId, pos, Len))

'-SAP GUI Script - Begin------------------------------------------------

Dim SapGuiAuto, app, connection, session, Id, aId

Set SapGuiAuto = GetObject("SAPGUI")
If Not IsObject(SapGuiAuto) Then
  Exit Sub
End If

Set app = SapGuiAuto.GetScriptingEngine
If Not IsObject(app) Then
  Exit Sub
End If

app.HistoryEnabled = False

Set connection = app.Children(CInt(ConnectionNumber))
If Not IsObject(connection) Then
  Exit Sub
End If

If connection.DisabledByServer = True Then
  Exit Sub
End If

Set session = connection.Children(CInt(SessionNumber))
If Not IsObject(session) Then
  Exit Sub
End If

If session.Info.IsLowSpeedConnection = True Then
  Exit Sub
End If

Id = FindIdByText(session.findById("wnd[0]/usr"), _
  WScript.Arguments.Item(1))
aId = Split(Id, "/")
Id = aId(UBound(aId))

app.HistoryEnabled = True

'-SAP GUI Script - End--------------------------------------------------

  WScript.Echo(Id)

End Sub

'-Main------------------------------------------------------------------
Main

'-End-------------------------------------------------------------------

Here my test sequence.

It delivers with the SearchText variable “open” the correct result.

image

Now it is possible to use this Id as variable in the selector.

This example shows us very good how to combine the possibilities of SAP GUI Scripting with the possibilities of UiPath automation. On this way we can detect text on an SAP GUI for Windows screen fast. This approach can be a good complement or alternative to the procedures that already available in the portfolio of the UiPath activities.

2 Likes

HI @StefanSchnell

Thanks for the idea and approach!

Just want to let you and everyone know, that we have implemented this idea in UiPath itself :white_check_mark:

I am working right now on documenting this feature into official documentation for UiPath Studio 21.4 :construction_worker_man:

Starting from UiAutomation Activity Pack 21.2 and higher we are offering the possibilities to use additional attributes such as Text and/or Tooltip and Type of element direct in selector.

See the same example here:

With this out-of-the-box approach the automation is faster than invoke activity.

Best regards, Lev

PS: Case-Sensitive Selectors

For i = 0 To cntObj - 1
  Set Child = oArea.Children.Item(CLng(i))
  If InStr(UCase(Child.Text), UCase(strText)) Then
    Id = Child.Id
    Exit For
  End If
Next

in the sample script above you are using case-insensitive matching, which is also available in our selectors, see here Case-Sensitive Selectors

2 Likes

@LevKushnir

Excellent Lev :star_struck:
Great to know that.

This really helps in stabilizing SAP based Automation. We often face the issue of changing the ID elements after each SAP version upgrade.
Text based search always makes the Bot efficient.

Thank You @LevKushnir for an update…

2 Likes