Creating new sheet works only first and for the next data it throws an error 'Run Time Error 9' - excel

I am trying to create a program that will copy a row based on the value in column P into another sheet in the same workbook. Column P can be:
Design
Production
Process
Safety
Quality
Purchasing
I want the program to look at the Column P and if it says "design" then copy and paste that row into the sheet labeled "Design" and so on and so forth.
Can anyone help me?
Line
Set tosheet = Worksheets("" & fromsheet.Cells(r, "P"))
works fine initially then throw off an error of 'Run Time Error 9 after the first iteration.
Sub lars_ake_copy_rows_to_sheets()
Dim firstrow, lastrow, r, torow As Integer
Dim fromsheet, tosheet As Worksheet
firstrow = 2
Set fromsheet = ActiveSheet
lastrow = ActiveSheet.Cells(Rows.Count, "P").End(xlUp).Row
For r = firstrow To lastrow
If fromsheet.Cells(r, "P") <> "" Then 'skip rows where column P is empty
On Error GoTo make_new_sheet
Set tosheet = Worksheets("" & fromsheet.Cells(r, "P"))
On Error GoTo 0
GoTo copy_row
make_new_sheet:
Set tosheet = Worksheets.Add(After:=Worksheets(Worksheets.Count))
tosheet.Name = fromsheet.Cells(r, "P")
copy_row:
torow = tosheet.Cells.SpecialCells(xlCellTypeLastCell).Row + 1
fromsheet.Cells(r, 1).EntireRow.Copy
tosheet.Cells(torow, 1).PasteSpecial Paste:=xlPasteValues
End If
Next r
Application.CutCopyMode = False
fromsheet.Activate
End Sub
I want this code to create new worksheet if already not created.
But this code create new sheet for only 1st record of column p which is design, if this sheet not created before but for the next record which is Production if the worksheet by the name of Production is not created before then this code throw an error of Run Time 9. Anyone who can fix this for me.

