VBA Inputbox Filter enhancements - vba

the code below works fine. However, when a user doesn't include anything in the InputBox or clicks on the 'Close' button or inputs a value which doesn't exist I want it to display a msgbox stating the reason and delete sheets 'PreTotal'.
Is there a better way to handle user input? Need some help here on how to go about it. Thank you.
Sub Filterme()
Dim wSheetStart As Worksheet
Dim rFilterHeads As Range
Dim strCriteria As String
Set wSheetStart = ActiveSheet
Set rFilterHeads = Range("M1", Range("M1").End(xlToLeft))
With wSheetStart
.AutoFilterMode = False
rFilterHeads.AutoFilter
strCriteria = InputBox("Enter Date - MMDDYY")
If strCriteria = vbNullString Then Exit Sub
rFilterHeads.AutoFilter Field:=13, Criteria1:="=*" & strCriteria & "*"
End With
Worksheets("PreTotal").UsedRange.Copy
Sheets.Add.Name = "Total"
Worksheets("Total").Range("A1").PasteSpecial
End Sub

Is this what you are trying?
Change
If strCriteria = vbNullString Then Exit Sub
to
If strCriteria = vbNullString Then
MsgBox "You choose not to continue"
Application.DisplayAlerts = False
Worksheets("PreTotal").Delete
Application.DisplayAlerts = True
Exit Sub
End If
FOLLOWUP
Thanks #Rout - This worked. One more thing what if the input criteria does not exist in the sheet? How should I tackle that? – user823911 11 mins ago
Is this what you are trying? Also if you are filtering the range based on Col M (1st Col in the range) then change the line
rFilterHeads.AutoFilter Field:=13, Criteria1:="=*" & strCriteria & "*"
to
rFilterHeads.AutoFilter Field:=1, Criteria1:="=*" & strCriteria & "*"
CODE
Sub Filterme()
Dim wSheetStart As Worksheet
Dim rFilterHeads As Range, aCell As Range
Dim strCriteria As String
Set wSheetStart = ActiveSheet
Set rFilterHeads = Range("M1", Range("M1").End(xlToLeft))
With wSheetStart
.AutoFilterMode = False
strCriteria = InputBox("Enter Date - MMDDYY")
If strCriteria = vbNullString Then
MsgBox "You choose not to continue"
Application.DisplayAlerts = False
Worksheets("PreTotal").Delete
Application.DisplayAlerts = True
Exit Sub
End If
Set aCell = .Columns(13).Find(What:=strCriteria, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
MsgBox "Search Criteria Not Found"
Exit Sub
End If
rFilterHeads.AutoFilter
rFilterHeads.AutoFilter Field:=13, Criteria1:="=*" & strCriteria & "*"
Sheets.Add.Name = "Total"
Worksheets("PreTotal").UsedRange.Copy
Worksheets("Total").Range("A1").PasteSpecial
End With
End Sub

Related

Vba script for automatic column detection in a table

I have an excel sheet where the columns and rows of the table are changed from time to time. The affected vba script, however, uses fixed values for rows and columns. How can I find the columns and rows if they change? The name of the columns is not changed, but only the location in the sheet.
I have to upadte my method manually everytime. (Like you see in the code example)
Hello Siddharth, thank you for your detailed description. Unfortunately I do not have experience with VBA, so I can not support the integration of your code. I suspect that the return variable does not match the specified method. Here is my VBA script that needs to be extended. I hope you can help me there =)
Option Explicit
Public Sub moduleStatus()
Dim iQZeMax As Integer
Dim iQZe As Integer
Dim iZZe As Integer
Dim iQSp As Integer
Dim shtSPR_R As Worksheet, shtAdd As Worksheet
Dim rng_2_check As Range
Dim lstLong(3) As String
lstLong(0) = "Initiated"
lstLong(1) = "Review ready"
lstLong(2) = "Reviewed"
Dim lstShort(2) As String
lstShort(0) = "Initiated"
lstShort(1) = "Review ready"
Application.EnableEvents = False
Application.ScreenUpdating = False
Set shtSPR_R = ThisWorkbook.Sheets("Report")
Set shtAdd = ThisWorkbook.Sheets("Add")
'Unprotect
shtSPR_R.Unprotect
'Clear old Data
'''shtSPR_R.Range("AB11:AB10000").ClearContents
'Status
iQSp = 28
'''iQZe = 11
'max row is determined by MA
For iQZeMax = 10010 To 1 Step -1
If shtSPR_R.Range("A" & iQZeMax).Value <> "" Or shtSPR_R.Range("B" & iQZeMax).Value <> "" Then Exit For
Next
shtSPR_R.Range("AC11:AD10010").Clear
shtSPR_R.Range("A1").FormatConditions(1).ModifyAppliesToRange Range:=shtSPR_R.Range("A1:AE10010")
For iQZe = 11 To iQZeMax
' If Application.WorksheetFunction.CountIfs(shtSPR_R.Range("A" & iQZe & ":AB" & iQZe), "") = iQSp Then
' Exit For
' End If
'Case Initiated
If shtSPR_R.Range("AB" & iQZe).Value = "" Then
shtSPR_R.Range("AB" & iQZe).Validation.Delete
shtSPR_R.Range("AB" & iQZe).Value = "Initiated"
shtSPR_R.Cells(iQZe, iQSp).Validation.Add _
Type:=xlValidateList, _
AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, _
Formula1:=Join(lstShort, ",")
End If
If Application.WorksheetFunction.CountIfs(shtSPR_R.Range("A9:AB9"), "Required", shtSPR_R.Range("A" & iQZe & ":AB" & iQZe), "") <> 0 Then
shtSPR_R.Range("AB" & iQZe).Validation.Delete
shtSPR_R.Range("AB" & iQZe).Validation.Add _
Type:=xlValidateList, _
AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, _
Formula1:=Join(lstShort, ",")
Else
shtSPR_R.Range("AB" & iQZe).Validation.Delete
shtSPR_R.Cells(iQZe, iQSp).Validation.Add _
Type:=xlValidateList, _
AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, _
Formula1:=Join(lstLong, ",")
End If
'shtSPR_R.Range("AC" & iQZe).FormulaArray = "=IFERROR(INDEX(general_report!R3C5:R10000C5,MATCH(RC[-27]&RC[-26]&RC[-22],general_report!R3C8:R10000C8&general_report!R3C2:R10000C2&general_report!R3C9:R10000C9,0)),""tbd."")"
'shtSPR_R.Range("AD" & iQZe).FormulaArray = "=IFERROR(INDEX(general_report!R3C6:R10000C6,MATCH(RC[-28]&RC[-27]&RC[-23],general_report!R3C8:R10000C8&general_report!R3C2:R10000C2&general_report!R3C9:R10000C9,0)),""tbd."")"
shtSPR_R.Range("AC" & iQZe).FormulaArray = "=IFERROR(INDEX(general_report!R4C6:R10000C6,MATCH(RC[-27]&RC[-26]&RC[-22],general_report!R4C9:R10000C9&general_report!R4C2:R10000C2&general_report!R4C10:R10000C10,0)),""tbd."")"
shtSPR_R.Range("AD" & iQZe).FormulaArray = "=IFERROR(INDEX(general_report!R4C7:R10000C7,MATCH(RC[-28]&RC[-27]&RC[-23],general_report!R4C9:R10000C9&general_report!R4C2:R10000C2&general_report!R4C10:R10000C10,0)),""tbd."")"
If shtSPR_R.Range("AB" & iQZe).Value = "Exported" Then
shtSPR_R.Range("A" & iQZe & ":AA" & iQZe).Locked = True
Else
shtSPR_R.Range("A" & iQZe & ":AA" & iQZe).Locked = False
End If
If shtSPR_R.Range("AE" & iQZe).Value = "" Then
shtAdd.Range("rngSPR_ID_Cnt").Value = shtAdd.Range("rngSPR_ID_Cnt").Value + 1
shtSPR_R.Range("AE" & iQZe).Value = shtSPR_R.Range("L" & iQZe).Value & "-" & Right("00000" & shtAdd.Range("rngSPR_ID_Cnt").Value, 5)
End If
Next iQZe
'Protect
shtSPR_R.Protect "", DrawingObjects:=False, Contents:=True, Scenarios:=True _
, AllowFormattingCells:=True, AllowFormattingColumns:=True, _
AllowFormattingRows:=True, AllowFiltering:=True
Application.ScreenUpdating = True
Application.EnableEvents = True
MsgBox "Done!"
End Sub
Here is another way to do it.
What you are actually trying to get is the R4C6:R10000C6 part of the formula. So what you can do is use a common sub to get the address and then create your own formula string. I am using .Find to locate the column header. To read more about .Find, you can see .Find and .FindNext
Here is an example for Linked Issues.
Option Explicit
Sub Sample()
Debug.Print GetAddress("Linked Issues")
End Sub
Private Function GetAddress(ColHeader As String) As String
Dim HeaderRow As Long, HeaderCol As Long
Dim rngAddress As String: rngAddress = "Not Found"
Dim aCell As Range
Dim ws As Worksheet
'~~> Change this to the relevant sheet
Set ws = Sheet1
With ws
Set aCell = .Cells.Find(What:=ColHeader, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
HeaderRow = aCell.Row
HeaderCol = aCell.Column
rngAddress = "R" & (HeaderRow + 1) & "C" & HeaderCol & _
":R10000C" & HeaderCol
End If
End With
GetAddress = rngAddress
End Function
CAUTION: You may get false positives if the column name is repeated elsewhere. I have used LookAt:=xlWhole to minimize that but you still need to be careful.
Screenshot:
When you run the code you will get R4C3:R10000C3
Also if you want to avoid the hardcoding of 10000, then find the last row. For that you can see THIS
Create a new spreadsheet, let's say "keys"
The 1st column of which will be "columns" and the 3rd of which will be rows,
then you add a MATCH function, that gives you the location of the row and column,
so what you'll need to do is link the VBA to keys sheet, and grab the location from there
The formula for each column:
IFERROR(ADDRESS(1,MATCH($A2,'1'!$A$1:$A$1000,0)),"missing")
IFERROR(ADDRESS(MATCH($C2,'1'!$A$2:$BA$2,0),2),"missing")
And lastly, connect the formulas' results witho your VBA:
shtSPR_R.Range("keys!B2").FormulaArray = ...
Hope that helps

Excel macros programming search

Can you help me with edit macro? I would like to search on another sheet but I don't known what I do wrong. Sheet where I would like to search is "Díly".
Sub díly()
Dim rngVis As Range
Dim VisCell As Range
Dim sFind As String
sFind = InputBox("Naskenujte zákaznické císlo.")
If Len(Trim(sFind)) = 0 Then Exit Sub 'Pressed cancel
Application.ScreenUpdating = False
With Intersect(Sheets("Díly").UsedRange, Sheets("Díly").Columns("A"))
.AutoFilter 1, sFind
On Error Resume Next
Set rngVis = .Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible)
On Error GoTo 0
.AutoFilter
End With
Application.ScreenUpdating = True
If rngVis Is Nothing Then
MsgBox sFind & " Nenalezeno."
Else
For Each VisCell In rngVis.Cells
MsgBox "Naskenované císlo: " & VisCell.Sheets("Díly").Cells(VisCell.Row, "A").Text & vbNewLine & _
"Vyhledáno: " & VisCell.Sheets("Díly").Cells(VisCell.Row, "B").Text
Next VisCell
End If
End Sub
try this
Option Explicit
Sub díly()
Dim rngVis As Range
Dim VisCell As Range
Dim sFind As String
sFind = InputBox("Naskenujte zákaznické císlo.")
If Len(Trim(sFind)) = 0 Then Exit Sub 'Pressed cancel
Application.ScreenUpdating = False
With Intersect(Sheets("Díly").UsedRange, Sheets("Díly").Columns("A"))
.AutoFilter 1, sFind
On Error Resume Next
Set rngVis = .Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible)
On Error GoTo 0
.AutoFilter
End With
Application.ScreenUpdating = True
If rngVis Is Nothing Then
MsgBox sFind & " Nenalezeno."
Else
For Each VisCell In rngVis.Cells
MsgBox "Naskenované císlo: " & VisCell.Text & vbNewLine & _
"Vyhledáno: " & VisCell.Offset(, 1).Text
Next VisCell
End If
End Sub

