'If' statement with multiple conditions over multiple lines in VB.net - vb.net

I am checking the existence of two files and after that setting a condition but I am getting an error message that the syntax is incorrect when I add the AND
If (System.IO.Directory.GetFiles(CStr(Dts.Variables("VNetworkFolderName").Value), "Z_Attendance.xls").Length > 0
and System.IO.Directory.GetFiles(CStr(Dts.Variables("VNetworkFolderName").Value), "Z_EP.xls").Length > 0) Then
Dts.Variables("VCountAPAListFile").Value = True
Else
Dts.Variables("VCountAPAListFile").Value = False
End If
But if I check just one file without using AND statement, it works fine.

Add an underscore _ before the line terminates to indicate a line break.
If (System.IO.Directory.GetFiles(CStr(Dts.Variables("VNetworkFolderName").Value), "Z_Attendance.xls").Length > 0 _
And System.IO.Directory.GetFiles(CStr(Dts.Variables("VNetworkFolderName").Value), "Z_EP.xls").Length > 0) Then
Dts.Variables("VCountAPAListFile").Value = True
Else
Dts.Variables("VCountAPAListFile").Value = False
End If

You need to either put the line break after the 'And' or use a line continuation character (underscore). Also, it's usually better to use 'AndAlso' in modern VB.
If condition _
AndAlso otherCondition Then
DoThing()
Else
DoOtherThing()
End If
Or
If condition AndAlso
otherCondition Then
DoThing()
Else
DoOtherThing()
End If

Depending on the version, the "And" should be on the first line with a _ at the end.
If (System.IO.Directory.GetFiles(CStr(Dts.Variables("VNetworkFolderName").Value), "Z_Attendance.xls").Length > 0 And _
System.IO.Directory.GetFiles(CStr(Dts.Variables("VNetworkFolderName").Value), "Z_EP.xls").Length > 0) Then
Dts.Variables("VCountAPAListFile").Value = True
Else
Dts.Variables("VCountAPAListFile").Value = False
End If

