Find and replace in text files

binoculars

Replacing text inside text files doesn't mean you need to open them or paste them into Excel. We can do everything strictly in VBA.

All we need to do is use VBA's own I/O commands: Open, Print, Close, etc…

This procedure will open a given text file and replace whatever you need. It works similar to the Replace function except instead of a string variable you pass it the name of a file. Although ultimately we do use the Replace function to do the dirty work.

Sub FindAndReplace(filePath As String, findWhat As String, _
                   replaceWith As String)
' from Excel Help:
' A variable-length string can contain up to approximately 2 billion
' (2^31) characters.
Dim nextFileNum As Long
Dim oldFileContents As String
Dim newFileContents As String
Dim textFileTypes() As String
Dim fileExtension As String

  If Len(Dir(filePath)) = 0 Then
    Exit Sub
  End If

  ' only act on "text" files
  textFileTypes = QuoteString("txt csv html xml", ",")

  fileExtension = LCase$(Right$(filePath, 3))

  If UBound(Filter(textFileTypes, fileExtension)) = -1 Then
    Exit Sub
  End If

  ' open file and read contents
  nextFileNum = FreeFile

  Open filePath For Input As #nextFileNum
  oldFileContents = Input$(LOF(nextFileNum), #nextFileNum)
  Close #nextFileNum

  ' replace old char with new char
  newFileContents = Replace(oldFileContents, findWhat, replaceWith)

  ' reopen file and write new contents
  nextFileNum = FreeFile

  Open filePath For Output As #nextFileNum
  Print #nextFileNum, newFileContents
  Close #nextFileNum

End Sub

Function QuoteString(str As String, delimiter As String) As String()

Dim tempString() As String
Dim newString As String

  newString = Replace(str, " ", delimiter)

  ' split the string into an array, using delimiter
  tempString = Split(newString, delimiter)

  QuoteString = tempString

End Function

Let's examine how this function (and the secondary function QuoteString) works.

We pass in a filename, the character being sought, and the character to replace it with. First we check if the filename is valid. Note that we could also skip this check and use this function to create the file if it doesn't exist.

We delimit the file types to just "text" files that can be opened using Notepad. You can add more filetypes here. Because I was lazy when I wrote this, I've kept these checks inline instead of factoring them out into their own functions.

The QuoteString function returns a String array of file extensions. I'll admit I did go a little out of the way to make the function harder to follow. All it does is take a space-delimited list of file extensions and the delimiter we want to use. It returns a String array of comma-delimited file extensions. I used it because I like declaring textFileTypes as String instead of as Variant (which I would need to do if I wanted to use the Array function to pass the comma-delimited string directly). Also, it's easier for me to write "txt csv html xml" than it is to encase each discrete String in quotes like this: "txt", "csv", "html", "xml". I usually mess it up.

The file is opened and its contents are placed into a String variable. There is a character limit here; although I doubt you'll hit it, it is something to be aware of. The Replace function takes out the sought after character(s) and puts in the desired character(s) in its stead. We reopen the file and place the newly revised contents in it. Finally, the file is closed.

You might ask why we have to open the file twice. After all, the Help documentation for the Open statement says:

In Binary, Input, and Random modes, you can open a file using a different file number without first closing the file. In Append and Output modes, you must close a file before opening it with a different file number.

Initially we're using Input mode, so we should be able to open the file with a new file number. I tried keeping the file open (i.e. not using the Close statement), using a different file number and reopening the file for Output, but I kept getting the "File In Use" error. So either I did it wrong, the Output parameter caused the error, or the documentation is wrong.

Sample usage

Sub TestFindAndReplace()

  On Error GoTo ErrorHandler

  Call FindAndReplace("C:\testfile.txt", "text to find", "text to replace")

ProgramExit:
  Exit Sub
ErrorHandler:
  MsgBox Err.Number & " - " & Err.Description
  Resume ProgramExit
End Sub

Related Articles:

About JP

I'm just an average guy who writes VBA code for a living. This is my personal blog. Excel and Outlook are my thing, with a sprinkle of Access and Word here and there. Follow this space to learn more about VBA. Keep Reading »

Share This Article:

Share and bookmark this articledelicious buttonfacebook buttonlinkedin buttonstumbleupon buttontwitter button

comment bubble 11 Comments:

  1. MicrosoftTrainingNeeded writes:

    I bloody knew there was a way to do it in the VBA, cheers a lot JP!

  2. If this thing is wrapped inside a FindFirst / FindNext loop, it becomes a "global-replace in all files in a folder" kind of function.

  3. Lubo writes:

    Hello,

    I am using vba 6.5 in excel 2003, and I receive error message "Compile error: Wrong number of arguments or invalid property assignment".

    I have tried another replace in .txt file VBA scripts, but no success.

    Dont you guess where could be a problem? Thanks for any clue.

    • JP writes:

      I put the code into Excel's VBA IDE and compiled it without error. Step through the code and post exactly what line causes the error. Also it would help to show how you are calling the procedure.

      • Lubo writes:

        Hello,

        Thank for your reply. I really dont know exactly where was a problem, but now it is running without errors.

        When I tried to run macro from the same excel file at home (office 2010, vba 7.0) I've received the same error message. After that I just pick the code with Ctrl+C and Ctrl+V to another excel file, and from this time everything went well.

        I dont know by what this was caused, but this first excel file must be somehow "buggy". It is really weird, but I am now lucky that script is running.

        Thanks for your help anyway.

        Lubo

  4. dustin writes:

    How about some VBA code that will do the following?
    So I have an email template (.oft) that i use on a regular basis. Its getting to the point where I am using this more and more. When I pull up the oft, I then do a "Find and Replace". I find all the instances of and replace with the employees name. I then find all instances of and replace with the Managers name.

    I'm curious if there is a way that I can pull up the oft, and when It pulls up I'm automatically prompted for and then . This would save me a ton of time.

    • JP writes:

      I'd use a different approach. First I'd prompt for the name using VBA.InputBox, then open the template using the CreateItemFromTemplate Method. You can use Instr and Mid to search the body of the template for the text you want to replace, and replace it with the name you prompted for in the beginning.

  5. cali writes:

    Hi
    I have tried this method to replace a delimiter on a large text file. I get the error 'out of string space' though. Am I doing something wrong? Any ideas?
    Thanks Cali

  6. Poov writes:

    Useful one. Can i modify and make it available in my blog?

Mentions:

  1. [...] Global replace April 28, 2010 at 9:26 AM | In General | Leave a Comment Tags: find, replace, VBA Here's a nifty and useful replace-all function. [...]

Comments on this article are closed. Why?

Site last updated: February 9, 2012