Need to change one little thing in this macro

I have this macro which does exactly what I want except for one change. I want it to sort by column "M" instead of "A". I've tried changing it manually, but I keep getting errors. I know it's probably a simple fix but I just can't seem to get it. Thanks in advance!
I've tried to change "Field:=1" to Field:="13", but I get "Run-time error '1004' AutoFilter method of range class failed".
Debug then highlights "rngFilter.AutoFilter Field:=13, Criteria1:=cell.Value"
Private Sub CommandButton1_Click()
Dim wbDest As Workbook
Dim rngFilter As Range, rngUniques As Range
Dim cell As Range
Set rngFilter = Range("A1", Range("A" & Rows.Count).End(xlUp))
Application.ScreenUpdating = False
With rngFilter
.AdvancedFilter Action:=xlFilterInPlace, Unique:=True
Set rngUniques = Range("A2", Range("A" & Rows.Count).End(xlUp)).SpecialCells(xlCellTypeVisible)
ActiveSheet.ShowAllData
End With
For Each cell In rngUniques
Set wbDest = Workbooks.Add(xlWBATWorksheet)
rngFilter.AutoFilter Field:=1, Criteria1:=cell.Value
rngFilter.EntireRow.Copy
With wbDest.Sheets(1).Range("A1")
.PasteSpecial xlPasteColumnWidths
.PasteSpecial xlPasteValuesAndNumberFormats
End With
Application.CutCopyMode = True
wbDest.Sheets(1).Name = cell.Value
wbDest.SaveAs ThisWorkbook.Path & Application.PathSeparator & _
cell.Value & " " & Format(Date, "mmm_dd_yyyy")
Next cell
rngFilter.Parent.AutoFilterMode = False
Application.ScreenUpdating = True
End Sub
Give this a try. I've updated the code so that all you need to do is change sColumn from A to whatever column letter you want:
Private Sub CommandButton1_Click()
Const sColumn As String = "A"
Dim wbDest As Workbook
Dim rngFilter As Range, rngUniques As Range
Dim cell As Range
Set rngFilter = Range(sColumn & "1", Range(sColumn & Rows.Count).End(xlUp))
Application.ScreenUpdating = False
With rngFilter
.AdvancedFilter Action:=xlFilterInPlace, Unique:=True
Set rngUniques = Range(sColumn & "2", Range(sColumn & Rows.Count).End(xlUp)).SpecialCells(xlCellTypeVisible)
On Error Resume Next
ActiveSheet.ShowAllData
On Error GoTo 0
End With
For Each cell In rngUniques
Set wbDest = Workbooks.Add(xlWBATWorksheet)
rngFilter.AutoFilter Field:=1, Criteria1:=cell.Value
rngFilter.EntireRow.Copy
With wbDest.Sheets(1).Range("A1")
.PasteSpecial xlPasteColumnWidths
.PasteSpecial xlPasteValuesAndNumberFormats
End With
Application.CutCopyMode = True
wbDest.Sheets(1).Name = cell.Value
Application.DisplayAlerts = False
wbDest.SaveAs ThisWorkbook.Path & Application.PathSeparator & cell.Value & " " & Format(Date, "mmm_dd_yyyy")
wbDest.Close False
Application.DisplayAlerts = True
Next cell
rngFilter.Parent.AutoFilterMode = False
Application.ScreenUpdating = True
End Sub
Try substituting this where your debug error is:
ActiveSheet.Range("A1").CurrentRegion.AutoFilter Field:=13, Criteria1:=cell.Value
Basically, it seemed that your rngFilter variable was restricting your range to Column A and you're trying to filter based on a column that's outside of this range.
Let me know if it works!

