What is the correct syntax for grouping rows - excel

Syntax error using the following code.
Both variables LR1 and LR2 were declared as integers:
sh.Rows("& LR1+1 &":"& LR2-1 &").Group 'Syntax error
No syntax error if hardcoded numbers are used:
sh.Rows("27:29").Group

If your question is how strings and concatenating work:
The & forces string concatenation which means it will take strings or non-string types (but not all types like arrays) like your integer/long variables and combine them into a string.
In your code you have two strings and a character outside the string. "& LR1+1 &":"& LR2-1 &"
String 1: "& LR1+1 &" This is a valid string but Rows can't parse it.
Character: : This is causing the syntax error
String 2: "& LR2-1 &" This is a valid string but Rows can't parse it.
This is throwing a syntax error because : is not a valid character and isn't in a string.
an & needs to be outside the string otherwise it is just a part of the string.
"&" will not concatenate.
What BigBen did in his comment is take your variables (which you have inside a string and as such are not variables they are just characters in a string that happen to look like your variables) and concatenate them into a string that Rows can work with.
So LR1 + 1 & ":" & LR2 - 1 Is taking the Value in LR1 and adding 1, then combining that number with ":", then subtracting 1 from LR2 and combining that into the string as well.
if LR1 = 10 and LR2 = 20 your final output will be:
"11:19"
You can check what your string will look like with debug.print

Variables don't belong inside quotes.
sh.Rows(LR + 1 & ":" & LR2 - 1)
Also, use Long instead of Integer.

Related

VBA-Excel: How to get text enclosed in Quotation Mark from String

I have a String in VBA with this text: < History Version="1.10" Client="TestClient001" >
I want to get this TestClient001 or anything that's inside Client="xxxx"
I made this code but it's not working
Client = MID(text,FIND("Client=""",text)+1,FIND("""",text)-FIND("Client=""",text)-1)
Is there a way to specifically get the text inside Client="xxxx"?
There's no such function as Find in VBA - that's a worksheet function. The VBA equivalent is InStr, but I don't think you need to use it here.
The best tool for extracting one string from another in VBA is often Split. It takes one string and splits it into an array based on a delimiting string. The best part is that the delimiter doesn't have to be a single character - you can make it an entire string. In this case, we'd probably do well with two nested Split functions.
Client = Split(Split(text,"Client=""")(1),Chr(34))(0)
The inner Split breaks your text string where it finds "Client="". The (1) returns array element 1. Then the outer Split breaks that returned text where it finds a " character, and returns array element 0 as the final result.
For better maintainability, you may want to use constants for your delimiters as well.
Sub EnclosedTextTest()
Const csFlag1 As String = "Client="""
Const csFlag2 As String = """"
Const csSource As String = "< History Version=""1.10"" Client=""TestClient001"" >"
Dim strClient As String
strClient = Split(Split(csSource, csFlag1)(1), csFlag2)(0)
Debug.Print strClient
End Sub
However, if the Split method doesn't work for you, we can use a method similar to the one you were using, with InStr. There are a couple of options here as well.
InStr will return the position in a string that it finds a matching value. Like Split, it can be given an entire string as its delimiter; however, if you use more than one character you need to account for the fact that it will return where it finds the start of that string.
InStr(1,text,"Client=""")
will return 26, the start of the string "Client="" in the text. This is one of the places where it's helpful to have your delimiter stored in a constant.
intStart = InStr(1,text,csFlag1)+len(csFlag1)
This will return the location it finds the start of the delimiter, plus the length of the delimiter, which positions you at the beginning of the text.
If you store this position in a variable, it makes the next part easier as well. You can use that position to run a second InStr and find the next occurrence of the " character.
intEnd = InStr(intStart,text,csFlag2)
With those values, you can perform your mid. You code overall will look something like this:
Sub InstrTextTest()
Const csFlag1 As String = "Client="""
Const csFlag2 As String = """"
Const csSource As String = "< History Version=""1.10"" Client=""TestClient001"" >"
Dim strClient As String
Dim intPos(0 To 1) As Integer
intPos(0) = InStr(1, csSource, csFlag1) + Len(csFlag1)
intPos(1) = InStr(intPos(0), csSource, csFlag2)
strClient = Mid(csSource, intPos(0), intPos(1) - intPos(0))
Debug.Print strClient
End Sub
This will work, but I prefer the Split method for ease of reading and reuse.
You can make use of Split function to split at character = then with last element of the resulting array remove character quotes and > with help of replace function and you will get the required output.
In the end I got it thanks to the idea given by #alok and #Bigben
Dim cl() As String
Dim ClientCode As String
If (InStr(1, temp, "Client=", vbTextCompare) > 0) Then
cl = Split(temp, "=")
ClientCode = cl(UBound(cl))
ClientCode = Replace(ClientCode, """", "")
ClientCode = Replace(ClientCode, ">", "")
It's XML, so you could do this:
Dim sXML As String
sXML = "<History Version=""1.10"" Client=""TestClient001"">"
With CreateObject("MSXML.Domdocument")
.LoadXML Replace(sXML, ">", "/>") 'close the element
Debug.Print .FirstChild.Attributes.getnameditem("Client").Value
End With

