VBA for Each loop - vba

Hi I do have a problem with for each elements in the range. I would like to use for each loop and for each element of that collection certain action must be taken meaning another sub procedure, everything works fine until first time. For the second element macro lives the loop does not continue what is wrong here HOW SHOULD I AVOID THIS?
Maybe is some better way to do some tasks for each elements in particular range.
In my case I do have 8 such ranges each consists of 20 elements.
NOTE if Im not calling Hiding_and_Creating_Dump(Celly) inside loop everything works fine.
PLEASE ADVICE
For Each Items In ThisWorkbook.Sheets("BU_SELECTOR").Range("A47:H47")
Debug.Print Items
Select Case Items.Value
Case Is = "ASCButton"
If ASCButton = True Then
For Each Celly In Workbooks(XLSname).Sheets("lookups").Range(Range_ASC)
Debug.Print Celly
CommSheetName = Celly.Value
Call Hiding_and_Creating_Dump(Celly)
Next Celly
End If
Case Is = "ICOButton"
enter image description here

Related

Make Text Box visible with condition

I am new at VBA and I am trying some code and I could not find a solution or where I am doing wrong.
What I want: The combination of two different text boxes make another text box visible(so it starts in useform not visible). With one condition I could do it using select case(LLL) but when I try it with another variant it does not work(XXX). There is no error message, the code runs but does not show the text box.
Sub Visible()
If userform.TextBox5.Value = "XXX" And userform.TextBox10.Value = "245" Then
userform.TextBox1.Visible = True
userform.T_1.Visible = True
Else
GoTo LLL
End If
LLL:
Select Case True
Case userform.TextBox5.Value = "LLL", userform.TextBox10.Value >= "145"
If userform.Option000.Value = True Then
userform.TextBox1.Visible = True
userform.T_1.Visible = True
Else
userform.TextBox1.Visible = False
userform.T_1.Visible = False
End If
End Select
I understand some of your questions I must say that my code is quite big one cause it is linked to SAP in order to get some values from there and due to its size the complete code is splitted in modules and I am only sharing the module where I am facing problems.
There is one case for select case statement cause it was the only way that it worked close for what I need. I have a lot of variables for the fields TextBox5 and TextBox10 the values of these textboxes come from SAP and when I combine them, other Text Boxes shall be visible depending on the variables given. The problem is that for just one combination (this one is the one that I applied the select case statement) I need another variable (option000) so that TextBox1 and T_1 become visible. When I tried to do it only with if statements it did not worked.

Saving Custom Document Properties in a Loop