VBA Excel AutoFilter Error

I am getting following error when trying to auto filter in vba:
The object invoked has disconnected from its clients.
So what i am trying to do is auto filter, search for empty spaces and delete the rows. Can anyone please help?
I have tried the standard solutions provided online e.g. option explicit etc but to no avail.
Data:
Code:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim lngLastRow As Long
Dim lngLastRowD As Long
Application.ScreenUpdating = False
'Concatenate the Row A and B
lngLastRow = Cells(Rows.Count, "A").End(xlUp).Row
Worksheets(1).Range("D2:D" & lngLastRow).Value = Evaluate("=A2:A" & lngLastRow & "&""""&" & "B2:B" & lngLastRow)
lngLastRowD = Worksheets(1).Cells(Rows.Count, "D").End(xlUp).Row
Set ws = Worksheets(1)
Set Rng = Worksheets(1).Range("A2:A" & lngLastRowD)
With Rng
.AutoFilter field:=1, Criteria1:=""
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
ws.AutoFilterMode = False
Application.ScreenUpdating = True
ThisWorkbook.Sheets(1).Range("A2").Select
End Sub
Since Worksheets() want the name of the sheet, like "Sheet1", use sheets(1).
Why are you creating the variable ws and rng when you only use them once
I ran this and it deleted rows with no data in column A.
Private Sub Worksheet_Change()
Dim lngLastRow As Long
Dim lngLastRowD As Long
Application.ScreenUpdating = False
'Concatenate the Row A and B
lngLastRow = Cells(Rows.Count, "A").End(xlUp).Row
sheets(1).Range("D2:D" & lngLastRow).Value = Evaluate("=A2:A" & lngLastRow & "&""""&" & "B2:B" & lngLastRow)
lngLastRowD = Worksheets(1).Cells(Rows.Count, "D").End(xlUp).Row
With sheets(1).Range("A2:A" & lngLastRowD)
.AutoFilter field:=1, Criteria1:=""
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
sheets(1).AutoFilterMode = False
Application.ScreenUpdating = True
Sheets(1).Range("A2").Select
End Sub
In the end i restored in approaching the issue from another angle:
Dim i As Integer, counter As Integer
i = 2
For counter = 1 To lngLastRowD
If Worksheets(1).Range("A2:A" & lngLastRowD).Cells(i) = "" And Worksheets(1).Range("D2:D" & lngLastRowD).Cells(i) <> "" Then
Worksheets(1).Range("A2:A" & lngLastRowD).Range("A" & i & ":D" & lngLastRowD).Select
Selection.Delete
GoTo TheEND
Else
i = i + 1
Debug.Print "i is " & i
End If
Next

