Months ago I wrote a small Makro for my Company and until now it worked just fine.
Recently (maybe because we updated Office Version) there is a bug, that excel adds a new line in a print statement.
Code:
outputString = value1 & " " & value2 & " " & value3 & " " & value4 & " " & value5 & " " & user & " " & date
used to give me this output:
22 S ***/***s 9932256 B*****t Fatma 811 R******r Alexander 27.12.2019
now gives me this output:
22 S ***/***s 9932256 B*****t Fatma 811 R******r Alexander
27.12.2019
As you can see, excel adds a newline.
Can somebody tell me what happends here?
EDIT:
Solution:
Excel adds the new line after using:
user = Application.UserName
Maybe this is due to the office update we had. So I just took substring and cut the last character and works fine now.
Application.Username returns as the documentation states the username. As it is Read/write it can indeed happen that you will get a username that contains a vbLf or vbCrLf. Have a look at the following example
Sub UserName_VbCrlf()
Dim origUser As String
Dim user As String
' Be careful when testing as it replaces your username!!
' Maybe you save it first
origUser = Application.UserName
Application.UserName = "Storax" & vbLf & "Home adress"
user = Application.UserName
' This will give different lengths
Debug.Print Len(user), Len(Replace(user, vbLf, ""))
' Restore original username
Application.UserName = origUser
End Sub
I am creating a userform with approximately 75 text boxes. I would like to create a common function to test the validity of the data for all text boxes by passing the allowable characters to the function along with the string I wish to validate.
For some boxes, I want to check only for numerics (like a phone number with (), -, and spaces stripped prior to calling the function).
For boxes such as last name, I want to test for upper and lower case alpha as well as allowing embedded spaces and a hyphen.
For other boxes that allow other free form text, I want to restrict input to selected character such as letters, numbers, hyphens, left and right parens "()", etc.
I cannot get the syntax right so that the "Is...Like" works correctly. I get "Run time error 5"..."Invalid procedure call or argument".
Here is my function:
Function IsValidString(strValue As String, strAllowed As String) As Boolean
Dim intPos As Integer
Dim strTemp As String
strTemp = """" & strAllowed & """"
MsgBox "StrValue = " & strValue & vbCrLf & vbCrLf & "StrAllowed = " & strAllowed & vbCrLf & vbCrLf & "strTemp = " & strTemp
For intPos = 1 To Len(strValue)
If Not (Mid(strValue, i, 1) Like strAllowed) Then IsValidString = False
Next intPos
IsValidString = True
End Function
To call the function, I use:
If Not IsValidString(strTemp, "[A-Za-z0-9]/#-") Then MsgBox "You Lose"
The error occurs within the Function code. It does not matter if I test for strAllowed or strTemp; I get the same error.
Thanks for looking at it.
Based upon the answer from #Comintern, I overlooked that I was checking the value of "i" instead of "intPos". Stupid mistake from a guy who is tired. Thanks for all the comments; it helped me solve the issue.
I've written some VBA code that cycles through the rows of an open Excel datasheet doing an Evaluate(Index(Match)) statement, that I found online, that searches for 2 values (LastName & LabCat) in a second Excel Workbook. The result (FirstName) is returned from the second Excel Workbook and stored in a local variable. I successfully return the value I'm looking for with this statement:
strFirstName = Evaluate("INDEX('[MyMatrix.xlsm]MySheet'!$C$2:$C$1000,MATCH(""Cain""&""ABO1"",'[MyMatrix.xlsm]MySheet'!$B$2:$B$1000&'[MyMatrix.xlsm]MySheet'!$H$2:$H$1000,0))")
But what I haven't been able to solve is how to substitute local variables for the hard coded values, such as this statement (where I substitute the string "cain" with the variable strLastName and I substitute the string "ABO1" with the variable strLabCat):
strFirstName = Evaluate("INDEX('[MyMatrix.xlsm]MySheet'!$C$2:$C$1000,MATCH(""strLastName""&""strLabCat"",'[MyMatrix.xlsm]MySheet'!$B$2:$B$1000&'[MyMatrix.xlsm]MySheet'!$H$2:$H$1000,0))")
This statement returns "Error 2042" into strFirstName.
Sometimes it's easier to use a token replacement approach than trying to do a bunch of concatenation.
E.g.:
Dim sht As Worksheet, f, strFirstName
Set sht = Workbooks("MyMatrix.xlsm").Worksheets("MySheet")
f = "INDEX($C$2:$C$1000,MATCH(""{LastName}""&""{LabCat}"",$B$2:$B$1000&$H$2:$H$1000,0))"
f = Replace(f, "{LastName}", "Cain")
f = Replace(f, "{LabCat}", "AB01")
strFirstName = sht.Evaluate(f) '<< note using the Worksheet.Evaluate form here
You almost had it but it's easy to get mixed up with all the ""double-double"" quotes you need in a string in order to assign "double quotes" to the value of the string.
With your specific example, if this is successful:
strFirstName = Evaluate("INDEX('[MyMatrix.xlsm]MySheet'!$C$2:$C$1000,MATCH(""Cain""&""ABO1"",'[MyMatrix.xlsm]MySheet'!$B$2:$B$1000&'[MyMatrix.xlsm]MySheet'!$H$2:$H$1000,0))")
...but instead of hardcoding Cain and AB01, you want to get the values from string variables as stated in your question, change the line to:
strFirstName = Evaluate("INDEX('[MyMatrix.xlsm]MySheet'!$C$2:$C$1000,MATCH(""" & strLastName & """&""" & strLabCat & """,'[MyMatrix.xlsm]MySheet'!$B$2:$B$1000&'[MyMatrix.xlsm]MySheet'!$H$2:$H$1000,0))")
Backing up a bit, consider the following simple example of a string being assigned to a variable:
Option Explicit
Sub varTest1()
Dim myGreeting As String
myGreeting = "Hello, My name is Juan and I live in Mexico"
MsgBox myGreeting
End Sub
Running this subroutine, causes a message to pop-up with a greeting from Juan. Very basic, but note:
The variable is explicitly declared. It would work without the As String part but it's good coding practice to always specify a data type.
I used the optional statement Option Explicit. If used, it must be the first line in the module, and only appear once per module. What is does is force you to declare all variables and handle objects properly, by generating "pickier" errors during compilation or prior to code execution. Why would you want more errors? Better now than [unexpectedly] later, and is highly recommended to newer-coders and/or when troubleshooting.
Next, let's replace Juan's hardcoded name with another variable.
Still simple, like this:
Sub varTest2()
Dim myGreeting As String, myName As String
myName = "Juan"
myGreeting = "Hello, My name is " & myName & " and I live in Mexico"
MsgBox myGreeting
End Sub
Basically you're just concatenating a string. A plus symbol + works for adding strings or numbers together, but again, best practice is to stick with the one specifically meant for strings, which is the ampersand &.
Let's add another variable again:
Sub varTest3()
Dim myGreeting As String, myName As String, myCountry As String
myName = "Juan"
myCountry = "Mexico"
myGreeting = "Hello, My name is " & myName & " and I live in " & myCountry
MsgBox myGreeting
End Sub
Same idea as #2; the reason I added example #2 is to demonstrate that if the variable is at the end of the string, there's no need for an additional " quote.
However if we wanted a period at the end of the sentence, the line would look like:
myGreeting = "Hello, My name is " & myName & " and I live in " & myCountry & "."
Note that all of the above examples have identical results.
Adding Double-Quotes within the String:
This is where the " double quotation marks can get a little confusing, since they are needed around the text that you are assigning to the string, but how do we put them inside the string? Well there's a couple ways.
Backing up again, we could add single quotes ' around the name like this:
myGreeting = "Hello, My name is 'Juan' and I live in Mexico."
...and the string would contain:
Hello, My name is 'Juan' and I live in Mexico.
...but if we instead wanted double-quotes " around part od the string for cosmetic reasons like these examples, or for mandatory reasons like requirement in a formula (like your example), we can do one of two things:
add the " symbol using the ASCII character code of 34. The function in VBA would be Chr(34) as as a worksheet function CHAR(34).
or, each time we want a " double-quote, we use two double-quotes together "" (or a quad-quote as I call it.)
For example, hardcoded:
Sub varTest4()
Dim myGreeting As String
myGreeting = "Hello, My name is ""Juan"" and I live in Mexico."
MsgBox myGreeting
End Sub
This would display a popup message box that says:
Hello, My name is "Juan" and I live in Mexico
Or, we could again use a variable with the name and double-quotes around it:
Sub varTest5()
Dim myGreeting As String, myName As String
myName = """Juan"""
myGreeting = "Hello, My name is " & myName & " and I live in Mexico"
MsgBox myGreeting
End Sub
...which will produce the same result as the previous example (#4).
Or we could add the double-quotes to myGreeting instead of via myName:\
Sub varTest6()
Dim myGreeting As String, myName As String
myName = "Juan"
myGreeting = "Hello, My name is """ & myName & """ and I live in Mexico"
MsgBox myGreeting
End Sub
...we will again get the exact same result as above.
And, to demonstrate what that would look like if we wanted double-quotes around both the Name and the Country (so with a double-quote appearing at the very end of the string):
Sub varTest7()
Dim myGreeting As String, myName As String, myCountry As String
myName = "Juan"
myCountry = "Mexico"
myGreeting = "Hello, My name is """ & myName & """ and I live in """ & myCountry & """"
MsgBox myGreeting
End Sub
There are at least a couple ways to add a double-quote within a string:
Using the "" "quad-quote" as above, or,
Using the ASCII character code (which is 34 for a double-quote.)
...because sometimes all these excessive quotes can get confusing.
For example, to show three double-quotes, like this:
"""
I would need to use:
MsgBox """"""""
...that's eight double-quotes: one to begin the string, one to end the string, and three sets of two for each one to display. (Would that be called an Octo-quote?!)
We could display this:
"Juan"
with:
MsgBox """Juan"""
...or exact same results (but a little cleaner in my mind):
MsgBox Chr(34) & "Juan" & Chr(34)
...so therefore changing the line in example #7, this:
myGreeting = "Hello, My name is " & Chr(34) & myName & Chr(34) & _
" and I live in " & Chr(34) & myCountry & Chr(34)
...would produce identical result as example #7 did:
Hello, My name is "Juan" and I live in "Mexico"
Finally, one more thought about the example from your question, on the topic of clarity with confusing strings. You can use the underscore _ as a "line continuation symbol" to break up a long line of code to multiple lines, making it easier to read, both in your VBA Editor (VBE), as well as for others to read or copy/paste when posting code on sites like this!
For example, my "correction" to your line of code was:
strFirstName = Evaluate("INDEX('[MyMatrix.xlsm]MySheet'!$C$2:$C$1000,MATCH(""" & strLastName & """&""" & strLabCat & """,'[MyMatrix.xlsm]MySheet'!$B$2:$B$1000&'[MyMatrix.xlsm]MySheet'!$H$2:$H$1000,0))")
...one loooong line (and they can get much loooonger!)
I didn't want to make my original response more confusing my adding extra symbols until I explained the quotes, but a "cleaner" to write lengthy lines is to add underscores anywhere you want to continue on the following line, like this:
strFirstName = Evaluate("INDEX('[MyMatrix.xlsm]MySheet'!$C$2:$C$1000, " & _
"MATCH(""" & strLastName & """&""" & strLabCat & """,'[MyMatrix.xlsm]" & _
"MySheet'!$B$2:$B$1000'[MyMatrix.xlsm]MySheet'!$H$2:$H$1000,0))")
You won't have to scroll-right in your VBE to see the code, and notice how Stack Overflow doesn't have to add the horizontal scroll bar either.
Clear as mud? :-)
Good Luck! (and your question was well-posted question too. Welcome, by the way!)
Further info on:
Quotation Marks in Strings
Declaring Variables in VBA
Breaking and Combining Statements in VB/VBA Code
String Basics in VB/VBA
I am trying to use vba to read all text in a text file and display it in an excel message box. the problem I have is whilst this is in effect working, it displays each line of text in a separate message box when instead I want it all in one?
can someone please show me where I am going wrong. thanks
If Range("L" & ActiveCell.Row).Value = "Performance" Then
Dim FilePath As String
Dim strLine As String
FilePath = "\\UKSH000-FILE06\Purchasing\New_Supplier_Set_Ups_&_Audits\ATTACHMENTS\" & Range("C" & ActiveCell.Row).Value & "\performance.txt"
Open FilePath For Input As #1
While EOF(1) = False
'read the next line of data in the text file
Line Input #1, strLine
'print the data in the current row
MsgBox strLine
'increment the row counter
i = i + 1
Wend
Close #1
End If
Within your loop you have to concatenate all the lines a string variable and output the result at the end. It's basically like this:
Dim Total As String
' ...
While EOF(1) = False
'read the next line of data in the text file
Line Input #1, strLine
Total = Total & vbNewLine & strLine
'increment the row counter
i = i + 1
Wend
MsgBox Total
Note: While this solution is working, for large files it may not be very efficient due to the fact that what looks like a concatenation in code, in fact means copying the existing content to a new memory location, and then inserting the new line's string. That is done for every line. So for 1000 lines, the incresingly large total string is copied around 999 times.
You need to accumulate the text in a separate string:
Write Dim strAll As String before the loop.
Replace the MsgBox in the loop with strAll = strAll & strLine.
After the loop, use MsgBox strAll
& is used to join strings in VBA. You could separate the individual lines with a space:
strAll = strAll & " " & strLine.
Or even multi-line
strAll = strAll & vbCrLf & strLine.
where vbCrLf is a VBA constant which means "carriage return followed by line feed". You'll introduce an extra space / line feed at the start of the string but I'll leave that for you to fix!
I have a function which sets a variable for the current user. The variable name is prefixed with the name of the module - basically, the way the application is set up, Client is a class, Server is a class, Agency is a class and so on. This is an attempt to create a system whereby we can find out any key information about a client or one of their websites, across over 200 servers, with as few clicks as possible and using live data from their DB.
The function is as follows:
public sub setVariable(varName, varValue)
varValue = cstr(varValue)
def = ""
if varValue = "" then def = "1"
response.write vbcrlf & "Variable: " & varName & " : " & varValue & vbcrlf
if not cstr("" & getVariable(varName, def)) = cstr("" & varValue) then
response.write vbcrlf & varName & " : " & varValue & vbcrlf
prepend varName, "Module." & Name & "."
response.write vbcrlf & varName & " : " & varValue & vbcrlf
session(varName) = varValue
Core.RunSproc "SetUserVariable", array("#name", "#value"), array(varName, cstr(varValue)), setVar
end if
end sub
Now on line 5, where it is first output, only "ID" is output as the variable name. However 2 lines later the name is set to "Module.<module-name>.ID" (for example Module.Server.ID. 2 lines after that, after the prepend statement (which acts the same as doing varName = "something" & varName), it outputs the something + "Module.<module-name>.ID". In effect, in this case, it outputs "Module.Server.Module.Server.ID". Note that if I take anything out, it is taken out of the first Module.Server but not the 2nd. Does anyone have any idea what is causing this? It seems as though Module.Server is being prepended to the variable name between lines 5 & 7, but the only line there is an if statement. Thanks in advance.
Seems I have found the answer. It's the fact that ASP automatically assumes variables input into functions are byref. Thus, when calling getVariable, I was actually prepending "Module.Server." there too, and because it was byref the variable maintained the value.
Regards,
Clarkey