ie getelementsbyID with same ID - excel

i have a script that works with internet explorder (ie) and i need to loop the select fields, that it zelf is no ploblem bu the 4 elements got the same ID (on the same page).
How do i let it loop through the 4 fields?
Can i make them more spesified?
the code i use is the following:
ie.document.getElementByID("DownloadImage").Click
The ie code is the following:
field 1
<a id="DownloadButton" href="javascript:__doPostBack('ctl00$ctl00$MainContent$MainContent$ctl00$declaratiebestandView$RetourInformatieGrid$ctl03$DownloadButton','')">CZ_Specificatie_150005697.pdf</a>
field 2
<a id="DownloadButton" href="javascript:__doPostBack('ctl00$ctl00$MainContent$MainContent$ctl00$declaratiebestandView$RetourInformatieGrid$ctl03$DownloadButton','')">CZ_Specificatie_150005697.pdf</a><input name="ctl00$ctl00$MainContent$MainContent$ctl00$declaratiebestandView$RetourInformatieGrid$ctl03$DownloadImage" class="inlineButton" id="DownloadImage" type="image" src="../images/download.png" text="CZ_Specificatie_150005697.pdf">
then it opens the download screen, and then my code continue's (and works :) )

You can loop them by using querySelectorAll to gather all the elements with an id attribute whose values match what you are after. You can distinguish between them by index. This method will allow you to gather them even though the ids are repeating. However, the HTML you have shared downloads the same document so a loop doesn't seem necessary.
Dim nodeList As Object, i As Long
Set nodeList = ie.document.querySelectorAll("[id=DownloadButton]")
For i = 0 to nodeList.Length-1
nodeList.item(i).Click
Next
That loops all of the matching elements and clicks
By index will be specific but if you familiarize yourself with CSS selectors there are a vast number of possibilities for specifying an element.

The id in HTLM must be unique. If it is not unique it is no valid HTML and should be fixed.
HTML4:
http://www.w3.org/TR/html4/struct/global.html
Section 7.5.2:
id = name [CS]
This attribute assigns a name to an element. This name must be unique in a document.
HTML5:
http://www.w3.org/TR/html5/dom.html#the-id-attribute
The id attribute specifies its element's unique identifier (ID). The
value must be unique amongst all the IDs in the element's home subtree
and must contain at least one character. The value must not contain
any space characters.

Related

filtering out elements found with beautiful soup based on a key word in any attribute

Here is an example of an url.
url = 'https://rapaxray.com'
# logo
html_content = requests.get(url, headers=headers).text
soup = BeautifulSoup(html_content, "lxml")
images_found = soup.findAll('img', {'src' : re.compile(r'(jpe?g)|(png)|(svg)$')})
images_found
First I'm narrowing down the list of elements to the ones containing jpg, png or svg in a tag. In this case I only get 3 elements. Then I would like to filter those elements to show me only the ones that have a key word 'logo' in ANY attribute.
The element I'm looking for in this example looks like this:
'img alt="Radiology Associates, P.A." class="attachment-full size-full astra-logo-svg" loading="lazy" src="https://rapaxray.com/wp-content/uploads/2019/09/RAPA100.svg"/'
I want to filter out this element out of all elements based on condition that it has a key word 'logo' in ANY of its attributes
The challenge is that:
I have thousands of urls, and key word logo could be in a different attribute for different url
logic: if 'logo' in ANY(attribute for attribute in list_of_possible_attributes_that_this_element_has) doesn't work the same way as list comprehensions because I couldn't find the way of how to access any possible attribute without using its specific name
Checking all specific names is also problematic because particular attribute could exist in one element but not the other which throws error
Case above is also extra challenging because attribute value is a list, so we would need to flatten it to be able to check if the key word is in it.
For most of the urls the element I'm looking for is not returned as the top one like in this example so choosing top first is not an option.
Is there a way of filtering out elements based on a key word in ANY of its attributes? (without prior knowledge of what the name of the attribute is?).
If I understood you correctly, you could use a filter function similar to this answer to search for all tags such that any tag attribute's value contains val:
def my_filter(tag, val):
types = ['.jpg','.jpeg','.svg','.png']
if tag is not None and tag.name == "img" and tag.has_attr("src"):
if all(y not in tag['src'] for y in types):
return False
for key in tag.attrs.keys():
if isinstance(tag[key], list):
if any(val in entry for entry in tag[key]):
return True
else:
if val in tag[key]:
return True
return False
res = soup.find_all(lambda tag: my_filter(tag, "logo"))

Hscan all items in a set of keys

Assuming I have the following hashes:
item:1 - field "a"
item:2 - field "b"
item:3 - field "a"
and a set called 'items' that stores the above hashes' keys as such:
items:
item:1
item:2
item:3
How could I go through each item in the items set to find all items with a field that equals "a"?
You really don't want to do that - a scan is expensive and requires time.
What you want to do is to keep a Set with the items that interest you, e.g. items:b would contain item:1 and item:2. This Set, which is essentially an index, will allow you to fetch the items with a "b" field efficiently.

Get members of a group in Lotus Domino