I'm trying to save the values of data that have been input into my form. There are a total of about 50 different fields to save across 5 different agents, so I loaded the data into arrays.
I've tried saving the fields in a loop, but it doesn't seem to work in a loop, only if each field has a separate line, which is a lot of code and messy. The Ag1Name, Ag2Name and Ag3Name are the names of my textboxes that the user enters to populate the form.
Sub LoadAndSaveData()
NumberofAgents = 3
Dim AgentName(3) as String
AgentName(1) = Ag1Name.Value
AgentName(2) = Ag2Name.Value
AgentName(3) = Ag3Name.Value
For Count = 1 To NumberOfAgents
With ActiveDocument.CustomDocumentProperties
.Add Name:="AgentName" & Count, LinkToContent:=False, Value:=AgentName(Count), Type:=msoPropertyTypeString
End With
Next Count
End Sub
The data doesn't get saved to the Custom Document Properties when the code is set up in a loop like the above. Since there are so many values to save and all the data is already in arrays, I would much prefer to use a loop rather than write out a separate line of code for all ~50 of the values. It does seem to work when each field is saved in a separate line of code.
I think this would probably get what you want. You don't really need to count the document properties first, only increment with the ones you want to update. Hopefully the only document properties you want contain the name AgentName in it.
ReDim AgentName(0) As String
Dim P As Long
For Each c In ThisDocument.CustomDocumentProperties
If InStr(1, c.Name, "AgentName", vbTextCompare) > 0 Then
ReDim Preserve AgentName(P)
AgentName(P) = c.Value
P = P + 1
End If
Next c
As a guest I cannot post a comment here, but the code you gave works OK here.
However, there is a problem with creating legacy custom document properties programmatically, because doing that does not mark the document as "changed". When you close the document, Word does not necessarily save it and you lose the Properties and their values.
However, if you actually open up the Custom Document Property dialog, Word does then mark the document as "changed" and the Properties are saved.
So it is possible that the difference between your two scenarios is not the code, but that in one scenario you have actually opened the dialog box to check the values before closing the document and in the other you have not.
If that is the case, here, I was able to change this behaviour by adding the line
ActiveDocument.Saved = False
after setting the property values.
If you do not actually need the values to be Document Properties, it might be better either to use Document Variables, which are slightly easier to use since you can add them and modify them with exactly the same code, or perhaps by storing them in A Custom XML Part, which is harder work but can be useful if you need to extract the values somewhere where Word is not available.
You can make this even easier by looping the controls on the UserForm, testing whether the control name contains "Ag" and, if it does, create the Custom Document Property with the control's value - all in one step.
For example, the following code sample loops the controls in the UserForm. It tests whether the controls Name starts with "Ag". If it does, the CustomDocumentProperty is added with that control's value.
Sub LoadAndSaveData()
Dim ctl As MSForms.control
Dim controlName As String
For Each ctl In Me.Controls
controlName = ctl.Name
If Left(controlName, 2) = "Ag" Then
With ActiveDocument.CustomDocumentProperties
.Add Name:=controlName, LinkToContent:=False, value:=ctl.value, Type:=msoPropertyTypeString
End With
End If
Next
End Sub
I feel a little stupid... I just realized that the reason that the code wasn't working was that the variable NumberofAgents was not being calculated correctly elsewhere in my code. I've got it working now. Thanks for your thoughts!

Attaching specific files based on the user's selection in a userform

For the next part of this project that I've been working on to speed up follow up emails to clients for the office, I'm looking to grab a specific attachment from a specified filepath based on the items that the user selected on the userform. These emails will always be sending the exact same files so the less time the user has to spend manually attaching files, the better it will be. My first assumption right off the bat was that I'd need a loop to do this, so I began to do my groundwork, but now I'm generally stuck.
The first loop grabs what the user selected from the userform:
For i = 0 To List1.ListCount - 1
If List1.Selected(i) Then
Counter = Counter + 1
msg = msg & "<font style = 'background: yellow'>" & List1.List(i) & "<br />"
Else: If Counter = 0 Then End
End If
Next
And the second loop attaches the files based on the selections above:
For i = 0 To List1.ListCount - 1
If List1.Selected(i) Then
Counter = Counter + 1
.Attachments.Add List1.List(i)
Else: If Counter = 0 Then End
End If
Next
The attachments process just fine.However, the program ends up displaying the highlighted body of the message as the filepath I tried to associate with the list item:
' test files
List1.List(0) = "C:\Users\jmarkman\Dropbox\Python Practice\ex1.py"
List1.List(1) = "C:\Users\jmarkman\Dropbox\Python Practice\ex2.py"
List1.List(2) = "C:\Users\jmarkman\Dropbox\Python Practice\ex3.py"
List1.List(3) = "C:\Users\jmarkman\Dropbox\Python Practice\ex4.py"
List1.List(4) = "C:\Users\jmarkman\Dropbox\Python Practice\ex5.py"
List1.List(5) = "C:\Users\jmarkman\Dropbox\Python Practice\ex6.py"
So my question is, how do I associate these file paths with corresponding items in the listbox within the userform? I'm pretty sure that although it worked, the process changed the list items since I assigned them a different value.
I'm not sure how complex or simple this might end up being, so your time and patience are well appreciated.
People have said that one can learn best just by doing and making mistakes, but let me tell you that not having someone you can at least talk to about where to start making mistakes is incredibly frustrating. I hope anyone else who, like me, was on the cusp of solving this problem is able to look here and have their own "a-ha!" moment.
When I first asked this question, I was on the right path with choosing to put all of my filepath locations within an array and I was further along the right path by using a loop to go through it. I declared the myAttach array with a range as I did at first, but unlike whatever example I saw during my google research, I kept my second attachment loop the same but simply changed out List1.List(i) for myAttach(i). That made the script's wheels turn and performed all the functions I needed it to.
The long and short of it was that I made an array that matched the quantity and order of the items in the userform and re-used the loop I made for picking the subjectivities, I was able to associate the choices in the userform to those in the array by having the second loop go through the array. Each listing in the array had a filepath associated with it.
' example
myAttach(0) = "[filepath]"
myAttach(1) = "[filepath]"
myAttach(2) = "[filepath]"
myAttach(3) = "[filepath]"
' ... and so on ...
It helped to visualize the array and the list items as two side-by-side columns; the first item in the list is parallel to the first item in the array, and can therefore be recognized by the second loop. If a mental image isn't forthcoming, try inputting some data into two or more Excel columns to witness the relationship or review Matricies.
A caveat of this line-up approach, I found out shortly after while continuing research to figure out exactly what I did right this time would be if I had to have the items in the list in a specific order (i.e., alphabetical), but fortunately the list items are phrases and complete sentences and don't require sorting.
Happy learning and programming!

