2

I'm trying to send value "100" in to Position (row: 2, column 3) of Table, here:

https://keisan.casio.com/exec/system/13800848854767

With this code below, could you tell me, what's wrong?

Code:

driver.get("https://keisan.casio.com/exec/system/13800848854767");
List<WebElement> inputTable = driver.findElements(By.xpath("//*[@id='var_a_EXL']//tbody//tr"));
System.out.println(inputTable.size());
List<WebElement> columns;
for (int rows = 0; rows < inputTable.size(); rows++) {
    if (rows == 2) {
        columns = inputTable.get(rows).findElements(By.tagName("td"));
        for (int i = 0; i < columns.size(); i++) {
            if (i == 3) {
                columns.get(i).clear();
                columns.get(i).sendKeys("100");
            }
        }
    }
} 
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352

3 Answers3

2

Your looping logic is correct, but your code produce this error:

org.openqa.selenium.InvalidElementStateException: invalid element state

You need to click first before taking the next action on that element to become an editable element, and you must use the Actions class to interact with it:

driver.get("https://keisan.casio.com/exec/system/13800848854767");
List<WebElement> inputTable = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//*[@id='var_a_EXL']//tbody//tr")));
System.out.println(inputTable.size());
List<WebElement> columns;
for (int rows = 0; rows < inputTable.size(); rows++) {
    if (rows == 2) {
        columns = inputTable.get(rows).findElements(By.tagName("td"));
        for (int i = 0; i < columns.size(); i++) {
            if (i == 3) {
                WebElement target = columns.get(i);
                Actions actions = new Actions(driver);
                actions.moveToElement(target)
                    .click(target)
                    .sendKeys("100")
                    .build()
                    .perform();
            }
        }
    }
}

And I also added WebDriverWait to the above code.

Following import:

import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

By the way with this xpath //*[@id='var_a_EXL']//tbody//tr[3]//td[4] there is a simpler way instead of using looping above:

driver.get("https://keisan.casio.com/exec/system/13800848854767");
WebElement target = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id='var_a_EXL']//tbody//tr[3]//td[4]")));
Actions actions = new Actions(driver);
actions.moveToElement(target)
    .click(target)
    .sendKeys("100")
    .build()
    .perform();

Or use the following css selector to better locate element:

By.cssSelector("#var_a_EXL tr:nth-child(3) td:nth-child(4)")
frianH
  • 7,295
  • 6
  • 20
  • 45
  • Hi, thankyou for your answer. It work for me. The code [List inputTable = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//*[@id='var_a_EXL']//tbody//tr")));] is neu for me, but i gonna try to understand and learn it rightnow :) – MusterTester Jun 10 '20 at 09:41
1

+1 to @frianH's answer, The reason why your code isn't working is because .clear() works only if the element is a text entry element. Text entry elements are INPUT and TEXTAREA which is not the scenario in your case

Here's a simpler way using a JSExecutor

    List<WebElement> inputTable = driver.findElements(By.xpath("//*[@id='var_a_EXL']//tbody//tr"));
    System.out.println(inputTable.size());
    List<WebElement> columns;
    int rowss = 3;
    int columnss = 3;

    for (int rows = 0; rows < inputTable.size(); rows++) {
        if (rows == rowss) {
            columns = inputTable.get(rows).findElements(By.tagName("td"));
            System.out.println(columns.size());
            for (int i = 0; i < columns.size(); i++) {
                if (i == columnss) {
                    JavascriptExecutor js = (JavascriptExecutor) driver;
                    js.executeScript("arguments[0].innerText = '300'", columns.get(i));
                }

            }
        }

    }
Wilfred Clement
  • 2,674
  • 2
  • 14
  • 29
  • Thank you for yor answer. It doesn't work with this code: js.executeScript("arguments[0].innerText = '300'", columns.get(i)); But the solution is interessting. I will analyze it for my case – MusterTester Jun 10 '20 at 09:43
  • jeez, I just tried this code and its working flawlessly, what error are you getting ? Here's my complete code [link](https://pastebin.com/Ke2BE2z1) – Wilfred Clement Jun 10 '20 at 09:45
  • Hi, my scope is to send a value (for example: 100) to the position (row x, column y) of the Table. But with your code i become the actual text of position (row x, column y) – MusterTester Jun 10 '20 at 09:52
  • Fair enough, I have updated the code and called out the variables for positions outside so you can update anywhere now – Wilfred Clement Jun 10 '20 at 09:56
  • 1
    Ah, Ok. Its working fine. with your solution i think i can creat a small function to position any node of a table and later in Main i can do anythings with it. Very fine. Many thanks :) – MusterTester Jun 10 '20 at 10:07
1

You haven't mentioned about the error you are facing. Mentioning the error would have helped us to construct a more canonical answer. Possibly you are facing InvalidElementStateException as you are trying to invoke clear() on a <td> element.

However, to send the character string 100 into position (row: 2, column z) of table you need to induce WebDriverWait for the elementToBeClickable() and you can use the following Locator Strategies:

  • Using xpath:

    driver.get("https://keisan.casio.com/exec/system/13800848854767");
    new WebDriverWait(driver, 5).until(ExpectedConditions.elementToBeClickable(By.xpath("//td/span[@id='var_a_EXL_2_3C']"))).click();
    new WebDriverWait(driver, 5).until(ExpectedConditions.elementToBeClickable(By.xpath("//td/input[@id='var_a_EXL_2_3_input']"))).sendKeys("100");
    
  • Browser Snapshot:

function_table


Row and Column number as variables

Considering row and column number as variables:

  • Code Block:

    driver.get("https://keisan.casio.com/exec/system/13800848854767");
    int row = 2;
    int column = 3;
    new WebDriverWait(driver, 5).until(ExpectedConditions.elementToBeClickable(By.xpath("//td/span[contains(@id, '"+String.valueOf(row)+"') and contains(@id, '"+String.valueOf(column)+"')]"))).click();
    new WebDriverWait(driver, 5).until(ExpectedConditions.elementToBeClickable(By.xpath("//td/input[contains(@id, '"+String.valueOf(row)+"') and contains(@id, '"+String.valueOf(column)+"')]"))).sendKeys("100");
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • Yes, i worked with (TypeScript and Protractor) and i can understand it. But in Java is this for me still new. Thank you for your help. I'm going to lern it :) – MusterTester Jun 10 '20 at 09:58