I'm currently trying to create a pattern to capture a name that generally is text [A-ZÅÄÖ] but there could be one or two numeric characters.
Here is one example: (there are more fields than this, this is just an example)
PT22 111222333 2 BROTHERS RP02 570244222333
PT25 888222333 THIS TIME IT'S ONLY TEXT RP01 888244222333
I'm trying to get 2 BROTHERS and THIS TIME IT'S ONLY TEXT in this tab delimited string (rows are for eached).
When I used the pattern "(\b[A-ZÅÄÖ \&\.\´\:-_]+\b)" it captured BROTHERS, if I add 0-9 in the pattern it takes either PT22 or 111222333 if the first field is empty.
So what I would need is something that captures the field that has at least three characters that is A-ZÅÄÖ and maximum 2 characters 0-9.
Is that even possible or do I need to loop through the fields and count each type of character to determine if I'm in the correct field or not?
The fields are not in the same order every time.
My backup plan is to split on tab, and loop. On each field remove all [0-9] characters and count.
That way I will get how many [0-9] and how many [A-ZÅÄÖ] (+other) there is, and that could be used I think to find the correct field.
I am not an regex expert, maybe it is possible, but I usually find it too hard to figure this out - and ending with an regex where you're not 100% sure it fits, plus it is hard to figure out what it does once you come back to it.
I would use a small function that simply count the number of chars and digits of a string. Easy to write, easy to read, easy to adapt. Could look like
Function checkWord(s As String) As Boolean
Const minChars = 3
Const maxDigits = 2
Dim i As Long, digits As Long, chars As Long
For i = 1 To Len(s)
Select Case AscW(Mid(s, i, 1))
Case AscW("A") To AscW("Z"), AscW("Ä"), AscW("Ö"), AscW("Å"):
chars = chars + 1
Case Asc("0") To Asc("9"):
digits = digits + 1
Case Else
' Think about what happens with all other characters...
End Select
Next
checkWord = (chars >= minChars And digits <= maxDigits)
End Function
Without RegEx:
Can't you turn the logic around and remove parts you don't want:
Loop over each value;
Your values are tab-delimited so split on VbTab;
Loop over each sub-element;
Test each sub-element with the Like() operator and check that it's not numeric.
To test this I came up with the following dummy-code:
Sub Test()
Dim r As Variant: r = Array("PT22" & vbTab & "111222333" & vbTab & "2 BROTHERS" & vbTab & "RP02" & vbTab & "570244222333", "PT25" & vbTab & "888222333" & vbTab & "THIS TIME IT'S ONLY TEXT" & vbTab & "RP01" & vbTab & "888244222333")
For Each el In r
For Each SubEl In Split(el, Chr(9))
If Not SubEl Like "??[0-9][0-9]" And Not IsNumeric(SubEl) Then
Debug.Print SubEl
Exit For
End If
Next
Next
End Sub
With RegEx:
If regex is a must, try to capture what you do want:
Sub Test()
Dim r As Variant: r = Array("PT22" & vbTab & "111222333" & vbTab & "2 BROTHERS" & vbTab & "RP02" & vbTab & "570244222333", "PT25" & vbTab & "888222333" & vbTab & "THIS TIME IT'S ONLY TEXT" & vbTab & "RP01" & vbTab & "888244222333")
With CreateObject("vbscript.regexp")
.Global = True
.Pattern = "(?:^|\s)((?:[A-ZÅÄÖ]+(?:[ &.'_-][A-ZÅÄÖ]+)*\s?)?(?:\b\d\d?\b)?(?:\s?[A-ZÅÄÖ]+(?:[ &.'_-][A-ZÅÄÖ]+)*)?)(?:\s|$)|."
For Each el In r
Debug.Print Trim(.Replace(el, "$1"))
Next
End With
End Sub
Or, again remove only those parts you don't want:
Sub Test()
Dim r As Variant: r = Array("PT22" & vbTab & "111222333" & vbTab & "2 BROTHERS" & vbTab & "RP02" & vbTab & "570244222333", "PT25" & vbTab & "888222333" & vbTab & "THIS TIME IT'S ONLY TEXT" & vbTab & "RP01" & vbTab & "888244222333")
With CreateObject("vbscript.regexp")
.Global = True
.Pattern = "\s*\b(?:[A-Z]{2}\d\d|\d{3,})\b\s*"
For Each el In r
Debug.Print .Replace(el, "")
Next
End With
End Sub
Results:
All above options would print:
2 BROTHERS
THIS TIME IT'S ONLY TEXT
Related
It may seem to be an easy one as i am novice at VBA. I am trying to fill the filtered blank visible cells with previous non blank hidden cell value in the same column. The Lookup formula is working fine on excel sheet but using it with variable range in VBA is giving Application defined or object defined Error on lookup formula line.
nlr = Cells(Rows.Count, 9).End(xlUp).Row
With Activehseet
Application.DisplayAlerts = False
Range("A1:K" & nlr).AutoFilter Field:=2, Criteria1:=""
Range("A1:K" & nlr).AutoFilter Field:=1, Criteria1:="P * Suite *"
Range("B2:B" & nlr).SpecialCells(xlCellTypeVisible).ClearContents
For Each c In Range("B1:B" & nlr).Offset(1, 0).SpecialCells(xlCellTypeVisible)
n = c.Row - 1
c.Formula = "=LOOKUP(2,1/($B$2:B&n&<>""),$B$2:B&n&)"
I have already tried it with below too, but it didn't work
c.Formula = "=LOOKUP(2,1/($B$2:B " & n & "<>""),$B$2:B" & n & ")"
Please help me resolve this
EDIT: I have already tried this approach, but it didn't work either
c.Formula = "=LOOKUP(2,1/($B$2:B " & n & "<>""""),$B$2:B" & n & ")"
This is the correct approach for concatenating a string into another string:
c.Formula = "=LOOKUP(2,1/($B$2:B " & n & "<>""),$B$2:B" & n & ")"
However, there is a problem with this part of it:
... & n & "<>""), ...
That will place one double quote into the text. I presume you are expecting it to look like <>"" when parsed, which means the line should look like this:
... & n & "<>""""), ...
Why? Because in a string to put one double quote you need to put a double, double quote: "" = " (in finished string). Therefore a double, double quote becomes: """" = "".
Here is the corrected original code:
c.Formula = "=LOOKUP(2,1/($B$2:B " & n & "<>""""),$B$2:B" & n & ")"
This question already has answers here:
Different languages issue when inserting formula from VBA
(1 answer)
How do I put double quotes in a string in vba?
(5 answers)
Closed 1 year ago.
Goodmorning everyone,
I'm a beginner with VBA trying out various things.
Atm I'm trying to get a formula to be placed inside a row of cells but I'm encountering a problem.
I use a number of variables that seem to be causing a problem in my formula.
I already changed some things I found on this site (like changing from ActiveCell to Range and adding the rr and r variables.
However this doesn't fix the error message I'm getting.
I looked up the error but didn't quite understand what the meaning was.
Could anyone tell me what is causing the problem in my code but also what the error message means so I can try and debug it myself.
With F8 I already made sure that all variables were filled in correctly.
the error comes from the Range(r).Formula line.
Sub Zoeker()
Sheets("Invoer").Select
NumRows_Gist = Range("A3", Range("A3").End(xlDown)).Rows.Count
NumRows_Vand = Range("I3", Range("I3").End(xlDown)).Rows.Count
For x = 1 To NumRows_Vand
Dim r As String
rr = Range("O" & 2 + x).Row
r = "O" & Range("O" & 2 + x).Row
Range(r).Formula = "=IF(IF(IFERROR(VLOOKUP(I" & rr & ";$A$3:$B$" & NumRows_Gist & ";2;FALSE);'Niet vorige upload') <> 'Niet vorige upload'; VLOOKUP(I" & rr & ";$A$3:$B$" & NumRows_Gist & ";2;FALSE) + J" & rr & "; 'correct') <> 0; ''; '0')"
Next
End Sub
Excel Formulas in VBA
Try the following:
Range(r).Formula = "=IF(IF(IFERROR(" _
& "VLOOKUP(I" & rr & ",$A$3:$B$" & NumRows_Gist & ",2,FALSE)," _
& """Niet vorige upload"")<>""Niet vorige upload""," _
& "VLOOKUP(I" & rr & ",$A$3:$B$" & NumRows_Gist & ",2,FALSE)+J" _
& rr & ",""correct"")<>0, """", ""0"")"
I used the following procedure until I got it right:
Option Explicit
Sub testFormula()
Const rr As Long = 5
Const NumRows_Gist As Long = 100
Dim s As String
s = "=IF(IF(IFERROR(" _
& "VLOOKUP(I" & rr & ",$A$3:$B$" & NumRows_Gist & ",2,FALSE)," _
& """Niet vorige upload"")<>""Niet vorige upload""," _
& "VLOOKUP(I" & rr & ",$A$3:$B$" & NumRows_Gist & ",2,FALSE)+J" _
& rr & ",""correct"")<>0, """", ""0"")"
Debug.Print s
End Sub
Writing formulas with VBA is tricky.
You have at least the following mistakes in your formula:
You need to write the formula with comma as separator, not semicolon
You need to write strings within the formula with double quotes, not single quotes. But as the VBA compiler would see a double quote character as end of string, you need to double it: 'Niet vorige upload' should be ""Niet vorige upload"", and at the end the empty string needs to be specified as """"
You should always write the formula into an intermediate variable and check the content using the debugger.
dim f as string
f = "=IF(IF(IFERROR(VLOOKUP ... ' <- Put your formula here
Debug.print f
To get an idea how you need to specify a formula in VBA, change to Excel, enter the desired formula into a cell, change back to the VBA editor and enter ? activeCell.formula into the immediate window.
I searched on internet, without any help coming out of that...
I simply would like to be able to have my VBA code to write this formula in a cell :
=IF(C4="-"; "-"; Cars!C4*C4*Data!$C$8)
As you guessed, there is a page called "Cars" and one called "Data" where I pick the informations needed.
Of course, as it is a VBA code, the C4 will be 2 variables, one for the C and one for the 4 that will evolve...
Actually, I tried this :
Worksheets("Calculation").Range(Column & PosStartCalc + 1).Formula = "=" & "IF(" & Column & PosStartCalc & " = " & "" - "" & ";" & " - " & ";" & "Cars!" & Column & PosStart & "*" & Column & PosStartCalc & "*" & "Data!" & "C" & "8" & ")"
(The variable Column contains the column letter and the variable PosStartCalc contains the row number)
This hurts my eyes and apparently VBA's ones too as it gives the error "Run-Time error '13': Type Mismatch'
Could anyone tell me how to do that?
Thanks in advance !
Try the following, assuming the column variable is a string and row a long variable. I might not have all the variables right, but you'll be able to get what I meant to do here.
Sub test()
Dim Col As String: Col = "C"
Dim Rw As Long: Rw = 4
With ThisWorkbook.Sheets("Calculation")
Debug.Print "=IF(" & Col & Rw & "=""-"",""-"",Cars!" & Col & Rw & "*" & Col & Rw & "*Data!$C$8)"
.Cells(Rw + 1, Col).Formula = "=IF(" & Col & Rw & "=""-"",""-"",Cars!" & Col & Rw & "*" & Col & Rw & "*Data!$C$8)"
End With
End Sub
So what you might forget easily is to use the , as parameter delimiter in a VBA programmed formula. When you put this on your sheet Excel will automatically replace that with the appropriate delimiter for your region.
Another thing to keep in mind; whenever you about to use a string value in such an function, don't forget to wrap it in double quotes!
Don't forget to remove the Debug.print .... line. It was merely there to show the output :)
I have a problem with my codes below,
As you can see, I am trying to find the row value of a search. I have 3 different criteria ( they are defined before ) and 3 different ranges ( also defined before ). But I cannot find the rows unfortunately.
Here you can see the codes;
Gorev = Worksheets(WS_All).Cells(p, o).Value
SlideNo = Worksheets(WS_All).Cells(p, 34).Value
Egitim_Adi = Worksheets(WS_All).Cells(2, 3).Value
Check1 = Worksheets(j_WS).Range("A:A") 'Egitim_Adi Kontrolü için'
Check2 = Worksheets(j_WS).Range("B:B") 'SlideNo Kontrolü için'
Check3 = Worksheets(j_WS).Range("C:C") 'Gorev Kontrolü için'
Satir_bul = Evaluate("=Match(" & Egitim_Adi & " & " & SlideNo & " & " & Gorev & ", Check1 & Check2 & Check3, 0)")
I am open to any suggestion..
You have a whole heap of problems there. WorksheetFunction.Match is not going to work because you are trying to replicate an array formula so Evaluate is definitely a better bet, but you need to construct the correct formula string for it. Unless you know whether the contents of the three cells will always be text or numbers, it is easier to just use cell addresses than to worry about enclosing the values in quotes:
Gorev = Cells(p, o).address
SlideNo = Cells(p, 34).address
Egitim_Adi = Cells(2, 3).address
Satir_bul = Worksheets(WS_All).Evaluate("=Match(" & Egitim_Adi & "&" & SlideNo & "&" & Gorev & ", '" & j_WS & "'!A:A&'" & j_WS & "'!B:B&'" & j_WS & "'!C:C, 0)")
If you can limit the ranges rather than using entire columns, you'll get better performance too.
Try it like this:
Satir_bul = WorksheetFunction.Match ( Egitim_Adi & " & " & SlideNo & " & " & Gorev & ", Check1 & Check2 & Check3, 0)
Here is a bit more about Match.
It will not work. You should include Union of the ranges in Match. Read more about Unions here.
You have three strings str1, str2, str3. You have three search areas: rng1, rng2 and rng3. Now, on every range you have to do the following (cell will be range variable):
For Each cell In rng1
'here you determine if one of your strings is contained uisng InStr function
'if the above condition is satisfied, then get the number of a row
Next cell
You'll do this then with rng2 and rng3.
In sheet 1 the value is 45 so I want in sheet RESULTADO the format like this: 0045
Worksheets("RESULTADO").Range("B" & row_counter) = Format(Worksheets(1).Range("B" & row_counter).Value, "0000")
Why this doesn't work?
I've tried also this, but neither it works:
Worksheets("RESULTADO").Range("B" & row_counter) = CStr(Format(Worksheets(1).Range("B" & row_counter).Value, "0000"))
You can do that in two(2) ways:
Set the number format first
With Worksheets("RESULTADO").Range("B" & row_counter)
.NumberFormat = "#"
.Value = Format(Worksheets(1).Range("B" & row_counter).Value, "0000")
End With
Use ' apostrophe
Worksheets("RESULTADO").Range("B" & row_counter) = "'" & _
Format(Worksheets(1).Range("B" & row_counter).Value, "0000")
this doesn't work because in the first case you're trying to format a number n to 00n wich always return n, in the second case, you do exactly the same then you transtype the result to a string.
You have to convert n to a string first. So in your case :
Worksheets("RESULTADO").Range("B" & row_counter) = Format(CStr(Worksheets(1).Range("B" & row_counter).Value), "0000")