I'm a beginner to VBA and I'm trying copy and paste a sheet from 1 workbook to multiple other workbooks. The latter workbooks have basically the same file name (increasing by 1). All the workbooks are currently open
I keep getting an error saying "Object variable or With block variable not set". But I can't see why the way I declared 'names' or 'wb' is wrong.
I've seen a lot of posts online iterate through open workbooks, but I can't do this because I'm copying something from one of the open workbooks.
Sub CopyWorkbook()
Dim i As Integer, s As String
Dim sh As Workbook, wb As Workbook, names As Worksheet
Set sh = Workbooks("schools.xlsx")
Set names = sh.Sheets("name")
For i = 6 To 15
If i <= 8 Then
s = "0" & i & "-0" & (i + 1) & "-_Year_data"
ElseIf i = 9 Then
s = "0" & i & "-" & (i + 1) & "-_Year_data"
Else
s = i & "-" & (i + 1) & "-_Year_data"
End If
Set wb = Workbooks(s & ".csv")
The error occurs in the first line here:
names.Copy After:=wb.Sheets(wb.Sheets.Count)
Next i
End Sub
Any help/links to tutorials that can help would be greatly appreciated!
I've seen a lot of posts online iterate through open workbooks, but I can't do this because I'm copying something from one of the open workbooks.
You could just add an if
For each wb in workbooks
IF Not wb.name = thisworkbook.name and wb.name <> "schools.xlsx" then
Workbooks("schools.xlsx").Sheets("name").copy _
after := wb.sheets(wb.worksheets.count)
End IF
Next wb
around your code to allow you to loop through all open workbooks, except the one hosting the code
EDIT: I've just noticed you're dealing with csv files, so they only have a single sheet anyway.
Related
I am writing a reporting system where the user fills out a form and a form button runs a macro to save the file with a name based on several fields including a timestamp.
All the data is is also on a second sheet but in one row for ease of copying to a master sheet.
I am trying to to extend the save macro to copy this row to the last line of a second workbook.
This was successful when the macro was run from a separate workbook but I can't for the life of me work out how to do it from within the file itself.
I've triple checked the paths themselves, I know they're right as the new files are being created, I've run msgbox in the code to check the filename and the variable are the same too.
timestampedfile = Worksheets("single_line").Range("b3")
totalpath = Path & timestampedfile & ".xlsm"
ActiveWorkbook.SaveCopyAs filename:=totalpath
master_wb = "s:\blah\blah\blah.xlsx"
master_sht = "Master_Database"
contact_wb = totalpath
contact_sht = "single_line"
Workbooks.Open (master_wb)
Workbooks.Open (contact_wb)
MsgBox (totalpath)
Workbooks(contact_wb).Worksheets(contact_sht).Range("A3:AQ3").Copy Worksheets(master_wb).Sheets(master_sht).Range("A" & Rows.Count).End(xlUp)(2)
'
Both the Workbooks open so I know the paths are right, can anyone help?
Solution by OP
Solved thanks to comment about workbook variables by BigBen:
Use workbook variables, instead of referencing the workbook by name: Dim masterWb as Workbook, then Set masterWb = Workbooks.Open("s:\blah\blah\blah.xlsx" ). Similarly for the contact workbook. You might consider using worksheet variables too, instead of using sheet names.
Code changed to:
Dim master_wb As Workbook
Dim contact_wb As Workbook
Dim master_sht As Worksheet
Dim contact_sht As Worksheet
Path = "S:\blah\" & Worksheets("report").Range("c8") & "\"
filename = Worksheets("back_end_formulas").Range("e10")
timestampedfile = Worksheets("single_line").Range("b3")
totalpath = Path & timestampedfile & ".xlsm"
ActiveWorkbook.SaveCopyAs filename:=totalpath
SetAttr totalpath, vbReadOnly
Set master_wb = Workbooks.Open("S:\blah\Master_Database2.xlsx")
Set master_sht = master_wb.Sheets("Master_Database")
Set contact_wb = Workbooks.Open(totalpath)
Set contact_sht = contact_wb.Sheets("single_line")
ThisWorkbook.Activate
contact_sht.Range("A3:AQ3").Copy master_sht.Range("A" & Rows.Count).End(xlUp)(2)
master_wb.Close SaveChanges:=True
contact_wb.Close SaveChanges:=False
ActiveWorkbook.Close SaveChanges:=False
I have an issue with my excel. To begin with, I create worksheets dynamically based on some parameters and then I export the worksheets as PDF. So far everything is fine. Now, when I am done with worksheets and I don't need them anymore I want to delete them. When I run the code excel crashes, repairs and then restarts itself. I am wondering if anyone has any idea why this keeps happening. I also delete named ranges for each sheet just in case.
Btw, if I delete them manually everything is fine.
Here's the code
Application.DisplayAlerts = False
Dim theName As Name
Dim newSheet As Worksheet
For i = 1 To unitsQty
Set newSheet = ThisWorkbook.Worksheets("Project Info " & i)
For Each theName In Names
If (TypeOf theName.Parent Is Worksheet) And (newSheet.Name = theName.Parent.Name) Then
theName.Delete
End If
Next
Set newSheet = ThisWorkbook.Worksheets("System Spec " & i)
For Each theName In Names
If (TypeOf theName.Parent Is Worksheet) And (newSheet.Name = theName.Parent.Name) Then
theName.Delete
End If
Next
Next i
Dim myArray() As Variant
ReDim myArray(unitsQty * 2)
With Sheets("Tables")
For i = 1 To unitsQty
myArray(i - 1) = "Project Info " & i
Debug.Print myArray(i)
Next i
For i = 1 To unitsQty
myArray(i - 1 + unitsQty) = "System Spec " & i
Debug.Print myArray(i)
Next i
End With
ThisWorkbook.Sheets(myArray(0)).Select
ThisWorkbook.Sheets(myArray).Select
ThisWorkbook.Sheets(myArray((unitsQty * 2 - 1))).Activate
ActiveWindow.SelectedSheets.Delete
Application.DisplayAlerts = True
thanks for your help. So basically in the worksheets I had OLE Object and therefore every time I was trying to delete a worksheets I had "Can't enter break mode at this time" and when I clicked continue but excel was crashing.
Even when I tried to delete all objects from the worksheet before i deleted it, excel still crashing.
I couldn't find any solution in the web, but I found a workaround that it is working fine and gives the desired results. The workaround is to copy the worksheets to a temp workbook and do all the work there and when I am done, i am just closing the workbook without saving it of course. That keeps my original workbook tidied up.
I've got a need to open some Excel files and "pause" then close them. In this process I run one macro on opening, and another on closing. The opening one works fine because it is done as each file is opened. But the closing part of the code I can't get it to run the correct macro. They have the same names, but the file contests are different, and what the macro does per file is different.
This is the gist of what I'm doing now
Set xlApp = CreateObject("Excel.Application")
xlApp.Visible = True
path = "\\Gaalpa1cdfile19\north_sa_staff\Reports\Rpt-ProductionCurves\"
filename2018P1 = "2018 P1.xlsm"
Set xlbook2018P1 = xlApp.WorkBooks.Open(path & filename2018P1)
' Run Macro
xlApp.Run "AutoRefresh"
filename2018P3 = "P3 2018 HRR.xlsm"
Set xlbook2018P3 = xlApp.WorkBooks.Open(path & filename2018P3)
'Run Macro
xlApp.Run "AutoRefresh"
'My "pause"
WScript.Echo ("All Files were" & Chr(013) & _
"opened and refreshed, update ppt before OK" & Chr(013) & _
" DO NOT CLICK OK" & Chr(013))
'==========================
'Below is the trouble spot.
'==========================
xlapp.Run "'" & filename2018P1 & "'" & "!AutoPublish"
xlbook2018P1.Close False
Set xlbook2018P1 = Nothing
xlapp.run "'" & filename2018P3 & "'" & "!AutoPublish"
xlbook2018P3.Close False
Set xlbook2018P3 = Nothing
The first part works fine, but trying to run the file's respective AutoPublish macro does not. The code works fine if I leave out that Run line. (The real file names have spaces and I had to add the single quotes to get it to accept the filename.)
What it appears to be doing is using the macros from the last file opened, not the one it's directed to use it the run line. I think I need a way to "select" the correct file, or give it focus so the macro could run without an explicit filename argument, which it appears to be ignoring anyway.
EDIT:
Solution was:
xlbook2018P1.Activate ' This fixed it, I think
xlapp.Run "'" & filename2018P1 & "'" & "!AutoPublish"
xlbook2018P1.Close False
Set xlbook2018P1 = Nothing
xlbook2018P3.Activate
xlapp.run "'" & filename2018P3 & "'" & "!AutoPublish"
xlbook2018P3.Close False
Set xlbook2018P3 = Nothing
When tackling similar tasks, I usually work around by implementing a master Excel file first, and call a sub in this master file via VBS. The advantage to me seems it is way easier to fullfill all tasks in the VBA of the master file rather than having to code all that in VBS.
Create a master file, e.g. "Master.xlsm", list all your files you need to open on a sheet named "Files" in column A, starting in row 1.
Insert a module and place the following sub in this module:
Sub Main()
Dim strPath As String
Dim strFile As String
Dim lRow As Long
Dim i As Long
Dim k As Integer
Dim n As Long
Dim wb(1 To 3) As Workbook
Dim wbTest As Workbook
Set wbMaster = ThisWorkbook
strPath = "\\Gaalpa1cdfile19\north_sa_staff\Reports\Rpt-ProductionCurves\"
'Check how many files you need to open
With Sheets("Files")
lRow = Sheets("Files").Range("A" & .Rows.Count).End(xlUp).Row
End With
'open all available files
For i = 1 To lRow
Workbooks.Open (wbMaster.Sheets("Files").Range("A" & i).Value)
Next
'now run the two macros in each open file
For k = 2 To Workbooks.Count 'this will work only if your master file is the only one open when starting the sub!
Workbooks(k).Run "'" & Workbooks(k).Name & "'!AutoRefresh"
DoEvents
Workbooks(k).Run "'" & Workbooks(k).Name & "'!AutoPublish"
DoEvents
Next
'and close all files previously opened except for the master file
For n = Workbooks.Count To 2 Step -1
Workbooks(n).Close False
Next
End Sub
It seems like a possible explanation for what you're seeing is that your AutoPublish macro refers to ActiveWorkbook and not the safer ThisWorkbook. If another workbook is active when it's called that could lead to unexpected results.
I have a single workbook which is edited by 6-7 different people. There are counts given be each person in the sheet and I am looking for a way where I can merge all the sheets and find the sum of the total count. For eg,
This is the sheet in 1st workbook,
A B c
10 15 10
The sheet in the 2nd workbook,
A B c
7 10 9
And it is similar for all the workbooks. I want the final consolidated one to have the sum of all the values in sheets of each workbook,
A B c
17 25 19
I thought one way to do this is to, put all the excel workbooks into a same folder and use the following code to merge it and then use a macro to count it.
Sub GetSheets()
Path = "C:\Users\username\Downloads\New folder"
Filename = Dir(Path & "*.xlsx")
Do While Filename <> ""
Workbooks.Open Filename:=Path & Filename, ReadOnly:=True
For Each Sheet In ActiveWorkbook.Sheets
Sheet.Copy After:=ThisWorkbook.Sheets(1)
Next Sheet
Workbooks(Filename).Close
Filename = Dir()
Loop
End Sub
But for some reason this code is getting executed without any errors but has no effect in the consolidated workbook. It is not merging the sheets of the remaining workbooks.
Can anybody tell me what is the error I am making here?
Also is there any alternate way to find the consolidated sum?
thanks
Asuming you still want to go with DIR (you need to input checks for name if there are also other files inside the folder)
Tested it at my pc and it worked perfectly:
Sub SumWB()
Dim Arr(2) As Long, MyWB As Workbook, fStr as String
Const Folder = "C:\NewFolder\"
fStr = Dir(Folder)
While (file <> "")
Set MyWB = Workbooks.Open(Folder & fStr, , True)
Arr(0) = Arr(0) + MyWB.Sheets(1).Range("A1").Value
Arr(1) = Arr(1) + MyWB.Sheets(1).Range("B1").Value
Arr(2) = Arr(2) + MyWB.Sheets(1).Range("C1").Value
MyWB.Close
file = Dir
Wend
Debug.Print Arr(0) & " - " & Arr(1) & " - " & Arr(2)
End Sub
If you are executing the vba code in an excel sheet which is in the same path(folder) as that of the sheets you want to combine ,this would happen.
Try executing the vba in a new excel workbook.
I am really new to VBA but I have managed to write some code basing on examples mainly from this site.The piece of code is supposed to copy data from multiple csv files into one xls file (and then to rename the source csv files). While it works fine in Excel 2003, it does not work so well in Excel 2010 / 2013 (I could not test it in E2007). It appears to stop after copying data from the first csv file into xls file, so after this line:
Range("B4:AZ" & LR).Copy wbDEST.Sheets("Data").Range("B" & NR)
with Error 1004 "Application-defined or Object-defined error". Debugger highlights the next line, i.e.
NR = wbDEST.Sheets("Data").Range("B" & Rows.Count).End(xlUp).Row + 1
I just cannot see what is wrong with it as the same line is used at the beginning of the code and does not stop there.
I would appreciate your advice.
And here is the whole code:
Option Explicit
Sub ImportData()
Dim fPATH As String, fNAMEcsv As String, fNAMEbak As String
Dim LR As Long, NR As Long
Dim wbSOURCE As Workbook, wbDEST As Workbook
Set wbDEST = Workbooks.Open("C:\Utility\Data.xls")
NR = wbDEST.Sheets("Data").Range("B" & Rows.Count).End(xlUp).Row + 1
fPATH = "C:\Utility\DataFiles\" 'remember the final \ in this string
fNAMEcsv = Dir(fPATH & "*.csv") 'get the first filename in fpath
Do While Len(fNAMEcsv) > 0
Set wbSOURCE = Workbooks.Open(fPATH & fNAMEcsv, Local:=True) 'open the file
LR = Range("B" & Rows.Count).End(xlUp).Row 'how many rows of info?
If LR > 1 Then
Range("B4:AZ" & LR).Copy wbDEST.Sheets("Data").Range("B" & NR)
NR = wbDEST.Sheets("Data").Range("B" & Rows.Count).End(xlUp).Row + 1
End If
wbSOURCE.Close False 'close data workbook
fNAMEbak = fNAMEcsv & ".bak" 'rename imported file to .bak
Name (fPATH & fNAMEcsv) As (fPATH & fNAMEbak)
fNAMEcsv = Dir 'get the next filename
Loop
MsgBox ("Completed. Check results on PRINTOUT sheet.")
End Sub
Try qualifying your Rows:
NR = wbDEST.Sheets("Data").Range("B" & wbDEST.Sheets("Data").Rows.Count).End(xlUp).Row + 1
The problem could be this:
Here you open a new "source" workbook wbSOURCE:
Set wbSOURCE = Workbooks.Open(fPATH & fNAMEcsv, Local:=True) 'open the file
Maybe it is a workbook in the "new" format (Excel 2007 and later, *.xlsx & Co.). Since you just opened it, it is the active workbook, and therefore the unqualified Rows.Count will return 1048576.
And maybe your destination workbook wbDEST is in the "old" Excel 2003 format (*.xls & Co.). So when you say this:
NR = wbDEST.Sheets("Data").Range("B" & Rows.Count).End(xlUp).Row + 1
you're trying to access wbDEST.Sheets("Data").Range("B" & 1048576) but cell B1048576 doesn't exist in this 2003-format workbook. This will indeed throw an Error 1004 "Application-defined or Object-defined error".
The solution would then be to fully qualify Rows.Count like this:
NR = wbDEST.Sheets("Data").Range("B" & wbDEST.Sheets("Data").Rows.Count).End(xlUp).Row + 1
It's always a good idea to fully qualify everything and not let it depend on the vagaries of Excel.