I work with a a group of six interlinked Excel workbooks that all feed into one summary/reporting workbook (let's call it "Main Report.xlsm").
Since the various workbooks are updated with new information throughout the day as it comes to hand, they need to be saved regularly throughout the day. I have therefore created a simple VBA macro that saves all open workbooks at the press of a button, which I have located as on object on Sheet1 of MainReport.xlsm. The macro works OK and saves all open workbooks as expected, however two aspects of the code are not working as expected:
No matter where I insert ScrenUpdating = FALSE, Excel still displays each workbook on the screen as it saves it. I don't want that because it slows down the save process, plus it looks weird as the macro toggels through each open workbook and the workbooks flash up momentarily on the screen. Since I activate the save macro from Main Report.xlsm, I want the screen to freeze on that workbook whilst Excel saves all open workbooks as a 'background' process. Can anyone tell me how I can make ScreenUpdating work properly with this code?
At the end the macro is supposed to select the 'Main Report.xlsm' workbook, but instead of activating that workbook, Excel seems to get stuck on displaying the second-last workbook in the group of six open workbooks. If I test the code by stepping through it, it seems to work OK, but when I run it from the assigned button on Main Report.xlsm, it does not work. Why would this be happening?
Here is my simple 'SaveAll' macro VBA code:
Sub SaveAll()
Application.ScreenUpdating = False
Dim Wkb As Workbook
Application.Calculate
For Each Wkb In Workbooks
If Not Wkb.ReadOnly And Windows(Wkb.Name).Visible Then
Wkb.Save
End If
Next
Application.Workbooks("Main Report.xlsm").Activate
ActiveWorkbook.Worksheets("Sheet1").Select
ActiveSheet.Range("C4").Select
Application.ScreenUpdating = True
End Sub
Can anyone spot what I am doing wrong?
Related
I am new to VBA!
I have a workbook A that I use as a template for spinoff workbooks B, C, D, etc.
I made an error in formulas range A36:E37. I need to correct it in all the subsequently created workbooks, which can have any random name
I want to open the corrected master workbook A, and copy range from A to whateverworkbookname
Every time I use thisworkbook refrerence, it pastes the data to my personal macro workbook, same thing with activeworkbook.
I'm sure there's a simple solution, (like assigning a variable to the freshly opened workbook that needs fixing?) but I don't know how to do that.
Help is much appreciated!
Also of note, I am planning on manually opening the whaverworkbookname, then VBA unprotecting the sheet, copy paste function, protecting the sheet, saving, and closing the whateverworkbookname book when the macro completes, to be repeated with the rest of the incorrect workbooks.
If there is a smarter way to do this (which is probably way over my head) like applying a macro to all workbooks in a folder for instance, I would be interested in a point in the right direction to learn about it.
First a note:
ThisWorkbook always refers to the workbook the code is written in. This never changes.
ActiveWorkbook is the workbook that has focus (is on top). This changes easily with a mouse click on any workbook.
The issue is probably that you run the code from VBA editor. But if it is in your personal workbook and you run from the editor, then as soon as you are in the code your active workbook is the personal one because that is where your code is and if you click there to run the code it has focus.
You can check if the active workbook is the personal one
If ActiveWorkbook.Name = ThisWorkbook.Name Then
MsgBox "The active workbook is the personal one. Make sure to focus on the correct workbook."
Exit Sub
End If
'rest of your code
Create a button or link a ribbon button to launch your macro and use ActiveWorkbook in your code.
I open an Excel workbook which has some VBA code in it including Event code on one of the worksheets. I open a second workbook which has no VBA code in it at all but as soon as the second workbook opens, it triggers the VBA code to run in the first workbook. The code fails because the first workbook is not the Active Workbook. Anybody got any ideas why opening a second workbook should trigger event code in the first workbook?
I can replicate that -seems like opening a workbook triggers the calculate event in other open workbooks. Having said that, your event-handling code should not rely on any particular workbook being active when it runs, so it would help to post that if you want suggestions for fixes.
For example the worksheet object which corresponds to the sheet module can be referenced via Me, and the workbook containing that sheet is Me.Parent
Private Sub Worksheet_Calculate()
Debug.print "calculating " & Me.Name & " in " Me.Parent.Name
End Sub
I have a workbook ("CodeBook.xlsm") that runs code using a BeforeSave event. When a user has multiple workbooks open and chooses to quit excel via File/Exit, the user is prompted whether to save workbooks, and if yes to CodeBook.xlsm, then the BeforeSave code is run. The problem is, at that point the ActiveWorkbook may not be CodeBook.xlsm, unless that happens to be the workbook that the user was in when he/she selected Exit Excel. If the user quit excel from another workbook, the BeforeSave code is running but the activeworkbook is some random file of the user, so all the references to specific worksheets and ranges in the BeforeSave code do not work.
I have tried various ways using a Static declaration to retain the name of CodeBook and workbook().activate to activate it when the application is quitting, but when BeforeSave runs, it can't pick up the name CodeBook anywhere, short of hard-coding the name into the code.
Any suggestions? How to retain a variable name in memory when there is no code running, but is there when a user initiates a quit excel, OR how to activate a specific workbook when Excel is quitting from a user command and not from application.quit. Using excel 2010.
I overcame this by including a reference to the specific workbook.
For example, this code simply saves the date/time stamp in cell A1 of Sheet1 before closing the document. By adding ThisWorkbook, it works on the specific workbook that the code resides in. If you don't add ThisWorkbook then it will work on the active workbook when the user quits.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
ThisWorkbook.Worksheets("Sheet1").Range("A1").Value = Now()
End Sub
Place this code in the ThisWorkbook module.
I'm trying to create a Macro in Excel 2007 that will delete itself when it finishes running and close Excel. The reason I want to do this is that I am going to be sending the Workbook out to other people, and I don't want them to see security warnings about the Macros. Several versions of this Workbook will be generated, so this I don't want to manually run and remove the Macro for each one.
I've tried the following code. It runs without error, but does not actually delete the Macro. If I remove the line "ActiveWorkbook.Close SaveChanges:=True" the Macro is deleted, but this prompts the user to save the Workbook as Excel closes. Is there any way to do this without User interaction?
Dim ActiveComponent
Set ActiveComponent = ActiveWorkbook.VBProject.VBComponents("ModuleName")
ActiveWorkbook.VBProject.VBComponents.Remove (ActiveComponent)
ActiveWorkbook.Save
Application.Quit
ActiveWorkbook.Close SaveChanges:=True
Why not just move your macros to another workbook and have them operate on the workbook(s) you're sending out?
Basically wondering if there's a way for me to create a VB application in Excel and have it run without a full version of MS Office. The VB application would load an Excel sheet that would import a CSV onload, then print a PDF of the sheet and close.
If you have any questions, let me know.
No. Not without converting to a standalone application.
If you had were familiar with VB6 (and had access to it; it's no longer for sale), you could create a VB6 app. that references the excel COM components (still need to be installed on each target PC).
Otherwise, build an app. using VB.NET and use Office VSTO 2010 (need to reference the Office PIAs)
How to: Target Office Applications Through Primary Interop Assemblies
Just a little conflict. In office, you code with VBA, which is different than VB. What you would need to do is create a VB app that uses excel libraries or something to do some meaningful work.
The short answer is no.
You could write an external visual basic script that calls in to office and opens excel using some excel libraries, if memory serves me correctly however - you'd still require office installed on this machine. (Unfortunately I can't find a link at the moment to back this up)
Your best bet is to parse the CSV data yourself and generate a PDF from that.
There is some information here: http://www.rlmueller.net/ReadCSV.htm on how to Read CSV data using VBS (to get the examples to run, you should simply have to rename the .txt to .vbs and double click it.)
I'll leave you to find out how you'd then generate the PDF.
I don't think however this is the best solution to your problem - a full .NET application or perhaps some Python would likely serve you better.
Code will go in several different places, "ThisWorkbook" object and the "UserForm" code.
"ThisWorkbook" contains code that will determine if the UserForm is the only Excel thing (workbook) open, and if it is it will hide the Excel application and hide the workbook itself. and if other workbooks are open it simply hides the workbook. I have it set to hide the application and the workbook in both cases so that a new instance of Excel can be opened after the UserForm is running without pulling up the workbook associated with the UserForm. The code for this is below (goes into the "ThisWorkbook" object):
Private Sub WorkBook_Open()
Dim wb As Workbook
Set wb = Workbooks("MyBook.xlsm")
If Workbooks.Count > 1 Then
wb.Windows(1).Visible = False
Else
wb.Windows(1).Visible = False
Application.Visible = False
End If
UserForm1.Show vbModeless
'Put defaults and populations here
End Sub
The UserForm1.Show vbModelessallows for Excel to be used while the UserForm is active.
A couple of notes on this section:
"UserForm1" is the name of my UserForm, change this to the name of yours
Where I Set wb = Workbooks("") change inside the quotes to the name of the
workbook the UserForm is in
The IfElse statement could be eliminated and moved to the If, if you don't need any other action on the opening with no other workbooks open
The next section of code goes in the UserForm Code. I have a button set up to show the Excel workbook in order to edit it and whatnot, you could have a region you click if you don't want a button to show up. When you want to activate the Excel sheet and the application will need to be activated. I unload (deactivate) the active thing (the UserForm). This bit of code isn't necessary if the user doesn't need access to the spreadsheet:
Private Sub See_Excel_Click()
Dim wb As Workbook
Set wb = Workbooks("MyBook.xlsm")
wb.Windows(1).Visible = True
Application.Visible = True
wb.Sheets("Sheet1").Activate
Unload Me
End Sub
Within the userform there should be a way to handle what happens when the userform is closed, as the excel application and workbook will stay open hidden in the background. I have the action close the workbook and the application. A quick note, if you set the Cancel = True then the red x button won't close the userform. The code I use for this is:
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = 0 Then
Cancel = False
Dim wb As Workbook
Set wb = Workbooks("MyBook.xlsm")
wb.Windows(1).Visible = True
Application.Visible = True
ThisWorkbook.Saved = True
ThisWorkbook.Activate
If Workbooks.Count > 1 Then
ActiveWorkbook.Close
Else
Application.Quit
End If
End If
End Sub
That is it for the code that goes inside the UserForm. And the code that is necessary to have the UserForm in VBA act as it's own application while allowing for Excel to operate normally at the same time as the UserForm.
To summarize what happens:
When the Workbook is launched the workbook is hidden, and if no other workbook is open the the Excel application is hidden.
The UserForm is initiated to allow for Excel to be used at the same time
When the spreadsheet is activated again excel is re-enabled and the application and un-hide the worksheet
When the user form is closed, the workbook is closed, and if there are no other workbooks the excel application is closed
If you set defaults or populate ComboBoxes put them in the "WorkBook" object code.