run-time error 424 while checking change events - vba

I have created a program which looks for items in Column A or Column I to change. If column I changes, it deletes and moves the row to a new sheet. If Column A changes, it should sort all of the data. However, when the second Application.Intersect(KeyCells2, Range(Target.Address)) is called, it errors out telling me I have a run-time error 424. Why is this happening? It seems to have both a key cells range and a target.address.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCells As Range
Dim KeyCells2 As Range
Dim LastRowCompleted As Long
Dim RowToDelete As Long
Dim CurCell As String
RowToDelete = 0
LastRow = Sheets("Current").Cells(Sheets("Current").Rows.Count, "A").End(xlUp).Row
LastRowCompleted = Sheets("completed").Cells(Sheets("completed").Rows.Count, "A").End(xlUp).Row
LastRowCompleted = LastRowCompleted + 1 'Next row after last row
Set KeyCells = Range("I3:I16384")
Set KeyCells2 = Range("A3:A16384")
CurCell = ActiveCell.Address
If Not Application.Intersect(KeyCells, Range(Target.Address)) Is Nothing Then
Application.EnableEvents = False
'Cut and Paste Row
Target.EntireRow.Copy Sheets("completed").Range(LastRowCompleted & ":" & LastRowCompleted)
'Mark to delete row
RowToDelete = Target.EntireRow.Row
Call DeleteRow(RowToDelete)
Application.EnableEvents = True
End If
Range(CurCell).Select
If Not Application.Intersect(KeyCells2, Range(Target.Address)) Is Nothing Then
Application.EnableEvents = False
'Sort
MsgBox "lastrow completed: " & LastRow
Range("A3:Z" & LastRow).Select
ActiveWorkbook.Worksheets("current").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("current").Sort.SortFields.Add Key:=Range("A3:A" & LastRow) _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("current").Sort.SortFields.Add Key:=Range("B3:B" & LastRow) _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
ActiveWorkbook.Worksheets("current").Sort.SortFields.Add Key:=Range("E3:E" & LastRow) _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("current").Sort
.SetRange Range("A3:J" & LastRow)
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Range(CurCell).Select
Application.EnableEvents = True
End If
End Sub
Sub DeleteRow(Row As Long)
If Row > 0 Then
Rows(Row).EntireRow.Delete Shift:=xlUp
End If
End Sub

If you delete the row in the first If block then Target no longer exists, so you can't use it in your second If block.
As a fix you could exit the Sub after deleting the row.
P.S. - that "auto-sort" seems like it would be pretty annoying if you're trying to edit data...

Related

Excel VBA automating Merge and Centering, Sorting

I am trying to automate a report generation process in excel.
So, let me give you guys a background:-
I have 3 columns in my datasheet:
Column A is manufacturing location
Column B is Vehicle line
Column C is Progress Update
I trying to generate a report which merges and centers MFG Locations in Column A and the same time Merge and Centers Vehicle lines in that plant with Column B
I am attaching a sample of the output I need. As of now , I am manually doing this process, I hope someone can guide me with automating this process
This code will help you what you have asked.
Sub MergeSameCells()
Dim Rng As Range
Dim xRows, lastRow As Integer
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
Range("A2:C" & lastRow).Select
With ActiveWorkbook.ActiveSheet.Sort
With .SortFields
.Clear
.Add Key:=Range("A2:A" & lastRow), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.Add Key:=Range("B2:B" & lastRow), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.Add Key:=Range("C2:C" & lastRow), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
End With
.SetRange Range("A2:C" & lastRow)
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Set WorkRng = Range("A2:B" & lastRow)
xRows = WorkRng.Rows.Count
If WorkRng Is Nothing Then Exit Sub
Application.ScreenUpdating = False
Application.DisplayAlerts = False
For Each Rng In WorkRng.Columns
For i = 1 To xRows - 1
For j = i + 1 To xRows
If Rng.Cells(i, 1).Value <> Rng.Cells(j, 1).Value Then
Exit For
End If
Next
WorkRng.Parent.Range(Rng.Cells(i, 1), Rng.Cells(j - 1, 1)).Merge
i = j - 1
Next
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
Try and let me know if it works.

Run-time error 13 when highlighting entire row

