If text compairson statement failing in Word VBA - vba

I've been fighting with this for a while and I'm not getting why the if statement is returning true when one of the AND statements is obviously false.
strtmp = TypeName(ctl) 'Take for instance (and have verified) this returns String type with the value of Label. However the below is returning true in this case.
If (strtmp = "TextBox") And (arControlName(2) = "Desc") And Trim(Me.Controls(ctl.Name).Value & "") = "" Then
'Do some stuff
End If
My problem is the first statement of the if is somehow equating to true OR "And" is not working as I expect "The AND = TRUE if all conditions are TRUE. The AND=FALSE if any of the conditions are FALSE." OR I'm using it wrong?
Perhaps I am simply loosing my marbles as well :)
EDIT: If the statements are broken out into 3 separate If statements (like below), the code works as expected.
If (strtmp = "TextBox") Then
If (arControlName(2) = "Desc") Then
If Trim(Me.Controls(ctl.Name).Value & "") = "" Then
' Set the value and exit loop
End If
End If
End If

Thanks to the help of the comments that got my brain jogging in a different direction, I've determined the problem.
It apparently has something to do with VBA and not liking to execute certain calls in an If Statement It seems to work fine putting the TypeName(ctl) = "TextBox" in the if statement but not the call to Me.Controls(ctl.Name).Value & "".
strctlTypeName = TypeName(ctl)
strctlVal = Trim(Me.Controls(ctl.Name).Value & "")
If ((strctlTypeName = "TextBox") And (arControlName(2) = "Desc")) And strctlVal = "" Then 'And (Trim(Me.Controls(ctl.Name).Value & "") = "") Then
'Set the value and exit inner for loop
End If

Related

Create dynamic input for variable

I hope someone can help, I am new to programming, my problem is this:
40 checkboxes on a form which one by one, needs to be checked for boolean "True" or "False" (checked or unchecked by user), so that I can run individual code for each "True" case.
I am trying to include a counter "i" in the "MS Access checkbox reference" which I use for the variable, to give me the value of the given checkbox. The following code should show what I try to accomplish, can anybody point me in the right direction, without using a very advanced solution? I presume it is because it cannot execute all of this in a single step or because it only sees my input for the variable as a string and not a command to execute :
Do While Flag = True
Dim CheckboxVar As Boolean
i = i + 1
If i = 40 Then
Flag = False
End If
CheckboxVar = "Me.Checkbox" & i & ".Value"
AddWhereSQL = SQLBuilder (CheckboxVar)
Loop
(Retrieve the value of Checkbox1 and send it to SQLBuilder, retrieve Checkbox2 and send it to SQLBuilder, and so on)
Loop through your checkboxes like this:
Sub Test()
Dim ctrl As Control
For Each ctrl In Me.Controls
If TypeOf ctrl Is CheckBox Then
If ctrl.Value = True Then
'do something
End If
End If
Next ctrl
End Sub
Naming your checkboxes "Checkbox1", "Checkbox2", etc. is tiresome and not the best naming practice. The code above will find every checkbox on the form but you could easily restrict it to all checkboxes with a specific tag, for example.
To loop through the controls, you can do this:
Dim i As Long
For i = 1 To 40
If Me.Controls("CheckBoxControlName" & i).Value = -1 Then
'The control value is True
End If
Next i
If you code is placed in a Standard Module, change Me to Forms!YourFormName.
I think you need a "for" loop. Maybe something like:
CheckboxVar = " WHERE "
For i = 1 to 40
CheckboxVar = Me.Controls("Checkbox" & i).Value = True & " AND " & checkboxVar
next

VBA Excel Return value based on list

