Количество заполненных строк в таблице SapTable

Я использую Silk4J и у меня есть таблица, которая сообщается как SapTable в шпионе локатора. Из этой таблицы я пытаюсь получить все тексты второго столбца, но он зависает или завершается с исключением. В следующем вы найдете код для моих попыток. Наконец я добрался до последнего ряда таблицы, но там снова висит.

Во всех примерах я использую цикл while вместо цикла for, потому что хочу добавить больше условий позже.

Попробуйте 1: прямо (я думал)

    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++;
    }

Однако этот код печатает все видимые столбцы, а затем зависает.

Попробуйте 2: добавление нажатия клавиши PageDn через Silk

Поскольку попытка 1 напечатала только видимые ячейки, я подумал, что добавление нажатия на каждую страницу может помочь. Это был мой код:

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);
}

К сожалению, это приводит к исключению "Виртуальный ключ не включен".

Попробуйте 3: добавление нажатия клавиши PageDn через AwtRobot

Поскольку встроенный sendVKey метод не работал, но нажатие PageDn вручную работает, я переключился на 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);
    }
}

Нажатие клавиши теперь работает, и я вижу, как таблица прокручивается до следующей записи. Тем не менее, мое тестовое приложение все еще зависает.

Попробуйте 4: Сброс счетчика строк

Снова используя Locator Spy, я обнаружил, что индекс строки сброшен на ноль, поэтому я подражал этому в своем коде:

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; // <-- 
    }
}

В этом случае он печатает первые N (количество видимых) элементов списка, прокручивает в положение N+1, печатает имя первой (!) Строки и затем зависает при доступе к элементу с индексом 1 (после сброса).).

Попробуйте 5: спать

Немного поспав, я могу дойти до конца стола:

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); // <--
    }
}

В этом случае я получаю все предметы в таблице. Но так как я не знаю, когда таблица заканчивается, она делает другое getCell() вызов, что приводит к зависанию снова.

Вопрос

Я действительно застрял. Я также искал другие методы, такие как получение реального числа строк в таблице (getRowCount() не), но еще не нашел.

Как получить реальное количество строк таблицы SapTable в Silk4J?

2 ответа

Решение

Потребовалось некоторое усилие - базовый API автоматизации SAP не очень помогает в этом случае - но вот как вы можете заставить его работать:

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;
}

Некоторые подводные камни, с которыми я столкнулся:

  • getRowCount() возвратил большее количество, чем было в реальных товарах
  • getVisibleRowCount() возвращает количество элементов, которые поместились бы на текущей странице, даже если не все строки были заполнены фактическими элементами
  • Возвращенные объекты ячеек действительны только до тех пор, пока ячейка находится на экране, поэтому вам нужно извлечь нужную информацию, прежде чем перейти к следующей странице.

Преамбула: мне нечего добавить к вашему ответу относительно Silk4J, я просто хочу добавить свою точку зрения как ABAP-разработчика относительно элемента управления SAP GUI, который соответствует «», это может помочь другим разработчикам Silk4J лучше понять, как он работает. ABAP — хорошо известный (старый) язык программирования SAP. Существует также библиотека SAP под названием SAP GUI Scripting, которую я описываю. У меня нет знаний о Silk4J, поэтому, возможно, мой ответ совершенно неверен, но, внимательно изучив ваш вопрос и ответ, я думаю, что смогу его опубликовать.

Элемент управления SAP GUI, соответствующий «SapTable" известен разработчикам ABAP/экспертам SAP GUI как Table Control ( документация ABAP &amp;gt; dynpro - Table Controls). Для информации: разработчики ABAP используют технологию "Dynpro" для создания экранов SAP GUI (которые называются "Dynpros"). Пример управления таблицей:

В этом примере показано всего 3 строки, а количество строк — 8 (строки видны на каждой «странице»).

Как вы сказали, бэкэнд-система отправляет только видимые строки таблицы в элементы управления таблицами на внешнем интерфейсе, и пользователь должен прокручивать, чтобы вызвать бэкэнд и получить следующие видимые строки.

Метод возвращает именно эту информацию.

При разработке ABAP рекомендуется хранить общее количество строк в технических свойствах элемента управления «Таблица», чтобы полоса прокрутки отображала эту информацию (небольшое положение курсора означает, что в элементе управления «Таблица» много строк, пользователь может перетащить его в нужную строку). По какой-то причине разработчики ABAP могут добавить несколько дополнительных пустых строк (обычно это максимум одна страница пустых строк), особенно чтобы позволить пользователю вводить новые строки без необходимости нажимать кнопку для добавления строки, что отражено в это общее количество строк.

Метод должен возвращать это общее количество строк.

Silk4J, вероятно, использует библиотеку SAP под названием SAP GUI Scripting, которая существует как для Windows, так и для Java, где элементы управления таблицей соответствуют объектам.

  • Для получения дополнительной информации см. документацию GuiTableControl (Справочный портал SAP > API сценариев SAP GUI > Объекты).
  • Методы Silk4J, похоже, имеют те же имена, что иGuiTableControlметоды, за исключением небольшой разницы в «Свойствах»: ваш код Silk4J ссылается на методыGetRowCountиGetVisibleRowCount, которые соответствуют свойствам, доступным только для чтения.RowCountиVisibleRowCountсценариев SAP GUI. Я предполагаю, что Silk4J оборачивает свойства графического интерфейса SAP с помощьюGetметоды плюсSetметоды для записываемых свойств (т.е. тех, которые не доступны только для чтения).

С помощью сценариев SAP GUI можно работать только с видимыми данными (чтобы подтвердить то, что вы видели с помощью Silk4J). Прокрутка необходима, чтобы сообщить серверной части SAP о том, что данные должны быть видны внешнему интерфейсу. Обратите внимание, что все столбцы отправляются во внешний интерфейс/в сценарии SAP GUI (так что, я думаю, то же самое и с Silk4J), даже если пользователю нужно прокручивать по горизонтали, чтобы сделать их видимыми для него/нее.

В сценариях SAP GUI методы синхронны: при прокрутке внутреннему серверу требуется некоторое время для отправки данных во внешний интерфейс, а метод прокрутки ожидает загрузки. Это часть вашего вопроса («Попытка 5: спать»), которую я не понимаю, хотя ее больше нет в предложенном вами решении (в вашем ответе).

Я также опубликовал другой ответ о том, как прокручивать элементы управления таблицами с помощью сценариев SAP GUI, что, возможно, может помочь.

Другие вопросы по тегам