Joe Messingschlager
Joe Messingschlager

Reputation: 11

In SAP GUI scripts, is it possible to select a column by name instead of by row position?

I have a script that successfully creates a layout variant. I choose the columns that I would like to be in the report by choosing the row number of where the column name is in the list, like this:

 session.findById("wnd[1]/usr/tabsG_TS_ALV/tabpALV_M_R1/ssubSUB_DYN0510:SAPLSKBH:0620/cntlCONTAINER1_LAYO/shellcont/shell").selectedRows = "142"

Since it is possible that sometime in the future, my item in row 142 could move up or down the list, I would like to pick it by its name, in this case the name, "Order". I've tried various methods using .select or .selected, but have not found anything that works. Ideally, it would look something like this:

 session.findById("wnd[1]/usr/tabsG_TS_ALV/tabpALV_M_R1/ssubSUB_DYN0510:SAPLSKBH:0620/cntlCONTAINER1_LAYO/shellcont/shell").selectedName = "Order"

Is anything like this possible?

Upvotes: 0

Views: 4567

Answers (3)

Ivan
Ivan

Reputation: 1304

The previous solutions work only if the layouts are visible in the list, otherwise if you have hundreds of layouts there, as it was in my case, it will fail to work.

Filters to the rescue:

session.findById("wnd[1]/usr/ssubD0500_SUBSCREEN:SAPLSLVC_DIALOG:0501/cntlG51_CONTAINER/shellcont/shell").selectColumn "VARIANT"
session.findById("wnd[1]/usr/ssubD0500_SUBSCREEN:SAPLSLVC_DIALOG:0501/cntlG51_CONTAINER/shellcont/shell").contextMenu
session.findById("wnd[1]/usr/ssubD0500_SUBSCREEN:SAPLSLVC_DIALOG:0501/cntlG51_CONTAINER/shellcont/shell").selectContextMenuItem "&FILTER"
session.findById("wnd[2]/usr/ssub%_SUBSCREEN_FREESEL:SAPLSSEL:1105/ctxt%%DYN001-LOW").text = "/ZSD52LAM"
session.findById("wnd[2]/usr/ssub%_SUBSCREEN_FREESEL:SAPLSSEL:1105/ctxt%%DYN001-LOW").caretPosition = 1
session.findById("wnd[2]").sendVKey 0
session.findById("wnd[1]/usr/ssubD0500_SUBSCREEN:SAPLSLVC_DIALOG:0501/cntlG51_CONTAINER/shellcont/shell").clickCurrentCell

By filtering the Layouts list column, we can directly target the layout we're interested it, regardless how many we have there.

You're welcome.

Upvotes: 0

Rogelio
Rogelio

Reputation: 1

I needed to do this as well, because I needed specific columns only in my layout. So instead, I chose my layout, saved it as a variant, then just called to get the layout. Pretty much the same method as from joe but looking for layout variant instead of column fields.

'open layout list
session.findById("wnd[0]/mbar/menu[5]/menu[2]/menu[1]").Select

'set list of all layouts
Set Layout = session.findById("wnd[1]/usr/ssubD0500_SUBSCREEN:SAPLSLVC_DIALOG:0501/cntlG51_CONTAINER/shellcont/shell")

'find Layout name in all the rows and choose it
iRows = Layout.RowCount()

For i = 0 To iRows - 1

  LayoutVariant = Layout.getCellValue(i, "VARIANT")

  If LayoutVariant = "/YourLayoutNameGoesHere" Then

    Layout.currentCellRow = i

    Layout.clickCurrentCell

    Exit For

  End If

Next
End Sub

modified this from this SAP thread

Upvotes: 0

Joe Messingschlager
Joe Messingschlager

Reputation: 11

It is possible to select from an SAP listbox without knowing which row contains the field that you want to use. Basically, you can step through the rows by row number and see if the current row's value is equal to field you want to display. Since SAP uses multiple processes for this, this solution only works for simple listboxes. I have solutions for listboxes displaying tables. If want to see that solution, let me know.

When I first wrote this code, I started at row zero each time and went towards the bottom of the listbox to find each subsequent item. This is a later version the process changes the search direction from the current row based predicting if the next field name is above or below alphabetically.

Create an object for the SAP listbox:

    Public gridView As Object

Put the SAP listbox into gridView and call the subroutine to look through the items in the listbox. The named range "mnHead" is the location of the first field name desired in the layout with the rest following in the same column.

    Set gridView = session.findById("wnd[1]/usr/tabsG_TS_ALV/tabpALV_M_R1/ssubSUB_DYN0510:SAPLSKBH:0620/cntlCONTAINER1_LAYO/shellcont/shell")
    Call getFields("mnhead")

The subroutine:

Sub getFields(fNames As String)
Dim i, j, k, m, n As Integer
Dim str1, str2, str3, str4, str5 As String
j = 0                                                      ' j is counter for loop - it points at the current desired field name
k = 0                                                      ' k is start for the item to check
m = 1                                                      ' m is counter step 1 for alpha, -1 for anti-alpha
str3 = "0000000000000000"                                  ' padding for later compare
n = gridView.rowcount - 1                                  ' n = the number of rows in the listbox, it starts at row zero, so take one away
Do While Range(fNames).Offset(j, 0) <> ""                  ' loop to get all the fields
  str2 = Range(fNames).Offset(j, 0)                        ' put the desired field name in string var str2
  For i = k To n Step m                                    ' loop through the rows in the listbox
    gridView.currentCellRow = i                            ' scroll to the row number i
    gridView.SetCurrentCell i, "SELTEXT"                   ' select the item in row i
    If gridView.GetCellValue(i, "SELTEXT") = str2 Then     ' get the value in row I and see if it's the same as the field name wanted
      str1 = str2                                          ' it's the same so save the heading in temp variable str1
      Exit For                                             ' found so exit the loop
      End If
    Next i
  If i >= gridView.rowcount Then                           ' if we went all the way to the bottom with no match, give a message
    MsgBox ("Match not found for " & str2)
    Stop
    End If
  gridView.doubleClickCurrentCell                          ' double click on the row to send it to the left listbox
  str4 = Left(LCase(Left(Replace(str2, " ", ""), 14)) & str3, 15)
  str5 = Left(LCase(Left(Replace(Range(fNames).Offset(j + 1, 0), " ", ""), 14)) & str3, 15)
  If str4 <= str5 Then                                     ' continue alphabetically the list in next search
    If i < 0 Then k = 0 Else k = i                         ' check to see if we're below the first item and reset to first if we are
    m = 1                                                  ' count step is plus one
    n = gridView.rowcount - 1                              ' endpoint is the end of the alphabet
    Else
    If i > gridView.rowcount - 1 Then k = gridView.rowcount - 1 Else k = i      ' if we're past the end then reset to the end
    m = -1                                                 ' count step is minus one - anti-alpha
    n = 0                                                  ' endpoint is the beginning
    End If
  j = j + 1                                                ' increment j and reloop
  Loop

Upvotes: 0

Related Questions