Whenever I try to highlight over column D I receive "Run-time error '13'". When I click debug it highlights this piece from the code, If Target.Value = "Closed" Or Target.Value = "Closed" Then. I would greatly appreciate any advice on how to fix this issue.
Edit*
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim wsd As Worksheet
Dim wsc As Worksheet
Application.ScreenUpdating = False
Set wsd = Sheets("Pipeline")
Set wsc = Sheets("Closed")
If Not Intersect(Target, Range("D6:D65536")) Is Nothing Then
If Target.Value = "Closed" Or Target.Value = "Closed" Then
erow = Target.Row
MsgBox "Moved to Closed"
numberofrow = wsc.Range("A65536").End(xlUp).Row
For i = 1 To numberofrow
If wsd.Cells(erow, 1) = wsc.Cells(i, 1) Then
Exit Sub
End If
Next
wsd.Range("A" & erow & ":A" & erow).EntireRow.Copy wsc.Range("A" & numberofrow + 1)
With Target.Parent
Union(.Range(.Cells(Target.Row, "A"), .Cells(Target.Row, "V")), _
.Range(.Cells(Target.Row, "Y"), .Cells(Target.Row, .Columns.Count))).ClearContents
`enter code here`End With
wsc.Activate
ActiveSheet.Range("A2:D" & numberofrow + 1).Select
ActiveWorkbook.Worksheets("Closed").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Closed").Sort.SortFields.Add Key:=Range("C2:C" & numberofrow + 1), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Closed").Sort
.SetRange Range("A2:D" & numberofrow + 1)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
wsd.Activate
End If
End If
End Sub
I had to piece a few things together in order to get this to work, which is why it's pretty ugly. I couldn't figure out where to put guard clause. This so far has worked for what I need it for (aside from the Run-time error), transferring accounts to a separate sheet based on the sales stage entered into column D. Again, I appreciate all the help.
Your handler assumes only 1 cell is selected. When you highlight an entire column, Target represents all selected cells, and then Target.Value can't be meaningfully evaluated, so it raises a run-time error.
You need to modify your handler to remove that assumption, as was suggested:
If Target.Cells.Count > 1 Then Exit Sub
Presumably that event handler needs more tweaks to verify the Target is what the macro thinks/assumes it is, but given the information you've provided that would be it.

why AutoFill failed?

Here I tried to random the colons, however, it tell me cannot autofill, and same thing works for my randomRow()
Sub randomCol()
Dim Line As Integer
Line = LastRow + 1
Range("N154").Select
ActiveCell.FormulaR1C1 = "=RAND()"
Dim randomRange As String
randomRange = "N" & Line & ":BF" & Line
MsgBox randomRange
Selection.AutoFill Destination:=Range(randomRange), Type:=xlFillDefault
Range("N2:BF" & Line).Select
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add key:=Range("N" & LastRow + 1), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").Sort
.SetRange Range("N1:BF" & Line)
.Header = xlGuess
.MatchCase = False
.Orientation = xlLeftToRight
.Apply
End With
End Sub
AutoFill method requires that the destination must include the source range. Proper Syntax for autofill as follows for example only.
Set sourceRange = Worksheets("Sheet1").Range("A1:A2")
Set fillRange = Worksheets("Sheet1").Range("A1:A20")
sourceRange.AutoFill Destination:=fillRange
Accordingly I have modified your program and hope it should work fine.
Sub randomCol()
Dim Line As Integer
Line = LastRow + 1
Range("N154").Select
ActiveCell.FormulaR1C1 = "=RAND()"
Set SourceRange = Worksheets("Sheet1").Range("N154") 'Changed you can set the range required by you.
Dim randomRange As String
randomRange = "N" & Line & ":BF" & Line
Set fillRange = Worksheets("Sheet1").Range("n1:BF154") 'Set fill range appropriately but should include source range
MsgBox randomRange
'changed
'Selection.AutoFill Destination:=Range(randomRange), Type:=xlFillDefault
SourceRange.AutoFill Destination:=fillRange
Range("N2:BF" & Line).Select
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("N" & LastRow + 1), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").Sort
.SetRange Range("N1:BF" & Line)
.Header = xlGuess
.MatchCase = False
.Orientation = xlLeftToRight
.Apply
End With
End Sub
edit after OP's specification that LastRow is a function returning ActiveSheet.Cells(Rows.Count, "L").End(xlUp).Row
the destination must include the source range, while the latter is "N154" and the former are cells in row Line between columns "N" and "BF", so it'd work only if Line is 154.
moreover it's best to define both Line and LastRow() as of Long type instead of Integer
so that your code could change like follows:
Sub randomCol()
Dim Line As Long
Line = Lastrow + 1
Range("N" & Line).Select
ActiveCell.FormulaR1C1 = "=RAND()"
Dim randomRange As String
randomRange = "N" & Line & ":BF" & Line
MsgBox randomRange
Selection.AutoFill Destination:=Range(randomRange), Type:=xlFillDefault
Range("N2:BF" & Line).Select
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("N" & Line), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").Sort
.SetRange Range("N1:BF" & Line)
.Header = xlGuess
.MatchCase = False
.Orientation = xlLeftToRight
.Apply
End With
End Sub
Function LastRow() As Long
LastRow = ActiveSheet.Cells(Rows.count, "L").End(xlUp).Row
End Function
but you may also consider:
to avoid selections and activation
there's no need for Autofill actually, since you're simply pasting a formula
so your code can become:
Sub randomCol2()
Dim Line As Long
With ActiveWorkbook.Worksheets("Sheet1")
Line = .Cells(.Rows.count, "L").End(xlUp).Row + 1
.Columns("N:BF").Rows(Line).FormulaR1C1 = "=RAND()"
With .Sort
.SortFields.Clear
.SortFields.Add Key:=Range("N" & Line), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.SetRange Range("N1:BF" & Line)
.Header = xlGuess
.MatchCase = False
.Orientation = xlLeftToRight
.Apply
End With
End With
End Sub

