how can i substitute this symbol' for = with vba - excel

I'm trying to substitute '. with =
but this code doens't work!
can any one help?
Cells.Replace What:="'.gcmd", Replacement:="=gcmd", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False

If the apostrophe is at the very start of the string, it is a Prefix Character and part of the formatting property of the string, not the value property. It tells excel to treat the value as text.
That being the case, you need to clear the format in addition to replacing the value.
Also note that if you do not have a named formula or range defined on your worksheet, the code will not work returning an application error (unless you define the format as Text).
Code could be something like below:
Option Explicit
Sub due()
Dim R As Range, C As Range
Dim FirstAddress As String
Set R = Range("A1:Z100") 'or whatever
With R
Set C = Cells.Find(What:=".gcmd", Lookat:=xlPart, _
LookIn:=xlFormulas, searchorder:=xlByRows, MatchCase:=False)
If Not C Is Nothing Then
FirstAddress = C.Address
If C.PrefixCharacter = "'" Then
C.ClearFormats
C.NumberFormat = "#" 'omit if `gcmd` is a valid name
End If
C.Value = "=" & Mid(C, 2)
Do
Set C = .FindNext(C)
If C Is Nothing Then Exit Do
If C.Address = FirstAddress Then Exit Do
'Note that you don't really have to test for the apostrophe.
'You could just ClearFormats whether it is present or not.
If C.PrefixCharacter = "'" Then
C.ClearFormats
C.NumberFormat = "#" 'omit if `gcmd` is a valid name
End If
C.Value = "=" & Mid(C, 2)
Loop
End If
End With
End Sub

Or perhaps try this?
(not actually really tested this, just rattled it off as an idea)
Private Sub SOAnswer()
Dim C As Range
Dim Str As String
For Each C In Range("A1: R35") 'Define your range here, or use Sheets(1).UsedRange for all cells on the sheet
If InStr(1, ".gcmd", C.Value) <> 0 Then
Str = C.Value
C.Clear
C.Formula = Replace(Str, ".gcmd", "=gcmd")
End If
Next
End Sub

Related

How do you get Excel VBA to recognize numeric cells?

