Extract Dates From String (textbox) - excel

I am trying to use VBA to loop through and find all dates within a textbox, regardless of format. I think I have my regex working. However, when trying to populate a combo box I am having difficulty.
Maybe my code is a bit messy and I am doing it the wrong way. Wha What I mean by that is it's putting every word in the combo box instead of just dates.
However, here is my code
Private Sub CommandButton2_Click()
Call dates1
End Sub
Function ExtractDates(S As String)
With CreateObject("VBScript.RegExp")
.Pattern = .Pattern = "^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$"
.Global = True
ExtractDates = Replace(Trim(.Replace(S, " $1")), " ", ", ")
End With
End Function
Sub dates1()
Dim dates1 As String
Dim dates2 As String
dates2 = ExtractDates(Me.txtS.Text)
Dim optarray
Dim opt
optarray = Split(dates2, ",")
With Me.ComboBox1
.Clear
For opt = 0 To UBound(optarray)
.AddItem (optarray(opt))
Next opt
End With
End Sub

I managed to do this if anyone else is interested:
Option Explicit
Private Sub CommandButton1_Click()
CountDates (Me.TextBox1.Text)
End Sub
Function CountDates(S As String) As Long
Dim i As Integer
Dim result As String
Dim RE As Object, MC As Object
Const sPat As String = "\b(?:\d{1,2}/){2}(?:\d{4}|\d{2})\b"
Set RE = CreateObject("vbscript.regexp")
With RE
.Pattern = sPat
.Global = True
Set MC = .Execute(S)
CountDates = MC.Count
CountDates = CountDates - 1
If MC.Count <> 0 Then
For i = 0 To CountDates
Me.ComboBox1.AddItem (MC.Item(i))
Next i
End If
End With
End Function

Related

Copy worksheet with specified name to another workbook

This macro copies Excel worksheets that have a numeric name to another Excel workbook.
For example only worksheets that are titled with 6 digits. For Example "140655".
I want to also copy over the worksheets that have a standard English name such as "Budget".
Const CalcDelay = 0.00000578704
Dim CopyRange As String
Dim PasteRange As String
Dim ScanFileOpen As Byte
Dim ScanCount As Byte
Dim ScanSaveSpec As String
Dim ScanSaveFile As String
Dim ReturnWindow As String
Dim ReportFile As String
Dim ExcelVersion As String
Sub OpenReportFile()
ReturnWindow = [ProcessWinSpec].Value
If [ReportFileFlag].Value = True Then
Application.ScreenUpdating = False
Workbooks.Open Filename:=[ReportFileSpec].Value
Windows(ReturnWindow).Activate
Application.ScreenUpdating = True
Else
MsgBox ("Error: File not found")
End If
End Sub
Sub DoScan()
Dim Work As Variant
Dim X As Interger
ReturnWindow = [ProcessWinSpec].Value
ReportFile = [ReportFileName].Value
ExcelVersion = IIf([FileNameExt].Value = ".xls", 2003, 2013)
For Each Work In [ScanFlags]
ScanFileOpen = 0
ScanCount = 0
If Work.Value = 1 Then
[ScanName].Value = Work.Offset(0, 1).Value
[ScanCalcRange].Calculate
ScanSaveFile = [ScanFile].Value
ScanSaveSpec = [ScanSpec].Value
For X = Work.Offset(0, 2).Value To 1 Step -1
ScanTabName = Work.Offset(0, X + 2).Value
[ScanTab].Value = ScanTabName
[ScanCalcRange].Calculate
If [ReadFlag].Value = 1 Then DoCopyTab
Next
End If
If ScanFileOpen = 1 Then
ActiveWorkbook.Save
ActiveWindow.Close
End If
Next
End Sub
With regards to your question on how to excecute a macro if files have a certain name, probably the best approach would be to create an array of words, and then loop through them seeking a match. See example with your code:
Sub OpenReportFile()
Const yourWords = "budget,actual,accept" '<--- fill these in separated by comman
ReturnWindow = [ProcessWinSpec].Value
Dim foundMatch As Boolean
If [ReportFileFlag].Value = True Then
foundMatch = True
Else
Dim wordArray() As String, i As Long
wordArray = Split(yourWords, ",")
'loopS through words
For i = LBound(wordArray) To UBound(wordArray)
If UCase(wordArray(i)) = UCase([ReportFileFlag].Value) Then
foundMatch = True
Exit For 'exits loop after match
End If
Next i
End If
If foundMatch Then
Application.ScreenUpdating = False
Workbooks.Open Filename:=[ReportFileSpec].Value
Windows(ReturnWindow).Activate
Application.ScreenUpdating = True
Else
MsgBox ("Error: File not found")
End If
End Sub
As you can see in the comments, your question isn't receiving the most favorable feedback as far as clarity. If this doesn't work, you may want to consider eleting your question and reposting after more carefully reviewing How to ask a question

