Reducing number of Line Breaks/chr(10) in a Cell - excel

I have an excel sheet that has cells with variable amounts of line breaks and I want to reduce it so that there is only one line break between each new line.
For example
HELLO
WORLD
GOODBYE
will be modified to:
HELLO
WORLD
GOODBYE
I've been banging my head over this for hours and have come up with a few ways but none are very efficient or produce the best results.
This is made especially difficult because I'm working with a dataset that has spaces preceeding the Line Breaks.
And so a regular parse doesn't work as well.
I've tried to replace all the instances of chr(10) in the cell with ~ to make it easier to work with, however i'm still not getting it to an exact amount. I'm wondering if there are better ways.
here is what I have so far:
myString = Replace(myString, Chr(10), "~")
Do While InStr(myString, "~~") > 0
str1 = Split(myString, "~")
For k = 0 To UBound(str1)
myString = Replace(myString, "~~", "~")
Next k
Loop
Do While InStr(myString, " ~") > 0
str1 = Split(myString, "~")
For k = 0 To UBound(str1)
myString = Replace(myString, " ~", "")
Next k
Loop
myString = Replace(myString, " ~", " ~")
myString = Replace(myString, " ~", "~")
myString = Replace(myString, "~", Chr(10))
Cells(2, 2).Value = myString
So i'm using a few do while loops to catch instances of different types of line breaks (or in this case, tildes) but I don't think this is the best way to tackle this.
I was thinking of ways to loop through the characters in the cell, and if there is an instance where there is more than one chr(10), replace it with "".
So the psuedocode would look like:
for i to len(mystring)
if mystring(i) = chr(10) AND myString(i+1) = chr(10) Then
myString(i + 1) = ""
but unfortunately I don't think this is possible through vba.
If anyone is kind enough to help me adjust my current code or assist me with the aforementioned psuedocode, it would be greatly appreciated!

You can do it with a formula:
=SUBSTITUTE(SUBSTITUTE(TRIM(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(TRIM(A1)," ","|"),"|"&CHAR(10)," "),CHAR(10)," "))," ",CHAR(10)),"|"," ")
This changes all the spaces to | and then the Char(10) to spaces. The trim removes the extra spaces. The we reverse, space to Char(10) and | to spaces.
VBA:
Function manytoone(str As String)
str = Replace(Application.Trim(str), " ", "|")
str = Replace(str, "|" & Chr(10), " ")
str = Replace(str, Chr(10), " ")
str = Application.Trim(str)
str = Replace(str, " ", Chr(10))
str = Replace(str, "|", " ")
manytoone = str
End Function

You can use Regular Expressions.
The regex pattern below removes any line that contains zero to any number of spaces, along with its terminating crlf, and also removes the crlf at the end of the final word.
Option Explicit
Sub trimXSLF()
Dim myRng As Range, myCell As Range, WS As Worksheet
Dim RE As Object
Const sPat As String = "^\s*[\x0A\x0D]+|[\x0A\x0D](?!\s*\S+\s*)"
Const sRepl As String = ""
Set WS = Worksheets("sheet4") 'or whatever
With WS
Set myRng = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp))
End With
Set RE = CreateObject("vbscript.regexp")
With RE
.Global = True
.MultiLine = True
.Pattern = sPat
For Each myCell In myRng
myCell = .Replace(myCell.Value2, sRepl)
Next myCell
End With
End Sub
If myRng is large (tens of thousands of rows), the macro could run the process over a VBA array for speed.

A VBA method would be replacing consecutive vbLf constants with a single one.
Loop through the string as long as there are more than one vbLf together, once removed, replace the string.
Sub RemoveExcessLinebreaks()
Dim s As String, rng As Range
Set rng = ThisWorkbook.Worksheets(1).Range("B4")
s = rng.Value
While InStr(1, s, vbLf & vbLf) > 0
s = Replace(s, vbLf & vbLf, vbLf)
Wend
rng.Value = s
End Sub
Obviously, you would need to modify the rng object to your purposes, or turn it into a parameter to the sub itself.
vbLf is a constant for a "LineFeed". There are multiple types of new lines, such as a vbCr (Carriage Return) or a vbCrLf (combined). Pressing Alt + Enter in a cell appears to use the vbLf variant, which is why I used this constant over the others.

