Find and Replace Hyperlinks from word Document - c#

Here is my Code....
Microsoft.Office.Interop.Word.Application applicationObject = new Microsoft.Office.Interop.Word.Application();
Microsoft.Office.Interop.Word.Document aDDoc = applicationObject.Documents.Open(FileName: FilePath);
Microsoft.Office.Interop.Word.Hyperlinks links = aDDoc.Hyperlinks;
for (int i = 0; i < links.Count; i++)
{
object index = (object)i;
string c = links[index].Target; //Here i am getting Com exception, see below
}
Com exception: the inner exception is null, Where the link count iam getting correct. Please tell me if any one have the idea how to retrieve the Hyperlink URL.

I was also facing the same issue but resolved using below code correction.
Instead of using:
for (int i = 0; i < links.Count; i++)
use this:
for (int i = 1; i <= links.Count; i++)

string c = links[i].Target
Should work fine.

try this:
foreach (Hyperlink link in links)
{
string c = link.Target;
}

Here is an example, where all fields' (all hyperlinks are fields) starting nodes are selected and then are executed in way you want. Check if you get the same com exception error on line with calling .Target property.

Related

Getting Error for td : stale element reference: element is not attached to the page document

I am new to selenium coding, and I have the below code where I am fetching values from the table it has multiple pages,
for 1st time, it reads all values from the table and control move to the next page, I m getting the error stale element reference: element is not attached to the page document
but when i m debugging the code, i m not getting any error for the below code, when i run it throws an error and it shows an error at line where I have defined tdCollection
Please guide me on this.
var ReportCount = Convert.ToInt32(_driver.FindElement(By.Id("Reporter_TotalPages")).Text);
for (int i = 0; i < ReportCount; i++)
{
IList<IWebElement> _records = (IList<IWebElement>)_driver.FindElements(By.XPath("//*[contains(#id,'ReportViewerControl')]//div//table//tbody//tr[position()>2]"));
IList<IWebElement> tdCollection;
for (int j = 0; j < _records.Count; j++)
{
tdCollection = _records[j].FindElements(By.TagName("td"));
var Patientdemolist = new XPatientDemographicsList();
{
Patientdemolist.PatientID = tdCollection[0].Text;
Patientdemolist.LastName = tdCollection[1].Text;
Patientdemolist.FirstName = tdCollection[2].Text;
};
PatientDemographicsList.Add(Patientdemolist);
tdCollection = null;
}
if (ReportCount - 1 > i)
{
// For Next Page
_driver.FindElement(By.Id("Report_Next")).Click();
}
}
Try adjusting your conditional to this.
if (ReportCount - 1 > i)
{
// For Next Page
_driver.FindElement(By.Id("Report_Next")).Click();
Thread.Sleep(5000)
}
Its possible you are getting a reference before the page has completed loading from the .Click() method.
If that works you can refine the tests to wait implictly/ use fluent waits instead of waiting for 5 seconds.
https://www.selenium.dev/documentation/webdriver/waits/

C# docx bookmarks loop

