i'm new here and to VBA and I need your assistance.
I have an excel spreadsheet with a dynamic table (Header is on Row 4). The data imported into the table contains a date values (5 September, 2018 6:11:17 PM EDT) that Excel cannot format to m-d-yyyy. the only way we can format the dates are to remove the 'comma', 'EDT' and 'EST' values. The macro runs and works as expected.
Now my challenge is to modify this macro (VBA) to look for the column header name instead of the whole column. As I keep getting asked to add a column to the table. The column names are 'Target Decomm Date', 'Actual Decomm Date', 'Created Date', 'Last Updated Date', 'Accreditation Date', and 'Accreditation Expiry Date'
All data is populated in row 5 and this is a dynamic table.
Here is my current code
Sub ConvertDateFormat()
'
' Macro1 Macro
'
' Keyboard Shortcut: Ctrl+Shift+D
'
Range("V:V,W:W,Z:Z,AA:AA,AC:AC,AD:AD").Select
Range("V5").Activate
Selection.NumberFormat = "m/d/yyyy"
Selection.Replace What:=",", Replacement:=" ", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Selection.Replace What:="EDT", Replacement:=" ", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Selection.Replace What:="EST", Replacement:=" ", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
End Sub
You can reference to the table and it's columns directly without using column letters.
Dim tbl As ListObject 'this will be the table
Dim rngData as Range
Set tbl = ActiveSheet.ListObjects("name_of_your_table")
Set rngData = tbl.ListColumns("Target Decomm Date").DataBodyRange
rngData.NumberFormat = "m/d/yyyy"
rngData.Replace [.....]
You can use an array to loop through all your different column names, but I won't cover that here, as it's well documented on the net, for example How can I use a for each loop on an array?
here is my end script and it worked well.
Sub FormatDate()
'
Dim tbl As ListObject 'this will be the table
Dim rng1, rng2, rng3, rng4, rng5, rng6, rngM As Range
Set tbl = ActiveSheet.ListObjects("tblProductList")
Set rng1 = tbl.ListColumns("Target Decomm Date").DataBodyRange
Set rng2 = tbl.ListColumns("Actual Decomm Date").DataBodyRange
Set rng3 = tbl.ListColumns("Created Date").DataBodyRange
Set rng4 = tbl.ListColumns("Last Updated Date").DataBodyRange
Set rng5 = tbl.ListColumns("Accreditation Date").DataBodyRange
Set rng6 = tbl.ListColumns("Accreditation expiry Date").DataBodyRange
Set rngM = Union(rng1, rng2, rng3, rng4, rng5, rng6)
rngM.NumberFormat = "m/d/yyyy"
rngM.Replace What:=",", Replacement:=" ", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
rngM.Replace What:="EDT", Replacement:=" ", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
rngM.Replace What:="EST", Replacement:=" ", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
End Sub
Related
In a variable selection of cells in single column, I'm needing to swap "Buy" with "Sell", and vice-versa.
I tried something like this...but when first Selection.Replace changes "Sell" to "Buy", then 2nd one just changes "Buy" back to "Sell" -
Data sample
I havent found that I can nest a Selection.Replace..would need to loop down thru each cell somehow?
....
Range("B4").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Range("C4").Select
Selection.PasteSpecial
Selection.Replace What:="Bought", Replacement:="Sold", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False, FormulaVersion:=xlReplaceFormula2
Selection.Replace What:="Sold", Replacement:="Bought", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False, FormulaVersion:=xlReplaceFormula2
To achieve what you want, you can replace three times instead of just two times.
The solution shows how to do it, while avoiding the use of Copy, Paste and Select, to make sure we don't interfere with the user selection and the clipboard.
Sub Doit()
Dim Rng1 As Range
Dim Rng2 As Range
Dim Rng As Range
Dim Lst As Variant
' Get the range in column B from row 4 and down.
Set Rng1 = Range("B4")
Set Rng2 = Rng1.End(xlDown)
Set Rng = Range(Rng1, Rng2)
' Copy the range to column C
Lst = Rng
Range("C4").Resize(UBound(Lst, 1), UBound(Lst, 2)) = Lst
' Replace Bought with Sold and Sold with Bought
Rng.Replace What:="Bought", Replacement:="#B#o#u#g#h#t", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False, FormulaVersion:=xlReplaceFormula2
Rng.Replace What:="Sold", Replacement:="Bought", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False, FormulaVersion:=xlReplaceFormula2
Rng.Replace What:="#B#o#u#g#h#t", Replacement:="Sold", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False, FormulaVersion:=xlReplaceFormula2
End Sub
The solution assumes that your data does not contain the string "#B#o#u#g#h#t". You can use whatever string you want instead of "#B#o#u#g#h#t", as long as the string does not appear in your data.
As with your example, the solution does not test, if there is any valid data in Column B from row 4 and down.
I need to remove some record from Excel spreadsheet. I want for macro to search for a certain name and upon finding a cell with that name, remove row containing it and next X rows.
So far I have a part that removes content of a cell upon certain words, but now I would need it to not clear but remove whole rows
Range("B2:H100").Replace What:="*Phone", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Range("B2:H100").Replace What:="*Queue", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Range("B2:H100").Replace What:="*2nd Line", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Try something like the code below:
Option Explicit
Sub RemoveRowsFindName()
Dim FindRng As Range
Dim xRows As Long
Dim FindWord As String
xRows = 7 ' number of extra rows to remove
FindWord = "Phone"
Set FindRng = Range("B2:H100").Find(What:=FindWord, LookAt:=xlPart, SearchOrder:=xlByRows)
If Not FindRng Is Nothing Then
Range("A" & FindRng.Row).Resize(1 + xRows, 1).EntireRow.Delete Shift:=xlShiftUp
Else ' word not found in range
MsgBox "Unable to find " & FindWord & " in range", vbCritical, "Find Error!"
End If
End Sub
#Shar Rado -
This would be a part of a bit larger script designed for clearing out excel spreadsheet to be more transparent for HR team, I've pasted your suggesion as:
Dim FindRng As Range
Dim xRows As Long
Dim FindWord As String
xRows = 7
FindWord = "Tony"
Set FindRng = Range("B2:H100").Find(What:=FindWord, LookAt:=xlPart, SearchOrder:=xlByRows)
If Not FindRng Is Nothing Then
Range("A" & FindRng.Row).Resize(1 + xRows, 1).EntireRow.Delete Shift:=xlShiftUp
End If
But the overall macro did the same it done previously - didn't return any errors nor did the needed removal.
first post :)
I have the following code below, which selects all within a set column and clears the two text phrases, from row 12 down.
What i want is to have the user input the column instead? possibly via InputBox?
Sub ClearColumn()
Dim lastCell As Long
Dim myRange As Range
' Find lastCell in column Z
lastCell = Cells(Rows.Count, "Z").End(xlUp).Row
' Set range to look at
Set myRange = Range("Z12:Z" & lastCell)
' Replace All Pass
myRange.Replace What:="Go", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
' Replace All Fail
myRange.Replace What:="Stop", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
End Sub
Welcome to Stack Exchange. You seem to have answered your own question. Below code is untested, but should take a small amount of time to implement.
Sub ClearColumn()
Dim lastCell As Long
Dim chooseColumn As Variant
Dim myRange As Range
chooseColumn = InputBox("Which Column do you want to alter?")
' Find lastCell in column Z
lastCell = Cells(Rows.Count, chooseColumn ).End(xlUp).Row
' Set range to look at
Set myRange = Range(chooseColumn &"12:"&chooseColumn & lastCell)
' Replace All Pass
myRange.Replace What:="Go", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
' Replace All Fail
myRange.Replace What:="Stop", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
End Sub
Let us know how you go :)
i want to pop up a inputbox when LR is coming..
Look in code:
LR = Range("G" & Rows.Count).End(xlUp).Row
Range("G2:G" & LR).Select
Sub FixIt()
Dim LR As Long
LR = Range("G" & Rows.Count).End(xlUp).Row
Range("G2:G" & LR).Select
Selection.Replace What:=Chr(160), Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Selection.Replace What:=",", Replacement:=".", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Selection.NumberFormat = "0.00"
Selection.Style = "Comma"
End Sub
You can use the Application.InputBox with Type:=8 to specify an input box which will have as its return value a Range object.
Here is an example of using such an input box to get the row number of a selected cell.
Dim inRange as Range
Set inRange = Application.InputBox("Please select a cell...", Type:=8)
If Not inRange Is Nothing Then
LR = inRange.Row
Else
'Probably you want to Exit Sub here or do some error-handling
End If
Or, to use the same approach to get the entire range of selection:
Dim myRange as Range
Set myRange = Application.InputBox("Please select some range...", Type:=8)
If myRange Is Nothing Then
'Probably you want to Exit Sub here or do some error-handling
End If
'proceed with the rest of your code...
With myRange
.Replace What:=Chr(160), Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
.Replace What:=",", Replacement:=".", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
.NumberFormat = "0.00" Selection.Style = "Comma"
End With
I'm working with hourly weather data in Excel that has each hour of every day of the year along with the corresponding temperature value that was recorded.
Some of the values weren't recorded, and instead show up as just an "M" on the spreadsheet. For example, A32 = 28, A33 = M, A34 = 30. I want to replace that "M" with a formula to take the average of the previous and next values. I know how to do this manually, but I am having difficulty writing a Macro to find all the M's in the spreadsheet, then auto-replace it as stated above.
My main obstacle is getting excel to use the correct values when replacing the "M".
Here is my code
Sub MReplace()
'
' MReplace Macro
'
'
ActiveCell.Select
Cells.Find(What:="M", After:=ActiveCell, LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
, SearchFormat:=False).Activate
Cells.FindNext(After:=ActiveCell).Activate
ActiveCell.Offset(-8, 1).Range("A1").Select
Cells.Find(What:="M", After:=ActiveCell, LookIn:=xlFormulas, LookAt:= _
xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=True _
, SearchFormat:=False).Activate
Cells.FindNext(After:=ActiveCell).Activate
ActiveCell.Replace What:="M", Replacement:="[****This is what I am having difficulty with****]", LookAt:=xlWhole, _
SearchOrder:=xlByRows, MatchCase:=True, SearchFormat:=False, _
ReplaceFormat:=False
Cells.Find(What:="M", After:=ActiveCell, LookIn:=xlFormulas, LookAt:= _
xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=True _
, SearchFormat:=False).Activate
End Sub
I have heard of something that you can put in to the code that can address the selected cell. I think it's cell() but I am not sure. Maybe that is a way to get it to work better?
Try this code:
Sub MReplace()
Dim ws As Worksheet
Dim cel As Range
Dim firstAddress As String
Set ws = ActiveSheet
Set cel = ws.Range("A:A").Find("M")
If Not cel Is Nothing Then
firstAddress = cel.Address
Do
cel.Value = (cel.Offset(1) + cel.Offset( -1)) / 2
Set cel = ws.Range("A:A").FindNext(cel)
hr = False
If Not cel Is Nothing Then
If cel.Address <> firstAddress Then
hr = True
End If
End If
Loop While hr
End If
End Sub
It loops through all the cells containing "M" and replaces it with the average of the one on the right and the one on the left. It will error on any that are in the first column as there is no column to the left.