I was wondering if it would be possible to call out several items from a single cell? I am very limited in space so having one cell with all the information would be a great benefit. for example if i had a single cell that had "Dog,2,5,8" the program could run the program could tell what it meant and run my calculation? Thank you for your help in advance.
As #Tim Williams said, Split() will do what you want.
Sub splitcell()
Dim TestString As String
TestString = CStr(Range("A3").Value)
Dim TestArray() As String
TestArray() = Split(TestString, ", ")
MsgBox (TestArray(0) & vbNewLine & TestArray(1) & vbNewLine & TestArray(2) & vbNewLine & TestArray(3))
End Sub
Macro will give you this message box:
Now you can just iterate through the TestArray() with a For loop and do your logic.
See MSDN documentation here
And here is another post
Related
I'm using Threaded Comments on my Excel workbooks. Most of them have multiple replies.
I want to convert the comments and replies to text.
I get the first comment using the function CommentThreaded.text but not the replies if any.
How to do it using VBA?
Here are some commands to work with threaded comments in VBA:
' To know if a cell has a threaded comment:
If Not Range("*c,r*").CommentThreaded Is Nothing Then
' To know if the threaded coment has replies:
Range("*c,r*").CommentThreaded. Replies.Count
' To add a threaded comment:
Range("*c,r*").AddCommentThreaded ("Add CommentThreaded")
' To response a threaded comment:
Range("*c,r*").CommentThreaded.AddReply ("*your reply here*")
' To resolve a threaded comment:
Range("*c,r*").CommentThreaded.Resolved = True
' To re-open a resolved threaded comment:
Range("*c,r*").CommentThreaded.Resolved = False
' To delete a threaded comment:
Range("*c,r*").CommentThreaded.Delete
' To get the author:
Range("*c,r*").CommentThreaded.Author.Name
' To get the date:
Range("*c,r*").CommentThreaded.Date
' To get the text on the cell where the threaded comment is:
Range("*c,r*").CommentThreaded.Parent
' To get the address where the threaded comment is:
Range("*c,r*").CommentThreaded.Parent.Address
' To get the text of the original comment:
Range("*c,r*").CommentThreaded.Text
' To get the text of the replies:
Range("*c,r*").CommentThreaded.Replies(*n*).text
' To get the replies author:
Range("*c,r*").CommentThreaded.Replies(*n*).Author.Name
' To get the date of the reply:
Range("*c,r*").CommentThreaded.Replies(*n*).Date
There is not too much information out there about threaded comments, so I hope this is useful.
I used Bernardo's list of commands to create my function (which also checks for Notes), and I'm sharing it in case anyone is looking for an already-complete solution:
Function UdfComment(rng As Range) As String
'This UDF returns a cell's Note or all its comments (prefixed by Date and Author Name).
'This UDF assumes the range is a single cell.
Application.Volatile
Dim str As String
'First, check for presence of Note (the thing that shows up when you press Shift+F2):
If Not rng.Comment Is Nothing Then
str = Trim(rng.Comment.Text)
'If the note has a standard name header on a separate line - if you want to remove it, uncomment this line:
'(to be safe, can delete the "- 1" at the end to prevent truncating if name header is NOT on a separate line)
'str = Right(str, Len(str) - InStr(1, str, ":") - 1)
'Notes and Comments seem to be mutually exclusive, so checking for comments in an "Else if":
ElseIf Not rng.CommentThreaded Is Nothing Then
'First, return the original comment (prefixed by date and author):
str = rng.CommentThreaded.Date & ", " & rng.CommentThreaded.Author.Name & ":" & vbNewLine & Trim(rng.CommentThreaded.Text)
'Now check if original comment has replies (if so, iterate through them and append them all to 'str'):
If rng.CommentThreaded.Replies.Count > 0 Then
For Each r In rng.CommentThreaded.Replies
str = str & vbNewLine & r.Date & ", " & r.Author.Name & ":" & vbNewLine & Trim(r.Text)
Next
End If
'Without notes and comments, simply return an empty string:
Else
str = ""
End If
UdfComment = str
End Function
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
My coworkers often have to send out invites for interviews (up to dozens at a time). I am writing a macro to help them autogenerate Outlook meeting invites based on all of the interviewees' information, which we store in an Excel data file.
E.g., "Dear [INSERT NAME], We would like to invite you to an interview about [INSERT SUBJECT] on [INSERT DATE]. Please call into the interview using [INSERT PHONE NUMBER] and be prepared to talk about patients with [INSERT CONDITION]."
Because my coworkers do not know VBA I'm trying to have them write it in an input sheet and have the program read it and the formatting and store it in a variable called MeetingInviteBody. So I need to take a cell's value and read it as a variable definition. The problem is the entire thing is entered as a string, even if the cell's contents are part string and part reference to another variable. Is there a way to fix this?
Thank you in advance!
Addendum: I'm hoping this will clarify what I was trying to do. This was the macro I wrote as a test:
Sub MultipleDataTypeInput()
Dim FirstLineofText As Variant
Dim PhysicianName As String
PhysicianName="Dr. Smith"
FirstLineofText=Sheets("Sheet1").Cells(1,1).Value
MsgBox(Prompt:=FirstLineofText)
End Sub
I put "Dear" & PhysicianName & "," in cell A1, What I was hoping was for Excel to then read the macro as
FirstLineofText="Dear" & PhysicianName & ","
If that happened the MsgBox would say "Dear Dr. Smith,"
Instead the prompt was ""Dear " & PhysicianName & ",""
Does this make sense?
One way to do this would be to use the replace function in VBA.
However, in cell A1, write "Dear PhysicianName," and get rid of your & concatenation. (The way you wrote it would work if you were writing it strictly in VBA. The code would concatenate the values together. For example: FirstLineofText = "Dear " & PhysicianName & ",")
Sub MultipleDataTypeInput()
Dim FirstLineofText As Variant
Dim PhysicianName As String
PhysicianName="Dr. Smith"
FirstLineofText=Sheets("Sheet1").Cells(1,1).Value
FirstLineofText = Replace(FirstLineOfText,"PhysicianName",PhysicianName)
MsgBox(Prompt:=FirstLineofText)
End Sub
I suggest this way because you said the coworkers are writing their own scripts and i didn't want to suggest an entire new methodology as it may confuse you. That said, I think there are way more efficient ways to design this.
i think that you have your logic backward
you probably want this
Sub MultipleDataTypeInput()
Dim PhysicianName As String
Dim PatientName As String
PhysicianName = Sheets("Sheet1").Range("A1").Value ' this cell should hold "Dr. Smith"
PatientName = Sheets("Sheet1").Range("B1").Value
MsgBox "Dear" & PhysicianName & ", We would like to invite you to an interview about " & PatientName
End Sub
We're managing some system bugs in a web system and setting priority for execs in a spreadsheet.
Each of the tickets has a "FD-" and four numbers as the ID.
The web system has a hyperlink that has that "FD-####" at the end of the link.
The end result would look like this -- http://www.mytickets.com/FD-####
I'd like to run a macro that finds all the FD-#### and inserts a hyperlink on each.
There may be multiple FD-#### in a single cell and there will certainly be other text in there.
I'd go through each and add the link but there are over 150 or so.
Thanks!
As mentioned in a comment, Excel doesn't seem to support multiple hyperlinks in a cell.
The code below will do the replacement from ticket to link:
Option Explicit
Sub loop_over_cells()
Dim a_cell
Dim replaced As String
For Each a_cell In ActiveSheet.UsedRange
Debug.Print "old value " & a_cell.Value
replaced = RegexReplace(a_cell.Value, "(fd-\d{4}\b)", "=hyperlink(" & Chr(34) & "http://cnn.com/$1" & Chr(34) & ")")
a_cell.Value = replaced
Debug.Print "new value " & a_cell.Value
Next
End Sub
Function RegexReplace(search_string, ptrn, rplc)
Dim regEx
Set regEx = CreateObject("VBScript.RegExp")
regEx.Pattern = ptrn
regEx.IgnoreCase = True
regEx.Global = True
RegexReplace = regEx.replace(search_string, rplc)
End Function