I have a table of numbers that are all left aligned (i.e. Excel recognizes them as text)
I run a VBA script on all cells:
cell.value = cell.Value * 1
This right aligns all of them and Excel recognized them as numbers except for decimals (e.g. 3.14 does not work while 314 works). I also run a find and replace script, where the search is for space (" ") and replace it with a blank(""), so this should get rid of atleast the common space.
Further clues: If i perform the =Value(A1) formula in Excel, Excel will recognize even the decimals as a number. If I run Workbookfunction.value(A1) Excel will not recognize as a number.
So the problem seems ro be related to VBA (?) and decimals. Any solutions?
I now ran the following after comments here:
For Each cell In rng
Dim vNumber As Double
On Error Resume Next
'Remove space
cell.Replace What:=" ", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
'Remove comma
cell.Replace What:=",", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
'Check if empty, if it is: Do nothing
If IsEmpty(cell) = True Then
Else
vNumber = CDbl(cell.Value)
cell.Value = vNumber
End If
'Check if numeric
If IsNumeric(cell) = True Then
cell.Interior.Color = RGB(0, 254, 0)
cell.Interior.TintAndShade = 0.8
Else
cell.Interior.Color = RGB(100, 0, 0)
cell.Interior.TintAndShade = 0.8
End If
Next cell
The result is the following Before and After (where one is with Double and other with Variant. Somehow its writing over cells that are not decimals...
You need to convert the value of the cell to a double. For example:
Dim myDouble As Double
myDouble = CDbl(Range("A1").Value)
Debug.Print myDouble
myDouble = myDouble + 1
Debug.Print myDouble
Lines 3 to 5 are just to demonstrate that it gets recognised as a decimal.
Did you try conversion?
Sub test()
Dim rng As Range, cell As Range
With ThisWorkbook.Worksheets("Sheet1")
Set rng = .Range("A1:A5")
For Each cell In rng
.Range("B" & cell.Row).Value = CDbl(cell)
Next cell
End With
End Sub
Results:
Val(Cells(1,1).Value will convert a string to a number if it's numeric, to zero if it's not. "123abc" will be converted to the number 123. IsNumeric(Cells(1,1).Value) will return True if there are no non-numeric characters in the cell's string.
Incidentally, VBA's Val() function will ignore blanks. Val(123 456") will return the number 123456.
The code below will meet your updated requirements. Please try it.
Sub ConvertTextToNumbers()
Dim Rng As Range
Dim Cell As Range
Dim Arr As Variant
Dim R As Long
With Worksheets("Sheet1") ' modify to suit
Set Rng = .Range(.Cells(2, "B"), .Cells(.Rows.Count, "B").End(xlUp))
Arr = Rng.Value
For R = 1 To UBound(Arr)
' remove commas and spaces
Arr(R, 1) = Val(Replace(Replace(Arr(R, 1), " ", ""), ",", ""))
Next R
Rng.Offset(0, 1).Value = Arr
For Each Cell In Rng.Offset(0, 1)
Cell.Interior.Color = IIf(Cell.Value, vbGreen, vbRed)
Next Cell
End With
End Sub

Replace method and changing format?

I'm using vba method Replace, and I need to change every "/" to ",". This looks like a simple task so I use:
ActiveWorkbook.Worksheets(2).Cells.Replace What:="_/_", Replacement:=",", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=True, _
ReplaceFormat:=True
The problem is when one of cells has value like:
04_/_2018
And the result is:
4,2018
instead of:
04,2018
All of my cells in this workbook has text formating before and after aplying the code. My guess is that Excel in a process is changing the format to general for a moment and it cut offs not necessary for a number left zero.
I've tried to bypass this issue by changing parameters of the method (none of this worked) and changing the decimal separator from "," to ".". This helped when using find and replace by hand from Excel, but when I record it and try to use as Macro it doesn't work. What can I do to prevent Excel from cutting off zeros in this scenarios?
If you want 04,2018 then use .Find/.FindNext then replace+reconstruct the value before placing in the cell.
Is this what you are trying?
Sub Sample()
Dim oRange As Range, aCell As Range, bCell As Range
Dim ws As Worksheet
Dim ExitLoop As Boolean
Dim SearchString As String
On Error GoTo Whoa
Set ws = Worksheets("Sheet1")
Set oRange = ws.UsedRange
SearchString = "_/_"
Set aCell = oRange.Find(What:=SearchString, LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
Set bCell = aCell
If Left(aCell.Value, 1) = 0 Then
aCell.Value = "'" & Replace(aCell.Value, SearchString, ",")
Else
aCell.Value = Replace(aCell.Value, SearchString, ",")
End If
Do While ExitLoop = False
Set aCell = oRange.FindNext(After:=aCell)
If Not aCell Is Nothing Then
If aCell.Address = bCell.Address Then Exit Do
If Left(aCell.Value, 1) = 0 Then
aCell.Value = "'" & Replace(aCell.Value, SearchString, ",")
Else
aCell.Value = Replace(aCell.Value, SearchString, ",")
End If
Else
ExitLoop = True
End If
Loop
Else
MsgBox SearchString & " not Found"
End If
Exit Sub
Whoa:
MsgBox Err.Description
End Sub
Screenshot
The leading zeroes are automatically removed in Excel by default. Thus 04,2014 is changed to 4,2014. A way to work around this is to format the cells as Text, adding this line before the Replace():
ActiveWorkbook.Worksheets(2).Cells.NumberFormat = "#"
Formatting to Text has a lot of unpleasant changes, e.g. the text goes to the left and Excel does not recognize the dates/numbers by default.
This is a simple sample of the code, changing 1 cell:
Sub TestMe()
ActiveWorkbook.Worksheets(1).Cells.NumberFormat = "General"
Range("B5") = "05_2018"
ActiveWorkbook.Worksheets(1).Cells.NumberFormat = "#"
Range("B5") = Replace(Range("B5"), "_", ".")
End Sub
Formatting to text can work like this, for bigger, unknown ranges:
Sub TestMe()
Worksheets(1).Cells.NumberFormat = "General"
Range("A1:B15") = "05_2018"
Dim findRange As Range
Set findRange = Worksheets(1).Cells.Find("_")
Dim myCell As Range
If Not findRange Is Nothing Then
For Each myCell In findRange
myCell.Replace "_", ","
Next myCell
End If
End Sub

Find and replace text

I'm new to VBA in Excel and have a fairly simple issue. I need to search for specific text string Bath in Column B. If it exists, then I need to replace specific text string KCab in Column C of the same row with BCab3. I need to run or loop this until it checks all the cells in Column B.
Here is what I have so far, which is not working:
Sub Correct_Attribute_Suffix()
Dim c As Range
Dim SrchRng
Set SrchRng = ActiveSheet.Range("B3", ActiveSheet.Range("B65536").End(xlUp))
Do
Set c = SrchRng.Find("BATH", LookIn:=xlValues)
If Not c Is Nothing Then Currentcell.Offset(, 1).Value = Replace("KCab", "K", "B")
Loop While Not c Is Nothing
End Sub
This is just a Find/FindNext operation using offset and replace to accomplish your attribute suffix adjustment.
Sub Correct_Attribute_Suffix()
Dim fnd As Range, addr As String
With ActiveSheet.Range("B3", ActiveSheet.Range("B65536").End(xlUp))
Set fnd = .Find(What:="BATH", After:=.Cells(.Cells.Count), LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not fnd Is Nothing Then
addr = fnd.Address
Do
fnd.Offset(0, 1) = Replace(fnd.Offset(0, 1).Value2, "KCab", "BCab3", 1, 1, vbTextCompare)
Set fnd = .FindNext(After:=fnd)
Loop While addr <> fnd.Address
End If
End With
End Sub

Using wildcards in VBA cells.replace

I'm looking to write a function in Excel to add leading zeroes to the octets that make up an IP address: e.g in 172.19.1.17 I want to to change .19. to .019., the .1. to .001., and the .17 at the end to .017.
Te Cells.Teplace function does not seem to accept ? as a wildcard. Also, is there a way I can represent 'end of string' so I'll be able to add leading zeroes to the last octet, .17 in the example above.
Thanks Ian
Cells.Replace What:=".1?.", Replacement:=".01?.", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
This does find "10." "11." "12." etc. but replaces them all with ".01?."
As an alternative you may use this formula to add zeros to IP parts (it looks terrible, but treats separately all the parts and finally mix them up):
=REPT(0,4-FIND(".",A1))&LEFT(A1,FIND(".",A1)-1)&"."&
REPT(0,4-FIND("#",SUBSTITUTE(A1,".","#",2))+FIND(".",A1))&MID(A1,FIND(".",A1)+1,FIND("#",SUBSTITUTE(A1,".","#",2))-FIND(".",A1)-1)&"."&
REPT(0,4-FIND("#",SUBSTITUTE(A1,".","#",3))+FIND("#",SUBSTITUTE(A1,".","#",2)))&MID(A1,FIND("#",SUBSTITUTE(A1,".","#",2))+1,FIND("#",SUBSTITUTE(A1,".","#",3))-FIND("#",SUBSTITUTE(A1,".","#",2))-1)&"."&
REPT(0,3-LEN(A1)+FIND("#",SUBSTITUTE(A1,".","#",3)))&RIGHT(A1,LEN(A1)-FIND("#",SUBSTITUTE(A1,".","#",3)))
You may paste it as it is to B1 (assuming your IPs are in column A starting A1) regardless line breaks.
Sample file: https://www.dropbox.com/s/vun6urvukch9uvv/IPoctets.xlsx
You could do something like this:
Be sure to replace Application.UsedRange with the actual range containing the IP addresses
Sub PadIP()
Dim Arr As Variant
Dim ipAddr As String
Dim vCell As Variant
Dim n As Long
'Replace ActiveSheet.UsedRange with the range containing your data
'
'If data is contained in column A and you have a column header
'Example: Range(Cells(2, 1), Cells(ActiveSheet.UsedRange.Rows.Count, 1))
For Each vCell In ActiveSheet.UsedRange
Arr = Split(vCell.Value, ".")
For n = 0 To UBound(Arr)
If (n + 1) Mod 4 = 0 Then
ipAddr = ipAddr & Right(String(3, "0") & Arr(n), 3)
Else
ipAddr = ipAddr & Right(String(3, "0") & Arr(n), 3) & "."
End If
Next
vCell.Value = ipAddr
ipAddr = ""
Next
End Sub
Can I play too :)?
This is further to my comment above. This is an example on how to find .??. and make it .0??.
I am assuming that the data can be ANYWHERE in the worksheet.
Sub Sample()
Dim oRange As Range, aCell As Range, bCell As Range
Dim ws As Worksheet
Dim ExitLoop As Boolean
Dim SearchString As String
On Error GoTo Whoa
Set ws = Worksheets("Sheet1")
Set oRange = ws.Cells
SearchString = ".??."
Set aCell = oRange.Find(What:=SearchString, LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
Set bCell = aCell
aCell.Value = CleanIt(aCell.Value)
Do While ExitLoop = False
Set aCell = oRange.FindNext(After:=aCell)
If Not aCell Is Nothing Then
If aCell.Address = bCell.Address Then Exit Do
aCell.Value = CleanIt(aCell.Value)
Else
ExitLoop = True
End If
Loop
End If
Exit Sub
Whoa:
MsgBox Err.Description
End Sub
Function CleanIt(rng)
Dim MyAr() As String
Dim strTemp As String
MyAr = Split(rng, ".")
For i = LBound(MyAr) To UBound(MyAr)
If Len(MyAr(i)) = 2 Then
MyAr(i) = "0" & MyAr(i)
End If
strTemp = strTemp & "." & MyAr(i)
Next i
CleanIt = Mid(strTemp, 2)
End Function
Screenshot
NOTE: This is just an example for demonstration purpose. The above code needs to be tweaked more so that it can handle other scenarios as well.

Change a String to Uppercase if it Exists - VBA

How do I change a particular string to Uppercase only if it exists.
If (Cells(i, "A") Like "*roada*") Or (Cells(i, "A") Like "*roadb*") _
Or (Cells(i, "A") Like "*roadc*") etc... Then 'Change only the found string to Uppercase.
Each cell contains two or more words. Example: Cell A1 consists of "roadhouse blues". I want only 'roadh' to change to Uppercase if it exists in that cell. Is this possible in VBA?
This will do the trick:
Const road As String = "road"
Dim s As String
Dim letterAfterRoad As String
s = "play that roadhouse blues" ' or get contents of some cell
letterAfterRoad = Mid(s, InStr(s, road) + Len(road), 1)
Mid(s, InStr(s, road)) = UCase(road & letterAfterRoad)
Debug.Print s ' returns "play that ROADHouse blues". Write to cell.
If I were you, I would heed #minitech's sarcastic remark. If what you're looking for is road? where ? is a letter a-z then let Like look for a-z rather than manually typing the entire alphabet...
Here is how I would do it:
Const road As String = "road"
Dim s As String
Dim charAfterRoad As String
Dim roadPos As Long
s = "play that roadhouse blues"
roadPos = InStr(s, road)
If roadPos > 0 And Len(s) >= roadPos + Len(road) Then
'Found "road" and there is at least one char after it.
charAfterRoad = Mid(s, roadPos + Len(road), 1)
If charAfterRoad Like "[a-z]" Then
Mid(s, InStr(s, road)) = UCase(road & charAfterRoad)
End If
End If
Debug.Print s ' returns "play that ROADHouse blues"
Here is another way. Let Excel do the dirty work ;)
Sub Sample()
Dim SearchString As String
Dim ReplaceString As String
Dim aCell As Range
'~~> Search String
SearchString = "roadh"
'~~> Replace string
ReplaceString = UCase(SearchString)
'~~> Change A1 to to the respective cell
Set aCell = Range("A1").Find(What:=SearchString, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False)
'~~> If Found
If Not aCell Is Nothing Then
Range("A1").Replace What:=SearchString, Replacement:=ReplaceString, _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
End If
End Sub
Also instead of looping you might want to use .FIND/.FINDNEXT ?
More on 'Find/FindNext': http://www.siddharthrout.com/index.php/2018/01/05/find-and-findnext-in-excel-vba/
FIND/FINDNEXT is far much more faster then looping and searching for values in Excel Cells ;)
AND the below is even faster (in fact the fastest). You don't need to find the word if your final intention is to replace the word. Simply issue the replace command. If the code finds any word then it will automatically replace.
Sub Sample()
Dim SearchString As String
Dim ReplaceString As String
'~~> Search String
SearchString = "roadh"
'~~> Replace string
ReplaceString = UCase(SearchString)
'~~> Replace the range below with the respective range
Range("A1:A1000").Replace What:=SearchString, Replacement:=ReplaceString, _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
End Sub
You don't need to use the wildcard character to check for the presence of a string inside a string. xlPart in "LookAt:=xlPart" takes care of that :)
FOLLOWUP (In Case the user meant this)
You may be missing the point here... OP is not only looking for roadh but for any road? where ? is a letter a-z. You have to figure out what ? is and make it uppercase. That's the (mildly) interesting twist of this problem. – Jean-François Corbett 1 hour ago
Also checking for the scenario where the cell can contain multiple "road" values (as shown in snapshot below which has a 'before' and 'after' snapshot.
Sub Sample()
Dim oRange As Range, aCell As Range, bCell As Range
Dim ws As Worksheet
Dim ExitLoop As Boolean
Dim SearchString As String, FoundAt As String
On Error GoTo Whoa
Set ws = Worksheets("Sheet1")
Set oRange = ws.Columns(1)
SearchString = "road"
Set aCell = oRange.Find(What:=SearchString & "?", LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
Set bCell = aCell
FoundAt = aCell.Address
aCell.Value = repl(aCell.Value, SearchString)
Do While ExitLoop = False
Set aCell = oRange.FindNext(After:=aCell)
If Not aCell Is Nothing Then
If aCell.Address = bCell.Address Then Exit Do
FoundAt = FoundAt & ", " & aCell.Address
aCell.Value = repl(aCell.Value, SearchString)
Else
ExitLoop = True
End If
Loop
MsgBox "The Search String has been found these locations: " & FoundAt & " and replaced by UPPERCASE"
Else
MsgBox SearchString & " not Found"
End If
Exit Sub
Whoa:
MsgBox Err.Description
End Sub
Function repl(cellValue As String, srchString As String) As String
Dim pos As Integer
pos = InStr(1, cellValue, srchString, vbTextCompare)
repl = cellValue
Do While pos <> 0
If pos = 1 Then
repl = UCase(Left(repl, Len(srchString) + 1)) & Mid(repl, Len(srchString) + 2)
Else
repl = Mid(repl, 1, pos - 1) & UCase(Mid(repl, pos, Len(srchString) + 1)) & _
Mid(repl, pos + Len(srchString) + 1)
End If
Debug.Print repl
pos = InStr(pos + 1, repl, srchString, vbTextCompare)
Loop
End Function
Snapshot:
HTH
Sid
A way with a regexp, replaces all Road* in the input.
Sub repl(value As String)
Dim re As Object: Set re = CreateObject("vbscript.regexp")
Dim matches As Object, i As Long
re.IgnoreCase = True
re.Global = True
re.Pattern = "(road[A-Z])"
Set matches = re.Execute(value)
For i = 0 To matches.Count - 1
value = Replace$(value, matches(i), UCase$(matches(i)))
Next
Debug.Print value
End Sub

Resources