Replace text using RegEx in Excel-VBA

18,410

Solution 1

The problem is with your selection.

ActiveDocument.Range = _
RegEx.Replace(ActiveDocument.Range, "")

ActiveDocument doesn't exist in the Excel namespace. We have ActiveWorkbook or ThisWorkbook, but what you need now is the Selection.

Use a for each loop to iterate all the cells in the current selection like this:

Dim myCell As Range

For Each myCell In Selection.Cells
  myCell.Value = RegEx.Replace(myCell.Value, "")
Next

Solution 2

A faster approach would be to combine your RegExp with a variant array:

'Press Alt + F11 to open the Visual Basic Editor (VBE)
'From the Menu, choose Insert-Module.
'Paste the code into the right-hand code window.
'Press Alt + F11 to close the VBE
'In Xl2003 Goto Tools … Macro … Macros and double-click KillDate

Sub KillDate()
    Dim rng1 As Range
    Dim rngArea As Range
    Dim lngRow As Long
    Dim lngCol As Long
    Dim lngCalc As Long
    Dim objReg As Object
    Dim X()


    On Error Resume Next
    Set rng1 = Application.InputBox("Select range for the replacement", "User select", Selection.Address, , , , , 8)
    If rng1 Is Nothing Then Exit Sub
    On Error GoTo 0

    'See Patrick Matthews excellent article on using Regular Expressions with VBA
    Set objReg = CreateObject("vbscript.regexp")
    objReg.Pattern = "\d\d\:\d\d"
    objReg.Global = True

   'Speed up the code by turning off screenupdating and setting calculation to manual
   'Disable any code events that may occur when writing to cells
    With Application
        lngCalc = .Calculation
        .ScreenUpdating = False
        .Calculation = xlCalculationManual
        .EnableEvents = False
    End With

    'Test each area in the user selected range

    'Non contiguous range areas are common when using SpecialCells to define specific cell types to work on
    For Each rngArea In rng1.Areas
        'The most common outcome is used for the True outcome to optimise code speed
        If rngArea.Cells.Count > 1 Then
           'If there is more than once cell then set the variant array to the dimensions of the range area
           'Using Value2 provides a useful speed improvement over Value. On my testing it was 2% on blank cells, up to 10% on non-blanks
            X = rngArea.Value2
            For lngRow = 1 To rngArea.Rows.Count
                For lngCol = 1 To rngArea.Columns.Count
                    'replace the leading zeroes
                    X(lngRow, lngCol) = objReg.Replace(X(lngRow, lngCol), vbNullString)
                Next lngCol
            Next lngRow
            'Dump the updated array sans leading zeroes back over the initial range
            rngArea.Value2 = X
        Else
            'caters for a single cell range area. No variant array required
            rngArea.Value = objReg.Replace(rngArea.Value, vbNullString)
        End If
    Next rngArea

    'cleanup the Application settings
    With Application
        .ScreenUpdating = True
        .Calculation = lngCalc
        .EnableEvents = True
    End With

    Set objReg = Nothing
End Sub
Share:
18,410
akarilimano
Author by

akarilimano

Updated on June 27, 2022

Comments

  • akarilimano
    akarilimano almost 2 years

    I have data in Excel like follows (one row here - one cell in Excel):

    07 July 2015 12:02 – 14 July 2015 17:02
    12 August 2015 22:02 – 01 September 2015 11:02
    

    I want to write a macro that will delete all time info (e.g. "12:02") within a user's selection (multiple cells) to look like this:

    07 July 2015 – 14 July 2015
    12 August 2015 – 01 September 2015
    

    When all "times" where similar ("00:00") this macro worked perfectly:

    Sub delete_time()     
        Selection.Replace What:="00:00", Replacement:="", LookAt:=xlPart, _
            SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
            ReplaceFormat:=False
    
    End Sub
    

    But then time-info stopped being uniform, so I decided to use RegEx. The problem is I can't find a proper way to do this on VBA. I tried this macro:

    Sub delete_time()
        Dim RegEx As Object
        Set RegEx = CreateObject("VBScript.RegExp")
        On Error Resume Next
    
        RegEx.Global = True
        RegEx.Pattern = "\d\d\:\d\d"
        ActiveDocument.Range = _
            RegEx.Replace(ActiveDocument.Range, "")
    End Sub
    

    But it didn't work. Also tried "[0-9]{2}:[0-9]{2}" and "[0-9][0-9]:[0-9][0-9]" patterns but nothing changed. So the problem must be in my misunderstanding of VBA (I'm new to it).

    Can anyone help?