Runtime Error 91 when sorting

I am writing a subroutine to dynamically copy 2 columns from one sheet to another. These column lengths might change from one report to another.
Here is the code:
Sub getAnalystsCount()
Dim rng As Range
Dim dict As Object
Set dict = CreateObject("scripting.dictionary")
Dim varray As Variant, element As Variant
Set ws = ThisWorkbook.Worksheets("ReportData")
With ws
Worksheets("ReportData").Activate
Columns("E:E").Select
ActiveWorkbook.Worksheets("ReportData").AutoFilter.Sort.SortFields.Clear
ActiveWorkbook.Worksheets("ReportData").AutoFilter.Sort.SortFields.Add Key:= _
Range("E1"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With ActiveWorkbook.Worksheets("ReportData").AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
lastrow = .Range("A" & .Rows.Count).End(xlUp).Row
'~~> Set First row
firstrow = 2
'~~> Set your range
Set rng = .Range("E" & firstrow & ":E" & lastrow)
varray = rng.Value
'Generate unique list and count
For Each element In varray
If dict.Exists(element) Then
dict.Item(element) = dict.Item(element) + 1
Else
dict.Add element, 1
End If
Next
End With
Set ws = ThisWorkbook.Worksheets("Analysts")
With ws
Worksheets("Analysts").Activate
'Paste report somewhere
ws.Range("A3").Resize(dict.Count, 1).Value = _
WorksheetFunction.Transpose(dict.Keys)
ws.Range("B3").Resize(dict.Count, 1).Value = _
WorksheetFunction.Transpose(dict.Items)
......
the error is in this line:
ActiveWorkbook.Worksheets("ReportData").AutoFilter.Sort.SortFields.Clear
Replace your below code
Columns("E:E").Select
ActiveWorkbook.Worksheets("ReportData").AutoFilter.Sort.SortFields.Clear
ActiveWorkbook.Worksheets("ReportData").AutoFilter.Sort.SortFields.Add Key:= _
Range("E1"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With ActiveWorkbook.Worksheets("ReportData").AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
With the below code
Columns("E:E").Select
lastrow1 = .Range("E" & .Rows.Count).End(xlUp).Row
ActiveWorkbook.Worksheets("ReportData").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("ReportData").Sort.SortFields.Add Key:=Range("E1") _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("ReportData").Sort
.SetRange Range("E2:E" & lastrow1)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
startCell = Range("A1").Address
endCell = Range("E100000").End(xlUp).Address
ActiveWorkbook.Worksheets("ReportData").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("ReportData").Sort.SortFields.Add Key:=Range("E1"), SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortTextAsNumbers
With ActiveWorkbook.Worksheets("ReportData").Sort
.SetRange Range(startCell,endCell)
.Header = xlNo
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Obviously this is rough, you will need to make it your own, but it will allow you to sort the E column which is what your initial code looks like it was trying to do.
The Range.Sort method can be used for a quick one column sort and discards much of the verbose code produced when recording a worksheet sort operation. Without an active AutoFilter, this is the better way to go.
Sub getAnalystsCount()
Dim el As Long, ws As Worksheet
Dim dict As Object
Dim varray As Variant
Set dict = CreateObject("scripting.dictionary")
'don't know what is in column E but this might be helpful
'dict.comparemode = vbTextCompare 'non-case-sensitive
Set ws = ThisWorkbook.Worksheets("ReportData")
With ws
'this is not necessary inside a With ... End With block
'Worksheets("ReportData").Activate
With .Range("A1").CurrentRegion
'this quick code line is all you need
.Cells.Sort Key1:=.Columns(5), Order1:=xlAscending, _
Orientation:=xlTopToBottom, Header:=xlYes
'resize to # of rows -1 × 1 column and shift 1 row down and over to column E
With .Resize(.Rows.Count - 1, 1).Offset(1, 4)
'store the raw values
varray = .Value2
End With
End With
End With 'done with the ReportData worksheet
'Generate unique list and count
'I prefer to work with LBound and UBound
For el = LBound(varray, 1) To UBound(varray, 1)
If dict.Exists(varray(el, 1)) Then
dict.Item(varray(el, 1)) = dict.Item(varray(el, 1)) + 1
Else
dict.Add Key:=varray(el, 1), Item:=1
End If
Next el
Set ws = ThisWorkbook.Worksheets("Analysts")
With ws
'this is not necessary inside a With ... End With block
'Worksheets("Analysts").Activate
'might want to clear the destination cell contents first if there is something there
if application.counta(.Range("A3:B3") = 2 then _
.Range("A3:B" & .Cells(Rows.Count, "B").End(xlUp).Row).ClearContents
'Paste report somewhere
.Range("A3").Resize(dict.Count, 1).Value = _
WorksheetFunction.Transpose(dict.Keys)
.Range("B3").Resize(dict.Count, 1).Value = _
WorksheetFunction.Transpose(dict.Items)
End With 'done with the Analysts worksheet
End Sub
I prefer to work with the LBound and UBound functions to determine the scope of an array.
When you are inside a With ... End With statement, use the . to note the parent worksheet and discard the Range .Activate method and ws variable.

How to do a sorting in VBA?

I have a table with header and data in columns from A to D with changing row number (number of rows is more than 66800). I'd like to sort data from Z to A order by column C.
There are a lot of different solutions in VBA on internet, but none worked correctly for me.
My code gives me an error:
Sub SortDescending()
Dim lRow As Long
Dim lCol As Long
lRow = Sheets("atm_hh").Cells(Rows.Count, 1).End(xlUp).Row
lCol = Sheets("atm_hh").Cells(1, Columns.Count).End(xlToLeft).Column
With Sheets("atm_hh")
.Select
.Range("A2:" & Cells(lRow, lCol).Address).Sort Key1:=Range("C2"), _
Order1:=xlDescending, _
Header:=xlGuess, _
OrderCustom:=1, _
MatchCase:=False, _
Orientation:=xlTopToBottom
End With
End Sub
try
Sub SortDescending()
Dim sh As Worksheet
Set sh = Sheets("atm_hh")
Dim lRow As Long
Dim lCol As Long
lRow = sh.Cells(Rows.Count, 1).End(xlUp).Row
lCol = sh.Cells(1, Columns.Count).End(xlToLeft).Column
Dim cell As Range
For Each cell In sh.Range("C2:C" & lRow)
cell = WorksheetFunction.Substitute(cell, ",", ".")
Next
Columns("C:C").NumberFormat = "0.0"
sh.Cells.AutoFilter
sh.AutoFilter.Sort.SortFields.Clear
sh.AutoFilter.Sort.SortFields.Add Key:=Range("C1:C" & lRow), _
SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
With sh.AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
sh.AutoFilterMode = False
End Sub