Excel VBA run-time Error '424' Object Required - vba

I've encountered a problem run-time Error '424' object required.
This is the solution i've acquired from my previous post, after spending some time to troubleshoot, i still can't solve it. Thanks to #rawrplus for the solution and I am still learning Excel vba.
Link: Excel VBA Cutting rows from workbook1 and paste it in workbook2
Option Explicit
Private Sub table_to_table()
'Declaration
Dim wb1 As Workbook
Dim wb2 As Workbook
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set wb1 = Workbooks.Open("C:\Documents and Settings\lye.yan.nian\My Documents\testingmacro2.xlsx")
Set wb2 = Workbooks.Open("C:\Documents and Settings\lye.yan.nian\My Documents\testingmacro3.xlsx")
Set ws1 = wb1.Sheets("Test2")
Set ws2 = wb2.Sheets("Test1")
Dim res_lr As Long
Dim lr2 As Long
lr2 = ws2.Cells(Rows.Count, 2).End(xlUp).Row
MsgBox lr2 /* Testing is done as i can get this value */
Dim r As Range, ary
Set r = ws1.Application.Range(Cells(1, 2), Cells(1, 6)) /* Tested working as i can get this value too*/
ary = Application.Transpose(Application.Transpose(r.Value))
MsgBox Join(ary, " ")
Dim copyrange As Range
Dim i As Long /* This is declared */
For i = 2 To lr2
MsgBox i /* i did some testing on this and removed the below code */
Set copyrange = ws2.Application.Range(Cells(i, 2), Cells(i, 6)).Copy /* This is the part where i got the error i can't figure out why*/
res_lr = ws2.Cells(Rows.Count, 8).End(xlUp).Row
ws2.Range(Cells(res_lr, 8), Cells(res_lr, 12)).PasteSpecial xlPasteValues
Set copyrange = ws1.Application.Range(Cells(i, 2), Cells(i, 6)).Copy
ws2.Range(Cells(res_lr + 1, 8), Cells(res_lr + 1, 12)).PasteSpecial xlPasteValues
Next i
wb1.Close
End Sub

Set copyrange = ws2.Application.Range(Cells(i, 2), Cells(i, 6)).Copy
Range.Copy does not return a Range object reference that you can assign to a Range object variable. It's a member method that takes the contents of a range, and copies it into the clipboard.
Your copyrange isn't the result of the .Copy operation, it's the result of a ws2.Application.Range(...) call... which is malformed.
This might fix it1:
Set copyrange = ws2.Application.Range(Cells(i, 2), Cells(i, 6))
copyrange.Copy
....and this is what you probably meant to be doing:
Set copyrange = ws2.Range(ws2.Cells(i, 2), ws2.Cells(i, 6))
copyrange.Copy
1 it's bad code, because you have an explicit Worksheet reference (ws2), and from there you go to Application to grab whatever worksheet is currently active, and work off that - so you think you're working off ws2 when in reality you're working off whatever ActiveSheet currently happens to be. Same with the unqualified Cells calls, which implicitly refer to Application.ActiveSheet.Cells.

Try adding the word set on the line where it throws error.
Example: set x = 'something

Related

Vlookup between workbooks doesn't work in VBA

I wish to vlookup a pivot table from one workbook to another but I get the following error:
The source workbook looks like this (Sheet Piv_Repos):
The target workbook looks like this (Sheet Nominator):
This is my code:
Dim sourceBook3 As Workbook
Dim Srepfile3 As String
MsgBox ("Select Adjusted data")
Srepfile3 = Application.GetOpenFilename
Set sourceBook3 = Application.Workbooks.Open(Srepfile3, UpdateLinks:=0)
Dim sourcesheet As Worksheet
Set sourcesheet = sourceBook3.Sheets("Piv_Repos")
Dim destSheet1 As Worksheet
Set destSheet1 = ThisWorkbook.Sheets("Nominator")
Dim lastrow As Long
lastrow = destSheet1.Range("B" & Rows.Count).End(xlUp).Row
Set myrange = sourcesheet.Range("A:B")
For i = 35 To lastrow
destSheet1.Cells(i, 8) = Application.WorksheetFunction.VLookup(destSheet1.Cells(i, 2), myrange, 2, False)
Next I
This seemingly exact code works fine when I use it between other workbooks though.
Really appreciate help. Thank you.
The problem is in the WorksheetFunction, not in the two workbooks.
Try something as small as these:
Option Explicit
Sub TestMeWS()
Dim myRange As Range
Set myRange = Worksheets(1).Range("A:B")
Debug.Print Application.WorksheetFunction.VLookup("something", myRange, 2, 0)
End Sub
Sub TestMeAPP()
Dim myRange As Range
Set myRange = Worksheets(1).Range("A:B")
Debug.Print Application.VLookup("something", myRange, 2, 0)
End Sub
You would notice, that if "something" is not present in myRange, you get the 1004 error in the TestMeWS. In the second case, you get error 2042 in the immediate window, but it works.