Removing first set of numbers in string

I have a list of items:
B100Q91, B75NX2, BR100, XN20ZN..
I want to remove the first set of numbers in every item, so that it looks like this:
BQ91, BNX2, BR, XNZN..
My approach looks like this:
Function RemoveFirstNumbers(Txt As String) As String
With CreateObject("VBScript.RegExp")
Dim posn As Integer
posn = GetPositionOfFirstNumericCharacter(Txt)
1
If (IsError(posn)) = True Then Replace(Txt, 1, 1) As String
Dim posn As Integer
Else
End With
End Function
End If
GoTo 1
with
Public Function GetPositionOfFirstNumericCharacter(ByVal s As String) As Integer
Dim i As Integer
For i = 1 To Len(s)
Dim currentCharacter As String
currentCharacter = Mid(s, i, 1)
If IsNumeric(currentCharacter) = True Then
GetPositionOfFirstNumericCharacter = i
Exit Function
End If
Next i
End Function
EDIT to package the below as a function
Function ReplaceFirstDigits(sLookupExpression) as String
Dim oReg As Object
Set oReg = CreateObject("VBScript.Regexp")
With oReg
.Global = True
.ignorecase = True
.MultiLine = False
.Pattern = "([A-Za-z]+)(\d+)(\w*)"
End With
ReplaceFirstDigits = oReg.Replace(sLookupExpression, "$1$3")
End Function
Then you can call the function directly from the spreadsheet with a standard syntax, such as =ReplaceFirstDigits(A1)
If you wanted to use a regular expression, code such as the following might do the trick for you.
Sub Test()
Dim oReg As Object
Set oReg = CreateObject("VBScript.Regexp")
With oReg
.Global = True
.ignorecase = True
.MultiLine = False
.Pattern = "([A-Za-z]+)(\d+)(\w*)"
End With
Debug.Print oReg.Replace(Selection, "$1$3")
End Sub
EDITED:
If you don't want to use RegExp, just straight VBA:
Option Explicit
Function RemoveFirstNumber(strInput As String) As String
Dim strRet As String
Dim bFirstNumber As Boolean
bFirstNumber = False
Dim strChar As String
Dim nChar As Integer
For nChar = 1 To Len(strInput)
strChar = Mid(strInput, nChar, 1)
If IsNumeric(strChar) Then
bFirstNumber = True
Else
If bFirstNumber Then
strRet = strRet & Mid(strInput, nChar)
Exit For
End If
strRet = strRet & strChar
End If
Next nChar
RemoveFirstNumber = strRet
End Function

Function returns cells value not cells location - VBA

