Filling a specific column based on user inputs and tracking result - excel

I have range of products that are routinely tested every quarter, each product is tested once annually.
I need an excel VBA that prompts the user to input what product was tested and then prompt the user to input in which quarter (e.g. Q1,Q2 etc ) the product was tested. Then in a specific column this information about which quarter the product is tested is displayed and inputted into a cell.
I then want to be able to keep track of this information about which quarter each product was tested every year so for the next test for each product, would like excel to fill the row next to it. Shown below is an visual example of what I'm trying to achieve.
Example of Excel Worksheet
Also attached is the code I have been trying mould to fit my problem.
Dim myValue As Variant
myValue = InputBox("Give me some input")
Dim SearchString As String
Dim SearchRange As Range, cl As Range
Dim FirstFound As String
Dim sh As Worksheet
' Set Search value
SearchString = myValue
Application.FindFormat.Clear
' loop through all sheets
For Each sh In ActiveWorkbook.Worksheets
' Find first instance on sheet
Set cl = sh.Cells.Find(What:=SearchString, _
After:=sh.Cells(1, 1), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
If Not cl Is Nothing Then
' if found, remember location
FirstFound = cl.Address
' format found cell
Do
cl.Font.Bold = True
cl.Interior.ColorIndex = 3
' find next instance
Set cl = sh.Cells.FindNext(After:=cl)
' repeat until back where we started
Loop Until FirstFound = cl.Address
End If
Next
End Sub

In your code you have this line to get the product
myValue = InputBox("Give me some input")
Just add another line to get the Quarter
myValue2 = InputBox("Give me some more input")
The search command is working correctly although it could be made more efficient by restricting the search to the first column not the whole sheet.
Set cl = sh.Cells.Find(What:=SearchString, _
After:=sh.Cells(1, 1), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
To match the whole string rather than a part change the parameter LookAt:=xlWhole.
If you only have one product that matches the user input then this code can be deleted.
Do
cl.Font.Bold = True
cl.Interior.ColorIndex = 3
' find next instance
Set cl = sh.Cells.FindNext(After:=cl)
' repeat until back where we started
Loop Until FirstFound = cl.Address
The row number is found simply with
rowno = cl.Row
The next part you seem to be having difficulty with is locating the next available
blank column in that row. The VBA is as a user would do by using Ctrl-CursorLeft
from the end column.
colno = ws.range(rowno,Columns.count).End(xlToLeft.Column +1
Since it's very unlikely your sheet will span more 702 years this might be clearer
colno = ws.range("ZZ" & rowno).End(xlToLeft).Column + 1
Now update that cell
wc.cell(rowno,colno) = Value2
Put those components together using sensible variable names, add some validation on what the user is entering, insert some debugging messages at critical points and you should get something like this ;
Sub enterdata()
Const DBUG As Boolean = False ' set to TRUE to see each step
Const YR1COL = 5 'E
Dim wb As Workbook, ws As Worksheet
Set wb = ThisWorkbook
Dim sProduct As String
Dim iRowno As Long, iQu As Integer, iColno As Integer
Dim rng As Range, iLastRow As Long, wsMatch As Worksheet, cellMatch As Range
Dim chances As Integer: chances = 3
LOOP1: ' get valid product
sProduct = InputBox(Title:="Input Product", prompt:="Product is ")
If DBUG Then Debug.Print sProduct
If Len(sProduct) > 0 Then
' search through all sheets
For Each ws In wb.Sheets
iLastRow = ws.Range("A" & ws.Rows.count).End(xlUp).Row
If DBUG Then Debug.Print ws.Name & " " & iLastRow
' Search col A of sheet using xlWhole for exact match
Set rng = ws.Range("A2:A" & iLastRow) ' avoid header
Set cellMatch = rng.Find( _
What:=sProduct, _
After:=rng.Cells(2, 1), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
' exit on first match
If Not cellMatch Is Nothing Then
Set wsMatch = ws
GoTo LOOP2
End If
Next
Else
Exit Sub
End If
' no match so try again
If cellMatch Is Nothing Then
chances = chances - 1
If chances < 1 Then
MsgBox "Too many tries", vbCritical, "Exiting"
Exit Sub
End If
MsgBox sProduct & " NOT FOUND - " & chances & " tries left", vbExclamation, "Error"
GoTo LOOP1
End If
LOOP2:
iRowno = cellMatch.Row
If DBUG Then Debug.Print wsMatch.Name & " Row = " & iRowno
' determine column
With wsMatch
iColno = .Cells(iRowno, Columns.count).End(xlToLeft).Column + 1
If iColno < YR1COL Then iColno = YR1COL ' start in E
End With
wsMatch.Activate
wsMatch.Cells(iRowno, iColno).Select
If DBUG Then
wsMatch.Cells(iRowno, iColno).Interior.ColorIndex = 6 ' yellow
Debug.Print "Column = " & iColno
End If
If DBUG Then MsgBox "Target cell " & wsMatch.Name & " Row " & iRowno & " Col " & iColno, vbInformation
chances = 3
LOOP3: ' get valid QU
iQu = Application.InputBox(Title:="Input Quarter", prompt:="Test Qu (1-4) for " & sProduct, Type:=1) ' type 1 number
If iQu = 0 Then
GoTo LOOP1
ElseIf iQu > 4 Then
chances = chances - 1
If chances < 1 Then
MsgBox "Too many tries", vbExclamation, "Error"
Exit Sub
End If
MsgBox iQu & " NOT VALID - " & chances & " tries left", vbExclamation, "Error"
GoTo LOOP3
End If
' Update sheet
wsMatch.Cells(iRowno, iColno) = iQu
If DBUG Then wsMatch.Cells(iRowno, iColno).Interior.ColorIndex = 4 ' green
MsgBox "Product=" & sProduct & vbCr _
& wsMatch.Name & " Row=" & iRowno & " Col=" & iColno & " Qu=" & iQu, vbInformation, "Updated"
GoTo LOOP1 ' next product
End Sub

Related

Locating all the tables on one spreadsheet using Excel VBA

I have a few spreadsheets with various tables in different formats. My task is to locate and identify anything on the spreadsheets that can be considered a table, and flatten it into a text file. Currently I am only looking for a solution to locate all tables on one spreadsheet.
The rules are:
Spreadsheet format is somewhat fixed, I have to process what I am given.
A completely empty line can split a table into two, unless there's a sure way to tell what is a missing line within one table and what is an actual new table.
I can handle merged fields beforehand if needs be (split them and backfill with the common value, that's already written and is working)
The tables could have a different number of columns, different header rows, and they could begin in any column.
I consider records in the same line to be part of the same table, I am not expecting to find tables next to one another.
The code I have so far as follows:
Sub Find_All_Tables()
'Finds all the separate tables in the worksheet
Dim rStart As Range, rFoundStart As Range, rFoundEnd As Range
Dim lRow As Long, lCol As Long
lRow = Cells.Find(What:="*", _
After:=Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
lCol = Cells.Find(What:="*", _
After:=Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
MsgBox "Last non-empty cell on the spreadsheet is " & Cells(lRow, lCol).Address
Set rStart = Range("A1")
MsgBox rStart.Row
While rStart.Row < lRow
On Error Resume Next
Set rFoundStart = Cells.Find(What:="*", _
After:=rStart, _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
On Error GoTo 0
If rFoundStart Is Nothing Then
MsgBox "All cells are blank."
Else
rFoundStart.End(xlToRight).End(xlDown).Select
Set rFoundEnd = Selection
'MsgBox "First Cell: " & rFoundStart.Address
'MsgBox "Last Cell: " & ActiveCell.Address
Range(rFoundStart.Address, rFoundEnd.Address).Select
MsgBox "There is a table between " & rFoundStart.Address & " and " & rFoundEnd.Address
End If
Set rStart = Range("A" & rFoundEnd.Row + 1)
Wend
End Sub
The sample sheet I am looking at is as messy as possible to account for "creative" formatting.
The error I'm getting is due to the fact that the second table starts from B7 and ends in E1048576, which is well past the loop condition - I would like this range to end in E8 (or E9 if possible or once the merged cells are broken up).
I've got this code from way back when.... 2008.
No idea if it works with ListObject tables.
Original MrExcel post: Find all lists in a workbook
Sub Test()
Dim aLists As Variant
Dim aLists1 As Variant
'//Find lists in a different workbook.
'' aLists = FindRegionsInWorkbook(Workbooks("Test Workbook.xls"))
'//Find lists in the this workbook.
aLists1 = FindRegionsInWorkbook(ThisWorkbook)
Debug.Assert False
End Sub
'//Returns each region in each worksheet within the workbook in the 'sRegion' variable.
'//
'//Written by Zack Barresse (MVP), Oregon, USA.
'//
'//http://www.mrexcel.com/forum/showthread.php?t=309052
Public Function FindRegionsInWorkbook(wrkBk As Workbook) As Variant
Dim ws As Worksheet, rRegion As Range, sRegion As String, sCheck As String
Dim sAddys As String, arrAddys() As String, aRegions() As Variant
Dim iCnt As Long, i As Long, j As Long
'//Cycle through each worksheet in workbook.
j = 0
For Each ws In wrkBk.Worksheets
sAddys = vbNullString
sRegion = vbNullString
On Error Resume Next
'//Find all ranges of constant & formula valies in worksheet.
sAddys = ws.Cells.SpecialCells(xlCellTypeConstants, 23).Address(0, 0) & ","
sAddys = sAddys & ws.Cells.SpecialCells(xlCellTypeFormulas, 23).Address(0, 0)
If Right(sAddys, 1) = "," Then sAddys = Left(sAddys, Len(sAddys) - 1)
On Error GoTo 0
If sAddys = vbNullString Then GoTo SkipWs
'//Put each seperate range into an array.
If InStr(1, sAddys, ",") = 0 Then
ReDim arrAddys(1 To 1, 1 To 2)
arrAddys(1, 1) = ws.Name
arrAddys(1, 2) = sAddys
Else
arrAddys = Split(sAddys, ",")
For i = LBound(arrAddys) To UBound(arrAddys)
arrAddys(i) = "'" & ws.Name & "'!" & arrAddys(i)
Next i
End If
'//Place region that range sits in into sRegion (if not already in there).
For i = LBound(arrAddys) To UBound(arrAddys)
If InStr(1, sRegion, ws.Range(arrAddys(i)).CurrentRegion.Address(0, 0)) = 0 Then
sRegion = sRegion & ws.Range(arrAddys(i)).CurrentRegion.Address(0, 0) & "," '*** no sheet
sCheck = Right(arrAddys(i), Len(arrAddys(i)) - InStr(1, arrAddys(i), "!"))
ReDim Preserve aRegions(0 To j)
aRegions(j) = Left(arrAddys(i), InStr(1, arrAddys(i), "!") - 1) & "!" & ws.Range(sCheck).CurrentRegion.Address(0, 0)
j = j + 1
End If
Next i
SkipWs:
Next ws
On Error GoTo ErrHandle
FindRegionsInWorkbook = aRegions
Exit Function
ErrHandle:
'things you might want done if no lists were found...
End Function

VBA filtering list using another list

I'm trying to filter the ID in a table, using IDs from another list. However, when I try to do so the macro only filters the first value in the list.
Table Format
Code:
Sub Test()
Dim wb As Workbook
Set wb = ThisWorkbook
ActiveSheet.AutoFilterMode = False
Workbooks.Open "C:\List.xlsx"
Criteria = Worksheets("DataArray").Range("A3:A103")
wb.Activate
ActiveSheet.Range("$A$8:$BE$5000").AutoFilter Field:=3, Criteria1:=Criteria, Operator:=xlFilterValues
End Sub
The "List" is in another workbook so I need the macro to open it first.
When I try changing the Range to A4:A103 the filter will just use the A4 (first value in the range).
Try the next way, please:
Dim Crit As Variant
Set Crit = Worksheets("DataArray").Range("A3:A103").Value
ActiveSheet.Range("$A$8:$BE$5000").AutoFilter Field:=3, Criteria1:=Application.Transpose(Crit), Operator:=xlFilterValues
The column list must be transposed on a row. Otherwise, only its first element will be used.
You can do all this by selecting the ranges (directly in the Excel interface). The following code is reusable:
Option Explicit
Public Sub FilterBySelection()
Dim rngFirst As Range
Dim rngSecond As Range
'
'Get Ranges from User Selection
Set rngFirst = GetRangeBySelection("Select range to filter!" _
& vbNewLine & "Please select a single continuous range!" _
& vbNewLine & vbNewLine & "Note that by selecting a single cell, your" _
& " selection will default to the current region for that cell!" _
, "Select Range")
If rngFirst Is Nothing Then Exit Sub
'
Set rngSecond = GetRangeBySelection("Select range containing filtering values!" _
& vbNewLine & "Please select a single continuous range!" _
& vbNewLine & vbNewLine & "Note that by selecting a single cell, your" _
& " selection will default to the current region for that cell!" _
, "Select Range")
If rngSecond Is Nothing Then Exit Sub
'
'Filter first range using values from the second range
Dim arrValues() As Variant: arrValues = rngSecond.Value2
Dim arrCriteria() As Variant
Dim i As Long
Dim v As Variant
'
'Criteria values must be a 1-dimension array
ReDim arrCriteria(0 To rngSecond.Count - 1)
i = 0
For Each v In arrValues
arrCriteria(i) = CStr(v) 'Criteria must be string data type
i = i + 1
Next v
'
'Filter
On Error Resume Next
If rngFirst.ListObject Is Nothing Then
rngFirst.AutoFilter
rngFirst.AutoFilter Field:=1, Criteria1:=arrCriteria, Operator:=xlFilterValues
Else
With rngFirst.ListObject.Range
.AutoFilter Field:=rngFirst.Column - .Column + 1 _
, Criteria1:=arrCriteria, Operator:=xlFilterValues
End With
End If
On Error GoTo 0
End Sub
Public Function GetRangeBySelection(ByVal prompt_ As String, ByVal title_ As String) As Range
Dim rng As Range
'
Do While rng Is Nothing
On Error Resume Next
Set rng = Application.InputBox(Prompt:=prompt_, Title:=title_, Type:=8)
If rng.Cells.Count = 1 Then Set rng = rng.CurrentRegion
On Error GoTo 0
If rng Is Nothing Then Exit Function
'
On Error GoTo ErrorHandler
If rng.Areas.Count > 1 Then
If MsgBox("Your selection contains " & rng.Areas.Count _
& " different ranges!" & vbNewLine & "Please select only 1 " _
& "range!", vbQuestion + vbRetryCancel, "Cancelled") _
<> vbRetry Then Exit Function
Set rng = Nothing
ElseIf rng.Cells.Count = 1 Then
If MsgBox("No region found from selected cell" & vbNewLine _
& "Please select more than 1 cell!", vbQuestion _
+ vbRetryCancel, "Cancelled") <> vbRetry Then Exit Function
Set rng = Nothing
ElseIf rng.Rows.Count = 1 Then
If MsgBox("Please select more than 1 row!", vbQuestion _
+ vbRetryCancel, "Cancelled") <> vbRetry Then Exit Function
Set rng = Nothing
End If
Loop
Set GetRangeBySelection = rng
Exit Function
ErrorHandler:
MsgBox "Try selecting a smaller range next time", vbInformation, "Cancelled"
End Function
Just run the FilterBySelection method
EDIT 1
Or, if you would like to have less restrictions and be able to select multiple ranges for the filtering values then use this instead:
Option Explicit
Public Sub FilterBySelection()
Dim rngFirst As Range
Dim rngSecond As Range
'
'Get Ranges from User Selection
Set rngFirst = GetRangeBySelection("Select range to filter!" _
& vbNewLine & "Please select a single continuous range!" _
, "Select Range", False)
If rngFirst Is Nothing Then Exit Sub
'
Set rngSecond = GetRangeBySelection("Select range(s) containing filtering values!" _
, "Select Range", True)
If rngSecond Is Nothing Then Exit Sub
'
'Filter first range using values from the second range
Dim rng As Range
Dim arrValues() As Variant
Dim arrCriteria() As Variant
Dim i As Long
Dim v As Variant
'
'Criteria values must be a 1-dimension array
i = 0
ReDim arrCriteria(0 To rngSecond.Count - 1)
For Each rng In rngSecond.Areas
If rng.Count = 1 Then
ReDim arrValues(0 To 0)
arrValues(0) = rng.Value2
Else
arrValues = rng.Value2
End If
For Each v In arrValues
arrCriteria(i) = CStr(v) 'Criteria must be string data type
i = i + 1
Next v
Next
'
'Filter
On Error Resume Next
If rngFirst.ListObject Is Nothing Then
rngFirst.AutoFilter
rngFirst.AutoFilter Field:=1, Criteria1:=arrCriteria, Operator:=xlFilterValues
Else
With rngFirst.ListObject.Range
.AutoFilter Field:=rngFirst.Column - .Column + 1 _
, Criteria1:=arrCriteria, Operator:=xlFilterValues
End With
End If
On Error GoTo 0
End Sub
Public Function GetRangeBySelection(ByVal prompt_ As String, ByVal title_ As String _
, allowMultiArea As Boolean) As Range
Dim rng As Range
'
Do While rng Is Nothing
On Error Resume Next
Set rng = Application.InputBox(Prompt:=prompt_, Title:=title_, Type:=8)
On Error GoTo 0
If rng Is Nothing Then Exit Function
'
On Error GoTo ErrorHandler
If rng.Areas.Count > 1 And Not allowMultiArea Then
If MsgBox("Your selection contains " & rng.Areas.Count _
& " different ranges!" & vbNewLine & "Please select only 1 " _
& "range!", vbQuestion + vbRetryCancel, "Cancelled") _
<> vbRetry Then Exit Function
Set rng = Nothing
End If
Loop
Set GetRangeBySelection = rng
Exit Function
ErrorHandler:
MsgBox "Try selecting a smaller range next time", vbInformation, "Cancelled"
End Function

Loop through all sheets to find cells which contain special characters

I have this macro to replace special characters in any sheet in my workbook.
It gets rid of these characters: ! # # $ % ^ & () /
Sub Macro3()
Dim splChars As String
Dim ch As Variant
Dim splCharArray() As String
splChars = "! # # $ % ^ & () /" splCharArray = Split(splChars, " ")
For Each ch In splCharArray
Cells.Replace What:="~" & ch, Replacement:="", LookAt:=xlPart, SearchOrder:= _
xlByRows, MatchCase:=True
Next ch
End Sub
I need a second macro which would do Cells.Find for every cell in every worksheet then create a new sheet to list all cell addresses and special characters found.
On the web I found:
Public Sub SearchForText()
Dim rngSearchRange As Range
Dim vntTextToFind As Variant
Dim strFirstAddr As String
Dim lngMatches As Long
Dim rngFound As Range
On Error GoTo ErrHandler
vntTextToFind = Application.InputBox( _
Prompt:="Enter text to find:", _
Default:="Search...", _
Type:=2 _
)
If VarType(vntTextToFind) = vbBoolean Then Exit Sub
On Error Resume Next
Set rngSearchRange = Application.InputBox( _
Prompt:="Enter range for search:", _
Default:=ActiveCell.Parent.UsedRange.Address, _
Type:=8 _
)
On Error GoTo ErrHandler
If rngSearchRange Is Nothing Then Exit Sub
Set rngFound = rngSearchRange.Find( _
What:=CStr(vntTextToFind), _
LookIn:=xlValues, _
LookAt:=xlPart _
)
If rngFound Is Nothing Then
MsgBox "No matches were found.", vbInformation
Else
With ThisWorkbook.Sheets.Add
With .Range("A1:B1")
.Value = Array("Cell", "Value")
.Font.Bold = True
End With
strFirstAddr = rngFound.Address
Do
lngMatches = lngMatches + 1
.Cells(lngMatches + 1, "A").Value = rngFound.Parent.Name & "!" _
& rngFound.Address(0, 0)
.Cells(lngMatches + 1, "B").Value = rngFound.Value
Set rngFound = rngSearchRange.FindNext(rngFound)
Loop Until (rngFound.Address = strFirstAddr)
.Columns("A:B").AutoFit
End With
End If
Exit Sub
ErrHandler:
MsgBox Err.Description, vbExclamation
End Sub
This code works. My problem is, I need to set a range in which it searches every time and it can only be one sheet, so essentially if I have 10 sheets I need to run this macro 10 times to get the desired result.
I would like to search for each character in every worksheet of my workbook, then create a new sheet and return the address of every cell in an entire workbook which contains any of my declared characters.
I thought I could declare new variable ws as worksheet and loop through all worksheets with the same range selected using for each.
Try this. You just need another loop for the worksheets, and a loop for the Find.
This code doesn't do any replacing.
Sub Macro3()
Dim splChars As String
Dim ch As Variant
Dim splCharArray() As String
Dim r As Range, s As String
Dim ws As Worksheet
splChars = "! # # $ % ^ & () /"
splCharArray = Split(splChars, " ")
Sheets.Add().Name = "Errors" 'to list characters and location
For Each ch In splCharArray
For Each ws In Worksheets
If ws.Name <> "Errors" Then
Set r = ws.Cells.Find(What:=ch, Lookat:=xlPart, SearchOrder:=xlByRows, MatchCase:=True, SearchFormat:=False)
If Not r Is Nothing Then
s = r.Address
Do
Sheets("Errors").Range("A" & Rows.Count).End(xlUp)(2) = ch 'character
Sheets("Errors").Range("B" & Rows.Count).End(xlUp)(2) = r.Address(external:=True)
Set r = ws.Cells.FindNext(r)
Loop Until r.Address = s 'loop until we are back to the first found cell
End If
End If
Next ws
Next ch
End Sub

Vba delete rows if cell in range is blank?

I have a worksheet like so:
Column A < - - - -
A |
B - - - - Range A30:A39
C |
|
< - - - -
Next Line
Text way down here
I am using this code to delete the empty cells in my range A30:39. This range sits above the 'Next Line' value.
wStemplaTE.Range("A30:A39").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
In an ideal world, this code should cause this to happen:
Column A
A
B
C
Next Line
Text way down here
But instead it's causing the last bit of text to shift upwards like this:
Column A
A
B
C
Next Line
Text Way down here
Next Line and Text way down here are not even in this range.
Can someone show me what i am doing wrong?
My Entire code:
Sub Create()
'On Error GoTo Message
Application.DisplayAlerts = False
Application.ScreenUpdating = False
Dim WbMaster As Workbook
Dim wbTemplate As Workbook
Dim wStemplaTE As Worksheet
Dim i As Long
Dim LastRow As Long
Dim rngToChk As Range
Dim rngToFill As Range
Dim rngToFill2 As Range
Dim rngToFill3 As Range
Dim rngToFill4 As Range
Dim rngToFill5 As Range
Dim rngToFill6 As Range
Dim rngToFill7 As Range
Dim rngToFill8 As Range
Dim rngToFill9 As Range
Dim rngToFil20 As Range
Dim CompName As String
Dim TreatedCompanies As String
Dim FirstAddress As String
'''Reference workbooks and worksheet
Set WbMaster = ThisWorkbook
'''Loop through Master Sheet to get company names
With WbMaster.Sheets(2)
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
'''Run Loop on Master
For i = 2 To LastRow
'''Company name
Set rngToChk = .Range("B" & i)
CompName = rngToChk.value
If InStr(1, TreatedCompanies, CompName) Or CompName = vbNullString Then
'''Company already treated, not doing it again
Else
'''Open a new template
Set wbTemplate = Workbooks.Open("G:\BUYING\Food Specials\2. Planning\3. Confirmation and Delivery\Announcements\Templates\template.xlsx")
Set wStemplaTE = wbTemplate.Sheets(1)
'''Set Company Name to Template
wStemplaTE.Range("C12").value = CompName
wStemplaTE.Range("C13").value = rngToChk.Offset(, 1).value
wStemplaTE.Range("C14").value = rngToChk.Offset(, 2).value
wStemplaTE.Range("C15").value = rngToChk.Offset(, 3).value
wStemplaTE.Range("C16").value = Application.UserName
wStemplaTE.Range("C17").value = Now()
wStemplaTE.Range("A20").value = "Announcement of Spot Buy Promotion - Week " & ThisWorkbook.Worksheets(1).Range("I8").value & " " & ThisWorkbook.Worksheets(1).Range("T8").value
Dim strDate
Dim strResult
strDate = rngToChk.Offset(, 14).value
wStemplaTE.Range("C25").value = "Week " & ThisWorkbook.Worksheets(1).Range("I8").value & " " & ThisWorkbook.Worksheets(1).Range("T8").value & " " & WeekdayName(Weekday(strDate)) & " (" & strDate & ")"
'Set Delivery Date
wStemplaTE.Range("C26").value = WeekdayName(Weekday(rngToChk.Offset(, 15).value)) & " (" & rngToChk.Offset(, 15).value & ")"
'''Add it to to the list of treated companies
TreatedCompanies = TreatedCompanies & "/" & CompName
'''Define the 1st cell to fill on the template
Set rngToFill = wStemplaTE.Range("A30")
Set rngToFill2 = wStemplaTE.Range("B30")
Set rngToFill3 = wStemplaTE.Range("C30")
Set rngToFill4 = wStemplaTE.Range("D30")
Set rngToFill5 = wStemplaTE.Range("E30")
Set rngToFill6 = wStemplaTE.Range("F30")
Set rngToFill7 = wStemplaTE.Range("G30")
Set rngToFill8 = wStemplaTE.Range("C13")
Set rngToFill9 = wStemplaTE.Range("C14")
Set rngToFil20 = wStemplaTE.Range("C15")
With .Columns(2)
'''Define properly the Find method to find all
Set rngToChk = .Find(What:=CompName, _
After:=rngToChk.Offset(-1, 0), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
'''If there is a result, keep looking with FindNext method
If Not rngToChk Is Nothing Then
FirstAddress = rngToChk.Address
Do
'''Transfer the cell value to the template
rngToFill.value = rngToChk.Offset(, 7).value
rngToFill2.value = rngToChk.Offset(, 8).value
rngToFill3.value = rngToChk.Offset(, 9).value
rngToFill4.value = rngToChk.Offset(, 10).value
rngToFill5.value = rngToChk.Offset(, 11).value
rngToFill6.value = rngToChk.Offset(, 12).value
rngToFill7.value = rngToChk.Offset(, 13).value
'''Go to next row on the template for next Transfer
Set rngToFill = rngToFill.Offset(1, 0)
Set rngToFill2 = rngToFill.Offset(0, 1)
Set rngToFill3 = rngToFill.Offset(0, 2)
Set rngToFill4 = rngToFill.Offset(0, 3)
Set rngToFill5 = rngToFill.Offset(0, 4)
Set rngToFill6 = rngToFill.Offset(0, 5)
Set rngToFill7 = rngToFill.Offset(0, 6)
'''Look until you find again the first result
Set rngToChk = .FindNext(rngToChk)
Loop While Not rngToChk Is Nothing And rngToChk.Address <> FirstAddress
Else
End If
End With '.Columns(2)
Set Rng = Range("D30:G39")
Rng.Select
Set cell = Selection.Find(What:="#VALUE!", After:=ActiveCell, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
If cell Is Nothing Then
'do it something
Else
For Each cell In Rng
cell.value = "TBC"
Next
'End For
wStemplaTE.Range("A41").value = "Please fill in the pallet factor and case size accordingly. Please amend total volume if necessary to accommodate full pallets."
End If
Rng.Select
Set cell = Selection.Find(What:="TBC", After:=ActiveCell, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
If cell Is Nothing Then
'do it something
Else
wStemplaTE.Range("A41").value = "Please fill in the pallet factor and case size accordingly. Please amend total volume if necessary to accommodate full pallets."
End If
'Remove uneeded announcement rows
wStemplaTE.Range("A30:A39").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
file = AlphaNumericOnly(CompName)
wbTemplate.SaveCopyAs filename:="G:\BUYING\Food Specials\2. Planning\3. Confirmation and Delivery\Announcements\2017\test\" & file & ".xlsx"
wbTemplate.Close False
End If
Next i
End With 'wbMaster.Sheets(2)
Application.DisplayAlerts = True
Application.ScreenUpdating = True
Dim answer As Integer
answer = MsgBox("Announcements Successfully Created." & vbNewLine & vbNewLine & "Would you like to view these now?", vbYesNo + vbQuestion, "Notice")
If answer = vbYes Then
Call List
Else
'do nothing
End If
Exit Sub
Message:
wbTemplate.Close savechanges:=False
MsgBox "One or more files are in use. Please make sure all Announcement files are closed and try again."
Exit Sub
End Sub
Function AlphaNumericOnly(strSource As String) As String
Dim i As Integer
Dim strResult As String
For i = 1 To Len(strSource)
Select Case Asc(Mid(strSource, i, 1))
Case 48 To 57, 65 To 90, 97 To 122: 'include 32 if you want to include space
strResult = strResult & Mid(strSource, i, 1)
End Select
Next
AlphaNumericOnly = strResult
End Function
Function FindAll(SearchRange As Range, _
FindWhat As Variant, _
Optional LookIn As XlFindLookIn = xlValues, _
Optional LookAt As XlLookAt = xlWhole, _
Optional SearchOrder As XlSearchOrder = xlByRows, _
Optional MatchCase As Boolean = False, _
Optional BeginsWith As String = vbNullString, _
Optional EndsWith As String = vbNullString, _
Optional BeginEndCompare As VbCompareMethod = vbTextCompare) As Range
End Function
Modify the column as you need. Right now it is working on column A. You can make it an argument to ask the user, like the second code
Public Sub DeleteRowOnCell()
'====================================================================================
'This macro will delete the entire row if a cell in the specified column is blank.
'Only one specified column is checked. Other columns are ignored.
'====================================================================================
On Error Resume Next
Range("A3:A" & Rows.count).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
On Error GoTo 0
End Sub
Public Sub DeleteRowOnCellAsk()
'====================================================================================
'This macro will delete the entire row if a cell in the specified column is blank.
'Only one specified column is checked. Other columns are ignored.
'====================================================================================
Dim inp As String
inp = InputBox("Please enter a column name based on which blank rows will be deleted", "Which Column?")
Debug.Print inp & ":" & inp & Rows.count
On Error Resume Next
Range(inp & "1" & ":" & inp & Rows.count).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End Sub

Error capture while using .Find is not identifing error

When .Find does not find a result, I want an error msg. I have used the method that is almost universally recommended online, but it is not working. When a value is not found, nothing happens. There should be a msg box identified the error.
If Not rFoundCell Is Nothing Then
MsgBox "val: " & rValue.Value & " Matching Cell: " & rFoundCell.Address
Cells(Range(rFoundCell.Address).Row, Range(rFoundCell.Address).Column).Select
Else
MsgBox (rValue.Value & " not found.")
GoTo end_search
End If
I've tried the other way as well:
If rFoundCell Is Nothing Then
Display a msg "not found"
else
Keep going.
That didn't work either. What am i missing?
Full code follows:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim PostRng As Range
Dim PendRng As Range
Dim rValue As Range
Dim lLoop As Long
Dim rFoundCell As Range
Dim INTRng As Range
Set PostRng = Range("g:g")
Set PendRng = Range("k:k")
'"Intersect" will ensure your current cell lies on correct column.
Set INTRng = Intersect(Target, PostRng)
'IF conditions to trigger code.
'This IF confirms only one cell changed. -- I think
If Target.Columns.Count = 1 And Target.Rows.Count = 1 Then
If Not INTRng Is Nothing And LCase(Target.Text) = "y" Then
'This block will return the range & value on the row where "y" or "Y" are entered.
Set rValue = Target.Offset(0, -3) 'Returns value in Col D
If rValue = 0 Or rValue = "" Then Set rValue = Target.Offset(0, -2)
Debug.Print "Target "; Target
Debug.Print "rvalue.value "; rValue.Value
'This will loop through a different column, to find the value identified above, and return its cell address in the other column.
With PendRng
Set rFoundCell = .Cells(1, 1)
For lLoop = 1 To WorksheetFunction.CountIf(.Cells, rValue.Value)
Set rFoundCell = .Find(What:=rValue.Value, _
After:=rFoundCell, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
Debug.Print "rfoundcell " & rFoundCell
If Not rFoundCell Is Nothing Then
MsgBox "val: " & rValue.Value & " Matching Cell: " & rFoundCell.Address
'This will use the cell address identified above to move the active cell to that address.
'Have to convert the address to row/column to use in Cell.Select.
Cells(Range(rFoundCell.Address).Row, Range(rFoundCell.Address).Column).Select
Else
MsgBox (rValue.Value & " not found.")
GoTo end_search
End If
Next lLoop
End With
End If
End If
end_search:
End Sub
Received help w/ this code here:
Execute a subroutine when a user enters a trigger into a cell
I believe that your code is skipping the If statement that generates the error box if there is not a match.
This is due to For lLoop = 1 To WorksheetFunction.CountIf(.Cells, rValue.Value) exiting when there is no matches because it equates to For lLoop = 1 To 0
I moved all of your error message code into an If statement above the lLoop as follows:
If WorksheetFunction.CountIf(.Cells, rValue.Value) = 0 Then
MsgBox (rValue.Value & " not found.")
GoTo end_search
End If

Resources