Excel VBA SUBSTITUTE

This guide treats “excel vba substitute” the way busy spreadsheet users actually want it: answer first, then the reasoning. It is written for Excel but calls out every place Google Sheets differs, and the platform toggle at the top switches all shortcuts between Windows and Mac so nothing here assumes the keyboard you are not on.

Exact answer

In Excel: Set hit = ws.Cells.Find(What:="text", LookIn:=xlValues, LookAt:=xlPart) locates the first match, and ws.Cells.Replace What:="old", Replacement:="new" changes them all in one call.

VBA macro: Find and Replace with VBA

Sub FindAndReplaceInSheet()
    Dim ws As Worksheet
    Dim hit As Range
    Set ws = ActiveSheet
    Set hit = ws.Cells.Find(What:="draft", LookIn:=xlValues, _
                            LookAt:=xlPart, MatchCase:=False)
    If hit Is Nothing Then
        MsgBox "Nothing to replace.", vbExclamation
        Exit Sub
    End If
    MsgBox "First match: " & hit.Address, vbInformation
    ws.Cells.Replace What:="draft", Replacement:="final", _
                     LookAt:=xlPart, MatchCase:=False
End Sub

Range.Find returns Nothing rather than raising an error when there is no match, so the If hit Is Nothing guard is required — using .Address on Nothing is error 91. Always name LookIn, LookAt and MatchCase explicitly; unset arguments inherit whatever the user last chose in the Find dialog.

How to run this macro

  1. Press Alt + F11 to open the VBA editor.
  2. Insert > Module.
  3. Paste the code above.
  4. Press F5, or close the editor and run it from Developer > Macros.
  5. Save the file as .xlsm so the macro is kept.
Annotated stepsExcel
1

Decide whether you need the location of matches (Find) or just to change them (Replace).

2

For Find, assign the result with Set and name What, LookIn, LookAt and MatchCase explicitly.

3

Guard immediately with If hit Is Nothing Then — a miss returns Nothing, not an error.

4

To visit every match, save the first hit's Address and loop with FindNext until the address comes round again.

5

For a bulk change, call Range.Replace once on the whole range instead of looping — it is dramatically faster.

Ctrl+CthenCtrl+Shift+V+Cthen+Ctrl+VPaste values · WindowsMac

What this does

VBA offers three related tools and they solve different problems. Range.Find locates a value and hands back the cell as a Range object, or Nothing when there is no match — it tells you where something is. Range.Replace changes every match in the target range in a single call and returns only True or False; it is far faster than looping when you do not need to know which cells changed. FindNext continues a search from a previous hit, and the correct way to iterate is to remember the address of the first result and stop when the search wraps back round to it, since Find loops the range endlessly otherwise. Separately, VBA's own Replace() function works on a string rather than a sheet: Replace(text, "a", "b") returns a modified copy and never touches a cell, which is what you want inside a loop over values you have already read. The single biggest trap is that Find's unspecified arguments persist from the last search anyone performed, including one a user did through the dialog — so a macro that omits LookIn behaves differently depending on the session. The same idea underpins a lot of everyday Excel work, so the few minutes spent getting it right here pay back across every sheet you build afterwards. Treat it as a pattern, not a one-off, and it stops being something you look up and starts being something you reach for. The difference between a quick fix and a sheet you can trust is the extra minute you spend validating “excel vba substitute”. Start on a copy or a tiny sample, keep the affected cells visible, and compare the result with the tool above before you touch the real workbook. When this is a ribbon command, the selection matters more than the button: confirm the range, apply the command, then spot-check the output before saving. The point is a text operation that turns messy entries into clean, usable data, but the practical win is that someone else can open the file and understand what happened without asking you.

A worked example

A sheet full of records is marked "DRAFT" in mixed positions and casing, and every one should read "FINAL". Sub FindAndReplaceInSheet() first calls Find to confirm at least one match exists and reports its address, then calls Replace once to change them all. The If hit Is Nothing guard is what stops the macro dying on the .Address line when the sheet is already clean. When you need to act on each match rather than just rewrite it — say, colouring every cell containing "draft" — use the FindNext pattern: store firstAddress = hit.Address, do the work, then Set hit = ws.Cells.FindNext(hit) and loop while Not hit Is Nothing And hit.Address <> firstAddress. Without that address comparison the loop never ends, because Find wraps around to the beginning of the range. Find and Replace is where macros meet messy real data — inconsistent labels, stray markers, values that need normalising before anything else can run. The two behaviours worth internalising are that a miss returns Nothing rather than erroring, and that omitted arguments are inherited rather than defaulted; between them they account for most of the bug reports this pair of methods generates. A practical tip before you scale it up: build it once on a small block of test data, confirm the number against the tool on this page, and only then point it at your real sheet. That one habit catches almost every mistake while it is still cheap to fix, long before a wrong figure reaches a report or a colleague.

In Google Sheets

Everything above works in Google Sheets too. Excel and Sheets share the formula syntax used here; only the surrounding menus are arranged differently. That portability is deliberate — learn it once and it follows you between the two tools and across Windows and Mac. The aim was to get you unstuck fast and leave you a little more capable than a copy-paste would. The answer is at the top, the tool proves it, and the detail above shows why it holds — so the next time a colleague asks, you can answer without reaching for search. Treat “excel vba substitute” as a small building block rather than a chore. Once the inputs sit in their own cells and the formula reads from them, the same setup answers a dozen related questions with a tweak, and Excel keeps every dependent figure current as the data changes. The tool above is there so you can rehearse and verify before committing anything to a real workbook; the steps and worked example are there so the logic sticks. Get it right once and it stops costing you time — it starts saving it, every time the question comes back around.

Common mistakes

  • Using the result of Find without checking for Nothing. Any property access on Nothing raises error 91, and a sheet that simply has no match is the normal case, not an exceptional one.
  • Leaving LookIn and LookAt unspecified. Those arguments persist between searches — including from the user's last use of Ctrl + F — so the same macro can match whole cells one day and partial text the next.
  • Looping FindNext without tracking the first address. The search wraps around at the end of the range, so the loop runs forever; comparing against the stored first address is the standard termination test.
  • Searching with LookIn:=xlValues when you meant formulas. xlValues sees displayed results, xlFormulas sees the underlying text, so a macro hunting for a cell reference must use the latter.
  • Confusing Range.Replace with VBA's Replace() function. The first edits cells on a sheet, the second returns a modified string and changes nothing — using the wrong one produces code that appears to do nothing at all.

Frequently asked questions

Why does my Find raise error 91?

Because it found nothing and returned Nothing, and the next line asked it for a property. Test If hit Is Nothing Then before touching the result — that branch is not optional.

How do I loop through every match?

Save the first hit's Address, act on it, then Set hit = rng.FindNext(hit) and repeat while the address differs from the saved one. Find wraps at the end of the range, so that comparison is what ends the loop.

Is Replace faster than looping over cells?

Considerably. Range.Replace performs the whole operation inside Excel in one call, while a loop crosses the VBA-to-Excel boundary once per cell. Loop only when each match needs different handling.

How do I search only part of a cell rather than the whole value?

Pass LookAt:=xlPart. LookAt:=xlWhole requires the entire cell to equal the search text. Always state it explicitly, because the unset value carries over from the previous search.