I want to iterate through all bookmarks inside document and set text to each bookmark.Name from datagridview cells values which is already loaded. I'm stuck here in this loop. Please, any suggestions?
using (Novacode.DocX document = DocX.Load(template))
{
foreach (Novacode.Bookmark bookmark in document.Bookmarks)
{
//MessageBox.Show("\tFound bookmarks {0}", bookmark.Name);
//var bookmarks = bookmark.Name;
//document.Bookmarks[bookmark.Name].SetText(dataGridViewRow.Cells[0].Value.ToString());
int i = document.Bookmarks.Count;
var bookmarks = document.Bookmarks[i].Name;
document.Bookmarks[bookmark.Name].SetText(dataGridViewRow.Cells[0].Value.ToString());
document.Bookmarks[0].SetText(dataGridViewRow.Cells[1].Value.ToString());
document.Bookmarks[1].SetText(dataGridViewRow.Cells[2].Value.ToString());
document.Bookmarks[2].SetText(dataGridViewRow.Cells[3].Value.ToString());
document.Bookmarks[3].SetText(dataGridViewRow.Cells[4].Value.ToString());
//document.Bookmarks[bookmark.Name].SetText(dataGridViewRow.Cells[2].Value.ToString());
//document.Bookmarks[bookmark.Name].SetText(dataGridViewRow.Cells[3].Value.ToString());
//document.Bookmarks[bookmark.Name].SetText(dataGridViewRow.Cells[4].Value.ToString());
//document.Bookmarks[bookmark.Name].SetText(dataGridViewRow.Cells[5].Value.ToString());
//document.Bookmarks[bookmark.Name].SetText(dataGridViewRow.Cells[6].Value.ToString());
//document.Bookmarks[bookmark.Name].SetText(dataGridViewRow.Cells[7].Value.ToString());
//document.Bookmarks[bookmark.Name].SetText(dataGridViewRow.Cells[8].Value.ToString());
//document.Bookmarks[bookmark.Name].SetText(dataGridViewRow.Cells[9].Value.ToString());
//document.Bookmarks[bookmark.Name].SetText(dataGridViewRow.Cells[10].Value.ToString());
//document.Bookmarks[bookmark.Name].SetText(dataGridViewRow.Cells[11].Value.ToString());
}
document.SaveAs(path2);
}
If I understand you correctly, this is what you are trying to achieve with the loop:
using (Novacode.DocX document = DocX.Load(template))
{
int i = 0;
foreach (Novacode.Bookmark bookmark in document.Bookmarks)
{
var bookmarks = document.Bookmarks[i].Name;
document.Bookmarks[bookmark.Name].SetText(dataGridViewRow.Cells[i+1].Value.ToString());
i++;
}
document.SaveAs(path2);
}
What we've done here is declared a variable i which is outside the loop but we increment its value with every foreach iteration. Alternatively, you could rewrite the loop and use a for loop instead:
for(int i=0; i< document.Bookmarks.Count)
{
//change the code here accordingly
}
Let me know if this helps.
Thank you.

How to get string value of a List<t> Item

I have some file paths stored in a List and need to attach them to an email. But how can I access the values (in my case: file paths as string values) of my List Items?
Here is the code:
List<string> filesToSend = new List<string>();
filesToSend = (List<string>)Session["filesListForFilesToSend"];
for (int i = 0; i < filesToSend.Count; i++)
{
//message.Attachments.Add(filesToSend[i].????????????????????);
}
Thanks in advance
filesToSend[i] will return the path string you want
Try This
foreach(string EachString in filesToSend)
{
message.Attachments.Add(EachString)
}
First, you do not need to instance a first list the after read the list in session, just:
List<string> filesToSend = (List<string>)Session["filesListForFilesToSend"];
When you access and List by index you will get the object of generic type. You can do it using a lot of ways, for sample:
using for loop:
for (int i = 0; i < filesToSend.Count; i++)
message.Attachments.Add(filesToSend[i]);
or foreach
foreach(string file in filesToSend)
message.Attachments.Add(file);
or while
int i = filesToSend.Lenght;
while(i--)
message.Attachments.Add(filesToSend[i]);
I would use foreach statement, but while will give you more performance (keep in mind you will loop in the reverse order).
The error was not how I was trying to get the string out of my List. The error was how I was trying to attach it to my message.
for (int i = 0; i < filesToSend.Count; i++)
{
string filePath = filesToSend[i];
Attachment attached = new Attachment(filePath);
attached.Name = filePath;
message.Attachments.Add(attached);
}
Thats the way it works for me. Thank you all

selenium to click on several links one after other

