Excel VBA remove unwanted worksheets - excel

I have MS Access producing a bunch of workbooks and worksheets. When a workbook is creates there are extra worksheets in the workbook named "Sheetn"
I know the following code works but my question is about timing.
Dim ws as excel.worksheet
For each ws in wbWorking.Worksheets
oxl.DisplayWarnings=False
If ws.name like "Sheet*" then ws.delete
oxl.DisplayWarnings=True
Next ws
The above code does not work until I save the Workbook. The issues is that the client is watching for the workbooks to populate the directory and will open them as soon as they show. This causes issues if the above code runs and the client has the workbook open. I would like to delete worksheets before the workbook is saved.
Please advise.

Working from when you first create the new workbook, something along these lines should work:
Public Function BuildWorkbook(wbkToCopy As Excel.Workbook) As Excel.Workbook
Dim xl As Excel.Application
Dim dummySheet As Excel.Worksheet
Dim sheetToClone As Excel.Worksheet
Dim i As Long
Set xl = wbkToCopy.Application
Set BuildWorkbook = xl.Workbooks.Add(1)
Set dummySheet = BuildWorkbook.Worksheets(1)
For Each sheetToClone In wbkToCopy.Worksheets
'This is just to handle naming conflicts
Do Until sheetToClone.Name <> dummySheet.Name
dummySheet.Name = Format(Now(), "yyyymmddhhnnss") & CStr(i)
i = i + 1
DoEvents
Loop
sheetToClone.Copy BuildWorkbook.Worksheets(1)
Next
If BuildWorkbook.Worksheets.Count > 1 Then
dummySheet.Delete
End If
End Function
Obviously, you can add the sheets however you need to, but the keys are:
Specify =Workbooks.Add(1) when you create the new workbook, so it is created with only 1 worksheet
Set a reference to the worksheet that you don't want when you first create the new workbook
Using that initial reference, delete the worksheet at the very end of the process, before saving the workbook

Related

Copy a range from a closed workbook to a specific sheet

I am currently working on a VBA script to automate a excel sheet. The goal is to have the code open a file from using a file path in cell A2 on a sheet called Reports (the file path is dynamic and is formed using information from the sheet) , copy the data from the file for range A1:E200 and to paste the data into the original workbook on a sheet called HOURS starting at A1. At the moment i have gotten to the point where the file is opened but there is a "Mismatch" error when trying to copy the information across. Below I've attached the code used. I was hoping that someone would be able to help to make sense of the error! I am having the same problem with the close section as well. Note: I am a rookie on VBA so if you could be as clear as possible
Sub Button1_Click()
Call Test
Call Copy_Method
Call CloseWorkbook
End Sub
Sub Test()
Dim strFName As String
strFName = Sheet4.Range("A2").Value
Workbooks.Open Filename:=strFName
End Sub
Sub Copy_Method()
'Copy range to another workbook using Range.Copy Method
Dim wb1 As Workbook
Dim wb2 As Workbook
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set wb2 = ThisWorkbook
Set ws2 = wb2.Sheets("HOURS")
Set wb1 = ThisWorkbook.Worksheets("Reports").Range("A2")
Set ws1 = wb1.Sheets("Sheet")
ws2.Range("A1:E200") = ws1.Range("A1:E200").Value
End Sub
Sub CloseWorkbook()
Workbooks("venues_theeway_hours_August2020.XLS").Close SaveChanges:=True
End Sub
Have you tried this ?
ws2.Range("A1:E200").Value = ws1.Range("A1:E200").Value
You're making life quite difficult for yourself there, splitting the code out across 3 subs. Better to
rename the references to make them easier to differentiate source/destination.
keep it all together so the workbooks/worksheets can still be referenced as they're created:
Apologies if I've misread your requirements, my code does the following:
Reads the original workbook, sheet "Reports", range A2 for a filename.
Opens that filename as a 'source' workbook
Copies data from..
that 'source' workbook, sheet "Sheet", range A1:E200
..to original workbook, sheet "HOURS", range A1:E200
and then closes the 'source' workbook, unsaved as you've not made any changes.
Dim wbSource As Workbook
Dim wbDest As Workbook
Dim wsSource As Worksheet
Dim wsDest As Worksheet
Dim strFName As String
Set wbDest = ThisWorkbook
Set wsDest = wbDest.Sheets("HOURS")
strFName = wbDest.Worksheets("Reports").Range("A2").Value
Set wbSource = Workbooks.Open(strFName)
Set wsSource = wbSource.Worksheets("Sheet")
wsDest.Range("A1:E200").Value = wsSource.Range("A1:E200").Value
wbSource.Close SaveChanges:=False
I'm a little puzzled about your workbook close with save? Perhaps you actually want to close the source sheet unsaved and maybe save the destination sheet you're adding data to? In that case you'll need to add this line to the end of the above code.
wbDest.Close SaveChanges:=True