I'm trying to setup a function for Regex which returns a cell.address. It's 99% working except it seems to return the value of the cell test vs the cell location and I can't figure it out.
Debugging:
It says Object variable or with block variable not set if I Dim celladdr As Range
but if I comment that out, then the error changes to Object doesn't support this property or method and I can see that celladdr = test.
I then tried Set celladdr = Range(celladdr.Address) and get Object Required.
Can anybody point out the error?
Here is some stripped down code:
Note, I hardcoded the RegEx pattern as that function works as expected, the problem seems to be in the RegExSearch function, but I can add more code back in if needed.
Public Sub TESTING()
Dim celladdr As Range
celladdr = RegExFunc("TEST")
ActiveSheet.celladdr.Select
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Function RegExFunc(var) As Variant
RegExSearchPattern = RegExPattern(var)
RegExFunc = RegExSearch(RegExSearchPattern)
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Function RegExPattern(my_string) As Variant
RegExPattern = "([a-z]{4})"
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Function RegExSearch(strPattern) As Range
Dim regexp As Object
Dim rcell As Range, rng As Range
Dim strInput As String
Set regexp = CreateObject("vbscript.regexp")
Set rng = Range("A1:Z255")
For Each rcell In rng.Cells
If rcell <> "" Then
If strPattern <> "" Then
strInput = rcell.Value
With regexp
.Global = False
.MultiLine = False
.ignoreCase = True
.Pattern = strPattern
End With
If regexp.Test(strInput) Then
MsgBox rcell & " Matched in Cell" & rcell.Address
Set RegExSearch = Range(rcell.Address)
MsgBox RegExSearch
End If
End If
End If
Next
End Function
There were various instances in which you needed to Set the object and one in which a Dim was needed. Since you declared almost everything a Variant, it makes it a bit harder to pinpoint the breakdown. It's best, in my experience to always specifically declare the variables in VBA.
I ran the following adjusted code (added a few sets as noted above) and it worked without any decompile or run time errors.
Public Sub TESTING()
Dim celladdr As Range
Set celladdr = RegExFunc("TEST")
celladdr.Select
End Sub
Public Function RegExFunc(var As String) As Range
Dim RegExSearchPattern As String
RegExSearchPattern = RegExPattern(var)
Set RegExFunc = RegExSearch(RegExSearchPattern)
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Function RegExPattern(my_string As String) As String
RegExPattern = "([a-z]{4})"
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Function RegExSearch(strPattern As String) As Range
Dim regexp As Object
Dim rcell As Range, rng As Range
Dim strInput As String
Set regexp = CreateObject("vbscript.regexp")
Set rng = Range("A1:Z255")
For Each rcell In rng.Cells
If rcell <> "" Then
If strPattern <> "" Then
strInput = rcell.Value
With regexp
.Global = False
.MultiLine = False
.ignoreCase = True
.Pattern = strPattern
End With
If regexp.Test(strInput) Then
MsgBox rcell & " Matched in Cell" & rcell.Address
Set RegExSearch = Range(rcell.Address)
MsgBox RegExSearch
End If
End If
End If
Next
End Function
A cell address is just a string; you don't Set it, simply assign it with =.
RegExSearch = rcell.Address
... will return the absolute cell address.
You might want to consider exiting the For Each rcell In rng.Cells loop if the pattern is found. There doesn't seem to be any point in continuing unless you want the cell addresses of the union of all matching cells.
If regexp.Test(strInput) Then
MsgBox rcell & " Matched in Cell" & rcell.Address
RegExSearch = rcell.Address
MsgBox RegExSearch
Exit For
End If
You're setting identical RegEx arguments inside the loop. Move the argument assignment above the For Each rcell In rng.Cells loop.
With regexp
.Global = False
.MultiLine = False
.ignoreCase = True
.Pattern = strPattern
End With
For Each rcell In rng.Cells

Using shape as button for macro to hide/unhide rows