Calling GetFiles twice is a bad idea. It will iterate through all the folders in the directory twice! You would be better off using File.Exists instead:
Dim folderName As String = CStr(Dts.Variables("VNetworkFolderName").Value
Dim filename1 = Path.Combine(folderName, "Z_Attendance.xls")
Dim filename2 = Path.Combine(folderName, "Z_EP.xls")
Dts.Variables("VCountAPAListFile").Value = File.Exists(filename1) AndAlso File.Exists(filename2)

Related

IsDate Function not recognizing date

I've got this code
If IsDate(EndTime) = True Then
Worksheets("Control_File2").Range("D" & lrow2).Value = EndTime
Else
Worksheets("Control_File2").Range("D" & lrow2).Value = "Not Provided"
End If
and currently End Time = "25/08/2021 07:35:47.546" but the code always goes to the "Else" condition.
why is it not recognizing it as a date?
As GSerg pointed out, the milliseconds are not being handled by IsDate().
Function IsDate2(Value As Variant) As Boolean
Rem I added this line to escape empty strings
If Len(Value) = 0 Then Exit Function
IsDate2 = IsDate(Split(Value, ".")(0))
End Function

VBA If Statement within For (Else Running even when If condition is met)

I'm pretty new to VBA and having issues with a Else statements running even when If conditions are met.
Pretty sure this is due to the If statement being within a For & Next
For iCnt = 1 To Len(Firstname)
If IsNumeric(Mid(Firstname, iCnt, 1)) Then
MsgBox "The Firstname cannot contain Numeric values"
ElseIf Len(Firstname) > 100 Then
MsgBox "The Firstname exceeds the character limit (100)"
Else
Sheet3.Cells(lRow, 2).Value = Me.Firstname.Value
End If
Next iCnt
Please any suggestions how to fix this?
Really you only want the first condition to exist in that FOR loop. The rest of it should be tested afterwards and only if that first condition never trips.
Consider instead:
Dim nameHasNumbers as boolean: nameHasNumbers = False
For iCnt = 1 To Len(Firstname)
If IsNumeric(Mid(Firstname, iCnt, 1)) Then
'number found toggle flag and exit the loop
nameHasNumbers = True
exit For
End If
Next iCnt
'Now alert the user or update the name cell
If nameHasNumbers Then
MsgBox "The Firstname cannot contain Numeric values"
ElseIf Len(Firstname) > 100 Then
MsgBox "The Firstname exceeds the character limit (100)"
Else
Sheet3.Cells(lRow, 2).Value = Me.Firstname.Value
End If
For each letter in the name you are going to get the Else to happen. Need to restructure the whole thing. I would put the checking into a function and then based on that result do your other work. If you need a message to inform the user of the reason for the name being invalid add that to the function. Your function can then do other testing on other conditions without affecting your calling code.
Private Function IsValidName(ByVal value As String) As Boolean
If Len(value) > 100 Then
IsValidName = False
Exit Function
Else
Dim charCounter As Long
For charCounter = 1 To Len(value)
If IsNumeric(Mid(value, charconter, 1)) Then
IsValidName = False
Exit Function
End If
Next
IsValidName = True
End If
End Function
When you want to check whether a string includes a digit, you can compare it to a Like pattern which matches a digit: FirstName Like "*[0-9]*"
That approach is simpler than looping through the string checking whether each character is a digit. And since it does not require the For loop, it should be easier to avoid the logic error in your code sample. (As long as the string length did not exceed 100 characters, it wrote a value to Sheet3.Cells(lRow, 2).Value again for each and every non-numeric character contained in FirstName.)
If FirstName Like "*[0-9]*" Then
MsgBox "The Firstname cannot contain Numeric values"
ElseIf Len(FirstName) > 100 Then
MsgBox "The Firstname exceeds the character limit (100)"
Else
Sheet3.Cells(lRow, 2).Value = Me.FirstName.Value
End If

Validating multiple textboxes with multiple checks

I have multiple textboxes in a groupbox, and can successfully cycle through them all. However the checkNumbers sub fails to recognise blank/null entries, and also non-numeric characters. The correctValidation boolean should return true if all the criteria are met (no blanks/nulls, and must be a number between 1-20). Any thoughts on how to solve this would be appreciated.
Private Sub checkNumbers()
Try
For Each txt As TextBox In Me.gbTechnical.Controls.OfType(Of TextBox)()
If txt.Text <> "" And IsNumeric(txt.Text) And (Integer.Parse(txt.Text) >= 1 And Integer.Parse(txt.Text) <= 20) Then
correctValidation = True
Else
correctValidation = False
MsgBox("Please ensure all numbers are between 1 and 20")
Exit Sub
End If
Next
Catch ex As Exception
MessageBox.Show("General: Please ensure all numbers are between 1 and 20")
End Try
End Sub
I would use Integer.TryParse and then >= 1 AndAlso <= 20. You could use this LINQ query:
Dim number As Int32
Dim invalidTextBoxes =
From txt In gbTechnical.Controls.OfType(Of TextBox)()
Where Not Integer.TryParse(txt.Text, number) OrElse number < 1 OrElse number > 20
Dim correctValidation = Not invalidTextBoxes.Any()
Note that you should almost always use AndAlso instead of And and OrElse instead of Or since those operators are Is short-circuiting boolean operators. This can be more efficient and - more important - can prevent errors. Consider this:
Dim text = ""
If txt IsNot Nothing And txt.Text.Length <> 0 Then text = txt.Text
This fails if txt is nothing since the second condition is evaluated even if the first already was evaluated to false which causes a NullReferenceException at txt.Text.
if you only want a number value, why don't you try to use NumericUpDown. You can also set the Minimum and Maximum in property or use
NumericUpDown1.Maximum = 20
so, there won't be a need to do checkNumbers.
Or is there any reason that you have to use textbox??

Setting value to a not-existing array item?

Please take a look at the following code:
Try
Dim Reader As New System.IO.StreamReader(PositionsFileName)
Do While Reader.Peek() <> -1
Dim Positions() As String = Reader.ReadLine().Split("|")
If (Positions(0) Is Nothing) Or (Positions(1) Is Nothing) Or (Positions(2) Is Nothing) Then
' something
End If
Loop
Catch ex As Exception
ex.Source = Nothing
End Try
I am reading a file and expecting format something|something1|something2. I am trying to make it set "Nothing" to the array index which does not exists (the file format is broken), so that the If statement goes smoothly, but it seem I am doing it wrong. Can you give me some hints?
If you do Split("|") and there are only 2 items (for example, something|something1), Positions(2) will not be Nothing, it will just not be there. So your code will raise an exception, something about index out of bounds of the array.
If you need Positions(2) contain Nothing in this case, you code can look like this:
Dim Positions(2) As String
Dim tmpArray() As String = Reader.ReadLine().Split("|")
For i = 0 To UBound(Positions)
If i <= UBound(tmpArray) Then
Positions(i) = tmpArray(i)
Else
Positions(i) = Nothing
End If
Next
I assume that you only have three "Somethings" per valid line. If so, try writing your Positions() assignment like this:
Dim Positions() As String = Reader _
.ReadLine() _
.Split("|") _
.Concat(Enumerable.Repeat("Nothing", 3)) _
.Take(3) _
.ToArray()
This will ensure that you have three items every time. No need to check for nothings.
Just check positions.length after the split. Also, if you want to check for cases like "||Something2|Something3", the first position will be "" not Nothing. The orelse is a shortcircuit that will keep the latter condtitions from being evaulated if an earlier condition is met.
If Positions.length < 3 OrElse Positions(0) = "" OrElse Positions(1) = "" OrElse Positions(2) = "" Then
' something
End If

Make sure that a string is exactly a 5 digit number

I want to return true if some strings = 'XXXXX'
Where every X is a number 0 through 9
I know there must be a dozen ways to do this but I would like to know the best way.
yourString Like "#####"
If you want the simplest way, you can go with this:
Function MyFunction(myString As String) As Boolean
MyFunction = ((Len(myString) = 5) And (IsNumeric(myString)))
End Function
If you want the more efficient way, you'd have to run some tests for the different methods people suggested.
Edit: The previous solution doesn't work well (see the first 2 comments) but I'm letting it there since it's what has been accepted. Here is what I would do :
Function MyFunction(myString As String) As Boolean
Dim myDouble As Double
Dim myLong As Long
myDouble = Val(myString)
myLong = Int(myDouble / 10000)
MyFunction = ((Len(myString) = 5) And (myLong > 0) And (myLong < 10))
End Function
There is no error "protection" in that function, so if you try to check a too large number like 22222222222222, it will not work.
Similar question previously asked: link text
Basically want to check
(Len(s) = 5) And IsNumeric(s)
You can also use regular expressions to solve this problem. If you include Microsoft VBScript Regular Expressions 5.5 in your VBA project, you can use RegExp and MatchCollection variables as in the function below. (This is a modification of the response to this post at ozgrid.com.)
Public Function FiveDigitString(strData As String) As Boolean
On Error GoTo HandleError
Dim RE As New RegExp
Dim REMatches As MatchCollection
With RE
.MultiLine = False
.Global = False
.IgnoreCase = True
.Pattern = "^[0-9][0-9][0-9][0-9][0-9]$"
End With
Set REMatches = RE.Execute(strData)
If REMatches.Count = 1 Then
FiveDigitString = True
Else
FiveDigitString = False
End If
Exit Function
HandleError:
Debug.Print "Error in FiveDigitString: " & Err.Description
FiveDigitString = False
End Function