I am dynamically loading and unloading an array of command buttons on a form.
I can do this:
Dim UnloadIndex As Integer
For UnloadIndex = 1 To 20
Unload frmMain.cmdAction(UnloadIndex)
Next
But I don't always have 20 elements. Is there a way to loop through each one until it reaches the end?
I know I can use a global variable and track the value but I'm trying to avoid this.
Any suggestions please...
Use UBound() which returns the highest available subscript for the indicated dimension of
an array.
Dim UnloadIndex As Integer
For UnloadIndex = LBound(frmMain.cmdAction) To UBound(frmMain.cmdAction)
Unload frmMain.cmdAction(UnloadIndex)
Next
If they're not sequential, you could also do:
Dim Control as CommandButton
For Each Control in frmMain.cmdAction
If Control.Index > 0 Then
Unload Control
End If
Next
Dim UnloadIndex As Integer
For UnloadIndex = LBound(frmMain.cmdAction.LBound) To UBound(frmMain.cmdAction.UBound)
Unload frmMain.cmdAction(UnloadIndex)
Next
I found that the accepted answer way gives a compile error
expected array
Using dot notation instead worked for me.
Related
I am a self taught amateur Visual Basic programmer. My programs are for myself, friends and some non-profit organizations. I have a situation that I thought would be reasonably simple but doesn't seems the case.
I have a text box array of 6 elements (1 -6) named "txtBilled" .When the value is entered into any but element 6 I want to add the values in 1-5 and put result in element 6. My problems start due to the fact that the properties for the text array does not provide for a lost focus option. Searching the inter provides statements that this is normal, others say the "Lost Focus" should always be there.
As a second approach I tried to use the validate element. Never used this before created a sub as follows that I found on the web.
Private sub txtBilled__Validate(Cancel as Boolean)
Found that the Validate event is also not included in the properties for the array
I am using VB6 version 8176 under Windows 10.
Any ideal as to what I am doing incorrectly would be appreciated.
Can you not create your own LostFocus sub using the Index of the textbox array?
Private Sub txtBilled_LostFocus(Index As Integer)
Dim i As Integer
dim sngTotal As Single
' Calculate sum only if not in last textbox
If Index <> uBound(txtBilled) Then
For i = LBound(txtBilled) to UBound(txtBilled) - 1
sngTotal = sngTotal + txtBilled(i)
Next i
txtBilled(uBound(txtBilled)) = sngTotal
End If
End Sub
I need to retrieve 25 images from resources and put them into 25 picturebox randomly without any repetition happening. The process should be done automatically when the page loaded from the very beginning. I had named the picture as 1-25 and i suppose this could help the process.
Do we have any way to complete this process. Sorry for my poor language expression. Please help me, thanks.
One way (could be not the best in performance):
You need to generate the random numbers and store it in a list.
If the generated number is already present in the list, you get another one... at the end... you will have all the numbers
This one is better:
Dim rand As New Random()
Dim new_list As New List(Of Image)
Do While Pictures.Count > 0
' Move a random Image to the new list.
Dim i As Integer = rand.Next(0, Pictures.Count)
new_list.Add(Pictures(i))
Pictures.RemoveAt(i)
Loop
"Pictures" is a collection of images.
This code was taken from here: http://www.vb-helper.com/howto_net_random_picture_forms.html
I am currently trying you learn VB6 and came across this issue.
I wanted to loop through a for loop and adding a number to a control name.
Dim I As Integer
For I = 1 To 5
S = CStr(I)
If TextS.Text = "" Then
LabelS.ForeColor = &HFF&
Else
LabelS.ForeColor = &H80000012
End If
Next I
This S needs to be added to Text and Label so the colour will be changed without needing to use 5 If Else statements
I hope you can help me with this.
From your comment below:
What i mean is this: If Text1.text = "" Then I need this 1 to be replaced with the variable I, so the for loop can loop through my 5 textboxes and the same for my Labels.
You can't do that (look up a variable using an expression to create its name) in VB6. (Edit: While that statement is true, it's not true that you can't look up form controls using a name from an expression. See "alternative" below.)
What you can do is make an array of your textboxes, and then index into that array. The dev env even helps you do that: Open your form in the dev env and click the first textbox. Change its name to the name you want the array to have (perhaps TextBoxes). Then click the next textbox and change its name to the same thing (TextBoxes). The dev env will ask you:
(Don't ask me why I have a VM lying around with VB6 on it...)
Click Yes, and then you can rename your other textboxes TextBoxes to add them to the array. Then do the same for your labels.
Then your code should look like this:
For I = TextBoxes.LBound To TextBoxes.UBound
If TextBoxes(I).Text = "" Then
Labels(I).ForeColor = &HFF&
Else
Labels(I).ForeColor = &H80000012
End If
Next
LBound is the lowest index of the control array, UBound is the highest. (You can't use the standard LBound and Ubound that take the array as an argument, because control arrays aren't quite normal arrays.) Note also that there's no need to put I on the Next line, that hasn't been required since VB4 or VB5. You can, though, if you like being explicit.
Just make sure that you have exactly the same number of TextBoxes as Labels. Alternately, you could create a user control that consisted of a label and a textbox, and then have a control array of your user control.
Alternative: : You can use the Controls array to look up a control using a name resulting from an expression, like this:
For I = 1 To 5
If Me.Controls("Text" & I).Text = "" Then
Me.Controls("Label" & I).ForeColor = &HFF&
Else
Me.Controls("Label" & I).ForeColor = &H80000012
End If
Next
This has the advantage of mapping over to a very similar construct in VB.Net, should you migrate at some point.
Side note:
I am currently trying you learn VB6...
(tl;dr - I'd recommend learning something else instead, VB6 is outdated and the dev env hasn't been supported in years.)
VB6's development environment has been discontinued and unsupported for years (since 2008). The runtime is still (I believe) supported because of the sheer number of apps that use it, although the most recent patch seems to be from 2012. But FWIW, you'd get a better return on your study time learning VB.net or C#.Net (or any of several non-Microsoft languages), rather than VB6...
I have a cell that is evaluated by
=IF(OR(J41="",J40=""),"",(1-($J$41/$J$40)))
computing the percent error between two cells that the user inputs. Additionally, I have an IFC on a seperate sheet that is validating this cell, among other cells, and setting it to a certain color with a warning if the percent error value is above/below a certain number. The problem is that the cell does not show the warning unless I click on it and hit enter (or F2 + Enter), which calculates the cell and populates the value at that time. Is there a way to Force the calculation to occur in that cell when the user inputs values into J41 and J40, thus populating the warning immediately? I have checked multiple threads on this, some say use the Application.Volatile statement, but I am not too sure if that will work..
Any suggestions?
Manually calculating a range is as simple as using Range.Calculate.
To run code when a value is changed in a certain range, use Worksheet_Change.
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rngTrigger As Range: Set rngTrigger = Range("D5")
Dim rngTarget As Range: Set rngTarget = Range("E5")
If Not Intersect(Target, rngTrigger) Is Nothing Then _
rngTarget.Calculate
End Sub
In VB6, I'm supporting code that loops through all the views in a Lotus Notes database thusly:
For lngdomViewidx = LBound(domDatabase.Views) To UBound(domDatabase.Views)
Set domView = domDatabase.Views(lngdomViewidx) ' note: this line right here is slow to execute
The amount of time it takes to retrieve a reference to the view by index with this method seems proportional to the number of documents in the view. This bit of code is just looping through the Notes database to build a list of all the view names. On really large databases this can take several minutes. Is there a faster way to get this information?
Thanks!
That is not a very efficient way, no.
Use something like the code below instead. It is Lotusscript, but it should be pretty much the same in VB. I haven't tested it, just copied it from a production database and modified it to look for views instead for forms like in my original...
Dim ncol As NotesNoteCollection
Set ncol = db.CreateNoteCollection(True)
Call ncol.SelectAllNotes(False)
ncol.SelectViews = True
Call ncol.BuildCollection
noteID = ncol.GetFirstNoteId
For i = 1 To ncol.Count
Set doc = targetdb.GetDocumentByID(noteID)
MsgBox "view = " + doc.GetItemValue("$Title")(0)
noteID = ncol.GetNextNoteId(noteID)
Next
Karl-Henry is absolutely right: The NotesNoteCollection is really the fastest way to loop through all views.
But you can speed up your code significantly by just changing the loop.
Instead of opening each view using its index, you coud, do something like:
Forall view in db.Views
'Do whatever you want
End Forall
Accessing elements in a collection in Lotus Notes using the index means, that it always has to count from the beginning, while using a forall- loop directly accesses the next element...