I retrieve names from a group using formula, and put them in a field of type Names this way:
#Name([CN];NAME)
I want to manipulate this data in my code, but using Lotusscript. Can't find it at Google or Lotus Domino's Help. Is there a way I can handle this?
In LotusScript there is a class named "NotesName" to do such manipulations.
If there is a field named "NAME" in you document, then the code would look like:
Dim doc as NotesDocument
Dim nnName as NotesName
'Somehow get the document, using ws.CurrentDocument.document
'or db.UnprocessedDocments.GetFirstDocument, depends on your situation
Set nnName = New NotesName( doc.GetItemValue("NAME")(0) )
Whatyourlookingfor = nnName.Common
If NAME is a Multivalue then you would have to write a loop to get the common- name for every element in the array doc.GetItemValue("NAME")
The next time you have a question, check out the language cross reference in the help...
There it tells you, what the LotusScript- Pendant for #Name is.
Please try with below suggestion for getting list of person names from group.
First need to check the availability of searching group on names.nsf (All the groups are available on "($VIMGroups)" view.
if the group is available means you need to get the list of values from "Members" item
The members item have variant(list) values. So need to iterate the members for getting each value
Please refer the below sample code:
Set namesDb=session.GetDatabase(db.Server,"names.nsf")
Set groupVw=namesDb.GetView("($VIMGroups)")
Set groupDoc=groupvw.GetDocumentByKey("groupname")
persons= groupDoc.members
Forall person In persons
Msgbox person
End Forall
You can use the Evaluate method. It will return you the result of a Notes Formula:
Dim result as Variant
formula$ = "#Name([CN];NAME)"
result = Evaluate(formula$)
If the formula needs to be evaluated within the context of a document, you can pass that document as a second parameter to the method.
More info here

Mongo DB C# code using 2 level , 3 level and 4 level of array

I have to update in C# code using MongoDB. Here I had implement 2nd level array of update in below (subBranchindex is taken in a generic list object):-
for (var index = 0; index < subBranchindex.Count; index++)
{
if (subBranchindex[index]._id == new ObjectId(subBranchid))
{
IMongoQuery queryEdit = Query.EQ("BranchOffice.SubBranchlist._id", new ObjectId(subBranchid));
UpdateBuilder update = Update.Set("BranchOffice.$.SubBranchlist."+ index +".Name",subBranch.SubName).
SafeModeResult s = dc.Collection.Update(queryEdit, update,
UpdateFlags.None, SafeMode.True);
}
}
Here 2nd level array, I was using (for loop Statement) to taken Index value for array. Next I can use 3rd, 4th and 5th level of array means more than (for loop statement) will be assign. So don't need [for loop Statement] and also don't need to assign hardcore number in index.
For example: ("BranchOffice.$.SubBranchlist.0.Name",subBranch.SubName). Here Don't Hardcore number[index] 0 or 1 or 2. "2nd" level array more than 100 record is there.
Is there any way I can use to array index value? Please explain how to solve this probelm. Please explain me with Example.
Based on your example above, my understanding of your schema is the following:
The top-level document has a BranchOffice field
BranchOffice is an array of objects
Each object within BranchOffice has an _id, SubName and SubBranchlist field
SubBranchlist is an array of objects
Each object within SubBranchlist has a Name field
Your update statement appears to be copying the SubName field to each Name field among objects within SubBranchlist (a sibling field of SubName).
Using the property path syntax to select fields through arrays (e.g. SubBranchlist.0.Name), there is no "wildcard" index that will allow you to modify Name fields among all objects in the array.
On a somewhat related note, the $ positional operator only applies to the first-matched array element, so you cannot use that to update multiple array elements. In your case, it would not be an option anyway, since you're using the positional operator for the BranchOffice array field.
You can either issue a series of update queries (for each element in SubBranchlist), or consider using $set to modify the entire SubBranchlist array in one query. The downside with using $set is that you'll need to read and write back the entire array, which may be a problem if other, concurrent operations are also issuing updates to the array.

Binding an edit box within a custom control to a form field programatically

I have a notes form with a series of fields such as city_1, city_2, city_3 etc.
I have an XPage and on that XPage I have a repeat.
The repeat is based on an array with ten values 1 - 10
var repArray = new Array() ;
for (var i=1;i<=10;i++) {
repArray.push(i) ;
}
return(repArray) ;
Within the repeat I have a custom control which is used to surface the fields city_1 through city_10
The repeat has a custom property docdatasource which is passed in
It also has a string custom property called cityFieldName which is computed using the repeat
collection name so that in the first repeat row it is city_1 and in the second it is city_2 etc..
The editable text field on the custom control is bound using the EL formula
compositeData.docdatasource[compositeData.cityFieldName]
This works fine but each time I add new fields I have to remember to create a new custom property and then a reference to it on the parent page.
I would like to be able to simply compute the data binding such as
compositeData.docdatasource['city_' + indexvar]
where indexvar is a variable representing the current row number.
Is this possible ? I have read that you cannot use '+' in Expression Language.
First: you wouldn't need an array for a counter. Just 10 would do (the number) - repeats 10 times too. But you could build an array of arrays:
var repArray = [];
for (var i=1;i<=10;i++) {
repArray.push(["city","street","zip","country","planet"]) ;
}
return repArray;
then you should be able to use
#{datasource.indexvar[0]}
to bind city,
#{datasource.indexvar[1]}
to bind street. etc.
Carries a little the danger of messing with the sequence of the array, if that's a concern you would need to dig deeper in using an Object here.
compute to javascript and use something like
var viewnam = "#{" + (compositeData.searchVar )+ "}"
return viewnam
make sure this is computed on page load in the custom control
I was never able to do the addition within EL but I have been very successful with simply computing the field names outside the custom control and then passing those values into the custom control.
I can send you some working code if you wish from a presentation I gave.

Resources