This has already been answered fairly well, but not meeting one of the requirements yet (have 1 line between each new line), so here is my take on answering this. Please see the comments through the code for more details:
Option Explicit
Sub reduceNewLines()
Dim ws As Worksheet: Set ws = ActiveWorkbook.Sheets("Sheet1")
Dim lRow As Long: lRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Dim lCol As Long: lCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
Dim arrData As Variant: arrData = ws.Range(ws.Cells(1, 1), ws.Cells(lRow, lCol))
Dim arrVal() As String
Dim R As Long, C As Long, X As Long
For R = LBound(arrData) To UBound(arrData) 'Iterate through each row of data
For C = LBound(arrData, 2) To UBound(arrData, 2) 'iterate through each column of data (though might be just 1)
arrVal = Split(arrData(R, C), Chr(10)) 'allocate each row to an array, split at new line
arrData(R, C) = "" 'reset the data inside this field
For X = LBound(arrVal) To UBound(arrVal)
arrVal(X) = Trim(arrVal(X)) 'clear leading/trailing spaces
If Left(arrVal(X), 1) <> " " And arrVal(X) <> "" Then
arrData(R, C) = arrData(R, C) & arrVal(X) & Chr(10) & Chr(10) 'allocate new data + 2 lines
End If
Next X
arrData(R, C) = Left(arrData(R, C), Len(arrData(R, C)) - 2) 'remove the last 2 extra new lines
Next C
Next R
ws.Range(ws.Cells(1, 1), ws.Cells(lRow, lCol)) = arrData 'allocate the data back to the sheet
End Sub
Happy to assist further if needed.

Related

Removing all data before the first '-' in a column in VBA

