View Full Version : Solved: Convert to proper
Djblois
05-30-2007, 07:18 AM
I use code I found in a book to covert what the user selects into proper case. However sometimes it takes too long, if they choose too many cells. I have a few ideas to speed it up but I can't figure out how to do it. I have tried a few but I can't get them to work.
Here is the code that I use:
For Each cellobject In Selection
cellobject.Formula = WorksheetFunction.Proper(cellobject.Formula)
cellobject.Replace What:="'S", Replacement:="'s"
Next
Function FinalRow(ByVal shtToCount As Worksheet)
Dim FinalRowD As Long, FinalRowLast As Long
FinalRow = shtToCount.Cells(Rows.Count, 1).End(xlUp).Row
FinalRowD = shtToCount.Cells(Rows.Count, "D").End(xlUp).Row
FinalRowLast = shtToCount.Cells(Rows.Count, FinalColumn(ActiveSheet)).End(xlUp).Row
If FinalRowD > FinalRow Then FinalRow = FinalRowD
If FinalRowLast > FinalRow Then FinalRow = FinalRowLast
End Function
Function FinalColumn(ByVal shtToCount As Worksheet)
Dim FinalColumnD As Long
FinalColumn = Cells(1, Columns.Count).End(xlToLeft).Column
FinalColumnD = Cells(4, Columns.Count).End(xlToLeft).Column
If FinalColumnD > FinalColumn Then FinalColumn = FinalColumnD
End Function
1) I want it to end if the cell is in a row larger than the finalrow
2) I want it to skip an item that is already proper case or if it isn't text or if it is blank
I can't figure it out
mikerickson
05-30-2007, 07:38 AM
For Each cellobject In Selection.Cells.SpecialCells(xlCellTypeConstants, 2)will restrict the loop to the cells containing a text constant (no formulas)
Djblois
05-30-2007, 09:34 AM
to exit the loop after I get to the last row, I tried
For Each cellobject In Selection
if selection.row > finalrow(Activesheet) then goto EndProper
cellobject.Formula = WorksheetFunction.Proper(cellobject.Formula)
cellobject.Replace What:="'S", Replacement:="'s"
Next
EndProper:
mikerickson
05-30-2007, 03:38 PM
instead of looping through Selection loop through
Application.Intersect (Selection, ActiveCell.UsedRange)
That way you can select entire rows, columns or the whole sheet and not go beyond finalRow or finalColumn.
Looping through
Selection.SpecialCells(xlCellTypeConstants, 2).Cells will further restrict your looping to those cells that hold text, no blanks, no formulas, no numbers
Djblois
05-31-2007, 06:08 AM
mikerickson
This is what I have now:
For Each cellobject In Application.Intersect _
(Selection.SpecialCells(xlCellTypeConstants, 2).Cells, ActiveCell.UsedRange)
cellobject.Formula = WorksheetFunction.Proper(cellobject.Formula)
cellobject.Replace What:="'S", Replacement:="'s"
Next
and at the moment it doesn't work. It keeps telling me object doesn't support that function
mikerickson
05-31-2007, 06:39 AM
I've been wondering what that cellobject.replace line is for. How does the routine do with it commented out? and the For Each statemtent is redundant.
Try this:
On Error Resume Next
For Each cellObject In Selection.SpecialCells(xlCellTypeConstants, 2).Cells
cellObject.Value = Application.Proper(cellObject.Value)
Next cellObject
On Error GoTo 0The error stuff is there in case there are no text constants in the selected range.
Djblois
05-31-2007, 08:18 AM
the replace.replace line is because if you use proper anything with a 'S will stay a 'S eg: MIKE'S would become Mike'S with proper. So I replace all the 'S with 's.
Djblois
05-31-2007, 08:25 AM
That is working good. But now is there a way to test if it is already proper? and then skip that line?
mdmackillop
05-31-2007, 10:37 AM
You can replace all the 'S in one line outwith the loop
Selection.Replace What:="'S", Replacement:="'s"
mikerickson
05-31-2007, 12:13 PM
It would be faster to put this line outside of the loop. It takes care of the entire sheet.
Cells.Replace What:="'S", Replacement:="'s", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=True, SearchFormat:=False, _
ReplaceFormat:=False
But now is there a way to test if it is already proper?
Other than checking letter by letter, I know of none.
Djblois
05-31-2007, 12:13 PM
You know I never thought about that but you are correct. lol
Djblois
05-31-2007, 12:34 PM
Now I have this:
Selection.SpecialCells(xlCellTypeConstants, 2).Formula = _
Application.Proper(Selection.Value) 'Change selection to proper case
Selection.Replace What:="'S", Replacement:="'s" 'Change 'S to 's
Much quicker, works on thousands of cells. The old way if you had to do 30,000 rows, it would lock up. The only other thing I wish it is possible to do is check if the content is proper before changing it. Anybody else know if this is possible?
mdmackillop
05-31-2007, 01:02 PM
Even if it were possible, would it be quicker?
Djblois
05-31-2007, 01:57 PM
it is a trade off sometimes it would be wouldn't it? Acutually you just made me think, it won't be because I will have to put it back in the loop to be able to test it. Thank you all for your help.
malik641
05-31-2007, 02:31 PM
Now I have this:
Selection.SpecialCells(xlCellTypeConstants, 2).Formula = _
Application.Proper(Selection.Value) 'Change selection to proper case
Selection.Replace What:="'S", Replacement:="'s" 'Change 'S to 's
Much quicker, works on thousands of cells. The old way if you had to do 30,000 rows, it would lock up. The only other thing I wish it is possible to do is check if the content is proper before changing it. Anybody else know if this is possible?
I thought there was a way to do this without a loop. I couldn't think of how, though. Nice solution Djblois :thumb It's awesome :yes
mikerickson
05-31-2007, 03:16 PM
Now I have this:
Selection.SpecialCells(xlCellTypeConstants, 2).Formula = _
Application.Proper(Selection.Value) 'Change selection to proper case
Selection.Replace What:="'S", Replacement:="'s" 'Change 'S to 's
Much quicker, works on thousands of cells. The old way if you had to do 30,000 rows, it would lock up. The only other thing I wish it is possible to do is check if the content is proper before changing it. Anybody else know if this is possible?
There is a problem with this code. I put "a" in A1, "b" in B2, and so on down the diagonal, leaving the other cells blank. When I ran the code, all the cells turned to "A". When I tested with a rectagularly filled area, it worked fine. I suspect that the Application.Proper is only working on the first area of the .Special Cells. If that is the case, looping through the areas will be faster than looping through cells.
mdmackillop
05-31-2007, 03:32 PM
Here's a non-looping solution
Application.ScreenUpdating = False
With Selection
.Offset(, 5).FormulaR1C1 = "=Proper(RC[-5])"
.Offset(, 5).Copy
.PasteSpecial xlValues
.Offset(, 5).ClearContents
.Replace What:="'S", Replacement:="'s" 'Change 'S to 's
End With
Application.ScreenUpdating = True
johnske
05-31-2007, 10:55 PM
Here's a non-looping solution
Application.ScreenUpdating = False
With Selection
.Offset(, 5).FormulaR1C1 = "=Proper(RC[-5])"
.Offset(, 5).Copy
.PasteSpecial xlValues
.Offset(, 5).ClearContents
.Replace What:="'S", Replacement:="'s" 'Change 'S to 's
End With
Application.ScreenUpdating = True
Nice Malcolm,
A slight variation on that - eliminates copy/paste and works on 'used range' for a column you specify instead of 'Selection'
Option Explicit
Sub ChangeToProper()
Application.ScreenUpdating = False
With ActiveSheet.UsedRange.Columns(1) '< change 1 to suit
.Offset(0, 5).FormulaR1C1 = "=Proper(RC[-5])"
.Value = .Offset(0, 5).Value '< change 5 to suit
.Offset(0, 5).ClearContents '< change 5 to suit
.Replace "'S", "'s" 'Change 'S to 's
End With
Application.ScreenUpdating = True
End Sub
mdmackillop
06-01-2007, 12:57 AM
Thanks John,
Much neater.
Djblois
06-01-2007, 04:33 PM
You made me do further testing. All of them have the same problem. If there is one blank in the range selected it messes everything up.
Here this one works the best:
With selection '< change 1 to suit
.Offset(0, 100).FormulaR1C1 = "=Proper(RC[-100])"
.Value = .Offset(0, 100).Value '< change 5 to suit
.Offset(0, 100).ClearContents '< change 5 to suit
.Replace "'S", "'s" 'Change 'S to 's
End With
I made one change, I changed 5 to 100 because there is a good chance that there will be data in 5 coulumns over. There is a much better chance of there being no data in 100 columns over.
mdmackillop
06-03-2007, 01:40 PM
Convert as you go
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
With Target
If .Column = 2 Then
.Value = WorksheetFunction.Proper(.Value)
.Replace "'S", "'s"
End If
End With
Application.EnableEvents = True
End Sub
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.