Paste data on new sheet and all cells are hidden

By some reason every time I run this code it hides all the data on the new sheet.
The row heights are set to 0.
I have to use the mouse to pull on the row height to make the last cell visible then from there I can click on a cell and "get up" to the data.
How can I fix this? It's very annoying.
Is it something with my code or do I need to set the row height after pasting data like this?
NumMax = NumMax + 1 'there is more code above that sets NumMax
ThisWorkbook.Activate
ThisWorkbook.Sheets.Add(After:=wb.Sheets(wb.Sheets.Count)).Name = "XCFIL_" & NumMax
ThisWorkbook.Sheets.Add(After:=wb.Sheets(wb.Sheets.Count)).Name = "Resultat_" & NumMax
Sheets("XCFIL").Activate
Cells.Copy
Sheets("XCFIL_" & NumMax).Activate
Range("A1").PasteSpecial xlPasteAll
Range("A1").Select ' a try to get up in the sheet, but it does not work
EDIT: Code panes:
Per the chat, a quick solution is:
'Other option is to simply copy/paste the sheet
NumMax = NumMax + 1 'there is more code above that sets NumMax
With ThisWorkbook
.Sheets("XCFIL").Copy After:=.Sheets(.Sheets.Count)
ActiveSheet.Name = "XCFIL_" & NumMax
End With
But, I was working on the below, which may work as well.
Sub t()
Dim originWS As Worksheet, destWS As Worksheet
Dim NumMax As Long
NumMax = NumMax + 1 'there is more code above that sets NumMax
With ThisWorkbook
Set originWS = .Sheets("XCFIL")
Set destWS = .Sheets.Add(After:=.Sheets(.Sheets.Count))
destWS.Name = "XCFIL_" & NumMax
End With
Dim copyRng As Range
Dim lastCol As Long, lastRow As Long
With originWS
lastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
lastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
Set copyRng = .Range(.Cells(1, 1), .Cells(lastRow, lastCol)) 'assuming your data starts in A1
End With
destWS.Range(destWS.Cells(1, 1), destWS.Cells(lastRow, lastCol)).Value = _
copyRng.Value
End Sub
And as a note, it's always a good idea to avoid using .Select/.Activate.
Also, this doesn't get to the very quirky issue of the rows hiding on PasteSpecial. ...but oh well, if it works, it works.

VBA Error 1004 While Setting Ranges Equal

No matter what I do I can't get this error to go away. This current version of code is an effort to completely spell out each reference. I'm getting the error after the 'set range for BOM components' line. Most topics point out that using .Range(Cells()) without specifying where the cells are located will lead to this error, but I've done the complete overkill referencing so I'm not sure why it still errors out. Only one workbook here as well.
#Scott Craner #BruceWayne I figured it out finally; the Oracle report comes out in a pretty f****d up format, and the first sheet in the loop was causing the ranges to actually be unequal. As soon as I deleted that sheet it ran perfectly.
Sub Macro3()
'
' Macro3 Macro
'
' Keyboard Shortcut: Ctrl+c
'
Dim ws As Worksheet
Dim lastRow As Integer
Dim summaryRow As Integer
Dim currentSheetRows As Integer
Dim i As Integer
Dim j As Integer
summaryRow = 2
For Each ws In ActiveWorkbook.Worksheets
If ws.Range("L3") = "" Then
currentSheetRows = ws.Cells(ws.Rows.Count, "F").End(xlUp).Row
i = summaryRow
j = summaryRow
'set range for item # and item UOM'
For j = summaryRow To (summaryRow + (currentSheetRows - 3))
Sheets("Summary").Cells(j, 1).Value = ws.Cells(2, 1).Value
Next j
For i = summaryRow To (summaryRow + (currentSheetRows - 3))
Sheets("Summary").Cells(i, 2).Value = ws.Cells(2, 1).Value
Next i
'set range for BOM components'
ThisWorkbook.Worksheets("Summary").Range(ThisWorkbook.Worksheets("Summary").Cells(summaryRow, 3), ThisWorkbook.Worksheets("Summary").Cells((summaryRow + (currentSheetRows - 3)), 6)).Value = ThisWorkbook.Worksheets(ws.Name).Range(ThisWorkbook.Worksheets(ws.Name).Cells(3, 6), ThisWorkbook.Worksheets(ws.Name).Cells(currentSheetRows, 9)).Value
summaryRow = summaryRow + currentSheetRows
End If
Next ws
End Sub
Woah - first, check that the ranges are equal sizes. Then, I highly suggest using some variables for your sheet names and ranges:
Sub t()
Dim summaryWS As Worksheet
Dim otherWS As Worksheet
Set summaryWS = ThisWorkbook.Sheets("Summary")
Set otherWS = ThisWorkbook.Worksheets(ws.Name)
Dim copyRng As Range, pasteRng As Range
With summaryWS
Set copyRng = .Range(.Cells(SummaryRow, 3), .Cells((SummaryRow + (currentSheetRows - 3)), 6))
End With
With otherWS
Set pasteRng = .Range(.Cells(3, 6), .Cells(currentSheetRows, 9))
End With
pasteRng.Value = copyRng.Value
End Sub
Does that help your issue?
You're using
ActiveWorkbook
To set the loop current sheet
and then
ThisWorkbook
in the copy/paste values statement that errors
It may then be the workbook you're running the macro from (ThisWorkbook) differs from the currently active one (ActiveWorkbook) whose worksheets you're looping through
In such a case just change ThisWorkbook to ActiveWorkbook
The problem is here:
ThisWorkbook.Worksheets("Summary").Range(ThisWorkbook.Worksheets("Summary").Cells(summaryRow, 3), ThisWorkbook.Worksheets("Summary").Cells((summaryRow + (currentSheetRows - 3)), 6)).Value = ThisWorkbook.Worksheets(ws.Name).Range(ThisWorkbook.Worksheets(ws.Name).Cells(3, 6), ThisWorkbook.Worksheets(ws.Name).Cells(currentSheetRows, 9)).Value
the subscript is out of range.
Try
With Sheets(ws.name)
.Cells({var},{var}).Value = {var}