The VBA code below was supplied to us, and should make it possible to return streetaddresses based on the postcode and housenumbers we have in excel.
But I can't seem to get it to work at all. Mind I am not a VBA expert :(
I have the key and know it's needed. I have a column with postcodes, and a column with streetnumbers. I need to output a streetname for each of those lines.
Any idea how to set this up?
Sub gkkx()
Dim xDoc As Object
Set xDoc = CreateObject("Microsoft.XMLDOM")
xDoc.async = False
If xDoc.Load("https://api.pro6pp.nl/v1/autocomplete?auth_key=KEYGOESHERE&format=xml&pretty=True&nl_sixpp=" & Postcode & "&streetnumber=" & Streetnumber) Then
If xDoc.DocumentElement.Text = "Not found" Then
Plaats = ""
Adres = ""
Else
If xDoc.DocumentElement.ChildNodes.Length = 0 Then
Dim xDoc2 As Object
Set xDoc2 = CreateObject("Microsoft.XMLDOM")
xDoc2.async = False
xDoc2.Load ("https://api.pro6pp.nl/v1/autocomplete?auth_key=KEYGOESHERE&format=xml&pretty=True&nl_sixpp=" & Left(Postcode, 4))
Plaats = xDoc2.DocumentElement.SelectSingleNode("result/city").Text
Adres = ""
Set xDoc2 = Nothing
Else
Plaats = xDoc.DocumentElement.SelectSingleNode("results/result/city").Text
Adres = xDoc.DocumentElement.SelectSingleNode("results/result/street").Text
End If
'If xDoc.documentElement.childNodes.length > 1 Then
' Tekst41 = MsgBox("Meerdere straten op deze Postcode", vbInformation, "Meerdere Straten")
'End If
End If
Else
' The document failed to load.
Plaats = ""
Adres = ""
End If
Set xDoc = Nothing
End Sub
I'm just glancing through your code and not doing any testing or really analyzing what it is supposed to do. There are some code lines commented-out at the bottom section:
'If xDoc.documentElement.childNodes.length > 1 Then
' Tekst41 = MsgBox("Meerdere straten op deze Postcode", vbInformation, "Meerdere Straten")
'End If
You may want to ask the code author if they intended this section of code to be left in as a comment - commenting-out code means the lines of code are ignored by the compiler. Comments are created by prefixing any text with the apostrophe character. Many times, when someone is writing code, they will comment out parts of the code so they can test individual sections of the code. It could be that the author was doing this and forgot to un-comment (by deleting the apostrophes) this section of code.
Also, I would point out that this code appears to be working with Microsoft.XMLDOM. To get a start on understanding what this code is doing, you may want to have a look HERE.
It's probably not a total answer but I hope it helps. It is a bit difficult, based on the brevity and vagueness of your question, to really have a picture of what you are trying to ask.

Access VBA ListBox ItemData Variant is always 1