As I mentioned in my comment, you are not properly handling the "Going out of the error handler". You can look Good Patterns For VBA Error Handling for some details on how handling errors.
This code should solve your problem (but I didn't test it)
Sub lars_ake_copy_rows_to_sheets()
Dim firstrow As Long, lastrow As Long, r As Long, torow As Long
Dim fromsheet As Worksheet, tosheet As Worksheet
firstrow = 2
Set fromsheet = ActiveSheet
lastrow = ActiveSheet.Cells(Rows.Count, "P").End(xlUp).Row
For r = firstrow To lastrow
If fromsheet.Cells(r, "P") <> "" Then 'skip rows where column P is empty
On Error GoTo make_new_sheet
Set tosheet = Worksheets("" & fromsheet.Cells(r, "P"))
On Error GoTo 0
torow = tosheet.Cells.SpecialCells(xlCellTypeLastCell).Row + 1
fromsheet.Cells(r, 1).EntireRow.Copy
tosheet.Cells(torow, 1).PasteSpecial Paste:=xlPasteValues
End If
Next r
Application.CutCopyMode = False
fromsheet.Activate
Exit Sub
make_new_sheet:
Set tosheet = Worksheets.Add(After:=Worksheets(Worksheets.Count))
tosheet.Name = fromsheet.Cells(r, "P")
resume next
End Sub

Related

While Deleting Repeated Headers

Using the below code to delete the repeated headers from combined into one excel but getting error.
Application.Goto DestSh.Cells(1)
' AutoFit the column width in the summary sheet.
DestSh.Columns.AutoFit
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
Dim xWs As Worksheet
Application.ScreenUpdating = False
Application.DisplayAlerts = False
For Each xWs In Application.ActiveWorkbook.Worksheets
If xWs.Name <> "Combined Sheet" Then
xWs.Delete
End If
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True
Dim lstRow As Integer, ws As Worksheet
Set ws = ThisWorkbook.Sheets("Combined Sheet")
With ws
lstRow = .Cells(rows.Count, "B").End(xlUp).Row ' Or "C" or "A" depends
.Range("A1:E" & lstRow).SpecialCells(xlCellTypeBlanks).EntireRow.Delete ERROR GETTING HERE
End With
enter image description here
Please add "on error resume next" before using SpecialCells method and after using use "on error GoTo 0"
.SpecialCells(xlCellTypeBlanks)
This expression gives you every blank cell in a Range. Rows that you are going to delete includes non-blank cells also, so vba will not delete them.
You can try a RemoveDuplicates method like:
.Range("A1:E" & lstRow).RemoveDuplicates Columns:=Array(1, 2, 3, 4, 5), Header :=xlNo
It can be not safe to use the method, but for your task it's may be Ok.
This sub is a safe variant to delete your headers. you can call the sub by the Call statement, and don't forget to set your header address.
Call removeHeaders()
Sub removeHeaders()
Dim hdrRangeAdr As String
Dim l, frstRow, lstRow, offsetRow As Long
Dim counter, row1, row2 As Integer
Dim item As Variant
Dim hdrRng, tRng As Range
Dim ws As Worksheet
' setting of the first header address
hdrRangeAdr = "A1:O1"
Set ws = ThisWorkbook.Sheets("Combined Sheet")
' setting of the header range
Set hdrRng = ws.Range(hdrRangeAdr)
hdrRowsQty = hdrRng.Rows.Count
frstRow = hdrRng.Row
lstRow = hdrRng.Parent.UsedRange.Rows.Count + frstRow
'checking row by row
For l = 1 To lstRow - frstRow
offsetRow = l + hdrRowsQty - 1
counter = 0
' compare row/rows value with the header
For Each item In hdrRng.Cells
If item = item.Offset(offsetRow, 0) Then
counter = counter + 1
End If
Next
' if they are equial then delete rows
If counter = hdrRng.Count Then
row1 = frstRow + offsetRow
row2 = row1 + hdrRowsQty - 1
ws.Rows(row1 & ":" & row2).Delete Shift:=xlUp
'reseting values as rows qty reduced
l = 1
lstRow = hdrRng.Parent.UsedRange.Rows.Count + frstRow
End If
Next
Set ws = Nothing
Set hdrRng = Nothing
End Sub
Good luck

Getting error 'object variable or With block variable not set' when trying to run sub

I did not create the code but am trying to troubleshoot an excel file and the original author is not available (layed off from company and not willing to help).
The following line is generating the error, 'object variable or With block variable not set'
Private Sub Workbook_Open()
Sheet1.Starttimer
End Sub
I looked at Sheet1 code and found the below, so I'm not sure what the problem is:
Sub Starttimer()
Application.DisplayAlerts = False
If Not Sheet4.ListObjects(1).DataBodyRange Is Nothing Then
Sheet4.ListObjects(1).DataBodyRange.Rows.Delete
End If
ActiveWorkbook.RefreshAll
Application.Calculate
SetProductionZeros
ActiveWorkbook.Save
ThisWorkbook.Close
End Sub
UPDATE
After setting the debug to break on all errors, the line that causes the error appears to be "r = Sheet4.ListObjects(1).DataBodyRange.Rows.Count" from the sub below:
Sub SetProductionZeros()
Dim tb1 As ListObject
Dim x As Long
Dim y As Long
Dim r As Long
Dim c As Long
'Set path for Table variable'
Set tb1 = Sheet4.ListObjects(1)
Sheet4.Activate
r = Sheet4.ListObjects(1).DataBodyRange.Rows.Count
c = Sheet4.ListObjects(1).DataBodyRange.Columns.Count
'Loop Through Each DataBody Row in Table
For y = 1 To r
'Loop Through Each Column in Table
For x = 1 To c
If IsEmpty(Sheet4.ListObjects(1).DataBodyRange.Cells(y, x)) Then Sheet4.ListObjects(1).DataBodyRange.Cells(y, x) = 0
Next x
Next y
Sheet4.Columns(5).EntireColumn.Delete
Dim lastrow As Long, lastcol As Long, thiscol As Long
Dim totalrow As Long, totalcol As Long, thisrow As Long
totalrow = 7 + Sheet4.ListObjects(1).Range.Rows.Count
totalcol = 2 + Sheet4.ListObjects(1).Range.Columns.Count
On Error GoTo Errorcatch
'lastrow = Cells(Rows.Count, 1).End(xlUp).row
'lastcol = Cells(1, Columns.Count).End(xlToLeft).Column
Sheet4.Cells(totalrow, 3).Value = "Total"
For thiscol = 5 To totalcol - 1
Sheet4.Cells(totalrow, thiscol).Select
ActiveCell.Value = WorksheetFunction.Sum(Sheet4.Range(Sheet4.Cells(1, ActiveCell.Column), ActiveCell))
Next
Sheet4.Rows(totalrow).Font.Bold = True
Sheet4.Cells(7, totalcol).Value = "Total"
For thisrow = 8 To totalrow
Sheet4.Cells(thisrow, totalcol).Select
ActiveCell.Value = WorksheetFunction.Sum(Sheet4.Range(Sheet4.Cells(ActiveCell.row, 5), ActiveCell))
Next
Sheet4.Columns(totalcol).Font.Bold = True
'Sheet4.Columns(2).HorizontalAlignment = xleft
For y = totalrow To 8 Step -1
If Sheet4.Cells(y, 2) = "T" And Sheet4.Cells(y, totalcol).Value = 0 Then
Sheet4.Rows(y).EntireRow.Delete
End If
Next
Exit Sub
Errorcatch:
MsgBox Err.Description
End Sub
Follow the logic:
When you open the workbook, you call Sheet1.StartTimer
Sheet1.StartTimer includes
If Not Sheet4.ListObjects(1).DataBodyRange Is Nothing Then
Sheet4.ListObjects(1).DataBodyRange.Rows.Delete
End If
At this point Sheet4.ListObjects(1).DataBodyRange will be Nothing (because you deleted all its rows)
Then you call SetProductionZeros
SetProductionZeros includes r = Sheet4.ListObjects(1).DataBodyRange.Rows.Count
But because Sheet4.ListObjects(1).DataBodyRange is Nothing this throws an error. (Same applies to .Columns.Count)
You can wrap references to DataBodyRange in
If Not Sheet4.ListObjects(1).DataBodyRange Is Nothing Then
' ...
End If
but you need to consider what you want to achieve when there are no rows in Sheet4.ListObjects(1)
This error seems to indicate that you are assigning an object to r without set. Nothing is an object. So in your case you are likely getting Nothing from Sheet4.ListObjects(1).DataBodyRange.Rows.Count. After Set tb1 = Sheet4.ListObjects(1), verify that tb1 is not nothing.
FYI, For code clarity, you should be using r = tb1.DataBodyRange.Rows.Count (same for c =).

Remove rows if existing in another sheet

I'm trying to search sheet_A for values in sheet_B / column A (starting from A2) and if they exist in sheet_A (column C, starting in C2) they get removed from sheet_A.
Sub Remover_Duplicados()
'Backup to another sheet
Const strSheetName As String = "BKP_sheet"
Set wsTest = Nothing
On Error Resume Next
Set wsTest = ActiveWorkbook.Worksheets(strSheetName)
On Error GoTo 0
If wsTest Is Nothing Then
Worksheets.Add.Name = strSheetName
End If
Sheets("sheet_A").Range("A1:BK3500").Copy Destination:=Sheets(strSheetName).Range("A1")
'Search and destroy
Dim searchableRange As Range
Dim toRemoveRange As Range
Dim lLoop As Long
Set searchableRange = Worksheets("sheet_B").Range("A2", "A3500")
Set toRemoveRange = Worksheets("sheet_A").Range("C2", "C3500")
For lLoop = searchableRange.Rows.Count To 2 Step -1
If WorksheetFunction.CountIf(searchableRange, toRemoveRange(lLoop).Value) > 0 Then
Worksheets("sheet_A").Rows(lLoop).Delete shift:=xlUp
End If
Next lLoop
End Sub
Sheet A, B and the result:
Some don't get removed.
I've gone through your code and amended it slightly to be more dynamic with the ranges, I've also used an Array to populate the values to be removed and then looped though that array to decide whether the row should be deleted or not:
Sub Remover_Duplicados()
'Backup to another sheet
Const strSheetName As String = "BKP_sheet"
Dim wsA As Worksheet: Set wsA = ThisWorkbook.Worksheets("Sheet_A")
Dim wsB As Worksheet: Set wsB = ThisWorkbook.Worksheets("Sheet_B")
Dim arrToRemove()
Set wsTest = Nothing
On Error Resume Next
Set wsTest = ThisWorkbook.Worksheets(strSheetName)
On Error GoTo 0
If wsTest Is Nothing Then
Worksheets.Add.Name = strSheetName
End If
LastRowA = wsA.Cells(wsA.Rows.Count, "A").End(xlUp).Row
wsA.Range("A1:BK" & LastRowA).Copy Destination:=Sheets(strSheetName).Range("A1")
LastRowB = wsB.Cells(wsB.Rows.Count, "A").End(xlUp).Row
arrToRemove = wsB.Range("A2:A" & LastRowB).Value
For iRow = LastRowA To 2 Step -1
For iArray = LBound(arrToRemove) To UBound(arrToRemove)
If wsA.Cells(iRow, "C").Value = arrToRemove(iArray, 1) Then
wsA.Rows(iRow).EntireRow.Delete shift:=xlUp
End If
Next iArray
Next iRow
End Sub

Autofill error on Excel VBA code

trying to work the VBA autofill function (end of code block) but I am running into an error everytime I try the execute the code. I get "Autofill method of Range class failed". Can someone help me out here? Searched google but nothing works. Probably overlooking something small. Thanks in advance for the help.
Sub UpdateLAB() '---> still need to work on this
'author: css
Dim SalesBook As Workbook
Dim ws2 As Worksheet
Dim wspath As String
Dim n As Integer
Dim FirstRow As Long
Dim LastRow As Long
Dim LastRow2 As Long
Dim sourceCol As Integer
Dim RefCellValue2 As String
Dim ps As String
Dim Platts As Workbook
Application.Calculation = xlCalculationAutomatic
Set SalesBook = Workbooks("ALamb.xlsm")
Set ws2 = SalesBook.Worksheets("US LAB Price")
wspath = "C:\Users\scullycs\Desktop\P&O\Platts Data\Platts 2016.xlsm"
FirstRow = ws2.Range("B4").Row
LastRow = ws2.Range("B4").End(xlDown).Row + 1
LastRow2 = ws2.Range("c4").End(xlDown).Row
sourceCol = 2 'refers to the column your data is in
For n = FirstRow To LastRow
RefCellValue2 = Cells(n, sourceCol).Value
If IsEmpty(RefCellValue2) Or RefCellValue2 = "" Then
Cells(n, sourceCol).Offset(0, -1).Copy
SalesBook.Worksheets("Control Page").Range("C8").PasteSpecial (xlPasteValues)
Else
End If
Next n
ps = SalesBook.Worksheets("Control Page").Range("C9").Text
Set Platts = Workbooks.Open(wspath)
Platts.Worksheets(ps).Activate
Range("A13").End(xlDown).Select
Selection.Offset(0, 11).Select
If Selection.Value = "" Then
MsgBox ("Platts data does not exist")
Platts.Close
Else
Selection.Copy
Set SalesBook = Workbooks("ALamb.xlsm")
SalesBook.Worksheets("US LAB Price").Range("b1").End(xlDown).Offset(1, 0).PasteSpecial (xlPasteValues)
'this is where I get the error
SalesBook.Worksheets("US LAB Price").Range("c4").AutoFill Destination:=Range("C4:C" & LastRow2), Type:=xlFillDefault
Platts.Close
End If
End Sub
Most probably your ranges are not overlapping OR range is too big. In case you want to refer, link.
Check the value of LastRow2.
Make sure the fill range is from same sheet to make them over lapping. To do so break your statement into simple steps. Later you can combine.
Will suggest to break down the statement into
Set SourceRange = SalesBook.Worksheets("US LAB Price").Range("C4:C4")
Set fillRange = SalesBook.Worksheets("US LAB Price").Range("C4:C" & LastRow2)
SourceRange.AutoFill Destination:=fillRange, Type:=xlFillDefault

Taking a Reference cell, searching through 2nd sheet, replace data with same identifier

I decided to change my tact.
I decided to take another shot at this, but in a new way. I did a weekend long Google marathon and found I believe my answer,
Option Explicit
Sub DataUpdate()
Dim rFind As Long, NR As Long, LR As Long, LC As Long
LR = Range("C" & Rows.Count).End(xlUp).Row
LC = Cells(2, Columns.Count).End(xlToLeft).Column
NR = LR + 1
On Error Resume Next
rFind = Range("A25:A" & LR).Find(Range("A1")).Row
On Error GoTo 0
If rFind = 0 Then
If MsgBox("Customer record not found, add to dataset?", vbYesNo + vbQuestion) = vbYes Then
Range("A2", Cells(LC, 2)).Copy
Range("C" & NR).PasteSpecial xlPasteValues
Range("A1", Cells(1, LC)).ClearContents
Exit Sub
End If
Else
Range("A2", Cells(2, LC)).Copy
Range("A" & rFind).PasteSpecial xlPasteValues
Range("A1", Cells(1, LC)).ClearContents
End If
End Sub
Looking at this I just want a cleaner explanation instead of just taking it as is, and using it without knowing what I am doing.
Here is the sheet it is on:
http://dl.dropbox.com/u/3327208/Excel/Replace.zip
If I add this to my code, regurgitate this code I see I can do this, I just want to verify that this is correct.
Option Explicit
Sub PENCMR()
Dim i As Integer
With Application
.ScreenUpdating = False
End With
'Internal NCMR
Dim wsPE As Worksheet
Dim wsNDA As Worksheet
'Copy Ranges
Dim c As Variant
'Paste Ranges
Dim p As Range
'Setting Sheet
Set wsPE = Sheets("Print-Edit NCMR")
Set wsNDA = Sheets("NCMR Data")
Set p = wsPE.Range("A54:U54")
With wsPE
c = Array(.Range("AG2"), .Range("B11"), .Range("B14"), .Range("B17"), .Range("B20"), .Range("B23") _
, .Range("Q11"), .Range("Q14"), .Range("Q17"), .Range("Q20"), .Range("R25"), .Range("V23") _
, .Range("V25"), .Range("V27"), .Range("B32"), .Range("B36"), .Range("B40"), .Range("B44") _
, .Range("D49"), .Range("L49"), .Range("V49"))
End With
For i = LBound(c) To UBound(c)
p(i + 1).Value = c(i).Value
Next
With wsNDA
Dim rFind As Long, NR As Long, LR As Long, LC As Long
LR = Range("C" & Rows.Count).End(xlUp).Row
LC = Cells(2, Columns.Count).End(xlToLeft).Column
NR = LR + 1
rFind = wsNDA.Range("A:A" & LR).Find(Range("A54")).Row
Range("A54", Cells(2, LC)).Copy
Range("A" & rFind).PasteSpecial xlPasteValues
Range("A54", Cells(1, LC)).ClearContents
End With
With Application
.ScreenUpdating = True
End With
End Sub
The code runs, but it doesn't come back with an error, yet it doesn't run completely. It hits to the point where it drags everything down, then it seems to die there. Can someone help me find out why it doesn't do what I think it should do, which is copy the row, search for the number in column A, and then write over it with the correct data in row 54...
I know something is wrong, but I don't have the skills to figure out what, if someone can help me it be greatly appreciated.
I am not 100% sure of what you are trying to achieve but there are several problems in your code:
Instead of
Set p = wsPE.Range("A54:U54")
For i = LBound(c) To UBound(c)
p(i + 1).Value = c(i).Value
Next
You probably mean
Set p = wsPE.Range("A54")
For i = LBound(c) To UBound(c)
p.Offset(0, i) = c(i)
Next
In your With wsNDA block, you need to put . before the Range and Cells, for example:
.Range("A54", .Cells(2, LC)).Copy
Finally:
I would remove the ScreenUpdating statements for now, and run the code in debug mode (F8) to see step by step what the code is doing and check the values of your variables if necessary use "Add Watch"
I would avoid using a range to store temporary data. You could use a 2D array instead, like this for example:
Dim data As Variant
Redim data(1 To 1, 1 To 21) As Variant
for i = xx To yy
data(1,i+1) = c(i)
Next i
yourTargetCell.Resize(1, UBound(data,2)) = data

Resources