Transferring only visible rows without using .select or .End(xlDown)

The code currently filters the data the way I need it to but when it copies it over it copies everything not just the filtered data. I know I can make it work using .select and then copying and pasting etc. but I would rather avoid that if possible. Any help would be appreciated.
Sub Auto_Filter()
Dim RNG As Range
Dim Open_Jobs_Report As Worksheet
Set Open_Jobs_Report = ThisWorkbook.Sheets("Open Jobs Report")
Dim Dashboard As Worksheet
Set Dashboard = ThisWorkbook.Sheets("Dashboard")
Dim PersonResponsible As Range
Dim Violations As Range
Dim CLM1 As Long
Dim CLM2 As Long
With Sheets("Open Jobs Report")
Set RNG = .Range("A1", .Cells(.Cells(.Rows.Count, "A").End(xlUp).Row, .Cells(1, .Columns.Count).End(xlToLeft).Column))
RNG.AutoFilter Field:=19, Criteria1:="<>"
CLM1 = .Range("1:1").Find(What:="Person Responsible").Column
Set PersonResponsible = .Range(.Cells(1, CLM1), .Cells(1, CLM1).End(xlDown))
CLM2 = .Range("1:1").Find(What:="Violations").Column
Set Violations = .Range(.Cells(1, CLM2), .Cells(1, CLM2).End(xlDown))
End With
Dashboard.Range("B4:B1000").Value = PersonResponsible.Value
Dashboard.Range("E4:E1000").Value = Violations.Value
Dashboard.Range("B4:B1000").RemoveDuplicates , Header:=xlYes
Dashboard.Range("E4:E1000").RemoveDuplicates , Header:=xlYes
Open_Jobs_Report.ListObjects(1).AutoFilter.ShowAllData
End Sub
This will only copy the visible rows from your table on the Open_Jobs_Report sheet
Open_Jobs_Report.ListObjects(1).DataBodyRange.SpecialCells(xlCellTypeVisible).Copy
Update after comments:
With Open_Jobs_Report.ListObjects(1)
Union(.ListColumns(9).DataBodyRange, .ListColumns(19).DataBodyRange).Copy
End With
Or using header names:
With Open_Jobs_Report.ListObjects(1)
Union(.ListColumns("Person Responsible").DataBodyRange, .ListColumns("Violations").DataBodyRange).Copy
End With
Thinking a bit more about it this is how I'd probably go about doing it:
Dim Open_Jobs_Report As Worksheet
Dim temp as Variant
Set Open_Jobs_Report = ThisWorkbook.Sheets("Open Jobs Report")
temp = Open_Jobs_Report.ListObjects(1).DataBodyRange.SpecialCells(xlCellTypeVisible).Value
With Dashboard
.Range(.Cells(4, 2), .Cells(3 + UBound(temp,1), 2)).Value = Application.Index(temp, , 9)
.Range(.cells(4, 5), .Cells(3 + UBound(temp, 1), 5)).Value = Application.Index(temp, , 19)
End With
This puts the entire visible part of the table into an array in memory and then sets the range equal to the bits you're interested in.
You are probably looking to use the the built-in AutoFilter.Range object of the worksheet.
ActiveSheet.AutoFilter.Range.Copy
Workbooks.Add.Worksheets(1).Paste
This link gives the full explanation

