Comment? Faster & more efficient?
In my mind the code below is a bit 'neater' & it should be a bit faster/more efficient though you probably will not notice unless there is a lot of data to process.
My main comment is that this sort of string manipulation can be extremely difficult to cover all bases.
As an example, your code converts
ANNA SMITH-JONES arrived yesterday
to
Anna Smith-jones arrived yesterday
I suspect that you wouldn't want that "J" converted to lower case?
We could change the pattern so that any upper case letter immediately after a word boundary
or certain other characters remained as upper case. That would help with the "J" in
SMITH-JONES to give
Smith-Jones and the "C" in
JAMES O'CONNOR to give
James O'Connor
However, that O'Connor example also brings a problem if you have a apostrophe like this:
JIM'S where I doubt you would want
Jim'S returned.
In any case, this is what I came up with for the equivalent of your first code (that is, not excluding short words).
Note also that at the moment, my code writes the results in the next column to the right so that it is easy to compare result with original. Eventually you could remove the blue code to over-write the original data.
This code still converts
SMITH-JONES to
Smith-jones but we can look at that later if required.
Rich (BB code):
Sub ConvertUppercaseWordsToProper_v2()
Dim RX As Object, ToReplace As Object
Dim a As Variant, itm As Variant
Dim ProperCaseVersion As String
Dim i As Long
Set RX = CreateObject("VBScript.RegExp")
RX.Global = True
RX.Pattern = "\b([A-Z][A-Z,'\-]*[A-Z])\b"
With Selection
a = .Value
For i = 1 To UBound(a)
ProperCaseVersion = a(i, 1)
Set ToReplace = RX.Execute(ProperCaseVersion)
For Each itm In ToReplace
ProperCaseVersion = Replace(ProperCaseVersion, itm, StrConv(itm, vbProperCase), 1, -1, 0)
Next itm
a(i, 1) = ProperCaseVersion
Next i
.Offset(, 1).Value = a
End With
End Sub
Sample data and code results.
Excel Workbook |
---|
|
---|
| A | B |
---|
1 | The fish is NOT allowed to swim in the water AFTER SUNSET. | The fish is Not allowed to swim in the water After Sunset. |
---|
2 | ANNA SMITH-JONES arrived yesterday | Anna Smith-jones arrived yesterday |
---|
3 | This is JIM'S book | This is Jim's book |
---|
4 | | |
---|
5 | No upper case words here. | No upper case words here. |
---|
6 | IF you look CAREFULLY, YOU WILL see AN insect. | If you look Carefully, You Will see An insect. |
---|
7 | Part of a word in uPPer case does not get converted | Part of a word in uPPer case does not get converted |
---|
|
---|
To exclude words of 3 characters or less, just change the Pattern to
Rich (BB code):
<del>RX.Pattern = "\b([A-Z][A-Z,'\-]*[A-Z])\b"</del>
RX.Pattern = "\b([A-Z][A-Z,'\-]{2,}[A-Z])\b"
Sample data and code results.
Excel Workbook |
---|
|
---|
| A | B |
---|
1 | The fish is NOT allowed to swim in the water AFTER SUNSET. | The fish is NOT allowed to swim in the water After Sunset. |
---|
2 | ANNA SMITH-JONES arrived yesterday | Anna Smith-jones arrived yesterday |
---|
3 | This is JIM'S book | This is Jim's book |
---|
4 | | |
---|
5 | No upper case words here. | No upper case words here. |
---|
6 | IF you look CAREFULLY, YOU WILL see AN insect. | IF you look Carefully, YOU Will see AN insect. |
---|
7 | Part of a word in uPPer case does not get converted | Part of a word in uPPer case does not get converted |
---|
|
---|
My other comment is that I am not a fan of using 'Selection' as the basis of what to process. If the data is in column A, I would prefer something like this
Rich (BB code):
<del>With Selection</del>
With Range("A1", Range("A" & Rows.Count).End(xlUp))