Help in Dynamic table reading

Using Kantu IDE for chrome:

I need to click on download “link” in
https://www.sample-videos.com/download-sample-sql.php

How can I refer and use Rows or size column value ?

In Kantu the link= locator has a very useful position attribute @POS=X. It tells Kantu to select the x-th link with the same name. On your website I recorded this macro:

{
  "CreationDate": "2018-6-17",
  "Commands": [
    {
      "Command": "open",
      "Target": "https://www.sample-videos.com/download-sample-sql.php",
      "Value": ""
    },
    {
      "Command": "click",
      "Target": "link=Click@POS=3",
      "Value": ""
    }
  ]
}

So if you want to click the 3rd link (= link in the 3rd row) you use POS=3. Of course you can also use variable here, for example with

      "Target": "link=Click@POS=${!loop}",

you can run the macro in loop, and then use the ${!loop} internal variable click every download link (1st link in the first macro run, 2nd link in the 2nd macro run and so on).

Of course, any other variable can be used here as well:

Thanks Ulrich for quick reply.
But my requirement is not the link number.
How do Kantu know POS=1 or 2 or 3, as I need to match with row value.
If row value is 5000 then click that download link.

If you want to click the link in row 5000 than you can use …@POS=5000.

Or maybe I do not understand the problem?

Really appreciate your effort Ulrich.
As I dont know the which row (POS=5000) how do I provide this number.
If you see “Download Sample SQL File” in the (https://www.sample-videos.com/download-sample-sql.php), I want to download row value 500, later instead of 500 I want some other number.

So, first it should find row contains the value (500 or some other numer) then need to get the download link.

Hope you got it.

Await your reply :slight_smile:

Here is a solution:

  • the macro searches the table for a row with a certain text in the first column (note the ${myrow} variable inside the xpath}, in this line: storeText | /html/body/div[4]/div[1]/div[2]/div[2]/table/tbody/tr[${myrow}]/td[1]"

  • it extracts text with storeText into a variable, and runs in a loop until the text is found : gotoIf ${text2search}"!="${rowtext}"

  • then uses the number of the found row to click the right link (“Download@POS=${myrow}”)

ADMIN note 2020/10/18: This example still uses GotoIf (deprecated). With the new GotoIf_V2 the syntax is slightly different: See gotoIf - Error in condition of gotoIf_v2: Invalid or unexpected token - #2 by admin

Macro:

    {
      "CreationDate": "2018-6-18",
      "Commands": [
        {
          "Command": "open",
          "Target": "https://www.sample-videos.com/download-sample-sql.php",
          "Value": ""
        },
        {
          "Command": "store",
          "Target": "fast",
          "Value": "!replayspeed"
        },
        {
          "Command": "store",
          "Target": "500,000",
          "Value": "text2search"
        },
        {
          "Command": "store",
          "Target": "0",
          "Value": "myrow"
        },
        {
          "Command": "label",
          "Target": "searchrow_loop",
          "Value": ""
        },
        {
          "Command": "storeEval",
          "Target": "${myrow}+1",
          "Value": "myrow"
        },
        {
          "Command": "storeText",
          "Target": "/html/body/div[4]/div[1]/div[2]/div[2]/table/tbody/tr[${myrow}]/td[1]",
          "Value": "rowtext"
        },
        {
          "Command": "echo",
          "Target": "Text from Row=${rowtext}",
          "Value": ""
        },
        {
          "Command": "echo",
          "Target": "text2search=${text2search} / rowtext=${rowtext}",
          "Value": ""
        },
        {
          "Command": "gotoIf",
          "Target": "\"${text2search}\"!=\"${rowtext}\"",
          "Value": "searchrow_loop"
        },
        {
          "Command": "echo",
          "Target": "myrow=${myrow}",
          "Value": ""
        },
        {
          "Command": "comment",
          "Target": "Row found, click link!",
          "Value": ""
        },
        {
          "Command": "click",
          "Target": "link=Click@POS=${myrow}",
          "Value": ""
        }
      ]
    }
2 Likes

Hi Ulrich,

I decide to learn more abt Kantu:

QN1: Can share with me how the below Kantu JSON elem works?
{
“Command”: “store”,
“Target”: “fast”,
“Value”: “!replayspeed”
},

Cuz from: Selenium IDE Commands 2021 - Overview and Tutorials
it says storing System variables will generate an error:
store A string The name of the variable storing the string. For example: “var_usr” Note: System variables start with ! like !TIMEOUT_WAIT. So you can not create a variable that starts with ! (=> error message)

QN2: Mind I ask abt why the below Kantu JSON elem

    {
      "Command": "store",
      "Target": "500,000",
      "Value": "text2search"
    },

is not written as

    {
      "Command": "store",
      "Value": "500,000",
      "Target": "text2search"
    },

Pardon my ignorance, as the syntax I read up on Command = “store” is
store (value, variable)

!replayspeed can use ! because it is an internal Kantu variable :wink:

You can read all internal variables, and write to some (e. g. a variable like !runtime can only be read). Essentially these internal variables allow you to set (override) certain kantu default setting during the macro run. In this case I made sure the replayspeed in this macro is “FAST”, no matter what the global settings of the user might be.

The table editor column names command, target and value are mostly historic. And the same goes for these names inside the JSON. The were introduced with the original Selenium IDE. For the typical click or type functions it still fits well. First the command, then the target (selector) and then the value.

But for other commands, “target” and “value” are just the names of the 2nd and 3rd column.

Oh, now I see: I think here they just mean that the value (as in: the value for the variable) goes to the 2nd column. This does not refer to the Json mame (but yes, this is confusing and the docs should be improved).

1 Like

apologies for delay in reply:

You are awesome Ulrich. It worked amazing.
Thanks for your time to understand my problem and give solution.

I have one more question, will post as new one, which help for others also.

I figured out how to do a search based off a value in a table - and this can even be used if there is a dynamic id. You just have to reference the element or value you’re trying to get relative to another element that is fixed and that you know you can find. No need to go through that looping program to search for a field. All you need is some knowledge of XPath functions. I just educated myself today by looking on Stack Overflow. Basically if the simple xpath reference doesn’t work because of a dynamic id, just use xpath axes as your guide. (reference siblings, parents, children, ancestors, descendants, etc.)

e.g.
xpath=//table/tbody/tr[td//text()[contains(.,“text string”)]]/td[1]

The above finds the row in the table that has a td text node equal to “text string” (the [ ] specifies a conditional - so we find the td that meets the criteria within [ ]) and then proceeds to return the td[1] of the row it matched to. The // after the td means that it will search all paths below td (e.g. in my case the text node was actually stored on td/span/text() so instead of me specifying td/span/text()[contains…] I simply put td//text()[contains…] so it will produce a match if it finds a text string within any descendent element.

To summarize, whenever you have a variable within the path, specify a conditional [ ] and it will find the one you want, then continue your path after the conditional to specify the end point where you want the command to operate (whether it be click, storeText, etc.)

1 Like