I have a form with multiple list boxes and all work fine save 1! This is the only list box whose source is number data-type. I know this shouldn't matter, but what I'm seeing is that for this list box only the variant returned is always 1, and I cannot understand why the others (data-type text) work properly and this one doesn't. All of my Google searches and MSN searches and here on StackOverflow have not helped my specific issue though there's a LOT out there about ListBoxes. Please help!
Edit: Sorry #Mat's Mug...I was hoping that wouldn't be necessary as it's lengthy with all the checking going on, but here's the gist.
For Each ctl In Form.Controls
With ctl
Select Case .ControlType
Case acListBox
If .Visible = True Then
.SetFocus
ItemCount = .ItemsSelected.Count
If .ItemsSelected.Count > 0 Then
For Each varItm In .ItemsSelected
If .Name = "lstRating" Then
sWhereClause = sWhereClause & "ThisRating=" & .ItemData(varItem) & " Or ThatRating = " & .ItemData(varItem)
Else
sWhereClause = sWhereClause & Mid(.Name, 4, Len(.Name)) & " = """ & .ItemData(varItm) & """"
End If
Next varItm
End If
End If
End Select
End With
Next ctl
Note: When .Name = "lstRating" is True is the line where varItem returned is 1 regardless of what is selected. The list box is populated with values from 1 to 5 in 0.5 increments.
Well, I can't believe I was overlooking it for hours...I was using varItem in the offending line when it's defined at varItm, no "e"! TOTALLY an oversight on my part. Thanks all for looking into this!

More efficient error catching?

So I am at an internship for school that is having me code a program using VB.NET. One of the forms has three combo boxes that must have a choice selected in each before moving on. If the user missed one of the comboboxes I am trying to bring it to their attention to go back and make a selection before continuing. I have an if statement, which works exactly how I want it to:
If cboYear.SelectedIndex = -1 Then
warningString = warningString + "Year" & vbNewLine & "Vendor" & vbNewLine & "Report"
txtYear.ForeColor = Color.Red
TextBox7.ForeColor = Color.Red
txtReport.ForeColor = Color.Red
MessageBox.Show(warningString)
ElseIf cboVendorName.SelectedIndex = -1 Then
warningString = warningString + "Vendor" + vbNewLine & "Report"
txtYear.ForeColor = Color.Black
TextBox7.ForeColor = Color.Red
txtReport.ForeColor = Color.Red
MessageBox.Show(warningString)
ElseIf cboReport.SelectedIndex = -1 Then
warningString = warningString + "Report" & vbNewLine
txtYear.ForeColor = Color.Black
TextBox7.ForeColor = Color.Black
txtReport.ForeColor = Color.Red
MessageBox.Show(warningString)
Else
Main.Show()
Me.Hide()
End If
(warningString is a generic string that says something like "Please fill in the following:")
So like I said this works exactly how I want it to, and its pretty easy to follow my logic here. My question is how can I make this code more efficient? I have tried arrays to hold combobox selections, and I have tried a for loop and a select case to try and streamline the code to no avail. The array always breaks out and returns a NullReferenceException before it gets to my Select Case or For loop to see if there is a value in the combobox or not.
If there is someone out there who can help walk me through the logic of getting some kind of loop to work for the above, that would be awesome. I'm not asking for working code or anything like that, however if there is a solution to be found and I get there myself I will post it here for future reference for people. Who knows, this might even be the most efficient way already?
Edit: Plutonix has been gracious enough to have offered some comments on my question, and he brought up a point about the if statements not being mutually exclusive. That is because the comboboxes are being populated by datasets, and each CBO in order determines what information from the datasets will populate the next one. So, depending on what year is selected in the 'Year' combobox, determines which vendors populate the 'Vendor' combobox, and that determines which reports are populated in the 'Report' combobox.
Since each test is doing something different a loop would be clumsy. Even if you only enable B once A is validated, you might need to allow for them to UnDo a previous selection. The code can be condensed though:
Dim IsValid As Boolean = True
txtYear.ForeColor = Color.Black
TextBox7.ForeColor = Color.Black
txtReport.ForeColor = Color.Black
If cboYear.SelectedIndex = -1 Then
warningString = warningString & "Year" & vbNewLine & "Vendor" & vbNewLine & "Report"
txtYear.ForeColor = Color.Red
TextBox7.ForeColor = Color.Red
txtReport.ForeColor = Color.Red
IsValid = False
End If
If cboVendorName.Enabled AndAlso cboVendorName.SelectedIndex = -1 Then
warningString = warningString & "Vendor" & vbNewLine & "Report"
TextBox7.ForeColor = Color.Red
txtReport.ForeColor = Color.Red
IsValid = False
End If
If cboReport.Enabled AndAlso cboReport.SelectedIndex = -1 Then
warningString = warningString & "Report" & vbNewLine
txtReport.ForeColor = Color.Red
IsValid = False
End If
' See note
If IsValid = False Then
MessageBox.Show(warningString)
Else
' DONT use default form instances!
Main.Show()
Me.Hide()
End If
The IF changed a bit: I dont know how you tell which ones are active, the code above is using .Enabled to see if each has been set up for use. That way you wont report errors on CBO 2 and 3 when validating #1.
I would make it a function which Returns IsValid and let the calling code manage the forms to show...and dont use default form instances.

VBA: Debug.Print without newline?

For debugging in VBA, I have several Debug.Print statements throughout my code. For a line-parsing block, I'd like to print the line, and output any flags inline with the line, without having multiple Debug.Print sFlag & sLine statements throughout the many if/elseif/else blocks.
Is there a way, within VBA, to suppress the newline at the end of a Debug.Print statement?
It turns out you can easily do this by simply adding a semicolon to the end of your Debug.Print statement. Like so:
While oExec.StdOut.AtEndOfStream = False
sLine = oExec.StdOut.ReadLine
If bInFileSystem Then
If AnalyzeFileSystemLine(sLine) = False Then
Debug.Print "[FSERR]: ";
End If
ElseIf bInWASCheck Then
If AnalyzeWASLine(sLine) = False Then
Debug.Print "[WASERR]: ";
End If
End If
Debug.Print sLine
Wend
So, some sample output will be:
test text things look good!
[FSERR]: uh oh this file system is at 90% capacity!
some more good looking text :)
[WASERR]: oh no an app server is down!