I have a table over a webpage having many values repeating 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
At the start of my app, it will ask the user to enter an appname of their choice. What I want is if I choose APP2 it should select "Some Desc2" first, that will lead to another page and there I will do something. Then again it should come back to previous page and this time it should select "Some Desc3", that will lead to another page. This should be repeated n number of times until selenium can't find an appname specified.
I have tried as shown below:
//Finding Table, its rows and coloumns
int rowcount = driver.FindElements(By.Id("someid")).Count;
for (int i = 0; i < rowcount; i++)
{
//Finding App name based on user entered text
var elems = driver.FindElements(By.PartialLinkText(text));
IList<IWebElement> list = elems;
for (int j = 0; j < list.Count; j++)
{
var table = driver.FindElement(By.Id("someid"));
IList<IWebElement> rows = table.FindElements(By.TagName("tr"));
IList<IWebElement> cells = rows[i].FindElements(By.TagName("td"));
//Again finding element based on user entered text
var elem = driver.FindElements(By.PartialLinkText(text));
list = elem;
if (list[1].Text.Equals(text))
{
list[0].Click();
string duration;
string price;
var elements = driver.FindElements(By.Id("SPFieldNumber"));
IList<IWebElement> lists = elements;
duration = lists.First().Text.ToString();
price = lists.ElementAt(1).Text.ToString();
MessageBox.Show(duration);
MessageBox.Show(price);
driver.Navigate().Back();
}
}
}
Running this code selects "Some Desc2" correctly and everything went fine. But after returning to the previous page c# throws an exception "element not found in the cache - perhaps the page has changed since it was looked up selenium".
For this particular issue, you find table and row elements before the loop, then by calling driver.Navigate().Back(); inside the loop, your table and row are no longer in the DOM (because your page changes, DOM changes, the table element is not the one you find outside the loop anymore)
Try put them inside the loop
int rowCount = driver.FindElements(By.CssSelector("#table_id tr")).Count; // replace table_id with the id of your table
for (int i = 0; i < rowCount ; i++)
{
var table = driver.FindElement(By.Id("some ID"));
rows = table.FindElements(By.TagName("tr"));
// the rest of the code
}
However, apart from solving your problems, I really suggest you read the Selenium documentation and learn some basic C# programming first, this will save you a lot time asking questions here.
Why are you doing this every time?
var elems = driver.FindElements(By.PartialLinkText(text));
IList<IWebElement> list = elems;
// IList<IWebElement> list = driver.FindElements(By.PartialLinkText(text));
element.Text is the string type you want, no need for calling ToString()
lists.First().Text.ToString();
// lists.First().Text;
You don't need this if there's no frames involved.
driver.SwitchTo().DefaultContent();
(from your earlier post) A list of IWebElement would never equal to a string, and the result can't be an element. Avoid using var if you don't know what type you want, as it may get you a totally different thing.
IList<IWebElement> list = elems;
var elem= list.Equals(text);
(from your earlier post) element.ToString() and element.Text are different
string targetele = elem.ToString(); // you want elem.Text;

Could not load type 'ADODB.FieldsToInternalFieldsMarshaler' from assembly

I have the following code:
MAPITable mt = rStores.MAPITable;
Recordset rs = new Recordset();
rs = mt.ExecSQL(#"SELECT EntryID, ""http://schemas.microsoft.com/mapi/proptag/0x0FF60102"" As PR_INSTANCE_KEY from Name");
while (!rs.EOF)
{
var fields = ((dynamic)rs.Fields);
for (int f = 0; f < fields.Count; f++)
{
var field = fields[f];
var name = field.Name;
var value = field.Value;
}
Debug.Print(rs.Fields["EntryID"].Value);
Debug.Print(rs.Fields["PR_INSTANCE_KEY"].Value);
rs.MoveNext();
When I try to access the recordset fields, I get the aforementioned error in the subject. I saw the question posted here, but that did not help me.
UPDATE: Nevermind - workaround listed here
Unfortunately your link to the workaround is broken. Page Not found. I found the following workaround.
ADODB Properties from References:
Embed Interop Types: false
Copy local: true
specific version (in English maybe isolated?): false

Categories

Resources