Selenium to select and click on correct link - c#

Please dont get bored of answering my questions continuously for the same type of data. I am using Selenium and c# for my application. Here also I have a web page with contents like this:
Description App Name Information
Some Desc1 App1 Some Info
Some Desc2 App2 Some Info
Some Desc3 App2 Some Info
Some Desc4 App3 Some Info
Some Desc5 App4 Some Info
As said in my earlier questions, in my application the user enters an appname of his own choice. And that appname I have stored it in a variable. What I need to do is that, I want selenium to search for that appname and it must click on corresponding Description of that.
An example scenario is: If the user enters APP2, then selenium should search for the appname "App2" and after that first it should click on Some Desc2 and then after some time it should click on some Desc3. For Your Information, all the "some Desc's" links have no classname, no id, and have same tagname.

Try this:
driver.findElement(By.id("table-id"));
List<WebElement> rows = table.findElements(By.tagName("tr"));
for (WebElement row : rows) {
List<WebElemebt> cells = row.findElements(By.tagName("td"));
if (cells[1].getText().equals("AppNameYouWantToFind")) {
cells[0].click();
}
}
I hope you understand what's going on here but I'll describe it anyway.
First, you find the table with the relevant data. Then you find each of the rows within that table, forming a list of webelemebts. For each of those rows you then create a list of all the cells. Due to your table layout you know that the App Name data is located in the second cell in your list, 'index=[1]'. So make a comparison there for the search term you want - if it matches click the proceeding cell.
That's in Java I'm afraid, you'll have to convert that to c#.
UPDATED ANSWER
driver.findElement(By.id("table-id"));
List<WebElement> rows = table.findElements(By.tagName("tr")); //get list to know how many times to loop
for (int i=0; i<rows.length(); i++) {
rows = table.findElements(By.tagName("tr")); //this is required as you'll be 'refreshing' the list to avoid 'stale element exceptions' after going back
List<WebElemebt> cells = rows[i].findElements(By.tagName("td"));
if (cells[1].getText().equals("AppNameYouWantToFind")) {
cells[0].click();
//do what you need to do on the new page
driver.navigate.back();
}
}

Related

How to determine header row while using ClosedXML

i have a small winforms application im working on and using ClosedXML to handle our excel files. Im trying to build the read logic in a way that no matter what row the headers are on, i can find that row and work with the data below that. Because our reports come from our enterprise reporting system, the files are not always the same in where they start with the data because the exports from our system appends the report filters and selections to the top x rows then below that it starts the data dump. So right now that only way i can get it to work is if i manually remove all those rows at the top and make the header row the first row.
Im looking for some assistance in how i can find the "header" row based on column names or any other method. I have already looked thru their wiki https://github.com/ClosedXML/ClosedXML/wiki but that only has mention of working with printing headers and footers..
Here is where i believe i need to focus my work, but unclear where to start:
// Look for the first row used
var firstRowUsed = ws.FirstRowUsed(); //{'Precision Calculator D'!A1:XFD1}
//var firstRowUsed = "'Precision Calculator D'!A9:XFD9";
// Narrow down the row so that it only includes the used part
var udasRow = firstRowUsed.RowUsed(); //{'Precision Calculator D'!A10:A10}
//var udasRow = "'Precision Calculator D'!A10:A10}";
// Move to the next row (it now has the titles)
udasRow = udasRow.RowBelow();
There are reports ive tried that have the header starting on row 5 and others that start on row 7 and so on, so there is no actual row that they will alays be on, so need to find a way to determine it automatically. is there anyway to determine the row that the column names are in? The columns will always be in the same order, so those i have determined.
So ran across this in a mention of closedXML and it def may help get me where i need to be, but unclear how to implement
var foundMonth = ws.Search("Month", System.Globalization.CompareOptions.OrdinalIgnoreCase);
Since it returns a IEnumerable there is a chance that there may be more than one cell with the value "Month" and in my file that im testing with, there is 2 rows that contain the word and not sure how i can determine in this case that i want the last cell it found if there are multiple.
Addressed the concern about the multiple cells returned, and can now determine which row the headers are on with the following:
var foundMonth = ws.Search("Month", System.Globalization.CompareOptions.OrdinalIgnoreCase);
var monthRow = foundMonth.Last().Address.ToString();
Still unclear how to implement this into the original code post above, so that the firstRowUsed is reflected correctly in this case would be A11:XFD11
After exhausting search of ClosedXML and reading thru a number of other questions, i was able to find a solution. Below is the code that will help set the used range based on my current data structure within the file..
var foundMonth = ws.Search("Month", System.Globalization.CompareOptions.OrdinalIgnoreCase);
var monthRow = foundMonth.Last().Address; // A11
var lastcell = ws.LastCellUsed().Address; // BC3950
var rangeUsed = ws.Range(monthRow, lastcell);
Since i have no idea where my header row will be from file to file, im searching for my column header name in column A, since all the usable data is mostly numbers i can safely assume that in column A, the last found instance of the word "Month" is my header row.
With that and the last cell used i am able to determine my data range as seen above. Although i still need to figure out how to replace my firstRowUsed logic to work the same way, this is a step closer to a final solution. Ill post back my findings on that one before i mark this question answered.
var firstRowUsed = ws.Range(monthRow, lastcell).FirstRowUsed();
This line provides you the same as this line below
var firstRowUsed = ws.FirstRowUsed();
I tried this logic with 3 different files, each one having more and less data and also having the header row on different rows. and works like a charm

