I am relatively new to VBA and have this script which searches for the Array "VC" and changes the matching cells within the range by colouring them red.
My problem is I need to change the criteria from -MyArr = Array("VC") to instead search column A and find any corresponding matches in the same row within the range "B2:D20" then colour the matches red as the below script does.
As per the below script I don't want a case sensitive search and am using XLpart to include partial matches. Please help, thanks
Sub Mark_cells_in_column()
Dim FirstAddress As String
Dim MyArr As Variant
Dim Rng As Range
Dim I As Long
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
MyArr = Array("VC")
With Sheets("Sheet1").Range("A2:d20")
For I = LBound(MyArr) To UBound(MyArr)
Set Rng = .Find(What:=MyArr(I), _
After:=.Cells(.Cells.Count), _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
FirstAddress = Rng.Address
Do
Rng.Interior.ColorIndex = 3
Set Rng = .FindNext(Rng)
Loop While Not Rng Is Nothing And Rng.Address <> FirstAddress
End If
Next I
End With
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
Sample data:
You may try this
Public Sub Main()
Dim cell As Range, cell2 As Range
For Each cell In ThisWorkbook.Worksheets("Sheet1").Range("A2:A20")
For Each cell2 In cell.Offset(, 1).Resize(, 3)
If Instr(cell.Value, cell2.Value) > 0 Then cell2.Interior.ColorIndex = 3
Next
Next
End Sub
Or
Public Sub Main()
Dim cell As Range
With ThisWorkbook.Worksheets("Sheet1")
For Each cell In .Range("B:D").SpecialCells(xlCellTypeConstants)
If Instr(.Cells(cell.Row,1).Value, cell.Value) > 0 Then cell.Interior.ColorIndex = 3
Next
End With
End Sub
This will go through all cells in column A, split each cell value (comma-delimited) into separate items, and search for each item in the same row (case insensitive), through columns B to D
Option Explicit
Public Sub MarkCellsInColumns()
Dim arr As Variant, r As Long, c As Long, i As Long, f As Range, vals As Variant
arr = Sheet1.UsedRange
With Sheet1.UsedRange
For r = 1 To UBound(arr)
If Not IsError(arr(r, 1)) Then
If Len(arr(r, 1)) > 0 Then
vals = Split(arr(r, 1), ",") 'check each value in one cell
For i = 0 To UBound(vals)
For c = 2 To UBound(arr, 2) 'check all columns on same row
If LCase(Trim$(vals(i))) = LCase(Trim$(arr(r, c))) Then
If f Is Nothing Then
Set f = .Cells(r, c)
Else
Set f = Union(f, .Cells(r, c)) 'union of found cells
End If
f.Select
End If
Next c
Next i
End If
End If
Next r
If Not f Is Nothing Then f.Interior.Color = vbRed 'color all in one operation
End With
End Sub
Result
Related
Data
Purpose is to highlight the non date cell based on column header.
(highlight the screenshot cell C3,c5,D2,D6)
The below code I try to work for the purpose but fail.
Could please help to see what i can change?
Sub colortest()
Dim MyPage As Range, currentCell As Range
With Sheets(2).Rows(1)
Set t = .Find("Cut Date", lookat:=xlPart)
Set A = Columns(t.Column).EntireColumn
For Each currentCell In A
If Not IsEmpty(currentCell) Then
Select Case Not IsDate(currentCell.Value)
Case 1
currentCell.Interior.Color = 56231
End Select
End If
Next currentCell
End With
End Sub
Or
Option Explicit
Public Sub colortest()
Dim MyPage As Range, currentCell As Range, t As Range, findString As String
findString = "Date"
With ThisWorkbook.Worksheets("Sheet2")
Set t = .Rows(1).Find(findString, LookAt:=xlPart)
Dim currMatch As Long
For currMatch = 1 To WorksheetFunction.CountIf(.Rows(1).Cells, "*" & findString & "*")
Set t = Rows(1).Find(What:=findString, After:=t, _
LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByColumns, _
SearchDirection:=xlNext, MatchCase:=False)
If t Is Nothing Then Exit Sub
For Each currentCell In Intersect(.Columns(t.Column), .UsedRange.Resize(.UsedRange.Rows.Count - 1, .UsedRange.Columns.Count).Offset(1, 0))
If Not IsEmpty(currentCell) And Not IsDate(currentCell.Value) Then currentCell.Interior.Color = 56231
Next currentCell
Next currMatch
End With
End Sub
Purpose is to highlight the non date cell based on column header.
(highlight the screenshot cell C3,c5,D2,D6)
this would do that:
Sub colortest()
Dim currentCell As Range, f As Range
Dim fAddress As String
With Sheets(2).Rows(1)
Set f = .Find(what:="Date", lookat:=xlPart, LookIn:=xlValues)
If Not f Is Nothing Then
fAddress = f.Address
Do
With Intersect(f.EntireColumn, .Parent.UsedRange)
For Each currentCell In .Resize(.Rows.count - 1).Offset(1).SpecialCells(xlCellTypeConstants, xlTextValues)
If Not IsDate(currentCell.Value) Then currentCell.Interior.Color = 56231
Next
End With
Set f = .FindNext(f)
Loop While f.Address <> fAddress
End If
End With
End Sub
Try this (untested)
Option Explicit
Public Sub ColorTest1()
Dim ur As Range, hdrRow As Range, hdr As Range, dtCol As Range, cel As Range
Set ur = ThisWorkbook.Worksheets(2).UsedRange
Application.ScreenUpdating = False
Set hdrRow = ur.Rows(1)
For Each hdr In hdrRow.Cells
If InStr(1, hdr.Value2, "date", vbTextCompare) > 0 Then '<- Date Header
Set dtCol = ur.Columns(hdr.Column).Offset(1) '<- Date column
For Each cel In dtCol.Cells
If Len(cel) > 0 Then 'If cell is not empty
If Not cel Is Error Then 'If not Error (#N/A, #REF!, #NUM!, etc)
If Not IsDate(cel) Then cel.Interior.Color = 56231
End If
End If
Next
End If
Next
Application.ScreenUpdating = True
End Sub
Try this:
Sub HighlightNonDate()
'simple function invocations
CheckColumn (3)
CheckColumn (4)
End Sub
Function CheckColumn(columnNumber As Long)
Dim lastRow As Long
lastRow = Cells(Rows.Count, columnNumber).End(xlUp).Row
'loop through column, start from 2 to omit headers
For i = 2 To lastRow
'if cell isn't a date, then color red
If Not IsDate(Cells(i, columnNumber)) Then
Cells(i, columnNumber).Interior.Color = RGB(255, 0, 0)
End If
Next
End Function
Looking for VBA to copy cell above (in column E) if cell in E is empty and AJ is anything other than empty. Currently this is copying the cell above but is not taking into account the AJ column. Fairly new to VBA and not sure where I am going wrong. Any input is greatly appreciated.
Sub CopyFIN() 'copies FIN from account above if E is empty and AJ is anything other than empty
Dim lr As Long
Dim rcell As Range
Dim col As Range
Application.ScreenUpdating = False
lr = Cells(Rows.Count, 6).End(xlUp).Row
Set col = Range("E12:E" & lr)
Set col2 = Range("AJ12:AJ" & lr)
For Each rcell In col2
If rcell.Value <> "" Then
End If
Next
For Each rcell In col
If rcell.Value = "" Then
rcell.Offset(-1, 0).Copy rcell
End If
Next
Application.ScreenUpdating = True
End Sub
Try this. Your first loop wasn't doing anything and your second was only checking column E.
Sub CopyFIN() 'copies FIN from account above if E is empty and AJ is anything other than empty
Dim lr As Long
Dim rcell As Range
Dim col As Range
Application.ScreenUpdating = False
lr = Cells(Rows.Count, 6).End(xlUp).Row
Set col = Range("E12:E" & lr)
For Each rcell In col
If Len(rcell) = 0 And Len(Cells(rcell.Row, "AJ")) > 0 Then
rcell.Offset(-1, 0).Copy rcell
End If
Next
Application.ScreenUpdating = True
End Sub
in a column I have multiple values (Vat numbers) but not in consecutive rows, for example in A1, A5, A8,...
I need to copy each value from column A and paste them in a new column but reordered in consecutive rows, for example B1,B2,B3,...
The following macro does this job but only if in the value it is included the symbol "#" because it uses the function "Array" (if I replace # with numbers as 1,2,3,4,5,6,7,8,9, I get the same VAT number multiple times and I do not require it).
Sub Copy_To_Another_Sheet_1()
Dim FirstAddress As String
Dim MyArr As Variant
Dim Rng As Range
Dim Rcount As Long
Dim I As Long
Dim NewSh As Worksheet
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
MyArr = Array("#")
Set NewSh = Sheets("Sheet2")
With Sheets("Sheet2").Range("A1:A100")
Rcount = 0
For I = LBound(MyArr) To UBound(MyArr)
'If you use LookIn:=xlValues it will also work with a
'formula cell that evaluates to "#"
'Note : I use xlPart in this example and not xlWhole 'MyArr(I)
Set Rng = .Find(What:=MyArr(I), _
After:=.Cells(.Cells.Count), _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
FirstAddress = Rng.Address
Do
Rcount = Rcount + 1
NewSh.Range("A" & Rcount).Value = Rng.Value
' Use this if you only want to copy the value
' NewSh.Range("A" & Rcount).Value = Rng.Value
Set Rng = .FindNext(Rng)
Loop While Not Rng Is Nothing And Rng.Address <> FirstAddress
End If
Next I
End With
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
Thanks
Marco
I am trying to delete the contents of duplicate cells in a single column. I want to keep the first occurrence of the entry, but remove all duplicates below it.
I could only find code that deletes the entire row and not clear the contents.
Sub Duplicate()
With Application
' Turn off screen updating to increase performance
.ScreenUpdating = False
Dim LastColumn As Integer
LastColumn = Cells.Find(What:="*", After:=Range("U1"), SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column + 1
With Range("U1:U" & Cells(Rows.Count, 1).End(xlUp).Row)
' Use AdvanceFilter to filter unique values
.AdvancedFilter Action:=xlFilterInPlace, Unique:=True
.SpecialCells(xlCellTypeVisible).Offset(0, LastColumn - 1).Value = 1
On Error Resume Next
ActiveSheet.ShowAllData
'Delete the blank rows
Columns(LastColumn).SpecialCells(xlCellTypeBlanks).Cells.Clear
Err.Clear
End With
Columns(LastColumn).Clear
.ScreenUpdating = True
End With
End Sub
Here is one way. We start at the bottom of a column and work upwards:
Sub RmDups()
Dim A As Range, N As Long, i As Long, wf As WorksheetFunction
Dim rUP As Range
Set A = Range("A:A")
Set wf = Application.WorksheetFunction
N = Cells(Rows.Count, "A").End(xlUp).Row
For i = N To 2 Step -1
Set rUP = Range(Cells(i - 1, 1), Cells(1, 1))
If wf.CountIf(rUP, Cells(i, 1).Value) > 0 Then Cells(i, 1).Clear
Next i
End Sub
We check above to see if there are any duplicates above us and clear the cell if yes. Before:
and after:
EDIT#1:
For column U:
Sub RmDupsU()
Dim U As Range, N As Long, i As Long, wf As WorksheetFunction
Dim rUP As Range
Set U = Range("U:U")
Set wf = Application.WorksheetFunction
N = Cells(Rows.Count, "U").End(xlUp).Row
For i = N To 2 Step -1
Set rUP = Range(Cells(i - 1, "U"), Cells(1, "U"))
If wf.CountIf(rUP, Cells(i, "U").Value) > 0 Then Cells(i, "U").Clear
Next i
End Sub
my 0.02 cents
Sub main()
Dim i As Long
With Range("A1", Cells(Rows.Count, 1).End(xlUp))
For i = 1 To .Rows.Count - 1
.Range(.Cells(i + 1, 1), .Cells(.Rows.Count)).Replace what:=.Cells(i, 1).Value, replacement:="", lookat:=xlWhole
Next i
End With
End Sub
Here is a routine that will work. It can be sped up considerably if necessary:
EDIT: I changed column number to column letter, where you would need to make changes if you want a column other than "A"
Option Explicit
Sub ClearDups()
Dim R As Range
Dim I As Long
Dim COL As Collection
Set R = Range(Cells(1, "A"), Cells(Rows.Count, "A").End(xlUp))
Set COL = New Collection
On Error Resume Next
For I = 1 To R.Rows.Count
COL.Add Item:=R(I, 1), Key:=CStr(R(I, 1))
Select Case Err.Number
Case 457 'Duplicate test (Collection object rejects duplicate keys)
Err.Clear
R(I, 1).ClearContents
Case Is <> 0 'unexpected error
MsgBox Err.Number & vbLf & Err.Description
End Select
Next I
On Error Goto 0
End Sub
'This code crisply does the job of clearing the duplicate values in a given column
Sub jkjFindAndClearDuplicatesInGivenColumn()
dupcol = Val(InputBox("Type column number"))
lastrow = Cells(Rows.Count, dupcol).End(xlUp).Row
For n = 1 To lastrow
nval = Cells(n, dupcol)
For m = n + 1 To lastrow
mval = Cells(m, dupcol)
If mval = nval Then
Cells(m, dupcol) = ""
End If
Next m
Next n
End Sub
I am trying to join cells in a row if a value exists in a cell in that row.
The data has been imported from a .txt file and various sub headers are split along 2, 3 or 4 columns.
The cells cant be merged as the data will only be kept from the first cell.
The only words which are always constant are "contain" and "for" in column B.
What I've tried resembles this:
If cell.Value like "contain", or "for" then join all cells from column "A" to column "H" into column "B", align them centrally and make them bold.
thanks, in advance, for any help.
Edit Here is the code:
Sub Joining()
Dim N As Long, i As Long, r1 As Range, r2 As Range
Dim z As Long
Dim arr() As Variant
z = 1
With Activesheet
N = .Cells(Rows.Count, "A").End(xlUp).Row
For i = 1 To N
If .Cells(i, "B").Value Like "Summary*" Then
arr = .Range(.Cells(i, "A"), .Cells(i, "H")).Value
.Cells(z, "B").Value = Join(arr, " ")
z = z + 1
End If
Next i
End With
End Sub
Not sure if this is exactly what you want but it will get you close:
Sub summary()
Dim sh1 As Worksheet, sh2 As Worksheet
Dim N As Long, i As Long, r1 As Range, r2 As Range
Dim z As Long
Dim arr() As Variant
z = 1
Set sh1 = ActiveSheet
With ActiveWorkbook
Set sh2 = .Worksheets.Add(After:=.Sheets(.Sheets.Count))
End With
With sh1
N = .Cells(Rows.Count, "A").End(xlUp).Row
For i = 1 To N
If .Cells(i, "A").Value Like "Summary*" Then
arr = .Range(.Cells(i, "A"), .Cells(i, "H")).Value
sh2.Cells(z, "A").Value = Join(arr, " ")
z = z + 1
End If
Next i
End With
End Sub
Ok, so I've created an answer, but it ain't pretty (kinda like the whole project I've created).
It works although I'm sure there is a much simpler way of creating it.
Maybe someone can have a go at cleaning it up?
Sub SelRows()
Dim ocell As Range
Dim rng As Range
Dim r2 As Range
For Each ocell In Range("B1:B1000")
If ocell.Value Like "*contain*" Then
Set r2 = Intersect(ocell.EntireRow, Columns("A:G"))
If rng Is Nothing Then
Set rng = Intersect(ocell.EntireRow, Columns("A:G"))
Else
Set rng = Union(rng, r2)
End If
End If
Next
Call JoinAndMerge
If Not rng Is Nothing Then rng.Select
Set rng = Nothing
Set ocell = Nothing
End Sub
Private Sub JoinAndMerge()
Dim outputText As String, Rw As Range, cell As Range
delim = " "
Application.ScreenUpdating = False
For Each Rw In Selection.Rows
For Each cell In Rw.Cells
outputText = outputText & cell.Value & delim
Next cell
With Rw
.Clear
.Cells(1).Value = outputText
.Merge
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.WrapText = True
End With
outputText = ""
Next Rw
Application.ScreenUpdating = True
End Sub