moving contents from cell to msgbox with spaces? - excel

I've got an interesting problem - I'm trying to write VBA code that will take the contents of a cell and put it into a msgbox. The problem is that I can't figure how to put carriage returns into this string.
My code looks something like this.
Dim myMsg as string
myMsg = Worksheets("Data").cells(1,1)
msgBox myMsg
so, if cell A1 contains...
THIS IS MY NEXT AND NOW THIS IS A NEW LINE
... how can I force a carriage return into the middle of that line?

I never used VBA, but a quick search online gave me this:
"some string" & vbCrLf & "next line"
and
"some string " & chr(13) & "next line"

To insert a new line is a message box, use vbCrLF.
So, let's say you wanted to put a new line every time there is a back slash. You would use:
Msgbox Replace(ActiveCell.Value, "\", vbCrLF)
To fit within the bounds of your sample code, use:
Dim myMsg as string
Dim newLineCharacter as string
newLineCharacter = "\" ' Replace with your delimiter
myMsg = Replace(Worksheets("Data").cells(1,1), newLineCharacter, vbCrLf)
msgBox myMsg

This depends what your goal is. If you want to pre-formatting text in Excel prior to displaying on message box, wrap you lines using <Alt+Enter> in Excel, then you VBA will just look like this:
MsgBox Worksheets("Data").cells(1,1).value
If you intend to auto-wrap, write a function to cut the string and supply the length.
MsgBox WrapText(Worksheets("Data").cells(1,1).value, 20)

Related

Start a new line while using the Sheets.Range.Formula property [duplicate]

How should I define large strings in VBA? Is there a better way than coding something like the below?
Dim largeString as String
largeString = "This is a long block of text that I want to fill " & _
"into a form field. I need to make sure I pay attention " & _
"to spacing and carriage return issues while doing so. " & _
"I also have to use quotes liberally, the concatenation " & _
"operator, and the continuance underscore to make sure " & _
"VBA can parse my code." & vbCr & vbCr & _
"It's kind of a pain in the ass and I wish I could use " & _
"a heredoc instead, letting me copy and paste the block" & _
"of text I need from another source and shove it into " & _
"a string."
Edit: Ugh, and there's a 25 line continuation limit too? So much for nice indenting and 80 characters of width, that only gives me enough room for a couple decent paragraphs.
I prefer doing it in this way:
Dim lStr As String
lStr = ""
lStr = lStr & "This is a long block of text that I want to fill "
lStr = lStr & "into a form field. I need to make sure I pay attention "
lStr = lStr & "to spacing and carriage return issues while doing so. "
lStr = lStr & "I also have to use quotes liberally, the concatenation "
lStr = lStr & "operator, and the continuance underscore to make sure "
lStr = lStr & "VBA can parse my code." & vbCr & vbCr
lStr = lStr & "It's kind of a pain in the ass and I wish I could use "
lStr = lStr & "a heredoc instead, letting me copy and paste the block"
lStr = lStr & "of text I need from another source and shove it into "
lStr = lStr & "a string."
I think this method is easier to work with than the line continuation method and there is no line number limit to get in with this way. You can comment out individual lines, which is useful for debugging SQL strings.
When handling long strings, I find it easier to use short variable names because VBA does not have the equivalent of += operator. largeString = largeString & "" takes up too much space and gets repetitive, so shortening the string name makes the format somewhat bearable.
For very large blocks of text, write it in a text editor then copy and paste it into your procedure. Then copy
lStr = lStr & "
and paste it at the beginning of each line. The VBA editor will automatically add the quotes at the end of the line making the process simple to do.
No, this is as good as it gets.
For really long strings it might be an option to keep the string in a separate file, or use some application feature. For example, in Word, you might want to store the string in a document variable, as hidden text or AutoText. In Excel, you might consider a hidden sheet for storing long string constants.
Another way is to store the text in comments, then parse it in a function. No external files required, good readability.
' TEXT to retrieve:
' SELECT
' field1, field2
' FROM table1
Function SQL_in_comments()
SQL_in_comments = Replace(Replace(Application.VBE.ActiveCodePane.CodeModule.Lines(2, 3), "' ", ""), "'", "")
End Function
In Excel, there's a much easier way than other answers here. Let Excel do the heavy lifting for you. This method will not require to break the string into smaller chunks -- it can handle up to 32,767 characters at once.
Put the string into a cell. Set aside a scrap worksheet for this purpose. Name the cell, eg MyLongString.
[MyLongString] = "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like)."
Now you can refer to the name in VBA as [MyLongString]. Eg:
MsgBox [MyLongString]

Custom Number Format from UserForm

I've got a text box in a user form where the user puts unit (for example "kg"). I am trying to use this unit to format number of a cell (to add the unit after the value in a cell)
Sub Custom_unit()
Dim Cust_un As String
Cust_un = IM_Form1.TextBox1.Value
Selection.NumberFormat = "0" & Cust_un
End Sub
This is my attempt but when I try to run it, I get a Run-time error '1004': Unable to set the NumberFormat property of the Range class.
How to add quotes to NumberFormat
Given an input from a textbox, you get a string value, e.g. "kg".
In order to use that as a NumberFormat suffix
you need to enclose the unit string with quotes.
You could do that by assigning
Selection.NumberFormat = "0" & """" & Cust_un & """"
or alternatively
Selection.NumberFormat = "0" & Chr(34) & Cust_un & Chr(34)
Note that VBA can neither interprete a single quote (") as string,
nor a single quote enclosed by a start and end quote (""").
Yyou have to include a pair of quotes within the surrounding quotes instead, i.e. """" to make it understood.
The alternative uses the Chr() function
returning a string containing the character associated with the specified character code 34, i.e. the double quote character.
You might prefer to use a help function to return the correct NumberFormat, such as
Function getNumberFormat(ByVal unit As String, Optional NumFmt As String = "0 ") As String
unit = Replace(unit, Chr(34), vbNullString) ' remove existing double quotes
getNumberFormat = NumFmt & Chr(34) & unit & Chr(34) ' build NumberFormat including quotes around unit
' or: getNumberFormat = NumFmt & """" & unit & """"
End Function
Example call
Assuming your Custom_unit() procedure resides in the UserForm code module use Me.TextBox1.Text to refer to the current UserForm instance instead of referring to the default instance of the userform. An example call could be as follows:
Sub Custom_unit()
Selection.NumberFormat = getNumberFormat(Me.TextBox1.Text)
End Sub
BTW a hint: in most cases it's better to avoid selection references, c.f. How to avoid using Select in VBA?

vba Is Like with a variable

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.

in Excel VBA, how do I substitute local variables in a MATCH function in place of hard coded values?

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

Display text link to open specific PDF page from Excel

I found a VBA code online that opens up an internal (shared drive) PDF document page in IE (e.g. goes to page 8 of PDF file). I would like to display text in the cell for a user to click (e.g. "Click here to view").
Problem: The cell currently displays '0' and I have to go to the function bar and hit [Enter] to execute.
Excel Version: 2003
Function call:
=GoToPDFpage("S:\...x_2011.pdf",8)
VBA Code:
Function GoToPDFpage(Fname As String, pg As Integer)
Set IE = CreateObject("InternetExplorer.Application")
With IE
.Navigate Fname & "#page=" & pg
.Visible = True
End With
End Function
:EDIT:
I was able to display text, but it's still not a link like I wanted.
="Click to view" & GoToPDFpage("S:\...x_2011.pdf",8)
Thank you for your help.
If you dont have a high complex workbook/worksheet you could try the following:
Turn the "Click to view" cell into a Hyperlink with following characteristics.
Make it point to itself
The text inside the cell must always be the string Page= plus the number that you what the pdf to open in. Eg.: Page=8
Then go to the workseet module and paste the following code:
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
If Left(ActiveCell.Value, 4) = "Page" Then
GoToPDFpage Range("A1").Value, Mid(ActiveCell.Value, 6)
'This code asumes that the file address is writen in the cell A1
End If
'
End Sub
'
The above written code will trigger every time you run a hyperlink in the worksheet.
As the hyperlink always point to itself, the "Activecell.Value" will always have the page number that you want to open.
I'm assuming that you can put the file address in the cell A1. You could modify this portion to point to any other cell. (including: The cell to the right of the current hyperlink, etc).
This might not be the best option, but if you only need a quick feature in a couple of cells, it might be enough.
Hope it helps !
EDIT:
To make each HLink reference to itself, you can select all the cells where you have the links and then run this procedure:
Sub RefHLink()
Dim xCell As Range
For Each xCell In Selection
ActiveSheet.Hyperlinks.Add Anchor:=xCell, Address:="", SubAddress:= _
xCell.Address, ScreenTip:="Click Here", TextToDisplay:="Page="
Next xCell
End Sub
how about letting excel write a batch file then running it?
*edit paths to pdf and AcroRd32.exe
Sub batfile()
Dim retVal
filePath = "path\pdf.bat"
pg = 2
Open filePath For Output As #1
Print #1, "Start /Max /w " & Chr(34) & "Current E-book" & Chr(34) & " " & Chr(34) & "C:\Program Files (x86)\Adobe\Reader 11.0\Reader\AcroRd32.exe" & Chr(34) & " /a " & Chr(34) & "page=" & pg & Chr(34) & " " & Chr(34) & "H:\Documents\RPG\Dragonlance\New folder\Sample File.pdf" & Chr(34) & ""
Close #1
retVal = Shell(strFilePath)
End Sub
Try Menu->Data->Data Validation. In the 2nd tab you can write your message.

Resources