Can I get the actual Excel row number of Excel spreadsheet row (not a sequential calculated number)

I am processing a multi-tab spreadsheet and saving the rows in a SQL database. I would like to store the actual Excel row number (that shows in the first column before column A). I have tried a number of ways to accomplish this but cannot seem to find a method that works. My current sample code is shown below. I would like to avoid counting rows as they are read from the file but would rather just get the actual Excel row number from Excel. I am hope I am explaining this adequately. I may only process 1 of every 5 or 10 rows and would have thought there would be a way to retrieve the row number that Excel displays to the left of Column A. Is that possible or am I out of luck? The code below seems to display only a sequential number of (for example) 1 through 5 if I only process 5 records. I am not doing any restriction of rows anywhere else in the code. I realize the following code is simplistic but it accurately reflects what I am trying to do.
foreach (IXLWorksheet works in workBook.Worksheets)
{
// get the name of the worksheet (the tab name)
string worksName = works.Name;
foreach (IXLRow row in works.Rows())
{
bProcessThisRow = false;
if (rowcontents == userrequest)
{
bProcessThisRow = true;
}
// more determination of rowcontents to user spec's
if (bProcessThisRow)
{
// get the Excel number of this row
int iRowNum = row.RowNumber();
// save row contents in database record
}
}
}
Well, this is embarrassing but I have to tell the truth because anything other than that would be "read" by everyone...yesterday was a really hectic day (I know, we all have them) and I just plain fouled up on the test data file. It was no one's fault but my own. And Scott Hannen was correct, RowNumber() does return the correct response. This was my first experience using the RowNumber() feature and a lack of faith in myself/experience with the RowNumber() probably contributed.
Sorry for wasting your time.

How to use a string content as a variable name in a SSIS C# script