VB.NET Compare two string for full or partial match

How do you programmatically Compare two string for full or partial match.
I may have a string called "ItemName" like "003.00.112.0" and a string I am trying to compare it to the string named "ItemNameToFind" like "001...**.*" where " * " is meant to be an unknown blank spot.
What I have figured out so far is that it's some sort of an if statement that needs to correctly compare the strings.
If ItemName = ItemNameToFind Then
MsgBox("Item " & ItemName & " was found based on " & ItemNameToFind)
End If
In the example above it would return that it's not a match because of the first three symbols in the string.
Could, someone, please, help with the code to make that happen correctly as I explained?
In VB.NET you can use the Like operator:
Dim ItemName = "001.00.112.0"
Dim ItemNameToFind = "001.??.???.?"
If ItemName Like ItemNameToFind Then
Console.Write("Item " & ItemName & " was found based on " & ItemNameToFind)
Else
Console.Write("not found")
End If
Note that i have replaced your * with ? since that means "Any single character".
? Any single character
* Zero or more characters
# Any single digit (0–9)
[charlist] Any single character in charlist
[!charlist] Any single character not in charlist

How to use .numberformat in VBA with variable of type double as comperator

Dear all i want to format my cell based on the Cell value. There are 3 possible Conditions:
Cell is larger than 0.05 -> the Value should stay the same but be fromated to 0.0
Cell is smaller than a variable (called Threshold) -> the Value should be replaced with a String "a.C."
Cell is Zero -> the Value should be replaced with a Dash"
I figured out how to do this without a vavriable in here. How to add a text string .numberformat in vba is discussed here!
This:
.NumberFormat = "[=0]---;[<0.05] ""a.C."";0.0 "
Does work, while this:
Dim threshold as Double
threshold = 0.05
.NumberFormat = "[=0]---;[<threshold] ""a.C."";0.0 "
Does not work. I guess i nedd to either pass a special variable typoe to the "<" comperator or i need to escape the variable somehow?
A hint would be really appreciated!
Thank you in advance
That's because threshold is part of your number format string. Basically everything that is within quotes is not touched by VBA - except for the double double quotes that tells VBA to use a quote character within the string rather than end the string.
To put the content of the variable into a string, use string concatenation. This is done in VBA using the "&" operator:
.NumberFormat = "[=0]---;[<" & threshold & "] ""a.C."";0.0 "
However, as Double can be a little bit nasty because of rounding, it's maybe better to use the format command to output it in the wanted form (eg 2 digits after the decimal). And it's usually a good idea to use an intermediate variable that you can easily check with the debugger:
Dim myNumberFormat as string
myNumberFormat = "[=0]---;[<" _
& format(threshold, "0.00") _
& "] ""a.C."";0.0 "
.NumberFormat = myNumberFormat

Is there an easy way to check if the string starts with letters (any 4 letters)?