I am using the following to hide and unhide some rows, but I want to use a shape - "RectangleRoundedCorners9" - instead of the ugly button. The script works great on a button (does exactly what I want it to) but only on an actual button.
I don't know VBA and am not sure how to get this code to work with that shape instead of a button:
Private Sub ToggleButton1_Click()
Dim xAddress As String
xAddress = "F:G"
If ToggleButton1.Value Then
Application.ActiveSheet.Columns(xAddress).Hidden = True
Else
Application.ActiveSheet.Columns(xAddress).Hidden = False
End If
End Sub
I tried replacing as follows but get a 424 "Object not found" error on the IF line:
Private Sub RectangleRoundedCorners9_Click()
Dim xAddress As String
xAddress = "F:G"
If RectangleRoundedCorners9.Value Then
Application.ActiveSheet.Columns(xAddress).Hidden = True
Else
Application.ActiveSheet.Columns(xAddress).Hidden = False
End If
End Sub
Thanks in advance.
BONUS: I'd like to inject the final product into the following to get the shape to visual behave like a button as well:
Sub SimulateButtonClick()
Dim vTopType As Variant
Dim iTopInset As Integer
Dim iTopDepth As Integer
With ActiveSheet.Shapes(Application.Caller).ThreeD
vTopType = .BevelTopType
iTopInset = .BevelTopInset
iTopDepth = .BevelTopDepth
End With
With ActiveSheet.Shapes(Application.Caller).ThreeD
.BevelTopType = msoBevelSoftRound
.BevelTopInset = 12
.BevelTopDepth = 4
End With
Application.ScreenUpdating = True
With ActiveSheet.Shapes(Application.Caller).ThreeD
.BevelTopType = vTopType
.BevelTopInset = iTopInset
.BevelTopDepth = iTopDepth
End With
'---------------
'HIDE/UNHIDE SCRIPT HERE
'---------------
End Sub
Something like this:
Sub ToggleCols()
Const RNG As String = "F:G"
Dim s, tr
Set s = ActiveSheet.Shapes(Application.Caller)
Set tr = s.TextFrame2.TextRange
ActiveSheet.Columns(RNG).Hidden = (tr.Text = "Hide")
tr.Text = IIf(tr.Text = "Hide", "Show", "Hide")
End Sub

Nested for...each loops with If statements

I am new to vb.script so this may just be a formatting question that I cannot find the answer.
The problem is validating data in cells that are on different sheets in the same workbook.
Looping through worksheets and then looping through the cell range:
Private Sub Validate(ByRef objWorkbook As Workbook)
Dim strPattern As String: strPattern = "^\-{0,1}\d+(.\d+){0,1}$"
Dim regEx As New VBScript_RegExp_55.RegExp
Dim strInput As String
Dim strOutput As String
Dim Myrange As Range
Dim regExCount As Object
Set regExCount = CreateObject("vbscript.regexp")
On Error Resume Next
For Each objWorksheet In objWorkbook.Worksheets
If (UCase(objWorksheet.Name) = "Foo") Then
objWorksheet.Select
Range("Q2").Select
ElseIf (UCase(objWorksheet.Name) = "Bar") Or (UCase(objWorksheet.Name) = "Poo") Then
objWorksheet.Select
Set Myrange = ActiveSheet.Range("D51:AA76")
For Each cell In Myrange.Cells
If strPattern <> "" Then
strInput = cell.Value
strReplace = ""
With regEx
.Global = True
.MultiLine = True
.IgnoreCase = False
.Pattern = strPattern
End With
Set regExCount = regEx.Execute(strInput)
If regExCount.Count = 0 Then
strOutput = strOutput + "Illegal character at " + cell.AddressLocal + "\r\n"
End If
Next cell
End If
Next
MsgBox (strOutput)
End Sub
When I compile I get an error of a Next without a For loop at the Next Cell. Removing that line and I get an error for Block If without an End Ff highlighting the End Sub. Adding an End If before the End sub and I get a Next without a For error.
Isn't it this block missing and end if?
If strPattern <> "" Then
strInput = cell.Value
strReplace = ""
Your
If strPattern <> "" Then
is not closed between
End If ' regExCount.Count
Next cell ' In Myrange.Cells

Resources