Hello everyone and thanks for your time and answers in advanced.
Let me give you some context first:
I'm working in a bank in a metrics project. We are re-engineering all the ETL processes and microstrategy dashboards of the commerce sector, they use a lot of non IT data sources and we have to map that info to IT centralized sources in SQL Server 2008R2 servers. For the ETL we are using SSIS.
I have an ETL for loans. Inside a data flow I gather all the information I need about loans, then from one particular table I got all the conditions that needs to be tested to classify the loan. The conditions table has this form:
sk_condition_name: varchar
sk_whatever: ...
...
where_clause: varchar(900)
In the "where_clause" column I have a where clause (duh!) that test some columns from the loan like this:
loan_type = x AND client_tipe = y AND loan_rate = z
Before I get deeper in this, I need to say that the example I'm giving is about loans, but the same goes for all the products the bank sell, like insurance or investment funds... And the conditions to classify the product can change in time. And one specific loan can be classified in multiple ways at the same time, each positive clasification writes a row in a specific table, that's why I need an asynchronous Script Component.
Where I was? Right, loans.. So in the ETL in get all the loans data and those where_clauses, in a C# Script Component we separate the clause with regular expressions, so we end up with 2 strings for every check that the clause was doing, using the example above I would end up with 3 pair of strings ("loan_type", "x"), ("client_type","y") and ("loan_rate",z).
And this is where the problem comes
I can't find a way in the script to use the first string content as the name of the row column, something like this is what I mean:
if Row.(string1.content()) = string2 then ...
Now the limitations:
It's a bank, they don't like new things, so the tools I can use are those of SSIS.
Changes in the model might be out of discussion, are out of discussion.
I need this to be completely dynamic, no hardcoded conditions because of the changing nature of this conditions.
I've search a lot for a solution to this but found non that works. This is my last resource.
I hope I have been decently clear in this, my first post ever.
Please please please help me!
Thank you very much!!
EDIT 1: To clarify..
My end result is generating a new row to be inserted in one particular table for each condition that tested positive. The information to be inserted and the target table are irrelevant to the problema in hands. The loan type, client and rate are just examples of what conditions test. My problema is that I can't use the string content as the name for the row's column.
You can do this with Reflection.
Add "using System.Reflection;" to the namespaces - then you can interate with the following code:
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
string sColumn = "Name";
string sFind = "John";
foreach (PropertyInfo p in Row.GetType().GetProperties())
{
string sval;
if (p.Name.ToString() == sColumn)
{
sval = p.GetValue(Row, null).ToString();
if (sval != sFind)
{
//Do Stuff
}
}
}
}
In This example I have hard-coded String1 (the Column to Check) to Name and String2 (the Value to Check) to John.

select ddl item based on the url

On my contact page (contact.aspx)I have a booking form that contains a drop down list control which is dynamically populated with the names of the available drivers to choose from. What I would like to do is on each drivers individual page e.g driver1.aspx provide a 'book this driver' link which when the user selects it they are taken to the contact page and the drop down list is populated with the drivers name of the page they have just come from.
so for example if i am a user viewing Pauls driver page and i select book this driver i am taken to the contact us page and the ddl list has pre selected paul as the prefered driver
Can this be achieved? If so has and one got any links or advice on how to do it?
Thanks
Paul
thanks for your response, I been busy working on this and have achieved it using the following (not sure its the best approach but its doing what i need)
if you can suggest anything better then please let me know :)
//gets the full url of the referal page e.g http://mysite.co.uk/our-drivers/joe-bloggs.aspx
string refererPage = Request.UrlReferrer.ToString();
//splits the referer url to get the latter part containing the name e.g joe-bloggs.aspx
string url = refererPage.Split('/').Last();
//splits the url to get the first part of the url e.g joe-bloggs
string url2 = url.Split('.').First();
// Take the value of url2 replace the hyphen with a space e.g Joe Bloggs then loop through
// the items in the DDL and if there is an item that matches make it the selected item
foreach (ListItem item in ddlPreferedDriver.Items)
{
if (url2.ToLower().Replace("-", " ").Contains(item.Text.ToLower()))
{
item.Selected = true;
}
}
cheers Paul

Dropdown with image and text together in Asp.net 3.5 and jquery

I've been given a task to make a dynamic drop down which takes it's data[image and value id] from table. I am wondering if any of you came across this scenario or if any one can help me out in this I need help in concept and coding. Definitely any help is appreciated.
I see the example in jquery here is the link:
http://www.marghoobsuleman.com/jquery-image-dropdown
something like this but data is coming from table.
If you use the plugin that you found in the link, then basically what you will want to do is create the dropdown dynamically based on the table content. Without having more details of how your table is structured I can't give you exact details, but something like this should get you close (I'm going to assume there is a drop-down element already on the page somewhere called "select", and your table is called "table" with the image in field 0, and the text in field 1) Note: This hasn't really been tested.
var options = "";
$("#table tr").each(function() {
var imagePath = $(this).find("td:eq(0) img").attr("src");
var title = $(this).find("td:eq(1)").text();
options += '<option value="'+title+'" title="'+imagePath+'">'+title+'</option>';
});
$("#select").html(options);

Categories