Extract specific cells from multiple closed workbooks

I have 500+ spreadsheets that I need to extract 5 rows from each one. They're all saved in the same folder. I just need to be able to create a code that runs through each file in the specified directory, extracts the first 5 rows of each file (only one worksheet per file), and paste the results all in one summarized worksheet.
This is the code I have so far (doesn't work as intended):
Public Sub CommandButton1_Click()
Dim mainBook As Workbook
Set mainBook = ActiveWorkbook
Dim fso As New Scripting.FileSystemObject
Dim fle As Scripting.File
Dim book As Workbook
For Each fle In fso.GetFolder("C:\dir").Files
Set book = Workbooks.Open(fle.Path)
Dim wks As Worksheet
For Each wks In book.Worksheets
wks.Range("A5:A10").Copy mainBook.Worksheets(1) 'copies to the start of the main workbook
Next
book.Close
Next
End Sub
Thank you.
wks.Range("A5:A10").Copy mainBook.Worksheets(1), you need to actually paste to a range, try
wks.Range("A5:A10").Copy mainBook.Worksheets(1).cells(mainBook.Worksheets(1).rows.count,"A").end(xlup).offset(1)

Excel VBA file name changes

I have to 2 Excel workbooks to work with: Book1october & Book2. Book1october18 is an import file, meaning that it changes monthly, along with the name (next month it will be Book1november18). I have to copy some data from Book1october to Book2 automatically through VBA code.
This is the code that I've written:
Windows("Book1october18").Activate
Sheets("Sheet1").Activate
Range("B2:AQ5").Select
Selection.Copy
Windows("Book2").Activate
Sheets("Sheet1").Activate
Range("R2:BG5").Select
ActiveSheet.Paste
My problem is that I don't know how to write the code in order to make the actions that I want whenever the month's name changes and also the year. (I have to make it for all the months and 2019)
You can automatically update your workbook name using the Date() function and Format()
Dim sWbName As String
sWbName = "Book1" & LCase(Format(Date, "mmmmyy"))
Debug.Print sWbName
'Prints Book1october18
The name/path of the workbook doesn't need to matter. Use K.Davis's code to come up with a filename, or prompt the user for a path/file to open - get that string into some sourceBookPath variable, then have the macro open the workbook. Now you can hold a reference to that Workbook object:
Dim sourceBook As Workbook
Set sourceBook = Application.Workbooks.Open(sourceBookPath)
Now, the worksheet.
Dim sourceSheet As Worksheet
If the sheet is always going to be named "Sheet1", then you can do this:
Set sourceSheet = sourceBook.Worksheets("Sheet1")
Or, if the sheet is always going to be the first sheet in the book (regardless of its name), you can do this:
Set sourceSheet = sourceBook.Worksheets(1)
Once you have a Worksheet object, you can get the Range you need - but first you need your target. Again if "book2" is opened by the macro, things are much simpler:
Dim targetBook As Workbook
Set targetBook = Application.Workbooks.Open(targetBookPath)
Or is it created by the macro?
Set targetBook = Application.Workbooks.Add
Anyway, we want the first sheet:
Dim targetSheet As Worksheet
Set targetSheet = targetBook.Worksheets(1)
And now we can copy from the source, and paste to the target:
sourceSheet.Range("B2:AQ5").Copy targetSheet.Range("R2:BG5")
And not once did we ever need to .Select or .Activate anything, and we never needed to care for any Window.
Replace:
Windows("Book1october18").Activate
with:
s = LCase(Format(Now, "mmmm")) & Right(Year(Now), 2)
Windows(s).Activate
Try this.
This is a recognition of the next month's document, assuming you have opened two documents.
Sub test()
Dim Wb1 As Workbook, wb2 As Workbook
Dim Wb As Workbook
For Each Wb In Workbooks
If InStr(Wb.Name, "Book1") Then
Set Wb1 = Wb
ElseIf InStr(Wb.Name, "Book2") Then
Set wb2 = Wb
End If
Next Wb
Wb1.Sheets("Sheet1").Range("B2:AQ5").Copy wb2.Sheets("Sheet1").Range("r2")
End Sub

How to reference an opened not active workbook?

I want to reference from code in an active workbook to another workbook,
I don't want to type path like that workbooks("path") , this reference should be flexible, is there something like array of already opened workbooks ?
You can assign an open workbook to a variable without providing the full path. You can then use the set object variable to perform any actions you wish.
Sub set_wb()
Dim wb As Workbook
Set wb = Workbooks("test_wb.xlsb")
wb.Activate
End Sub
You can also iterate through each open workbook using for each
Sub wb_names()
Dim wb As Workbook
For Each wb In Workbooks
Debug.Print wb.Name
Next wb
End Sub
Similarly, you can use for to iterate through each workbook using their index (the index is dependant on which order workbooks were opened).
Sub wb_index()
Dim i As Byte
For i = 1 To Workbooks.Count
Debug.Print Workbooks(i).Name
Next i
End Sub
Hope this helps.
See this answer.
To reference an already open workbook, you can use
Workbooks("book_name.xlsx")
You can also iterate through the collection
Dim i As Integer
For i = 1 To Workbooks.Count
MsgBox Workbooks(i).Name
Next i

Declaring variable workbook / Worksheet vba

I know this might come off as a trivial question, but I can't seem to declare a workbook or a worksheet as a variable in VBA. I have the following code, but I can't figure out what I am doing wrong, it should be straight forward. Normally I don't have any problems declaring variables such as Dim i As Integer etc.
sub kl()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ActiveWorkbook
Set ws = Sheet("name")
wb.ws.Select
End Sub
When I run the above code, I receive a type missmatch error.
Use Sheets rather than Sheet and activate them sequentially:
Sub kl()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ActiveWorkbook
Set ws = Sheets("Sheet1")
wb.Activate
ws.Select
End Sub
If the worksheet you want to retrieve exists at compile-time in ThisWorkbook (i.e. the workbook that contains the VBA code you're looking at), then the simplest and most consistently reliable way to refer to that Worksheet object is to use its code name:
Debug.Print Sheet1.Range("A1").Value
You can set the code name to anything you need (as long as it's a valid VBA identifier), independently of its "tab name" (which the user can modify at any time), by changing the (Name) property in the Properties toolwindow (F4):
The Name property refers to the "tab name" that the user can change on a whim; the (Name) property refers to the code name of the worksheet, and the user can't change it without accessing the Visual Basic Editor.
VBA uses this code name to automatically declare a global-scope Worksheet object variable that your code gets to use anywhere to refer to that sheet, for free.
In other words, if the sheet exists in ThisWorkbook at compile-time, there's never a need to declare a variable for it - the variable is already there!
If the worksheet is created at run-time (inside ThisWorkbook or not), then you need to declare & assign a Worksheet variable for it.
Use the Worksheets property of a Workbook object to retrieve it:
Dim wb As Workbook
Set wb = Application.Workbooks.Open(path)
Dim ws As Worksheet
Set ws = wb.Worksheets(nameOrIndex)
Important notes...
Both the name and index of a worksheet can easily be modified by the user (accidentally or not), unless workbook structure is protected. If workbook isn't protected, you simply cannot assume that the name or index alone will give you the specific worksheet you're after - it's always a good idea to validate the format of the sheet (e.g. verify that cell A1 contains some specific text, or that there's a table with a specific name, that contains some specific column headings).
Using the Sheets collection contains Worksheet objects, but can also contain Chart instances, and a half-dozen more legacy sheet types that are not worksheets. Assigning a Worksheet reference from whatever Sheets(nameOrIndex) returns, risks throwing a type mismatch run-time error for that reason.
Not qualifying the Worksheets collection is an implicit ActiveWorkbook reference - meaning the Worksheets collection is pulling from whatever workbook is active at the moment the instruction is executing. Such implicit references make the code frail and bug-prone, especially if the user can navigate and interact with the Excel UI while code is running.
Unless you mean to activate a specific sheet, you never need to call ws.Activate in order to do 99% of what you want to do with a worksheet. Just use your ws variable instead.
Third solution:
I would set ws to a sheet of workbook wb as the use of Sheet("name") always refers to the active workbook, which might change as your code develops.
sub kl()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ActiveWorkbook
'be aware as this might produce an error, if Shet "name" does not exist
Set ws = wb.Sheets("name")
' if wb is other than the active workbook
wb.activate
ws.Select
End Sub
Just coming across the same problem.
What you need to do is to declare ws as Object
Also it should be:
Set ws = wb.Sheets("Sheet1")
And should not be:
Set ws = Sheet("Sheet1")
The code below are working to me.
sub kl()
Dim wb As Workbook
Dim ws As Object
Set wb = ThisWorkbook
Set ws = wb.Sheets("Sheet1")
MsgBox ws.Name
End Sub
Try changing the name of the variable as sometimes it clashes with other modules/subs
Dim Workbk As Workbook
Dim Worksh As Worksheet
But also, try
Set ws = wb.Sheets("name")
I can't remember if it works with Sheet
to your surprise, you do need to declare variable for workbook and worksheet in excel 2007 or later version. Just add single line expression.
Sub kl()
Set ws = ThisWorkbook.Sheets("name")
ws.select
End Sub
Remove everything else and enjoy.
But why to select a sheet? selection of sheets is now old fashioned for calculation and manipulation.
Just add formula like this
Sub kl()
Set ws = ThisWorkbook.Sheets("name")
ws.range("cell reference").formula = "your formula"
'OR in case you are using copy paste formula, just use 'insert or formula method instead of ActiveSheet.paste e.g.:
ws.range("your cell").formula
'or
ws.colums("your col: one col e.g. "A:A").insert
'if you need to clear the previous value, just add the following above insert line
ws.columns("your column").delete
End Sub
I had the same issue. I used Worksheet instead of Worksheets and it was resolved. Not sure what the difference is between them.
Dim ws as Object
Set ws = Worksheets("name")
when declaring the worksheet as worksheet instead of an ojbect I had issues working with OptionButtons (Active X) in this worksheet (I guess the same will be with any Active-X element. When declared as object everything works fine.
Lots of answers above! here is my take:
Sub kl()
Dim wb As Workbook
Dim ws As Worksheet
Set ws = Sheets("name")
Set wb = ThisWorkbook
With ws
.Select
End With
End Sub
your first (perhaps accidental) mistake as we have all mentioned is "Sheet"... should be "Sheets"
The with block is useful because if you set wb to anything other than the current workbook, it will ececute properly

Resources