VBA 1004 Error on Loop execution of Macro - vba

Can anybody give me a sense of why I'd be receiving a 1004 error on the following code?
If it's not clear, I'm trying to loop all sheets that are not my named sheet and try to select a particular range and copy and paste it to the compiled "Quant Sheet"
Dim ws As Worksheet
Dim x As Integer
Dim y As Integer
Dim a As Integer
Dim b As Integer
Set ws = Worksheets("Quant Sheet")
x = 1
y = 3
a = 3
b = 2
Worksheets("Quant Sheet").Activate
For Each ws In ActiveWorkbook.Worksheets
If (ws.Name <> "Quant Sheet") Then
ws.Range("A3").Select
Selection.Copy
Sheets("Quant Sheet").Select
Cells(y, 1).Select
ActiveSheet.Paste
y = y + 1
End If
Next ws

You set WS as Worksheets("Quant Sheet") but then use that same variable ws to use in your loop. That may be causing the issue.
Try this:
Dim ws As Worksheet, mainWS As Worksheet
Dim x As Integer, y As Integer, a As Integer, b As Integer
Set mainWS = Worksheets("Quant Sheet")
x = 1
y = 3
a = 3
b = 2
For Each ws In ActiveWorkbook.Worksheets
If (ws.Name <> "Quant Sheet") Then
ws.Range("A3").Copy Destination:=mainWS.Cells(y, 1)
y = y + 1
End If
Next ws
Mainly, you want to avoid using .Select/.Activate to make sure you work more directly with the data.
Edit: FYI you can likely further make this more dynamic by not using something like y=y+1 and instead use offset, or a lastRow variable, but that's personal preference as it'll accomplish the same thing. (I'm also assuming the x, a, and b variables are used elsewhere in your macro...

As was already stated, you can't .Select a cell on a worksheet you haven't called .Activate on first - that would fix the problem, but leave you with frail & slow .Select and .Activate calls everywhere. Instead, iterate the Worksheets collection with a For Each loop, so you get a Worksheet object to work with each iteration:
Sub test()
Dim quantSheet As Worksheet, tempSheet as Worksheet
Dim i As Integer
Set quantSheet = ThisWorkbook.Worksheets("Quant Sheet")
i = 3
For Each tempSheet In ThisWorkbook.Worksheets
If tempSheet.Name <> quantSheet.Name Then
quantSheet.Cells(i, 1).Value = tempSheet.Range("A3").Value
i = i + 1
End If
Next tempSheet
End Sub
Further to the good answers and comments already provided, you can neaten up your code a lot.
Indentation is key. You can avoid loads of errors just by sticking to simple indentation
Remove of all those unused variables (unless you're using them later and haven't shown us!)
Rather than copying and pasting, set your values directly using .Value. It's quicker and better
Avoid Select and Activate as much as possible, as has already been pointed out. That includes ActiveSheet and ActiveWorkbook
Give your variables good, meaningful names and your code will almost read like a geeky VBA novel. That way you'll always know what's going on.
Post your working code on Code Review Stack Exchange for a full-blown peer review.

Related

gather data from multiple worksheets

How can i get this to gather from 3 of the 9 worksheets in my workbook?
Option Explicit
Sub CopyCCellVals()
Dim sht1 As Worksheet, sht6 As Worksheet
Dim i As Integer, lastRow As Integer, sht6Row As Integer
sht6Row = 5
Set sht1 = Worksheets("MAINGANG")
Set sht6 = Worksheets("REPAIRS")
With sht1
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = 5 To lastRow
If .Cells(i, "C") = "X" Or .Cells(i, "C") = "x" Then
sht6.Cells(sht6Row, "A") = .Cells(i, "A")
sht6Row = sht6Row + 1
End If
Next
End With
End Sub
You can use Worksheets("name").select and then manipulate the data from there?
If there is something else you are trying to do please be more specific.
also this is code to loop through sheets:
Sub GetSelectedSheetsName()
Dim ws As Worksheet
For Each ws In ActiveWindow.SelectedSheets
MsgBox ws.Name
Next ws
End Sub
Your question is not very clear but I "think" you want to gather data from multiple sheets and post to one sheet.
One way to do it is to set a worksheet array and loop through it.
Here is an example I put together on a new worksheet. I added a bunch of sheets called: Hello, World, This, Is, A, Collection, Of, Sheets and this code returned 3 message boxes showing Hello, World & Collection
Sub Temp()
Dim MySheets(2) As Worksheet, X As Long
Set MySheets(0) = Worksheets("Hello"): Set MySheets(1) = Worksheets("World"): Set MySheets(2) = Worksheets("Collection")
For X = LBound(MySheets) To UBound(MySheets)
MsgBox (MySheets(X).Name)
Next
End Sub
You can use the MyWorksheets(X) object in the same way you are using sht1 but now you can loop through them by iterating X
If this is not the answer you are looking for please post back more detail of your requirements.
Also a side note, never use Integer when dimming in VBA, Always use Long. Search on this site for some great explanations of why.

Excel copy range and paste in a specific range available and print

I would like to copy a range in one sheet and paste it as a value in another sheet, but just in a specific range in the next available cell in column B. Starting from B4 to B23 only.
I changed some code I found online but it's not working for me in finding the next available row. After I run the macro the first time, when I run it again and again it does nothing, and it's not working in pasting only the values either.
I tried saving the file before running the Macro again, but still it's not working.
At the end, when the range in the Print sheet is full, I would like a message box asking me to select one of the printers (not the default) on one of my servers (specifying the server path in the code like \a_server_name) and print this Print Sheet only, or clear the records in the range in the Print Sheet, or save only the Sheet Print in a new file (SaveAs) to a location I can choose on one of my servers (specifying the server path in the code \a_server_name) or simply do nothing and end the sub.
Thank you.
Application.ScreenUpdating = False
Dim copySheet As Worksheet
Dim pasteSheet As Worksheet
Set copySheet = Worksheets(“Data”)
Set pasteSheet = Worksheets("Print”)
copySheet.Range("J11:Q11").Copy
pasteSheet.Range("B4:I23").End(xlUp).Offset(1,0)
.PasteSpecial.xlPasteValues
Application.CutCopyMode = False
Application.ScreenUpdating = True
This will set the values equal to each other without copying/pasting.
Option Explicit
Sub Testing()
Dim wsC As Worksheet: Set wsC = ThisWorkbook.Sheets("Data")
Dim wsP As Worksheet: Set wsP = ThisWorkbook.Sheets("Print")
Dim LRow As Long
LRow = wsP.Range("B" & wsP.Rows.Count).End(xlUp).Offset(1).Row
wsP.Range("B" & LRow).Resize(wsC.Range("J11:Q11").Rows.Count, wsC.Range("J11:Q11").Columns.Count).Value = wsC.Range("J11:Q11").Value
End Sub
Modifying your code - and reducing to minimal example
Sub test()
Dim copySheet As Worksheet: Set copySheet = Worksheets("Data")
Dim pasteSheet As Worksheet: Set pasteSheet = Worksheets("Print")
copySheet.Range("J11:Q11").Copy
pasteSheet.Range("B" & pasteSheet.Rows.Count).End(xlUp).Offset(1).PasteSpecial xlPasteValues
End Sub
From what i can gather, you want to copy 8 cells and paste all 8 cells to 20 rows, starting at B4. You are not clear on how you want to rerun the macro, it will just write over the data you just pasted.
The first code will copy the 8 cells into the 20 rows
With ThisWorkbook
Sheets("Data").Range("J11:Q11").Copy
Sheets("Print").Range("B4:I23").PasteSpecial Paste:=xlPasteValues
End With
This second code uses a for loop to accoplish the same task, but it also will write over the previously pasted data.
Dim i As Long
With ThisWorkbook
For i = 4 To 23
Sheets("Data").Range("J11:Q11").Copy
Sheets("Print").Cells(i, 2).PasteSpecial Paste:=xlPasteValues
Next i
End With
If you want to be able to reuse the macro, you will have to modify the range to be copied that allows you to select the range you want to copy. Maybe a variable that allows a user input with a InputBox.
Edit:
Dim lRow As Long
lRow = Sheets("Print").Cells(Rows.Count, 2).End(xlUp).Row
With ThisWorkbook
Sheets("Data").Range("J11:Q11").Copy
Sheets("Print").Cells(lRow, 2).Offset(1).PasteSpecial Paste:=xlPasteValues
End With
Edit #3
With ThisWorkbook
Dim lRow As Long
lRow = .Sheets("Print").Range("B" & Rows.Count).End(xlUp).Row
Sheets("Data").Range("J11:Q11").Copy
Sheets("Print").Cells(lRow, 2).Offset(1).PasteSpecial Paste:=xlPasteValues
End With

VBA macro that loops through changing sheet names

So we have an instrument that generates a bunch of data but names the sheets effectively randomly. I have the easy commands to go copy, paste and sort the respective text on the excel sheets but my problem is I can't figure out how to make the list of sheets that I generate loop through all those sheets while not specifying the name in the beginning..I don't want it to loop through all sheets because I need it to overlook the first sheet...
I'm getting an error 424 Object Req'd error. Any help would be greatly appreciated.
So I set all of my integers and variables
Dim x As Integer
Dim y As Integer
Dim a As Integer
Dim b As Integer
Dim compoundname As Range
Dim compoundtype As Range
Dim compoundrng As Range
x = 1
y = 3
a = 3
b = 2
y,a,b are all associated with my settings omitted from the last part.
So here I tell it that I want compound name to be the range only on the active sheet, which I think is my actual problem?
Set compoundname = Workbook.ActiveSheet.Range("A3")
Set compoundrng = Sheets("AllSheets").Range("A3:A100")
And after I've added all the sheets to the workbook, I have the loop for the names that store on the "AllSheets" worksheet
For Each ws In Worksheets
Sheets("AllSheets").Cells(x, 1) = ws.Name
x = x + 1
Next ws
Then we have to tell it to access that list:
For Each compoundtype In compoundrng.Cells
copy, paste and sort my info here
Next compoundtype
Why don't you do something like
For Each ws In Worksheets
if(ws.Name <> 'YourFirstSheetName') Then
'copy, paste and sort info here.
end if
Next ws
Edit: Updated for your comment.
If you don't care about cell formatting then don't use the copy/paste command. Just set the cell equal to the value of the other cell. That way you don't have to play around with clipboard or active sheets/cells, etc.
Dim ws As Worksheet
Dim x As Integer
Dim y As Integer
Dim a As Integer
Dim b As Integer
Set ws = Worksheets("Quant Sheet")
y = 3
Worksheets("Quant Sheet").Activate
For Each ws In ActiveWorkbook.Worksheets
If (ws.Name <> "Quant Sheet") Then
Sheets("Quant Sheet").Cells(y, 1) = ws.Range("A3")
y = y + 1
End If
Next ws

if else statement at copying and pasting a cell value

I have the following code which will copy/paste some columns from "data" worksheet and pastes to the next empty column in to the column that i specify in the mastersheet called "KomKo".
Dim copySheet As Worksheet
Dim pasteSheet As Worksheet
Set copySheet = Worksheets("data")
Set pasteSheet = Worksheets("KoMKo")
lRow = copySheet.Cells(copySheet.Rows.Count, 1).End(xlUp).Row
With copySheet.Range("BX2:BX" & lRow)
pasteSheet.Cells(Rows.Count, "A").End(xlUp).Offset(1, 0).Resize(.Rows.Count, .Columns.Count) = .Value
End With
Now i would like to add an if condition for another column; which should say "if column U in Worksheet "data" has cell value "8636" then these values should be pasted to Column H in Worksheet "KomKo"(pastesheet); to the next row as i used the code above in the "with" part.
Else( If the value in Column H is not 8636) then it should paste the value inside this column to Column G at Worksheet "KomKo"(pastesheet) with same preferences as above again.
How can i do this ?
So, I've come up with a suggestion below using an if-then within a loop. I think it's close to what you want...
Sub try6()
Dim ws As Worksheet
Dim ws2 As Worksheet
Dim x As Range
Set ws = Worksheets("data")
Set ws2 = Worksheets("KomKo")
For Each x In ws.Range("C1:C100")
If x.Value = 8636 Then
ws2.Range("H:H").Value = ws.Cells(Rows.Count, "A").Value
ElseIf x <> 8636 Then
ws2.Range("G:G").Value = ws.Range(Rows.Count, "B").Value
End If
Next x
End Sub
Testing it, it took a while to execute. I'd say, set a dynamic range at something like A10000 and copy it directly without needing to necessarily test for whether there is a value in the range being copied.
You can also use the Select method for the purpose and copy the selection - from personal experience, I've had mixed success with it and I've seen people advise against using it here.
These are my .02, hope it helps! Cheers.

What is wrong with my VBA IsNumeric function?

I cannot find what is wrong with this segment of code, every time I try to change it to something that I think will work better it shows up as an error. Many thanks in advance for your help!
This is the code, its specifically to do with the use of the isnumeric function and I am using Excel 2016 on a Mac.
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set ws1 = Sheets("Sheet1")
Set ws2 = Sheets("Sheet2")
Set i = 1
Set n = 1
Do While ws1.Cell(i, "F") <> "End"
Num1 = ws1.Cell(i, "F")
If IsNumeric(Num1.value) <> False And Num1 <> ""
Set ws2.Cell(n, "B") = ws1.Cell(i, "F")
n = n + 1
End If
Next i
Perhaps you don't need VBA at all. For a non-vba solution enter this formula in Sheet2 cell B1 and drag down for as many rows as needed (in Sheet1 column F).
=IF(AND(NOT(ISNUMBER(Sheet1!F1)),Sheet1!F1=""),Sheet1!F1,"")
For a VBA solution, I cleaned up your code a bit for many syntax errors that were off. Also, heed the following:
Always use Option Explicit in your modules and declare all variable types
Always qualify objects with variables
(1 and 2 are best practices, but not required. Leaving things out can produce unexpected results).
Option Explicit
'... Sub Name ...
Dim wb as Workbook
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim Num1 as Variant
Set wb = ThisWorkbook 'or Workbooks("myBook")
Set ws1 = wb.Sheets("Sheet1")
Set ws2 = wb.Sheets("Sheet2")
Dim i as Long, n as Long
i = 1 'no need to "Set" numerical integers
n = 1
Do While ws1.Cells(i, "F") <> "End"
Num1 = ws1.Cells(i, "F").Value2 'set this to the value2 property of the cell
If Not IsNumeric(Num1) And Num1 <> "" 'remove .Value from variable
ws2.Cells(n, "B").Value = ws1.Cells(i, "F").Value 'set the cells Value property equal to each ... again, Set will not work here
n = n + 1
i = i + 1 'need to increment i as well
End If
Loop 'not Next I, since you are using a Do While Loop