Looping through all worksheets VBA

I am trying to loop through all the worksheets in the activeworkbook to perform a repetitive task.
I currently have the code below:
Sub sort_sectors()
Dim i As Integer
Dim rng As Range
Dim SortRng As Range
Dim rng1 As Integer
Dim ws As Worksheet
Dim wb As Workbook
Dim LastCol As Long
Dim LastRow As Long
Set wb = ActiveWorkbook
For Each ws In wb.Worksheets
'This is marking several of the sheets of which I do not want to run the sub
If ws.Range("a9").Value = "x" Then
NextIteration:
End If
'Reference point is rng1 to select the desired range
With Range("a1:t100")
rng1 = .Find(what:="sector", LookIn:=xlValues).Row
End With
'return the row number for the sector header
LastCol = ws.Cells(20, ws.Columns.Count).End(xlToLeft).Column
LastRow = ws.Range("a15").End(xlDown).Row
'I am going to add the code below to finish out the task that I want to complete
Next
End Sub
I am sure the problem is that I'm misunderstanding something about how the for each loop actually works. Hopefully someone's answer will allow to better understand.
I really appreciate any help on this.
I made some edits to the code, and now I actually do have an error :) I tried making the changes you suggested for the "with ws.range etc..." piece of the code, and I get the object error 91.
Below is my new and "improved" code.
Sub sort_sectors()
Dim i As Integer
Dim rng As Range
Dim SortRng As Range
Dim intAnchorRow As Integer
Dim intMktCapAnchor As Integer
Dim intSectorAnchor As Integer
Dim ws As Worksheet
Dim wb As Workbook
Dim LastCol As Long
Dim LastRow As Long
Set wb = ActiveWorkbook
For Each ws In ActiveWorkbook.Worksheets
'Filter out the sheets that we don't want to run
If ws.Range("a9").Value <> "x" Or ws.Name = "__FDSCACHE__" Or ws.Name = "INDEX" Then
'Get the anchor points for getting sort range and the sort keys
''''''THIS IS THE PART THAT IS NOW GIVING ME THE ERROR'''''''
With ws.Range("a1:t100")
intAnchorRow = .Find(what:="sector", LookIn:=xlValues).Row
intSectorAnchor = .Find(what:="sector", LookIn:=xlValues).Column
intMktCapAnchor = .Find(what:="Market Cap", LookIn:=xlValues).Column
End With
'Find the last row and column of the data range
LastCol = ws.Cells(20, ws.Columns.Count).End(xlToLeft).Column
LastRow = ws.Range("a15").End(xlDown).Row
Set SortRng = Range(Cells(intAnchorRow + 1, 1), Cells(LastRow, LastCol))
Range(SortRng).Sort key1:=Range(Cells(intAnchorRow + 1, intSectorAnchor), Cells(LastRow, intSectorAnchor)), _
order1:=xlAscending, key2:=Range(Cells(intAnchorRow + 1, intMktCapAnchor), Cells(LastRow, intMktCapAnchor)), _
order2:=xlDescending, Header:=xlNo
End If
Next
End Sub
Thanks again. This has been very helpful for me.
If I've understood your issue correctly, you don't want to use a worksheet with an x in cell A9.
If that's the case I would change the condition of the if statement to check if the cell does not contain the x. If this is true, it enters the rest of the code. If not, it goes to the next iteration.
Also, your NextIteration: doesn't do anything in the If statement.
Sub sort_sectors()
Dim i As Integer
Dim rng As Range
Dim SortRng As Range
Dim rng1 As Integer
Dim ws As Worksheet
Dim wb As Workbook
Dim LastCol As Long
Dim LastRow As Long
Set wb = ActiveWorkbook
For Each ws In wb.Worksheets
'This is marking several of the sheets of which I do not want to run the sub
If ws.Range("a9").Value <> "x" Then
'Reference point is rng1 to select the desired range
With Range("a1:t100")
rng1 = .Find(what:="sector", LookIn:=xlValues).Row
End With
'return the row number for the sector header
LastCol = ws.Cells(20, ws.Columns.Count).End(xlToLeft).Column
LastRow = ws.Range("a15").End(xlDown).Row
'I am going to add the code below to finish out the task that I want to complete
End If
Next
End Sub
The : operator is used to return the code to that line after a goto call.
For example
sub gotoEx()
for i = 1 to 10
if i = 5 then
goto jumpToHere
end if
next i
jumpToHere: '<~~ the code will come here when i = 5
'do some more code
end sub
And of course you can use this structure in your code if you wish, and have the jumpToHere: line just before the next
e.g.
for each ws in wb.Worksheets
if ws.Range("a9").Value = "x" then
goto jumpToHere
end if
'the rest of your code goes here
jumpToHere:
next