My spreadsheet currently has a column C with rows of data that have this structure below:
123 - abc - xyz
I want my VBA code to remove all the data before the first - including the - so that the column C would look like this:
abc - xyz
My current code is removing both "-"
Sub TrimCell()
Dim i As String
Dim k As String
i = "-"
k = ""
Columns("C").Replace what:=i, replacement:=k, lookat:=xlPart,
MatchCase:=False
End Sub
The Excel function I have for this is =REPLACE(C1,1,FIND("-",C1),""). This works but I want something in VBA.
This will work on column C:
Sub my_sub()
Dim c As Range
For Each c In Intersect(ActiveSheet.UsedRange, ActiveSheet.Range("C:C"))
c = Trim(Mid(c, InStr(c, "-") + 1))
Next
End Sub
You want to find the location of the first "-"
location = instr(1, cells(iRow,3), "-", vbTextCompare)
Taking advantage of fact that instr only returns the first entry...
Then trim the cell to the right using that location
if location > 0 then
'Found a "-" within this cell
cells(iRow,3) = right(cells(iRow,3), len(cells(iRow,3)-location)
end if
iRows is obviously just my iterator over the rows in your data. Define it whatever way you want.
You could dot it in one go using Evaluate.
With Range("C1", Range("C" & Rows.Count).End(xlUp))
.Value = Evaluate("MID(" & .Address & ", FIND(""-"", " & .Address & ")+1, LEN(" & .Address & "))")
End With
Please, try the next function:
Function replaceFirstGroup(x As String) As String
Dim arr
arr = Split(x, " - ")
arr(0) = "###$"
replaceFirstGroup = Join(Filter(arr, "###$", False), " - ")
End Function
It can be called/tested in this way:
Sub testReplaceFirstGroup()
Dim x As String
x = "123 - abc - xyz"
MsgBox replaceFirstGroup(x)
End Sub
In order to process C:C column, using the above function, please use the next code. It should be extremely fast using an array, working in memory and dropping the processing result at once:
Sub ProcessCCColumn()
Dim sh As Worksheet, lastR As Long, arr, i As Long
Set sh = ActiveSheet
lastR = sh.Range("C" & sh.rows.count).End(xlUp).row
arr = sh.Range("C2:C" & lastR).value
For i = 1 To UBound(arr)
arr(i, 1) = replaceFirstGroup(CStr(arr(i, 1)))
Next i
sh.Range("C2").Resize(UBound(arr), 1).value = arr
End Sub

How to split a cell of text and transpose it into column and split it again?

I have searched many posts, forums, tutorials, I tried combine some of them, but nothing really worked for me. Now I write some code, that by logic I learn from other programming languages it should work, but I'm missing few steps.
Let's assume I have string like this
Test User <TUser#my-domain.pl>; Test User2 <TUser2#my-domain.pl>; Test User3 <TUser3#my-domain.pl>; Test User4 <TUser4#my-domain.pl>;
I paste that into cell, let's say A1. My goal is to be left with Test User or TUser for each smaller string.
I can achive my goal by doing so:
Click Text as columns -> Delimited -> Other ;, now each string is in separate column
Copy whole A row and paste it with transpose(rotate), so each string is in separate row
Now easiest way is to use Text as columns, by < delimiter. So all I'm left with is Name Surname in one cell and rest in other
I want to achive that, by clicking on the button of course.
My code so far:
Sub GetName()
Dim WordList As String
Dim ArrayOfWords
Dim i, i2 As Integer
'Define my word list, based on cell
WordList = Cells(1, 1)
'Use SPLIT function to convert the string to an array
ArrayOfWords = Split(WordList, "<")
'Iterate through array, and put each string into new row cell
i = 2
i2 = 1
Do While (ThereIsNoMoreText)'That I cannot figure out
Cells(2, i).Value = ArrayOfWords(i2)
i = i + 1
i2 = i2 + 1
Loop
End Sub
Thanks for you help in advance and I hope I make it clear :)
Fun little alternative:
Sub Test()
With CreateObject("VBScript.RegExp")
.Global = True
.Pattern = "(?:<.*?>)"
arr = Split(.Replace([A1], ""), ";")
End With
With Cells(1, 2).Resize(UBound(arr))
.Value = Application.Transpose(arr)
.Value = Application.Trim(.Value)
End With
End Sub
Obviously, be sure to create an explicit sheet reference for Cells.
You need to split by semicolon first.
Break the following apart to get the strings you need:
userlist = Split(Cells(1, 1).Value, ";")
i = 1
For Each user In userlist
i = i + 1
splituser = Split(user, "<")
Cells(i, 1) = splituser(0)
Cells(i, 2) = Mid(splituser(1), 1, Len(splituser(1)) - 1)
Next
In addition to the methods shown in others answers (in particular the very impressive one by #JvdV) you could also try this.
This method does not use For…Next
Sub Users_Email_Split()
Dim aData As Variant
With ThisWorkbook.Worksheets("TEST")
aData = .Cells(1).Value
aData = Left(aData, -2 + Len(aData))
aData = Replace(aData, " <", """,""")
aData = Replace(aData, ">; ", """;""")
aData = "{""" & aData & """}"
aData = Application.Evaluate(aData)
.Cells(2, 2).Resize(UBound(aData), UBound(aData, 2)).Value = aData
End With
End Sub
EDIT
If the string is expected to exceed the 255 characters limit for the Evaluate Function then you could use this method (up to a max of 2086 characters).
This method a creates an User Defined Name with the array string as a formula, then applies the Name as a FormulaArray, and finally sets the value of the range.
Sub Users_Email_Split_Plus255()
Dim aData As Variant
Dim lR As Long, lC As Long
With ThisWorkbook.Worksheets("TEST")
aData = .Cells(11, 1).Value
aData = Left(aData, -2 + Len(aData))
aData = Replace(aData, " <", """,""")
aData = Replace(aData, ">; ", """;""")
aData = "={""" & aData & """}"
lR = 1 + UBound(Split(aData, ";"))
lC = 1 + UBound(Split(Split(aData, ";")(0), ","))
With .Cells(12, 2).Resize(lR, lC)
.Worksheet.Names.Add Name:="_FmlX", RefersTo:=aData
.FormulaArray = "=_FmlX"
.Value = .Value
End With: End With
End Sub
You have to modify the construct a bit
Dim i As Long
Dim FirstPart As String, SecondPart As String
Dim ArrayOfWords
ArrayOfWords = Split(Cells(1, 1).Value, ";")
For i = LBound(ArrayOfWords) To UBound(ArrayOfWords)
If InStr(1, ArrayOfWords(i), "<") > 0 Then
FirstPart = Left(ArrayOfWords(i), InStr(1, ArrayOfWords(i), "<") - 1)
SecondPart = Mid(ArrayOfWords(i), Len(FirstPart) + 1, Len(ArrayOfWords(i)))
Debug.Print FirstPart & "--" & SecondPart
End If
Next i

cell.Value not retrieving the carriage returns in the cell

My Excel cells have carriage return(s) \ line feeds, but when reading into cell.value, the carriage returns disappear. Is there a way to handle this so that I can determine where the line breaks were (without modifying my source Excel sheet data)?
In the code below (at the bottom of this thread), I would have expected the ProductText variable to be set as:
Orange<CR>
Red<CR>
Yellow<CR>
where <cr> means carriage return.
I can confirm that the line-feeds are present when I copy from an Excel cell into Notepad.
But in VBA, ProductText is populated as: "Orange Red Yellow" and the carriage returns are gone.
'YOU MAY SKIP TO THE ******************************************* for the purposes of this post
Public Sub ProcessCharmMingFile(Excel_UNC_Path As String)
Dim src As Workbook
Dim ProdPushWorkbook As Workbook
Set ProdPushWorkbook = ActiveWorkbook
Set src = Workbooks.Open(Excel_UNC_Path, True, True)
Dim c As Range
Dim r As Range
Dim LastRow As Long
Dim Text As String
src.Sheets("Table 1").Activate
src.ActiveSheet.Range("A1").Select
LastRow = src.ActiveSheet.Range("A30000").End(xlUp).Row
Text = LastRow
Text = "A1:T" + CStr(Text)
Set r = Range(Text)
Dim i As Integer
For i = 1 To MaxItems
PONumber(i) = ""
Next
Dim PageCounter As Integer
PageCounter = 0
RecordCounter = 0
Dim ProductText As String
Dim QtyText As String
Dim HeatText As String
'***********************************************************
'***********************************************************
'***********************************************************
For Each c In r
If c.Value = "ALLIED FITTING Product Code" Then
PageCounter = PageCounter + 1
ProductText = c.Offset(1, 0).Value
HeatText = c.Offset(1, 1).Value
QtyText = c.Offset(1, 2).Value
End If
Next
'***********************************************************
'***********************************************************
'***********************************************************
If RecordCounter = 0 Then
Call AbortFileProcessing("No Valid Reoords Dected", False, ProdPushWorkbook)
End If
src.Close
End Sub
The thing is that you need a Line Feed to get the lines to display separately in a cell.
VBA has the appropriate constants for this:
Sub CRLFString()
Dim str As String
str = "hello" & vbCr & "world!"
Range("A1").Value = str 'Reads: "helloworld!" - Wrap Text won't change this.
str = "hello" & vbLf & "world!"
Range("A2").Value = str
str = "hello" & vbCrLf & "world!"
Range("A3").Value = str 'Both of these read
'hello
'world!
End Sub
However, if you would output these strings using Debug.Print all three of them would be on 2 lines as expected.
In short: Add a line feed, otherwise you get the result described in the question.
You can just use Replace on vbCr to do so:
Sub AddLineBreaksAndOutput(str As String)
str = Replace(str, vbCr, vbCrLf)
Range("A4").Value = str
End Sub
Sub Test()
Dim str As String
str = "hello" & vbCr & "world!"
AddLineBreaksAndOutput str
End Sub
Carriage Return Trouble
Out of curiosity what is the code number of the "CR" character. You can get it using this formula: =CODE(MID(A1,7,1)) in Excel (adjust A1 and 7 appropriately).
If this behavior persists you can split the string into an array and concatenate with the appropriate character e.g. Chr(10):
Declare two variables, then after the line ProductText = ... you know what to do.
Dim j As Integer
Dim vntText As Variant
ProductText = c.Offset(1, 0).Value
vntText = Split(ProductText, " ")
For j = 0 To UBound(vntText)
If j > 0 Then
ProductText = ProductText & Chr(10) & vntText(j)
Else
ProductText = vntText(0)
End If
Next
I want to enhance the answer already posted....
You should replace all types of LF's and CR's with vbCRLF, then use that as your splitter.
Here is my code... it can be enhanced further, based on your needs. In my case, it was vbLF that was the culprit, not vbCR. I replaced both, though, with vbCrLF, and then used that as my splitter...
ProductText = Replace(Replace(c.Offset(1, 0).Value, vbCr, vbCrLf), vbLf, vbCrLf)
ProdAry = Split(ProductText, vbCrLf)

vba subroutine works on one sheet but not another

I'm trying to clean names on two separate sheets "Alpha Roster" and "Paid". Alpha Roster is updated by other people and Paid is my master tracker of who has paid. I have a function called "MakeProper" that works fairly well at making corrections on Alpha Roster but for some reason does not make any corrections to Paid. Both sheets are set up the same.
Sub CleanUpPaid()
Sheets("Paid").Activate
Sheets("Paid").Select
Range("A2").Select
MakeProper
End Sub
Sub MakeProper()
Dim rngSrc As Range
Dim lMax As Long, lCtr As Long
Set rngSrc = ActiveSheet.Range(ActiveWindow.Selection.Address)
lMax = rngSrc.Cells.Count
' clean up Sponsor's Names
For lCtr = 3 To lMax
If Not rngSrc.Cells(lCtr, 1).HasFormula And _
rngSrc.Cells(lCtr, 1) <> "CMC" Then
rngSrc.Cells(lCtr, 1) = MakeBetterProper(rngSrc.Cells(lCtr, 1))
End If
' clean up Guest's Names
If Not rngSrc.Cells(lCtr, 7).HasFormula Then
rngSrc.Cells(lCtr, 7) = MakeBetterProper(rngSrc.Cells(lCtr, 7))
End If
Next lCtr
'MsgBox ("Make Proper " & ActiveSheet.Name)
End Sub
Function MakeBetterProper(ByVal ref As Range) As String
Dim vaArray As Variant
Dim c As String
Dim i As Integer
Dim J As Integer
Dim vaLCase As Variant
Dim str As String
' Array contains terms that should be lower case
vaLCase = Array("CMC", "II", "II,", "III", "III,")
ref.Replace what:=",", Replacement:=", "
ref.Replace what:=", ", Replacement:=", "
ref.Replace what:="-", Replacement:=" - "
c = StrConv(ref, 3)
'split the words into an array
vaArray = Split(c, " ")
For i = (LBound(vaArray) + 1) To UBound(vaArray)
For J = LBound(vaLCase) To UBound(vaLCase)
' compare each word in the cell against the
' list of words to remain lowercase. If the
' Upper versions match then replace the
' cell word with the lowercase version.
If UCase(vaArray(i)) = UCase(vaLCase(J)) Then
vaArray(i) = vaLCase(J)
End If
Next J
Next i
' rebuild the sentence
str = ""
For i = LBound(vaArray) To UBound(vaArray)
str = str & " " & vaArray(i)
str = Replace(str, " - ", "-")
str = Replace(str, "J'q", "J'Q")
str = Replace(str, "Jr", "Jr.")
str = Replace(str, "Jr..", "Jr.")
str = Replace(str, "(Jr.)", "Jr.")
str = Replace(str, "Sr", "Sr.")
str = Replace(str, "Sr..", "Sr.")
Next i
MakeBetterProper = Trim(str)
End Function
I read up on the difference between select and activate. As you can see, in CleanUpPaid, I try a couple different ways to make the Paid sheet the active sheet but nothing appears to occur on the sheet like it does in Alpha Roster.
You are only processing one cell on the Worksheets("Paid") and that is Range("A2"). You can eleiminate Set rngSrc = ActiveSheet.Range(ActiveWindow.Selection.Address) and just use Selection it is returning a range object.
Assuming that you want to process the cells in columns A and G. I'm using my function TitleCase to correct the capitalization but you can substitute MakeBetterProper if you would like.
Sub FixNames()
Application.ScreenUpdating = False
Dim ws As Worksheet
Dim c As Range
For Each ws In Worksheets(Array("Alpha Roster", "Paid"))
With ws
For Each c In Intersect(.Columns(1), .UsedRange)
If Not c.HasFormula And c.Value <> "CMC" Then c.Value = TitleCase(c.text)
Next
For Each c In Intersect(.Columns(7), .UsedRange)
If Not c.HasFormula Then c.Value = TitleCase(c.text)
Next
End With
Next
Application.ScreenUpdating = True
End Sub
My answer to How to make every letter of word into caps but not for letter “of”, “and”, “it”, “for” ?. will correct the capitalization for you.
I used Rules for Capitalization in Titles of Articles as a reference to create a capitalization exceptions list.
Function TitleCase uses WorksheetFunction.ProperCase to preproccess the text. For this reason, I put in an exception for contractions because WorksheetFunction.ProperCase improperly capitalizes them.
The first word in each sentence and the first word after a double quotation mark will remain capitalized. Punctuation marks are also handled properly.
Function TitleCase(text As String) As String
Dim doc
Dim sentence, word, w
Dim i As Long, j As Integer
Dim arrLowerCaseWords
arrLowerCaseWords = Array("a", "an", "and", "as", "at", "but", "by", "for", "in", "of", "on", "or", "the", "to", "up", "nor", "it", "am", "is")
text = WorksheetFunction.Proper(text)
Set doc = CreateObject("Word.Document")
doc.Range.text = text
For Each sentence In doc.Sentences
For i = 2 To sentence.Words.Count
If sentence.Words.Item(i - 1) <> """" Then
Set w = sentence.Words.Item(i)
For Each word In arrLowerCaseWords
If LCase(Trim(w)) = word Then
w.text = LCase(w.text)
End If
j = InStr(w.text, "'")
If j Then w.text = Left(w.text, j) & LCase(Right(w.text, Len(w.text) - j))
Next
End If
Next
Next
TitleCase = doc.Range.text
doc.Close False
Set doc = Nothing
End Function

Replace words in a cell

I'm trying to create a simple translation script that will look at a sentence in each cell from a range (column), and translate word by word based on the simple two-column (lookat/replace) translation memory I've created.
If the cell contains
"This app is cool"
and the translation memory is
This | 1
app | 2
cool | 3
Result should be:
"1 2 is 3"
However, using .Replace method, The below string:
"This apple from the cooler"
Would return
"1 2le from the 3er"
I used an array and split method to break the sentence into words, and then looked up at each words from my translation list for a xlwhole match. I have about 10,000 lines of sentences, and to break down each sentence into words would be roughly about 100,000 words and each word looking through about 1,000 list of translation words. It words.. but kind of slow.
Are there any other way, perhaps a better approach?
Here's another regex solution using the replace method and word boundaries (the "\b" in the regex pattern represents a word boundary). It assumes your source is in column A, and the results will go into column B.
The translation table is hard coded in the macro, but you could easily change that to be picked up from a table in your workbook.
Option Explicit
Sub Translate()
Dim V As Variant
Dim RE As Object
Dim arrTranslate As Variant
Dim I As Long, J As Long
Dim S As String
V = Range("a1", Cells(Rows.Count, "A").End(xlUp))
ReDim Preserve V(1 To UBound(V, 1), 1 To 2)
arrTranslate = VBA.Array(Array("This", 1), Array("app", 2), Array("cool", 3))
Set RE = CreateObject("vbscript.regexp")
With RE
.Global = True
.ignorecase = True
End With
For I = 1 To UBound(V, 1)
S = V(I, 1)
For J = 0 To UBound(arrTranslate)
RE.Pattern = "\b" & arrTranslate(J)(0) & "\b"
S = RE.Replace(S, arrTranslate(J)(1))
Next J
V(I, 2) = S
Next I
Range(Cells(1, 1), Cells(UBound(V, 1), UBound(V, 2))) = V
End Sub
Word to the rescue: Here I make use of of the "Match whole words only" option in Word's Find/Replace functionality.
Dim rngSentences As Range
Dim sentences, translatedSentences, wordsToReplace, newStrings
Dim iWord As Long
Dim iSentence As Long
Dim cell As Range
Dim w As Word.Application
Dim d As Word.Document
Set rngSentences = Range("A1:A5")
wordsToReplace = Array("this", "app", "cool")
newStrings = Array("1", "2", "3")
Set w = New Word.Application
Set d = w.Documents.Add(DocumentType:=wdNewBlankDocument)
sentences = rngSentences.Value ' read sentences from sheet
ReDim translatedSentences(LBound(sentences, 1) To UBound(sentences, 1), _
LBound(sentences, 2) To UBound(sentences, 2))
For iSentence = LBound(sentences, 1) To UBound(sentences, 1)
'Put sentence in Word document
d.Range.Text = sentences(iSentence, 1)
'Replace the words
For iWord = LBound(wordsToReplace) To UBound(wordsToReplace)
d.Range.Find.Execute Findtext:=wordsToReplace(iWord), _
Replacewith:=newStrings(iWord), MatchWholeWord:=True
Next iWord
'Grab sentence back from Word doc
translatedSentences(iSentence, 1) = d.Range.Text
Next iSentence
'slap translated sentences onto sheet
rngSentences.Offset(0, 1) = translatedSentences
w.Quit savechanges:=False
Another, potentially faster alternative is to paste all your sentences into the Word doc at once, replace everything, then copy-paste everything back to Excel sheet at once. It may be faster; I don't know, I haven't tested it extensively; up to you to do so.
To implement this, the lines after Set d = ... can be replaced with this:
'Copy-paste all sentences into Word doc
rngSentences.Copy
d.Range.PasteSpecial DataType:=wdPasteText
'Replace words
For iWord = LBound(wordsToReplace) To UBound(wordsToReplace)
d.Range.Find.Execute Findtext:=wordsToReplace(iWord), Replacewith:=newStrings(iWord), _
MatchWholeWord:=True
Next iWord
'Copy-paste back to Excel sheet
d.Range.Copy
rngSentences.Offset(0, 1).PasteSpecial xlPasteValues
w.Quit savechanges:=False
If you want you can use Regex.
Following the Scheme:
The Code:
' reference: "Microsoft VBScript Regular Expressions 5.5"
Dim RegX As Object, Mats As Object, Counter As Long
Set RegX = CreateObject("VBScript.RegExp")
Dim TrA(1 To 1000) As String
Dim TrB(1 To 1000) As String
Dim TrMax As Integer
Dim StrSp
For i = 1 To 9999
If Range("D" & i).Value = "" Then Exit For
TrA(i) = Range("D" & i).Value
TrB(i) = Range("E" & i).Value
TrMax = i
Next
Range("B1:B10").ClearContents
For i = 1 To 9999
If Range("A" & i).Value = "" Then Exit For
With RegX
.Global = True
.Pattern = "[a-zA-Z0-9]+"
Set Mats = .Execute(Range("A" & i).Value)
End With
kk = Range("A" & i).Value
For Counter = 0 To Mats.Count - 1
For e = 1 To TrMax
If LCase(Mats(Counter)) = TrA(e) Then
kk = Replace(kk, Mats(Counter), TrB(e), , 1)
End If
Next
Next
Range("B" & i).Value = kk
Next
Set Mats = Nothing
Set RegX = Nothing
Regex it's quickly, but the Word code it's very interesting (Copy & Paste ... :-)

Resources