sap-guisilktest

Number of filled rows in a SapTable


I'm using Silk4J and I have a table which is reported as SapTable in the Locator Spy. From that table, I'm trying to get all the texts of the second column, but it hangs or terminates with an exception. In the following you find the code for my tries. Finally I reached the last row of the table, but it hangs there again.

In all examples I'm using a while loop instead of a for loop, because I want to insert more conditions later.

Try 1: Straight forward (I thought)

    SapTable table; // initialized somewhere else
    int maxrows = table.getRowCount();
    int row = 0;
    while (row < maxrows)
    {
        String text = table.getCell(row, COLUMN).getText();
        logger.debug(text);
        row++;
    }

However, this code prints all visible columns, then hangs.

Try 2: adding a PageDn keypress via Silk

Since try 1 printed only the visible cells, I thought adding a keypress every page could help. That was my code:

SapTable table; // initialized somewhere else
int maxrows = table.getRowCount();
int row = 0;
int visibleRows = table.getVisibleRowCount();
table.setFocus();
while (row < maxrows)
{
    String text = table.getCell(row, COLUMN).getText();
    logger.debug(text);
    row++;
    if (row % visibleRows == 0)
        window.sendVKey(VKey.PAGE_DOWN);
}

Unfortunately this results in an exception "The virtual key is not enabled".

Try 3: adding a PageDn keypress via AwtRobot

Since the built-in sendVKey method did not work, but pressing the PageDn manually works, I switched to an AwtRobot:

SapTable table; // initialized somewhere else
int maxrows = table.getRowCount();
int row = 0;
int visibleRows = table.getVisibleRowCount();
table.setFocus();
while (row < maxrows)
{
    String text = table.getCell(row, COLUMN).getText();
    logger.debug(text);
    row++;
    if (row % visibleRows == 0)
    {
        Robot robot = new Robot();
        robot.keyPress(KeyEvent.VK_PAGE_DOWN);
        robot.keyRelease(KeyEvent.VK_PAGE_DOWN);
    }
}

Pressing the key now works and I can see the table scroll to the next entry. However, my test application still hangs.

Try 4: Resetting the row count

Using the Locator Spy again, I found out that the index of the row is reset to zero, so I mimiced that in my code:

SapTable table; // initialized somewhere else
int maxrows = table.getRowCount();
int row = 0;
int visibleRows = table.getVisibleRowCount();
table.setFocus();
while (row < maxrows)
{
    String text = table.getCell(row, COLUMN).getText();
    logger.debug(text);
    row++;
    if (row % visibleRows == 0)
    {
        Robot robot = new Robot();
        robot.keyPress(KeyEvent.VK_PAGE_DOWN);
        robot.keyRelease(KeyEvent.VK_PAGE_DOWN);
        row = 0; // <-- 
    }
}

In this case, it prints the first N (number of visible) items of the list, scrolls to position N+1, prints the name of the first (!) row and then hangs when accessing the item with index 1 (after the reset).

Try 5: Sleeping

With some sleeping, I can reach the end of the table:

SapTable table; // initialized somewhere else
int maxrows = table.getRowCount();
int row = 0;
int visibleRows = table.getVisibleRowCount();
table.setFocus();
while (row < maxrows)
{
    String text = table.getCell(row, COLUMN).getText();
    logger.debug(text);
    row++;
    if (row % visibleRows == 0)
    {
        Robot robot = new Robot();
        robot.keyPress(KeyEvent.VK_PAGE_DOWN);
        robot.keyRelease(KeyEvent.VK_PAGE_DOWN);
        row = 0;
        Thread.sleep(1000); // <--
    }
}

In this case, I get all items in the table. But since I don't know when the table ends, it does another getCell() call, which results in a hang again.

The question

I'm really stuck. I've also looked for other methods like getting the real number of rows in the table (getRowCount() doesn't), but didn't find one yet.

How do I get the real number of rows of a SapTable in Silk4J?


Solution

  • It took some trying - the underlying SAP automation API is not really helpful in this case - but here is how you can make it work:

    private List<String> fetchItems() {
        SapTable table = desktop.find("sap.Table");
        SapVerticalScrollBar scrollBar = table.find("/SapVerticalScrollBar");
    
        // the scrollbar maximum value seems to be a more reliable
        // way to get the number of items than getRowCount
        int itemCount = scrollBar.getMaximum() + 1;
    
        List<String> items = new ArrayList<String>();
        int currentAbsoluteRow = 0;
        // the first loop iterates through the table page by page
        for (int firstRowInPage = 0; 
                firstRowInPage < itemCount; 
                firstRowInPage = scrollToNextPage(firstRowInPage)) {
    
            // this loop goes through the items of the current page
            for (int currentRowInPage = 0; 
                    currentRowInPage < table.getVisibleRowCount(); 
                    currentRowInPage++) {
    
                if(++currentAbsoluteRow > itemCount) {
                    // we've read all the available items
                    return items;
                }
    
                SapComponent cell = table.getCell(currentRowInPage, 1);
                items.add(cell.getProperty("Text").toString());
            }
        }
        return items;
    }
    
    private int scrollToNextPage(int firstRowInPage) {
        SapTable table = desktop.find("sap.Table");
        SapVerticalScrollBar scrollBar = table.find("/SapVerticalScrollBar");
        firstRowInPage += scrollBar.getPageSize();
        scrollBar.scrollTo(firstRowInPage);
        return firstRowInPage;
    }
    

    Some pitfalls that I encountered: