Find two consecutive numbers - excel

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

Related

VBA excel search tool

Tried doing a search tool to the excel sheet (VBA) I'm working on.
So far every time I search for the text, it ends up filtering only the first row and not any row that has the value I'm looking for. I added a picture to show what it returns and the code as well. Is there anything I need to change to the code to make it search for all the data in the sheet instead of having it to show only one row? Any help is appreciated.
Search result of only the first row:
Sub SearchAllSheets()
Dim ws As Worksheet, OutputWs As Worksheet
Dim rFound As Range
Dim strName As String
Dim count As Long, LastRow As Long
Dim IsValueFound As Boolean
IsValueFound = False
Set OutputWs = Worksheets("sheet1") '---->change the sheet name as required
LastRow = OutputWs.Cells(Rows.count, "A").End(xlUp).Row
On Error Resume Next
strName = InputBox("What are you looking for?")
If strName = "" Then Exit Sub
For Each ws In Worksheets
If ws.Name <> "Output" Then
With ws.UsedRange
Set rFound = .Find(What:=strName, After:=.Cells(1, 1), LookIn:=xlValues, LookAt:=xlWhole)
If Not rFound Is Nothing Then
Application.Goto rFound, True
IsValueFound = True
'MsgBox rFound.Row
rFound.EntireRow.Copy
OutputWs.Cells(LastRow + 1, 1).PasteSpecial xlPasteAll
Application.CutCopyMode = False
LastRow = LastRow + 1
End If
End With
End If
Next ws
On Error GoTo 0
If IsValueFound Then
OutputWs.Select
MsgBox "Result pasted to Sheet Output"
Else
MsgBox "Value not found"
End If
End Sub
Try this:
Sub SearchAllSheets()
Dim ws As Worksheet, OutputWs As Worksheet
Dim rFound As Range, IsValueFound As Boolean
Dim strName As String
Dim count As Long, LastRow As Long
Set OutputWs = Worksheets("Output") '---->change the sheet name as required
LastRow = OutputWs.Cells(Rows.count, "A").End(xlUp).row
strName = Trim(InputBox("What are you looking for?"))
If strName = "" Then Exit Sub
For Each ws In Worksheets
If ws.Name <> OutputWs.Name Then
Debug.Print "Checking " & ws.Name
Set rFound = FindAll(ws.UsedRange, strName)
If Not rFound Is Nothing Then
Set rFound = rFound.EntireRow
count = rFound.Cells.count / Columns.count 'how many matched rows?
Debug.Print "Found " & count & " rows"
rFound.Copy OutputWs.Cells(LastRow + 1, 1)
LastRow = LastRow + count
IsValueFound = True
End If
End If
Next ws
If IsValueFound Then
OutputWs.Select
MsgBox "Result(s) pasted to Sheet " & OutputWs.Name
Else
MsgBox "Value not found"
End If
End Sub
'find all cells in range `rng` with value `val` and return as a range
Public Function FindAll(rng As Range, val As String) As Range
Dim rv As Range, f As Range
Dim addr As String
Set f = rng.Find(what:=val, After:=rng.Cells(rng.Cells.count), _
LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False)
If Not f Is Nothing Then addr = f.Address()
Do Until f Is Nothing
If rv Is Nothing Then
Set rv = f
Else
Set rv = Application.Union(rv, f)
End If
Set f = rng.FindNext(After:=f)
If f.Address() = addr Then Exit Do
Loop
Set FindAll = rv
End Function

Need help searching entire workbook and not just a single sheet

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

find and select the finding until the next find

Basically, I'm writing a code that finds text in a Master sheet, I am looking for "Admin" after finding the admin I need to select from this cell unit next find and paste in separate sheets.
I tried different ways but now work, any suggestions?
Example
Sub FindNext_Example()
Dim FindValue As String
FindValue = "Bangalore"
Dim Rng As Range
Set Rng = Range("A2:A11")
Dim FindRng As Range
Set FindRng = Rng.Find(What:=FindValue)
Dim FirstCell As String
FirstCell = FindRng.Address
Do
Range(FristCell).Select
Selection.Copy
Worksheets.Add
ActiveSheet.Paste
Sheets("Sheet0").Select
Set FindRng = Rng.FindNext(FindRng)
Loop While FirstCell <> FindRng.Address
MsgBox "Search is over"
End Sub
Example
Example of finding and select the find row until next find
paste in new sheet
next find
until the end
Try this code:
Sub SubChopList()
'Declarations.
Dim DblColumnOffset As Double
Dim RngSource As Range
Dim RngSearch As Range
Dim RngTop As Range
Dim RngBottom As Range
Dim StrSearch As String
Dim StrDestinationAddress As String
Dim WksSource As Worksheet
'Settings.
Set WksSource = ActiveSheet
Set RngSource = WksSource.Range("A1")
Set RngSource = Range(RngSource, RngSource.End(xlDown).End(xlToRight))
'Setting DblColumnOffset equal to the offset from the first column of RngSource and the column to be searched.
DblColumnOffset = 2
'Setting the column to be searched.
Set RngSearch = RngSource.Columns(1).Offset(0, DblColumnOffset)
'Setting the value to be searched.
StrSearch = "Admin"
'Setting the address of the cell where the data will be pasted in the new sheets.
StrDestinationAddress = "A1"
'Setting RngTop as the first cell that contains StrSearch after the first cell of RngSearch.
Set RngTop = RngSearch.Find(What:=StrSearch, _
After:=RngSearch.Cells(1, 1), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False _
)
'Setting RngBottom as the cell in the row upon the first cell that contains StrSearch after RngTop.
Set RngBottom = RngSearch.Find(What:=StrSearch, _
After:=RngTop, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False _
).Offset(-1, 0)
'Repeating until the last block is reached.
Do
'Creating a new sheet.
Worksheets.Add
'Copy-pasting the block delimited by RngTop and RngBottom in the new sheet at the address specified in StrDestinationAddress.
WksSource.Range(RngTop, RngBottom).Offset(0, -DblColumnOffset).Resize(, RngSource.Columns.Count).Copy Range(StrDestinationAddress)
'Setting RngTop as the first cell that contains StrSearch after RngBottom.
Set RngTop = RngSearch.Find(What:=StrSearch, _
After:=RngBottom, _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False _
)
'Setting RngBottom as the cell in the row upon the first cell that contains StrSearch after RngTop.
Set RngBottom = RngSearch.Find(What:=StrSearch, _
After:=RngTop, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False _
).Offset(-1, 0)
Loop Until RngTop.Row > RngBottom.Row
'Reporting the last block as did for all the previous blocks in the Do Loop cycle.
Set RngBottom = RngSearch.Cells(RngSearch.Rows.Count, 1)
Worksheets.Add
WksSource.Range(RngTop, RngBottom).Offset(0, -DblColumnOffset).Resize(, RngSource.Columns.Count).Copy Range(StrDestinationAddress)
End Sub
Select the sheet with the data you want to chop and run it.
Create Criteria Worksheets
Adjust the values in the constants section.
The Code
Option Explicit
Sub addCriteriaWorksheets()
Const wsName As String = "Sheet1"
Const sCellAddress As String = "A1"
Const Criteria As String = "Admin*"
Const CriteriaColumn As Long = 3
Const dCellAddress As String = "A1"
Dim wb As Workbook: Set wb = ThisWorkbook
Application.ScreenUpdating = False
With wb.Worksheets(wsName).Range(sCellAddress).CurrentRegion
.Worksheet.AutoFilterMode = False
.AutoFilter CriteriaColumn, Criteria
Dim rg As Range
On Error GoTo SpecialCellsError
Set rg = .Columns(CriteriaColumn).Resize(.Rows.Count - 1).Offset(1) _
.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
Dim nCount As Long: nCount = rg.Cells.Count
Dim Coord As Variant: ReDim Coord(1 To nCount, 1 To 3)
Dim arg As Range
Dim cel As Range
Dim n As Long
For Each arg In rg.Areas
For Each cel In arg.Cells
n = n + 1
Coord(n, 1) = cel.Row
If n > 1 Then
Coord(n - 1, 2) = Coord(n, 1) - 1
Coord(n - 1, 3) = Coord(n - 1, 2) - Coord(n - 1, 1) + 2
End If
Next cel
Next arg
n = n + 1
Coord(n - 1, 2) = .Rows.Count
Coord(n - 1, 3) = Coord(n - 1, 2) - Coord(n - 1, 1) + 2
.Worksheet.AutoFilterMode = False
Dim cCount As Long: cCount = .Columns.Count
Dim Data As Variant: Data = .Value
Dim Result As Variant
Dim i As Long, j As Long, k As Long
For n = 1 To nCount
ReDim Result(1 To Coord(n, 3), 1 To cCount)
For j = 1 To cCount
Result(1, j) = Data(1, j)
Next j
k = 1
For i = Coord(n, 1) To Coord(n, 2)
k = k + 1
For j = 1 To cCount
Result(k, j) = Data(i, j)
Next j
Next i
With wb.Worksheets.Add(After:=wb.Sheets(wb.Sheets.Count))
.Range(dCellAddress).Resize(k, cCount).Value = Result
End With
Next n
.Worksheet.Select
End With
ProcExit:
Application.ScreenUpdating = True
Exit Sub
SpecialCellsError:
Resume ProcExit
End Sub

Remove || (pipes) at the end of text inside a column

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

Insert row before over a row containing a word vba excel

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.

Resources