How to send text within a webtable cell using Selenium and Java

Viewed 496

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");
            }
        }
    }
} 
3 Answers

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)")

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

            }
        }

    }

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");
    
Related