is there a way to check if the string begins with any 4 letters. I am looking for something like this:
If string like "####*" then
'DO STUFF
end if
"#" is for digits, I need the same thing but for letters only.
Can this be done without regEx?
I don't know a way to do this without using regular expressions. We can try using regex Test along with the pattern ^[A-Z]{4}.*$:
Dim input As String
Dim regex As Object
Set regex = New RegExp
regex.Pattern = "^[A-Z]{4}.*$"
input = "ABCD blah"
If regex.Test(input) Then
'DO STUFF
End If
You can do it with Like almost the same as with RegEx.
"{#}" - doesn't exist in Like operators, but "[A-Z]" absolutely valid
if string like "[A-Z][A-Z][A-Z][A-Z]*" then
'DO STUFF
end if
Can this be done without regEx?
Yes, there is no specific need for Regular Expressions since the Like operator is quite capable as some sort of last resort to handle the situation, just like the writer of this article explains. Also, RegEx is sort of slow on a larger database. Nonetheless, RegEX is a great tool to use!
The solution provided by #AlexandruHapco would tell you if the string starts with 4 capital letters. But to account for lower OR upper, you can extend this logic:
If str Like "[a-zA-Z][a-zA-Z][a-zA-Z][a-zA-Z]*" Then
However, to shorten this a bit we can use [!charlist] to tell the operator we are looking for something that is NOT in the provided range. In other words, we could use:
If str Like "[!0-9][!0-9][!0-9][!0-9]*" Then
This last solution won't work when your string has any other characters than alphanumeric ones.
Approach using the FilterXML function
The WorksheetFunction FilterXML() has been added in ►Excel 2013 and allows to specify any XPath search string for a given XML document, which hasn't to be a locally saved file (needing WebService() function), but can be a string within well formed opening and closing nodes, i.e. our test string with some easy node additions (partly comparable to a html structure).
Example call
Sub TextXML()
Dim myString As String
myString = "ABCD blah"
If check(myString) Then
'DO STUFF
Debug.Print "okay"
Else
Debug.Print "oh no"
End If
End Sub
Help function
Function check(ByVal teststring As String) As Boolean
Const s As String = Chr(185) ' unusual character, e.g. Chr(185): "¹"
On Error GoTo oops
If Len(WorksheetFunction.FilterXML("<all><i>" & teststring & "</i></all>", "//i[substring(translate(.,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','" & _
String(26, s) & "'),1,4)='" & String(4, s) & "']")) > 0 Then check = True
Exit Function
oops:
Err.Clear
End Function
tl;tr - how to use VBA in Excel versions before 2013
For the sake of the art the classic way to use XPath via XMLDOM methods:
Example call
Sub TextXML2()
Dim myString As String
myString = "ABCD blah"
If check2(myString) Then
'DO STUFF
Debug.Print "okay"
Else
Debug.Print "oh no"
End If
End Sub
Help functions
Function check2(ByVal teststring As String) As Boolean
' Purpose: check if first 4 characters of a test string are upper case letters A-Z
' [0] late bind XML document
Dim xDoc As Object
Set xDoc = CreateObject("MSXML2.DOMDocument.6.0")
' [1] form XML string by adding opening and closing node names ("tags")
teststring = "<all><i>" & teststring & "</i></all>"
' [2] load XML
If xDoc.LoadXML(teststring) Then
' [3a] list matching item(s) via XPath
Dim myNodeList As Object
Set myNodeList = xDoc.SelectNodes(XPath())
'Debug.Print teststring, " found: " & myNodeList.Length
' [3b] return true if the item matches, i.e. the list length is greater than zero
If myNodeList.Length > 0 Then check2 = True
End If
End Function
Function XPath() As String
' Purpose: create XPath string to get nodes where the first 4 characters are upper case letters A-Z
' Result: //i[substring(translate(.,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹'),1,4)="¹¹¹¹"]
' get UPPER case alphabet
Const ABC As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
' define replacement string consisting of an unusual character repeated 26 times
Const UNUSUAL As String = "¹" ' << replace by your preferenced character
Dim replacement As String: replacement = String(Len(ABC), UNUSUAL)
'return XPath string
XPath = "//i[substring(translate(.,'" & ABC & "','" & replacement & "'),1,4)=""" & String(4, UNUSUAL) & """]"
End Function
To test a few characters -- the first 4 letters in this case -- you can always do the following:
If Not (Mid(string, 1, 1) Like "#" And Mid(string, 2, 1) Like "#" _
And Mid(string, 3, 1) Like "#" And Mid(string, 4, 1) Like "#") Then
' DO STUFF
End If
It's a bit more to type then when using the Like operator, but so what? Also, you can use Select Case in a loop...
Another option is to use IsNumeric(Mid(string, i, 1)) instead of Mid(string, i, 1) Like "#", etc.
Granted, this approach is still quite practical with 4 characters, but is not as flexible and very much not scalable like RegEx is.

access to excel vba double quotation issue

am exporting data from access to excel using vba , and i want to excel to receive these lines:-
=COUNTIF('Sheet1'!G2:G68,"1/1")
=COUNTIF('Sheet1'!G2:G68,"1/2")
etc...
my problem is that i can't add these double quotations right,i know that to print this symbol i should put it twice like this "" but still no luck,am getting all kinds of error,can you please modify my code:=
For r = 6 To 16
.Range("B" & r).Value = "=COUNTIF('Sheet1'!C1:C67,1/" & r - 5 & ")"
Next
thanks
If you wish to embed double quotes into the string you are building you can either do it by (as you mentioned) using two pairs of double quotes to 'escape' the double quote you are attempting to add, as follows:
"=COUNTIF('Sheet1'!C1:C67,""1/" & r - 5 & """)"
...which will return:
=COUNTIF('Sheet1'!C1:C67,"1/-5")
An important point to remember is that in order to properly escape the double quote you are inserting, you dont count the double quotes that are defining the string itself as one of the two pairs; That is why in the above example there are 4 pairs at the end:
""")"
The outer two define the string itself; the inner two represent the escaped double quote character.
I always found this form somewhat confusing, and would often opt to instead insert the double quotes by using the chr function, passing in the ascii value for the double quotes character, which is 34;
"=COUNTIF('Sheet1'!C1:C67," & chr(34) & "1/" & r - 5 & chr(34) & ")"
...which will return the same result as the first example:
=COUNTIF('Sheet1'!C1:C67,"1/-5")
Hope this helps,
nim

Resources