Search for string in each open worksheet

I would like to use values from each instance of the string FindString to populate textboxes in UserForm1.
I am getting the unique WorkSheet per textbox. But the rest of the values are from the sheet active when I run the module.
This mean the string Rng isn't looping through the WorkSheets, but staying with the initial WorkSheet. How can I remedy this?
Public Sub FindString()
Dim FindString As Variant
Dim Rng As Range
Dim SheetName As String
Dim ws As Worksheet
Dim i As Integer
Application.ScreenUpdating = False
SheetName = ActiveSheet.Name
FindString = Cells(ActiveCell.Row, 1).Value
FindString = InputBox("Enter the case number to search for:", "Case ID", FindString)
If FindString = "" Then Exit Sub
If FindString = False Then Exit Sub
i = 1
For Each ws In Worksheets
If ws.Name Like "Lang*" Then
With ws
If Trim(FindString) <> "" Then
With Range("A:A")
Set Rng = .Find(What:=FindString, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
UserForm1.Controls("TextBox" & i) = ws.Name & vbTab & _
Rng.Offset(0, 2).Value & vbTab & _
Rng.Offset(0, 5).Value & vbTab & _
Rng.Offset(0, 6).Value & vbTab & _
Rng.Offset(0, 7).Value & vbTab & _
Rng.Offset(0, 8).Value
i = i + 1
Else: GoTo NotFound
End If
End With
End If
End With
End If
Next ws
Sheets(SheetName).Activate
Application.ScreenUpdating = True
UserForm1.Show
Exit Sub
NotFound:
Sheets(SheetName).Activate
Application.ScreenUpdating = True
MsgBox "Case ID not found"
Exit Sub
End Sub
Got it!
Just needed to add
ws.Activate
after
If ws.Name Like "Lang*" Then