To give some context I got this module below. This module is also in my worksheet. Before starting the macro it works fine it highlights whenever there is not "Testing" in column L.
The problem: When I start my macro it does everything without error, but doesn't update.
So an example when I start it after the macro runs and is completed when I change "testing" into "Atesting" then it doesn't mark the cell red.
EDIT: Or when everything runs and is completed whenever I see "Atesting" in column L. I have to click the cell to see the change of the background becoming red.
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Const RolesList As String = "Testing"
Const FirstCellAddress As String = "L2"
Const Delimiter As String = "||"
Dim rng As Range
With Range(FirstCellAddress)
Set rng = Intersect(.Resize(.Worksheet.Rows.Count - .Row + 1), Target)
End With
If rng Is Nothing Then
Exit Sub
End If
Dim Roles() As String: Roles = Split(RolesList, ",")
Dim dRng As Range
Dim aRng As Range
Dim cel As Range
Dim Curr() As String
Dim cMatch As Variant
Dim n As Long
Dim isFound As Boolean
For Each aRng In rng.Areas
For Each cel In aRng.Cells
If Not IsError(cel) Then
Curr = Split(cel.Value, Delimiter)
For n = 0 To UBound(Curr)
cMatch = Application.Match(Curr(n), Roles, 0)
If IsError(cMatch) Then
isFound = True
Exit For
Else
' Remove this block if you don't need case-sensitivity.
If StrComp(Curr(n), Roles(cMatch - 1), _
vbBinaryCompare) <> 0 Then
isFound = True
Exit For
End If
End If
Next n
If isFound Then
isFound = False
If dRng Is Nothing Then
Set dRng = cel
Else
Set dRng = Union(dRng, cel)
End If
End If
End If
Next cel
Next aRng
Application.ScreenUpdating = True
rng.Interior.Color = xlNone
If Not dRng Is Nothing Then
dRng.Interior.Color = vbRed
End If
Application.ScreenUpdating = True
End Sub
Maybe this helps, this is the whole code I'm using, are there any mistakes?
Before I start macro:
After I start macro:
After starting the macro it should still be red because it isn't in the role list, but it isn't't.
Sub AllInOne()
Application.EnableEvents = False
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Range("F2:F" & Cells(Rows.Count, "F").End(xlUp).Row).Copy Destination:=Range("J2")
Range("F2:F" & Cells(Rows.Count, "F").End(xlUp).Row).Copy Destination:=Range("K2")
ActiveSheet.Hyperlinks.Delete
For Each rng In Range("F2:F" & Cells(Rows.Count, "F").End(xlUp).Row): rng.Value = LCase(rng.Value): Next rng
For Each rng In Range("K2:K" & Cells(Rows.Count, "K").End(xlUp).Row): rng.Value = LCase(rng.Value): Next rng
For Each rng In Range("J2:J" & Cells(Rows.Count, "J").End(xlUp).Row): rng.Value = LCase(rng.Value): Next rng
Worksheets("sheet1").Columns("A:M").AutoFit
ActiveWorkbook.Worksheets("sheet1").UsedRange.Font.Underline = False
ActiveWorkbook.Worksheets("sheet1").Range("A2:Z5000").Font.Bold = False
ThisWorkbook.ActiveSheet.Cells.Range("A2:Z5000").ClearFormats
Range("A1:Z5000").Font.Color = vbBlack
Worksheets("sheet1").Columns("A:M").AutoFit
Dim cell As Range
lastRow = ActiveSheet.Cells(ActiveSheet.Rows.Count, "C").End(xlUp).Row
For Each cell In ActiveSheet.Range("C2:C" & lastRow)
S = vbNullString
If cell.Value <> vbNullString Then
v = Split(cell.Value, " ")
For Each W In v
S = S & Left$(W, 1) & "."
Next W
cell.Offset(ColumnOffset:=-1).Value = S
End If
Next cell
Application.Range("B1").Value = "testing"
Worksheets("sheet1").Range("B1").Font.Bold = True
Dim LastRowIndex As Integer
Dim RowIndex As Integer
Dim UsedRng As Range
Set UsedRng = ActiveSheet.UsedRange
LastRowIndex = UsedRng.Row - 1 + UsedRng.Rows.Count
Application.ScreenUpdating = False
For RowIndex = LastRowIndex To 1 Step -1
If Application.CountA(Rows(RowIndex)) = 0 Then
Rows(RowIndex).Delete
End If
Next RowIndex
Application.ScreenUpdating = False
Dim n As Long
Columns("D").Replace What:="vander", _
Replacement:="van der", _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
MatchCase:=False, _
SearchFormat:=False, _
ReplaceFormat:=False
Columns("D").Replace What:="vanden", _
Replacement:="van den", _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
MatchCase:=False, _
SearchFormat:=False, _
ReplaceFormat:=False
Columns("B").Replace What:="..", _
Replacement:=".", _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
MatchCase:=False, _
SearchFormat:=False, _
ReplaceFormat:=False
'Beta code'
Dim r As Range
For Each r In ActiveSheet.UsedRange
If Not IsError(r.Value) Then
v = r.Value
If v <> vbNullString Then
If Not r.HasFormula Then
r.Value = Trim(v)
End If
End If
End If
Next r
'NIEUW NIEUW NIEUW NIEUW NIEUW NIEUW NIEUW NIEUW '
Range("G2:G5000,A2:A5000,H2:H5000").Clear
Worksheets("sheet1").Columns("A:M").AutoFit
Application.EnableEvents = True
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Const RolesList As String = "Testing"
Const FirstCellAddress As String = "L2"
Const Delimiter As String = "||"
Dim rng As Range
With Range(FirstCellAddress)
Set rng = Intersect(.Resize(.Worksheet.Rows.Count - .Row + 1), Target)
End With
If rng Is Nothing Then
Exit Sub
End If
Dim Roles() As String: Roles = Split(RolesList, ",")
Dim dRng As Range
Dim aRng As Range
Dim cel As Range
Dim Curr() As String
Dim cMatch As Variant
Dim n As Long
Dim isFound As Boolean
For Each aRng In rng.Areas
For Each cel In aRng.Cells
If Not IsError(cel) Then
Curr = Split(cel.Value, Delimiter)
For n = 0 To UBound(Curr)
cMatch = Application.Match(Curr(n), Roles, 0)
If IsError(cMatch) Then
isFound = True
Exit For
Else
' Remove this block if you don't need case-sensitivity.
If StrComp(Curr(n), Roles(cMatch - 1), _
vbBinaryCompare) <> 0 Then
isFound = True
Exit For
End If
End If
Next n
If isFound Then
isFound = False
If dRng Is Nothing Then
Set dRng = cel
Else
Set dRng = Union(dRng, cel)
End If
End If
End If
Next cel
Next aRng
Application.ScreenUpdating = True
rng.Interior.Color = xlNone
If Not dRng Is Nothing Then
dRng.Interior.Color = vbRed
End If
Application.ScreenUpdating = True
End Sub
Related
I need help modifying the code below to look through the entire workbook searching for "$" instead of just one. I would love it if it could just search for CGYSR-"##". I have had help putting the code together as I am new to VBA
Here is the code:
Option Explicit
Sub FindPriceTagInformation()
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
'Fill in the search Value
MyArr = Array("$")
Set NewSh = Sheets("Sheet2")
With Sheets("CGYSR-3").Range("A1:ZZ300")
Rcount = 0
For I = LBound(MyArr) To UBound(MyArr)
Set Rng = .Find(What:=MyArr(I), _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
FirstAddress = Rng.Address
Do
Rcount = Rcount + 1
NewSh.Cells(Rcount, 3).Value = Rng.Value
NewSh.Cells(Rcount, 2).Value = Rng.Offset(-3, 0).Value
NewSh.Cells(Rcount, 1).Value = Rng.Offset(-5, 0).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
Please, try the next adapted code:
Sub FindPriceTagInformation()
Dim FirstAddress As String, MyArr, Rng As Range, Rcount As Long, I As Long
Dim ws As Worksheet, NewSh As Worksheet
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
'Fill in the search Value
MyArr = Array("$")
Set NewSh = Sheets("Sheet2")
Rcount = 0
For Each ws In ActiveWorkbook.Sheets
If left(ws.Name, 6) = "CGYSR-" Then
With ws.Range("A1:ZZ300")
For I = LBound(MyArr) To UBound(MyArr)
Set Rng = .Find(What:=MyArr(I), _
After:=.cells(.cells.count), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
FirstAddress = Rng.Address
Do
Rcount = Rcount + 1
NewSh.cells(Rcount, 3).value = Rng.value
NewSh.cells(Rcount, 2).value = Rng.Offset(-3, 0).value
NewSh.cells(Rcount, 1).value = Rng.Offset(-5, 0).value
Set Rng = .FindNext(Rng)
Loop While Not Rng Is Nothing And Rng.Address <> FirstAddress
End If
Next I
End With
End If
Next ws
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
Searching in Worksheets
In the workbook containing this code (ThisWorkbook), loops through each worksheet trying to identify the ones whose name starts with a given string (CGYSR-). Then it searches for a $ identifying cells with prices and retrieves these cell's values and the values of two other associated cells (3 and 5 cells above) and writes them to a row in another worksheet (Sheet2).
Option Explicit
Sub FindPriceTagInformation()
Const swsNameBegin As String = "CGYSR-"
Const srgAddress As String = "A1:ZZ300"
Const dwsName As String = "Sheet2"
Dim SearchStrings As Variant: SearchStrings = Array("$")
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Destination Worksheet
Dim dws As Worksheet: Set dws = wb.Worksheets(dwsName)
' You do it once here, so you don't have to do it many times in the loops.
Dim sCellsCount As Long: sCellsCount = dws.Range(srgAddress).Cells.Count
Dim npLen As String: npLen = Len(swsNameBegin)
Dim ssLower As Long: ssLower = LBound(SearchStrings)
Dim ssUpper As Long: ssUpper = UBound(SearchStrings)
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Dim sws As Worksheet ' Source Worksheet
Dim srg As Range ' Srouce Range
Dim sfCell As Range ' Source Found Cell
Dim slCell As Range ' Source Last Cell
Dim dr As Long ' Current Destination Row
Dim ss As Long ' Current Search String
Dim FirstAddress As String
For Each sws In wb.Worksheets
' A 'begins-with' ('Left') comparison where 'StrComp' will return 0 if
' the strings are equal. Combined with 'vbTextCompare', it will
' ignore case i.e. 'CG=cg'.
If StrComp(Left(sws.Name, npLen), swsNameBegin, vbTextCompare) = 0 Then
Set srg = sws.Range(srgAddress)
Set slCell = srg.Cells(sCellsCount) ' the same for all strings
For ss = ssLower To ssUpper
Set sfCell = srg.Find( _
What:=SearchStrings(ss), _
After:=slCell, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows)
If Not sfCell Is Nothing Then ' string was found
FirstAddress = sfCell.Address ' to prevent an endless loop
Do
' Write to the Destination Worksheet.
dr = dr + 1
dws.Cells(dr, 3).Value = sfCell.Value
dws.Cells(dr, 2).Value = sfCell.Offset(-3, 0).Value
dws.Cells(dr, 1).Value = sfCell.Offset(-5, 0).Value
' Find next string.
Set sfCell = srg.FindNext(sfCell)
' Note that in this case, 'sfCell' will never ever
' be 'Nothing' once it's 'something'. The 'Find' method
' doesn't 'know' where it found the first: it just finds
' the next even if it's the same (it goes round and round)
' i.e. if there is one cell to find,
' it will find it 'forever'.
' That's the reason behind comparing with the first address.
Loop While sfCell.Address <> FirstAddress
Set sfCell = Nothing ' reset for the next string
'Else ' string was not found
End If
Next ss
End If
Next sws
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
'Inform: useful for short and long operations.
MsgBox "Retrieved price tag information.", vbInformation
End Sub
I have this problem I can't seem to fix...
In column L I have certain roles, these roles are divided by || (pipes).
The problem: Some people deliver these roles they want to use like this:
Testing||Admin||Moderator||
But this doesn't work for the script we use to import these roles, what I would like to see is that whenever || (pipes) are used and after the pipes are used if there isn't any text following it up it should delete the pipes at the end.
What I tried is the find and replace option, but this also removes the pipes in between the text.
Hope someone can help me!
Problem:
Testing||Admin||Moderator||
Solution:
Testing||Admin||Moderator
A simple formula can solve your requirements
=IF(RIGHT(TRIM(A1),2)="||",LEFT(TRIM(A1),LEN(TRIM(A1))-2),A1)
The above formula is based on the below logic.
Check if the right 2 characters are ||
If "Yes", then take the left characters (LEN - 2)
If "No", then return the string as it is.
If you still want VBA then try this code which will make the change in the entire column in one go. Explanation about this method is given HERE.
For demonstration purpose, I am assuming that the data is in column A of Sheet1. Change as applicable.
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim lrow As Long
Dim rng As Range
Dim sAddr As String
Set ws = Sheet1
With ws
lrow = .Range("A" & .Rows.Count).End(xlUp).Row
Set rng = .Range("A1:A" & lrow)
sAddr = rng.Address
rng = Evaluate("index(IF(RIGHT(TRIM(" & sAddr & _
"),2)=""||"",LEFT(TRIM(" & sAddr & _
"),LEN(TRIM(" & sAddr & _
"))-2)," & sAddr & _
"),)")
End With
End Sub
In Action:
I only changed the name of the worksheet and the range to L and L2:L. – Ulquiorra Schiffer 17 mins ago
There are different ways of doing this, but here is one:
Function FixPipes(val As String) As String
Dim v As Variant
v = Split(val, "||")
If Len(v(UBound(v))) > 0 Then
FixPipes = val
Else
FixPipes = Mid$(val, 1, Len(val) - 2)
End If
End Function
Here's another way to do it:
Function FixPipes(val As String) As String
If Mid$(val, Len(val) - 1, 2) <> "||" Then
FixPipes = val
Else
FixPipes = Mid$(val, 1, Len(val) - 2)
End If
End Function
Usage:
Sub test()
Debug.Print FixPipes("Testing||Admin||Moderator||")
End Sub
Or:
Sub LoopIt()
' remove this line after verifying the sheet name
MsgBox ActiveSheet.Name
Dim lIndex As Long
Dim lastRow As Long
lastRow = Range("L" & Rows.Count).End(xlUp).Row
For lIndex = 1 To lastRow
Range("L" & lIndex) = FixPipes(Range("L" & lIndex))
Next
End Sub
https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/split-function
https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/mid-function
A tiny alternative using negative filtering would be:
Function FixPipes(ByVal s As String, Optional delim As String = "||") As String
Dim tmp: tmp = Filter(Split(s & "$$", delim), "$$", False)
FixPipes = Replace(Join(tmp, delim), "$$", "")
End Function
=IF(UNICODE(RIGHT(A2,1))+UNICODE(LEFT(RIGHT(A2,2),1))=248,LEFT(A2,LEN(A2)-2),A2)
Solution using the Replace formula, if you want to do this in VBA you can use the replace function in VBA as well
Remove Trailing String
All Except OP
This is a follow-up question on How to create data validation based on multiple roles?
.
The answers from Siddharth Rout and braX are valid for someone who might stumble upon this post.
They would have to be adjusted for OP because this case is 'clouded' by an already existing Worksheet_Change event.
OP (Ulquiorra)
To not complicate I have integrated a code snippet, which uses a function (similar to the posted solutions), into your existing code and removed Areas since it seems redundant after seeing what you are trying to accomplish.
The Snippet
Application.ScreenUpdating = False
Application.EnableEvents = False
Dim cel As Range
For Each cel In rng.Cells
cel.Value = removeTrail(cel.Value, Delimiter)
Next cel
Application.EnableEvents = True
The Function
Function removeTrail( _
ByVal SearchString As String, _
ByVal RemoveString As String, _
Optional ByVal doTrim As Boolean = True) _
As String
If doTrim Then
removeTrail = Trim(SearchString)
Else
removeTrail = SearchString
End If
If Right(removeTrail, Len(RemoveString)) = RemoveString Then
removeTrail = Left(removeTrail, Len(removeTrail) - Len(RemoveString))
End If
End Function
The Worksheet Change (modified)
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Const RolesList As String = "Admin,Clerk,Moderator,User"
Const FirstCellAddress As String = "L2"
Const Delimiter As String = "||"
Dim rng As Range
With Range(FirstCellAddress)
Set rng = Intersect(.Resize(.Worksheet.Rows.Count - .Row + 1), Target)
End With
If rng Is Nothing Then
Exit Sub
End If
' The Snippet
Application.ScreenUpdating = False
Application.EnableEvents = False
Dim cel As Range
For Each cel In rng.Cells
cel.Value = removeTrail(cel.Value, Delimiter)
Next cel
Application.EnableEvents = True
Dim Roles() As String: Roles = Split(RolesList, ",")
Dim dRng As Range
Dim aRng As Range
Dim Curr() As String
Dim cMatch As Variant
Dim n As Long
Dim isFound As Boolean
For Each cel In rng.Cells
If Not IsError(cel) Then
Curr = Split(cel.Value, Delimiter)
For n = 0 To UBound(Curr)
cMatch = Application.Match(Curr(n), Roles, 0)
If IsError(cMatch) Then
isFound = True
Exit For
Else
' Remove this block if you don't need case-sensitivity.
If StrComp(Curr(n), Roles(cMatch - 1), _
vbBinaryCompare) <> 0 Then
isFound = True
Exit For
End If
End If
Next n
If isFound Then
isFound = False
If dRng Is Nothing Then
Set dRng = cel
Else
Set dRng = Union(dRng, cel)
End If
End If
End If
Next cel
rng.Interior.Color = xlNone
If Not dRng Is Nothing Then
dRng.Interior.Color = vbRed
End If
Application.ScreenUpdating = True
End Sub
This is the piece of code I have in the worksheet change event (also module1) and also in the same active worksheet as module2:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Const RolesList As String = "Testing"
Const FirstCellAddress As String = "L2"
Const Delimiter As String = "||"
Dim rng As Range
With Range(FirstCellAddress)
Set rng = Intersect(.Resize(.Worksheet.rows.Count - .Row + 1), Target)
End With
If rng Is Nothing Then
Exit Sub
End If
Dim Roles() As String: Roles = Split(RolesList, ",")
Dim dRng As Range
Dim aRng As Range
Dim cel As Range
Dim Curr() As String
Dim cMatch As Variant
Dim n As Long
Dim isFound As Boolean
For Each aRng In rng.Areas
For Each cel In aRng.Cells
If Not IsError(cel) Then
Curr = Split(cel.Value, Delimiter)
For n = 0 To UBound(Curr)
cMatch = Application.Match(Curr(n), Roles, 0)
If IsError(cMatch) Then
isFound = True
Exit For
Else
If StrComp(Curr(n), Roles(cMatch - 1), _
vbBinaryCompare) <> 0 Then
isFound = True
Exit For
End If
End If
Next n
If isFound Then
isFound = False
If dRng Is Nothing Then
Set dRng = cel
Else
Set dRng = Union(dRng, cel)
End If
End If
End If
Next cel
Next aRng
Application.ScreenUpdating = False
rng.Interior.Color = xlNone
If Not dRng Is Nothing Then
dRng.Interior.Color = vbRed
End If
Application.ScreenUpdating = True
End Sub
I did put your code inside a module2 and also in an active worksheet:
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim lrow As Long
Dim rng As Range
Dim sAddr As String
Set ws = Sheet1
With ws
lrow = .Range("L" & .Rows.Count).End(xlUp).Row
Set rng = .Range("L2:L" & lrow)
sAddr = rng.Address
rng = Evaluate("index(IF(RIGHT(TRIM(" & sAddr & _
"),2)=""||"",LEFT(TRIM(" & sAddr & _
"),LEN(TRIM(" & sAddr & _
"))-2)," & sAddr & _
"),)")
End With
End Sub
For some reason, module2 won't work I suspect module1 to interfere with it indeed but can't find a solution.
My whole code looks like this:
Sub AllInOne()
Application.EnableEvents = True
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Range("F2:F" & Cells(rows.Count, "F").End(xlUp).Row).Copy Destination:=Range("J2")
Range("F2:F" & Cells(rows.Count, "F").End(xlUp).Row).Copy Destination:=Range("K2")
ActiveSheet.Hyperlinks.Delete
For Each rng In Range("F2:F" & Cells(rows.Count, "F").End(xlUp).Row): rng.Value = LCase(rng.Value): Next rng
For Each rng In Range("K2:K" & Cells(rows.Count, "K").End(xlUp).Row): rng.Value = LCase(rng.Value): Next rng
For Each rng In Range("J2:J" & Cells(rows.Count, "J").End(xlUp).Row): rng.Value = LCase(rng.Value): Next rng
Dim cell As Range
lastRow = ActiveSheet.Cells(ActiveSheet.rows.Count, "C").End(xlUp).Row
For Each cell In ActiveSheet.Range("C2:C" & lastRow)
S = vbNullString
If cell.Value <> vbNullString Then
v = Split(cell.Value, " ")
For Each W In v
S = S & Left$(W, 1) & "."
Next W
cell.Offset(ColumnOffset:=-1).Value = S
End If
Next cell
Application.Range("B1").Value = "tesing"
Worksheets("Sheet1").Range("B1").Font.Bold = True
Columns("D").Replace What:="vander", _
Replacement:="van der", _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
MatchCase:=False, _
SearchFormat:=False, _
ReplaceFormat:=False
Columns("D").Replace What:="vanden", _
Replacement:="van den", _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
MatchCase:=False, _
SearchFormat:=False, _
ReplaceFormat:=False
Columns("B").Replace What:="..", _
Replacement:=".", _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
MatchCase:=False, _
SearchFormat:=False, _
ReplaceFormat:=False
Dim r As Range
For Each r In ActiveSheet.UsedRange
If Not IsError(r.Value) Then
v = r.Value
If v <> vbNullString Then
If Not r.HasFormula Then
r.Value = Trim(v)
End If
End If
End If
Next r
Dim i As Long
Dim DelRange As Range
On Error GoTo Whoa
Application.ScreenUpdating = False
For i = 1 To 50
If Application.WorksheetFunction.CountA(Range("A" & i & ":" & "Z" & i)) = 0 Then
If DelRange Is Nothing Then
Set DelRange = Range("A" & i & ":" & "Z" & i)
Else
Set DelRange = Union(DelRange, Range("A" & i & ":" & "Z" & i))
End If
End If
Next i
If Not DelRange Is Nothing Then DelRange.Delete shift:=xlUp
LetsContinue:
Application.ScreenUpdating = True
Exit Sub
Whoa:
MsgBox Err.Description
Resume LetsContinue
Worksheets("Sheet1").Columns("L").Replace _
What:=" ", _
Replacement:="", _
SearchOrder:=xlByColumns, _
MatchCase:=True
Application.EnableEvents = True
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Const RolesList As String = "Testing"
Const FirstCellAddress As String = "L2"
Const Delimiter As String = "||"
Dim rng As Range
With Range(FirstCellAddress)
Set rng = Intersect(.Resize(.Worksheet.rows.Count - .Row + 1), Target)
End With
If rng Is Nothing Then
Exit Sub
End If
Dim Roles() As String: Roles = Split(RolesList, ",")
Dim dRng As Range
Dim aRng As Range
Dim cel As Range
Dim Curr() As String
Dim cMatch As Variant
Dim n As Long
Dim isFound As Boolean
For Each aRng In rng.Areas
For Each cel In aRng.Cells
If Not IsError(cel) Then
Curr = Split(cel.Value, Delimiter)
For n = 0 To UBound(Curr)
cMatch = Application.Match(Curr(n), Roles, 0)
If IsError(cMatch) Then
isFound = True
Exit For
Else
If StrComp(Curr(n), Roles(cMatch - 1), _
vbBinaryCompare) <> 0 Then
isFound = True
Exit For
End If
End If
Next n
If isFound Then
isFound = False
If dRng Is Nothing Then
Set dRng = cel
Else
Set dRng = Union(dRng, cel)
End If
End If
End If
Next cel
Next aRng
Application.ScreenUpdating = False
rng.Interior.Color = xlNone
If Not dRng Is Nothing Then
dRng.Interior.Color = vbRed
End If
Application.ScreenUpdating = True
End Sub
I am trying to insert a blank row above a row that contains a specific word. But so far I can only insert it below this row.
Sub INSERTROW()
Dim c As Range
Dim lRow As Long
lRow = 1
Dim lRowLast As Long
Dim bFound As Boolean
With ActiveSheet
lRowLast = .Cells(.Rows.Count, 1).End(xlUp).Row
Do
Set c = .Range("A" & lRow)
If c.Value Like "*SEARCHED VALUE*" Then
bFound = True
ElseIf bFound Then
bFound = False
If c.Value <> "BLANKROW" Then
c.EntireRow.Insert
lRowLast = lRowLast + 1
c.Offset(-1, 0).Value = "BLANKROW"
c.Offset(-1, 0).Font.Color = RGB(0, 0, 0)
End If
End If
lRow = lRow + 1
Loop While lRow <= lRowLast + 1
End With
End Sub
It's easier and faster (AFAIK) if you use the find method.
See that I insert the row where the value is found and then I refer to the previous row with the offset function.
Finally, as a good practice, try to name your procedures and variables to something meaningful and indent your code (you may use www.rubberduckvba.com)
Public Sub InsertRowBeforeWord()
Dim findString As String
findString = "*SEARCHED VALUE*"
Dim lastRow As Long
lastRow = ActiveSheet.Cells(ActiveSheet.Rows.Count, 1).End(xlUp).Row
Dim searchRange As Range
Set searchRange = ActiveSheet.Range("A1:A" & lastRow)
Dim returnRange As Range
Set returnRange = searchRange.Find(What:=findString, _
After:=searchRange.Cells(searchRange.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not returnRange Is Nothing Then
returnRange.Offset(0, 0).EntireRow.Insert
returnRange.Offset(-1, 0).Value = "BLANKROW"
returnRange.Offset(-1, 0).Font.Color = RGB(0, 0, 0)
End If
End Sub
Let me know if it works.
I have this code, but I'd like for it to find two adjacent cells with the values 7 and 2 (7 first in every pair) in column A and offset (from the 7) to the next column and insert a value to a specific row range.
Sub mark()
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("X")
With Sheets("Sheet1").Range("A:A")
.Offset(0, 1).ClearContents
For I = LBound(MyArr) To UBound(MyArr)
Set Rng = .Find(What:=MyArr(I), _
After:=.Cells(.Cells.Count), _
LookIn:=xlFormulas, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
FirstAddress = Rng.Address
Do
Rng.Offset(0, 1).Value = "X"
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
Any suggestions appreciated.
Please try this code. I have expanded it to provide for specifying different results to be inserted at the found location.
Sub Mark2()
' 14 Feb 2018
Dim Ws As Worksheet
Dim Crits() As Variant
Dim Fun() As Variant
Dim MarkRng As Range
Dim R As Long
Dim i As Long
Dim Count As Integer
Set Ws = Worksheets("FindPair") ' replace with actual name
Crits = Array(7, 2, 13, 3, 17, 4) ' 1st, 2nd, 1st, 2nd, 1st, 2nd criterium
' Match the ranges in Fun() to the targets in Crits()
' 2 ranges for each Crit, each range 1 or more cells
' Omitted ranges must be represented by a comma
' Fun ranges specified in excess of available space will be ignored
' (for example, A32 + B28:B32 = 6 cells but MarkRng has only 5 cells)
Fun = Array("A32", "B28:B32", "A33:A35", "B33:B34", , "B100:B104")
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
For i = LBound(Crits) To UBound(Crits) Step 2
Count = 0
Do
R = MatchRow(Crits(i), Ws, (R = 0))
If R Then
With Ws
If .Cells(R + 1, 1).Value = Crits(i + 1) Then
' column 2 = column B
Set MarkRng = Range(.Cells(R, 2), .Cells(R + 5, 2))
WriteResult i, Fun, MarkRng
Count = Count + 1
End If
End With
Else
If Count = 0 Then
MsgBox "No match was found for " & Crits(i), _
vbInformation, "Failure advice"
End If
Exit Do
End If
Loop
Next i
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
Private Function MatchRow(ByVal Crit As Variant, _
Ws As Worksheet, _
ByVal NewSearch As Boolean) As Long
' 13 Feb 2018
Static Rng As Range
Static Rstart As Long
Static Rend As Long
Dim Fnd As Range
With Ws
If NewSearch Then
Rstart = 2 ' start search in row 2
' find last used row
Rend = .Cells(.Rows.Count, 1).End(xlUp).Row
End If
Set Rng = Range(.Cells(Rstart, 1), .Cells(Rend, 1))
End With
With Rng
Set Fnd = .Find(What:=Crit, _
After:=.Cells(.Cells.Count), _
LookIn:=xlFormulas, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
End With
If Not Fnd Is Nothing Then
MatchRow = Fnd.Row
Rstart = Fnd.Row + 1
End If
End Function
Private Sub WriteResult(ByVal Ix As Long, _
Fun() As Variant, _
Target As Range)
' 14 Feb 2018
Dim Ws As Worksheet
Dim Rng As Range, R As Long ' source
Dim Rt As Long
Dim i As Long
With Target
Set Ws = .Worksheet
For i = 0 To 1
If Not IsError(Fun(Ix + i)) Then
Set Rng = Ws.Range(Fun(Ix + i))
For R = 1 To Rng.Cells.Count
If Rt < .Cells.Count Then
Rt = Rt + 1
.Cells(Rt).Value = Rng.Cells(R).Value
End If
Next R
End If
Next i
End With
End Sub
I want to find a specific word in a range of cells then highlight it in red. To do so I created this code but it just worked on one line and highlighted all the cell text:
Sub Find_highlight()
Dim ws As Worksheet
Dim match As Range
Dim findMe As String
Set ws = ThisWorkbook.Sheets("MYSHEET")
findMe = "Background"
Set match = ws.Range("G3:G1362").Find(findMe)
match.Font.Color = RGB(255, 0, 0)
End Sub
Let's say your excel file looks like htis
To color specific word, you have to use the cell's .Characters property. You need to find where does the word start from and then color it.
Try this
Option Explicit
Sub Sample()
Dim sPos As Long, sLen As Long
Dim aCell As Range
Dim ws As Worksheet
Dim rng As Range
Dim findMe As String
Set ws = ThisWorkbook.Sheets("MYSHEET")
Set rng = ws.Range("G3:G1362")
findMe = "Background"
With rng
Set aCell = .Find(What:=findMe, LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
sPos = InStr(1, aCell.Value, findMe)
sLen = Len(findMe)
aCell.Characters(Start:=sPos, Length:=sLen).Font.Color = RGB(255, 0, 0)
End If
End With
End Sub
OUTPUT
i made some change to be more general and accurate
Option Explicit
Sub HIGHLIGHTER()
Dim sPos As Long, sLen As Long
Dim rng As Range
Dim findMe As String
Dim i As Integer
Set rng = Application.InputBox(Prompt:= _
"Please Select a range", _
Title:="HIGHLIGHTER", Type:=8)
findMe = Application.InputBox(Prompt:= _
"FIND WHAT?(YOU CAN USE PATTERN USED IN LIKE OPERATOR ", _
Title:="HIGHLIGHTER", Type:=2)
For Each rng In rng
With rng
If rng.Value Like "*" & findMe & "*" Then
If Not rng Is Nothing Then
For i = 1 To Len(rng.Value)
sPos = InStr(i, rng.Value, findMe)
sLen = Len(findMe)
If (sPos <> 0) Then
rng.Characters(Start:=sPos, Length:=sLen).Font.Color = RGB(255, 0, 0)
i = sPos + Len(findMe) - 1
End If
Next i
End If
End If
End With
Next rng
End Sub
added an option to loop
Option Explicit
Sub Macro1()
Dim sPos As Long, sLen As Long
Dim aCell As Range
Dim ws As Worksheet
Dim rng As Range
Dim findMe As String
Set ws = ThisWorkbook.Sheets("Sheet2")
Set rng = ws.Range("A3:A322")
findMe = "find"
For Each rng In Selection
With rng
Set aCell = .Find(What:=findMe, LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
sPos = InStr(1, aCell.Value, findMe)
sLen = Len(findMe)
aCell.Characters(Start:=sPos, Length:=sLen).Font.Color = RGB(0, 255, 0)
End If
End With
Next rng
End Sub
I too made some changes to allow for searching multiple words at the same time. I also took away the prompts and hard coded the search words. The only issue left is to make the search non-case sensitive...
Sub HIGHLIGHTER()
Dim sPos As Long, sLen As Long
Dim rng As Range
Dim findMe As String
Dim i As Integer
Dim t As Integer
Dim SearchArray
SearchArray = Array("WORD1", "WORD2")
For t = 0 To UBound(SearchArray)
Set rng = Range("N2:N10000")
findMe = SearchArray(t)
For Each rng In rng
With rng
If rng.Value Like "*" & findMe & "*" Then
If Not rng Is Nothing Then
For i = 1 To Len(rng.Value)
sPos = InStr(i, rng.Value, findMe)
sLen = Len(findMe)
If (sPos <> 0) Then
rng.Characters(Start:=sPos, Length:=sLen).Font.Color = RGB(255, 0, 0)
rng.Characters(Start:=sPos, Length:=sLen).Font.Bold = True
i = sPos + Len(findMe) - 1
End If
Next i
End If
End If
End With
Next rng
Next t
End Sub