VBA to GetElementByID on a Web form

I'm having a bit of trouble with my VBA code filling in a form on an intranet page. It generally works okay but every so often, the ID's of the fields on this form change and I have to update my code but not until I've had lots of errors reported. Is there anyway I can use a wildcard, or loop through the possibilities before it tries to fill out the form? The bit of code I'm using is
WebBrowser1.Document.GetElementById("Template_ctl24_ctl00_Shelfmark" & x & "_TextField").value = Range("Q" & x + 11).value
But the ID can change to Template_ctl22_ctl00.... or Template_ctl25_ctl00.... for a reason unknown to me. I don't have control over that area - i'm really only front end.
So is there some variation on using a * wildcard?
Or looping through whether the ID is a 22, 24, 25 or whatever before it proceeds?
What can and can't you do with this sort of line of VBA code?
Thanks in advance
Paul
If you know where the element is positioned on the page it would be much better to locate it using something like getElementsByTagName.
However, you could use a simple loop. In the following I've assumed the attempt to reference a non-existing element results in Nothing, but perhaps it generates an error - I haven't tested. If so, you'll need to use error-handling code instead.
Dim elem As Variant
For x = 22 To 25
Set elem = WebBrowser1.Document.GetElementById("Template_ctl24_ctl00_Shelfmark" _
& x & "_TextField")
If Not elem Is Nothing Then
Exit For
End If
Next x
If elem Is Nothing Then
'Doh! not found
Else
'obtain elem.value
End If

Using a for loop to call consecutive variable names (ie car1, car2.... car10) in VBA

Scenario)
I have seven variables; labelKid1, labelKid2, ...LabelKid3. I'm searching through cells to find ones that are not empty, and then entering the value into the label, starting with labelKid1, and then moving on to the next label.
Question)
Is there a way to us a for loop to go through these variables? By this I mean can I somehow call the variable with something such as labelKid + j , with j being the value of the for loop? This would allow me to march through the labels a lot more easily.
Now, I understand that I could probably do this by putting the labels into an array and using a for loop to call their indicies, but is there a way to do it as I stated above?
No, VBA does not support variable variables (as they are called in PHP). As you said you will need to use a list, dictionary or similar instead.
You can achieve this using UserForm1.Controls("labelKid" & i) Which calls any form control by name associated with UserForm1
So you would need something like this
Sub ControlName()
Dim i As Long
For i = 1 To 10
UserForm1.Controls("labelKid" & i).Value = i
Next
End Sub
Hope this helps!