Robotic Process Automation (RPA)

 View Only
  • 1.  Get the "ListViewItem" number from a "List Box"

    Posted Tue December 28, 2021 09:11 AM
    Hello everyone!

    I would like to take the number of the ListView Items from a ListBox (class name SysListView32). Some Windows applications has a "table" like the picture below (msinfo32.exe). I have used the recorder in order to take the Xpath from the ListBox. I still can't find any commands in order to get the number of rows from this screen element (List box '202'), in this case I have 40 ListView Items:


    I tried with Get Table and Get Table Informations commands receiving the error 'Control is not a type Itable'.

    Thanks.


    ------------------------------
    -------------------
    ENRICO ROMEO
    -------------------
    ------------------------------


  • 2.  RE: Get the "ListViewItem" number from a "List Box"

    Posted Tue January 04, 2022 06:59 AM
    The getOptions command returns a datatable with the data you need, then you just count the rows of the table.

    ------------------------------
    Joba Diniz
    Product Manager
    IBM
    ------------------------------



  • 3.  RE: Get the "ListViewItem" number from a "List Box"

    Posted Fri January 07, 2022 04:56 AM
    Hello,

    Thanks for your quick reply. I tried the "GetOptions" command many times using different selectors but I get always the same error "Could not find Test Control for Control Type list item and FrameWorkId:Win32 .

    Using the Get Value command I can get the value from a ListView Item (the first row of the list for example, the OS name: Microsoft Windows 10 Enterprise).
    (Xpath used for the selector is: /root/list[1]/listitem[41]/text[1] )

    From the following picture you can see the Get Options command result. I tried to get the data table from the whole list box with no success:
    (Xpath used for the selector is: /root/list[1] )

      What would you do?

    Thanks

    ------------------------------
    ENRICO ROMEO
    ------------------------------



  • 4.  RE: Get the "ListViewItem" number from a "List Box"

    Posted Thu January 20, 2022 10:09 AM
    Hi, I have provided @ENRICO ROMEO the solution for this. I'm sharing it here.
    Just change the testing variables to the appropriate values for you (my OS was in Spanish).
    The main script is get_table_from_listview_control.wal.

    I've broken down the problem into 3 parts:
    launch_or_attach_msinfo32.wal
    Responsible to launch the msinfo32 application.

    defVar --name window --type Window --output
    defVar --name processId --type Numeric --output
    defVar --name success --type Boolean
    waitWindow --useregex  --regexPattern "\"Información del sistema\"|\"System Information\"" --regexOptions "IgnoreCase" --recursive  --safesearch  --timeout "00:00:02" --comment "remember: always use \'Safe Search\'" window=value processId=processId success=success
    if --left "${success}" --operator "Is_True" --negate
        launchWindow --executablepath "msinfo32.exe" --safesearch  --timeout "00:00:04" --comment "remember: always use \'Safe Search\'" window=value processId=processId success=success
    endIf
    assert --message "Could not find system info window" --left "${success}" --operator "Is_True"
    focusWindow --window ${window}

    get_table_from_listview_control.wal
    Responsible to get the table from any ListView control. It works for the msinfo32.exe application or any other application that has this control. It also handles empty tables.

    defVar --name value --type String
    defVar --name lastControl --type Control
    defVar --name lastControlIndex --type Numeric
    defVar --name columnIndex --type Numeric
    defVar --name table --type DataTable --output
    defVar --name currentControl --type Control
    defVar --name rowIndex --type Numeric
    defVar --name totalColumns --type Numeric
    defVar --name values --type List --innertype String
    defVar --name scriptsFolder --type String
    defVar --name treePath --type String
    defVar --name treeControlXPath --type String
    defVar --name window --type Window
    defVar --name errorOnIfCommand --type Boolean
    #region testing data
    setVar --name "${scriptsFolder}" --value "C:\\Users\\JobertoDinizJunior\\Downloads"
    setVar --name "${treeControlXPath}" --value "/root/tree[1]"
    setVar --name "${treePath}" --value "Recursos de hardware/DMA"
    #endregion

    executeScript --isfromfile  --filename "${scriptsFolder}\\launch_or_attach_msinfo32.wal" --output "window=${window}" --comment "launches or attaches the \'msinfo.exe\'"
    attachWindow --window ${window}
    executeScript --isfromfile  --filename "${scriptsFolder}\\expand_SysTreeView32.wal" --parameters "scriptsFolder=${scriptsFolder},treePath=${treePath},controlXPath=${treeControlXPath},window=${window},interval=2000" --comment "expands the tree view as the \'expandTree\' command is not working for this tree"

    goSub --label BuildColumns --comment "build the table columns dynamically"

    goSub --label BuildRows --comment "build the table rows dynamically"

    logMessage --message "${table}" --type "Info"
    beginSub --name BuildColumns
        getControl --selector "XPath" --forcerefresh  --xpath "/root/list[1]/header[1]/headeritem[last()]" lastControl=control
        assert --message "Could not find last control of the header" --left "${lastControl}" --operator "Is_Null" --negate
        evaluate --expression "${lastControl.Index} + 1" --comment "xpath indexes start at \'1\' and the control.index starts at \'0\'" lastControlIndex=value
        for --variable ${columnIndex} --from ${lastControlIndex} --to 1 --step -1
            getControl --selector "XPath" --xpath "/root/list[1]/header[1]/headeritem[${columnIndex}]" currentControl=control
            addColumn --dataTable ${table} --columnname "${currentControl.InnerText}" --type String
            incrementVar --number ${totalColumns} --comment "unfortunately, \'table\' does not have \'Columns\' property =("
        next
    endSub
    beginSub --name BuildRows
        onError --label ErrorOnGetControl
        getControl --selector "XPath" --xpath "/root/list[1]/listitem[last()]" lastControl=control
        if --left "${lastControl}" --operator "Is_Null" --negate  --comment "only read rows if the \'lastControl\' exists. If it does not exist, it might mean the table is empty, and therefore no exception should be thrown"
            #region REMOVE THIS WHEN THE BUG IS FIXED
            if --left "${errorOnIfCommand}" --operator "Is_True"
                return
            endIf
            #endregion
            evaluate --expression "${lastControl.Index} + 1" --comment "xpath indexes start at \'1\' and the control.index starts at \'0\'" lastControlIndex=value
            for --variable ${rowIndex} --from ${lastControlIndex} --to 1 --step -1 --comment "loop each row"
                for --variable ${columnIndex} --from ${totalColumns} --to 1 --step -1 --comment "loop each column (cell)"
                    getValue --selector "XPath" --xpath "/root/list[1]/listitem[${rowIndex}]/text[${columnIndex}]" value=value
                    add --collection "${values}" --value "${value}"
                next
                addRow --valueset ${values} --dataTable ${table}
                clear --collection "${values}"
            next
        endIf
    endSub
    beginSub --name ErrorOnGetControl
    //This code should be really simple, however there is a BUG in the 'if' command that throws an error when checking for NULL in the 'lastControl' variable
        #region ENABLE THIS WHEN THE BUG IS FIXED
    //setVar --name "${lastControl}" --comment "when an error occurs in the \'BuildRows\', assign NULL to the \'lastControl\' and let the code continue."
    //recover
        #endregion
        
        #region REMOVE THIS WHEN THE BUG IS FIXED
        case --switches "CaseSwitchesAll"
            when --left "${wdg:error.Command}" --operator "Equal_To" --right if
            when --left "${wdg:error.Message}" --operator "Begins_With" --right "Object reference"
        then
            setVar --name "${errorOnIfCommand}" --value true
        otherwise
            setVar --name "${lastControl}"
        endCase
        recover
        #endregion
    endSub

    expand_SysTreeView32.wal
    This is not required for the problem, but I have created another generic script that expands the TreeView of any application similar to msinfo32.exe. The expandTree command is not working with this tree, but this script will.

    defVar --name controlXPath --type String --parameter
    defVar --name scriptsFolder --type String --parameter
    defVar --name treePath --type String --parameter
    defVar --name interval --type TimeSpan --parameter
    defVar --name nodes --type List --innertype String
    defVar --name node --type String
    defVar --name window --type Window --parameter
    #region testing
    setVarIf --variablename "${scriptsFolder}" --value "C:\\Users\\JobertoDinizJunior\\Downloads" --left "${scriptsFolder}" --operator "Is_Null_Or_Empty"
    setVarIf --variablename "${interval}" --value "00:00:02" --left "${interval}" --operator "Equal_To" --right 0
    setVarIf --variablename "${controlXPath}" --value "/root/tree[1]" --left "${controlXPath}" --operator "Is_Null_Or_Empty"
    setVarIf --variablename "${treePath}" --value "Recursos de hardware/DMA" --left "${treePath}" --operator "Is_Null_Or_Empty"
    if --left "${window}" --operator "Is_Null"
        executeScript --isfromfile  --filename "${scriptsFolder}\\launch_or_attach_msinfo32.wal" --output "window=${window}"
    endIf
    #endregion

    attachWindow --window ${window}
    splitString --text "${treePath}" --delimiteroption "CustomDelimiter" --customdelimiter "/" nodes=value
    foreach --collection "${nodes}" --variable "${node}"
        click --selector "Name" --doubleclick  --controlsimilarity 100 --forcerefresh  --name "${node}"
        delay --timeout "${interval}"
    endFor


    ------------------------------
    Joba Diniz
    Product Manager
    IBM
    ------------------------------



  • 5.  RE: Get the "ListViewItem" number from a "List Box"

    Posted Fri January 14, 2022 07:06 AM
    Ciao Enrico!

    Have you tried to use different selectors to identify the table? I dunno if it makes any difference, but worth of trying perhaps?

    ------------------------------
    Jukka Juselius
    Senior Solution Architect - IBM EMEA
    IBM RPA Program Lead for EMEA
    IBM Technology - Business Automation
    ------------------------------