I am trying to write a VBA macro to track changes to a workbook in a separate sheet.
If you do this manually, the sequence of commands is Tools > Track Changes > Highlight Changes, taking the option Separate Worksheet. You have to do two iterations of the command, one to activate tracking inline, a second to move the tracking to a separate sheet.
Using the macro recorder, I got to this piece of code:
With ActiveWorkbook
.Save
.KeepChangeHistory = True
.HighlightChangesOptions When:=xlAllChanges
.ListChangesOnNewSheet = True
.HighlightChangesOnScreen = False
.Worksheets("History").Select
End With
When I run this, I get the error HighlightChangesOptions method fails. Any suggestions?
The HighlightChangesOptions method will only work if the workbook is already shared. In the UI, turning on HighlightChange will share the workbook automatically, but not so in VBA.
Application.DisplayAlerts = False
With ActiveWorkbook
.SaveAs , , , , , , xlShared
.KeepChangeHistory = True
.HighlightChangesOptions When:=xlAllChanges
.ListChangesOnNewSheet = True
.HighlightChangesOnScreen = False
.Worksheets("History").Select
End With
The DisplayAlerts call will prevent Excel from warning you that you are overwriting an existing workbook - itself. You may want to comment that line out just to see what's going on.
Note that this code cannot live in the shared workbook. Once you share the workbook, the code stops executing and errors. It has to live in a different workbook or add-in.
Related
I need to construct a workbook that opens two separate workbooks, each in a separate instance of Excel, and run the macro in their respective workbooks.
After some research, I got:
Sub runMacro()
Application.DisplayAlerts = False
Dim appXL As New Excel.Application
appXL.Workbooks.Open Filename:="E:\ExcelFiles\Workbook1.xlsm", UpdateLinks:=True, ReadOnly:=False
appXL.ActiveWorkbook.Windows(1).Visible = True
appXL.Visible = True
appXL.Application.Run ("'Workbook1.xlsm'!Macro1")
End Sub
The code does not produce an error is able to run the correct subprocedure in the correct instance of Excel, however the workbook is opened in read-only mode. I have tried a few more different syntax but they either resulted in an error or had no effect.
I have recently finished an Excel workbook that utilizes a fair amount of VBA. The spreadsheet is always able to perform all of its intended functions, and there are no issues when it is the only workbook open in Excel. However, when any other workbook is open (unrelated files included), the workbook will not close. Clicking on the red "x" in the top right corner simply does not do anything, and no error messages are shown. In order to close it, all other Excel windows must be closed beforehand.
While this does not detract from the functionality of the workbook itself, enough people will be using it that I want to avoid bringing about the inconvenience of having to close any other workbooks they have open before being able to close this one.
So, does anyone have any ideas as to what is causing this to happen? I do have code for the Workbook_Close() event, but this is designated as private and only located within the ThisWorkbook part of this spreadsheet. I'm confused as to why another sheet with no VBA involved prevents this one from closing. Please let me know if there is anything I can clarify, thank you.
EDIT - Here is the code for the Workbook_BeforeClose() event:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
If Me.Saved = False Then Me.Save
Call PrepareWorkbook
End Sub
Sub PrepareWorkbook()
Application.ScreenUpdating = False
Call UnprotectWorkbook
Dim masterSheet As Worksheet
Set masterSheet = ActiveWorkbook.Worksheets("PLANNING")
For Each sheet In ActiveWorkbook.Worksheets
If Not (sheet.Name = "README" Or sheet.Name = "PLANNING" Or sheet.Name = "PREV") Then
sheet.Visible = xlSheetVeryHidden
End If
If (sheet.Name = "README" Or sheet.Name = "PLANNING" Or sheet.Name = "PREV" Or sheet.Name = "ADMIN") Then
Call ProtectSheet(ActiveWorkbook.Worksheets(sheet.Name))
Else
Call ProtectPlannerSheet(ActiveWorkbook.Worksheets(sheet.Name))
End If
Next
If ActiveWorkbook.ActiveSheet.Name <> "PLANNING" Then
masterSheet.Select
End If
Call ProtectWorkbook
Application.ScreenUpdating = True
End Sub
I should note that commenting out the call to PrepareWorkbook() within the Workbook_BeforeClose() event did not solve the problem.
Sounds like your are doing something to that Workbook like "editing a cell" which is preventing it from closing (other things like having the formatting popup open will also do this).
Trying selecting the workbook, pressing ESC, and then manually closing it. If that works then look for the place in your code where you are "editing a cell" or something similar.
I've found the source of my problem, which lies within how I'm protecting the workbook. In my VBA code, I set the "Windows" property of the Workbook.Protect function to True; I'm not sure if this is Excel's intended functionality or not, but regardless, this made it so that the current workbook could not be closed if any other workbook was also open. Changing this property to False fixed the problem, and I can close the workbook as would normally be expected.
So, I would suggest to avoid ever setting the "Windows" property to True unless absolutely necessary and you have a complete grasp of its actual function.
First of all, I have searched and read similar threads and I have tried the solutions that were proposed and solved the other people's problem but it hasn't worked in my case.
I basically want to create temporary excel sheet where I want to do all the calculations in the back-end and display only the output to the user in the front-end sheet.
Can anyone tell me how do I go got creating the temporary sheets and deleting them as soon as numbers are copied in the front-end sheet i.e. the sheet that user will see.
My main motive is not let the user see the various calculations that are happening in the back-end.
you can create a temp sheet in VBA by using
Sheets.Add.Name = "Temp Sheet" or any other name really
and after you calculations done on it, delete it with
Sheets("Temp Sheet").Delete
bear in mind if your alerts are on it will prompt user to agree to delete the sheet, you can avoid that by using Application.DisplayAlerts = False before deleting and follow by Application.DisplayAlerts = True after
I'd suggest to hide one sheet to perform calculations instead of creating temporary sheet.
Let's say you have input sheet, where user input his data. Another sheet is hidden. There the calculations are performed.
How to hide Sheet?
Go to VBA Code editor window (ALT+F11). Select sheet you want to hide. In a "Properties" window choose option: SheetHidden. Now, you can copy data from hidden sheet into destination sheet via using macro.
ThisWorkbook.Worksheets("HiddenSheetName").Range("A1:C56").Copy
ThisWorkbook.Worksheets("VisibleSheetName").Range("A66:C106").PasteSecial xlValues
Note: i wrote above code straight from my head. Didn't tested!
Sample code to create temp sheet:
Sub Sample()
Dim TempSheet As Worksheet
Application.ScreenUpdating = False
On Error Goto ErrorHandler:
Set TempSheet = ThisWorkbook.Worksheets.Add
TempSheet.Visible = xlSheetHidden
'Do the calculations
Application.DisplayAlerts = False
TempSheet.Delete
Application.DisplayAlerts = True
ErrorHandler:
Application.ScreenUpdating = True
End Sub
I am using this function to copy a sheet from a Workbook to another Workbook.
I works, but it seems that if I disable the macros from Workbook,
it can not copy the sheet anymore.
If I chage this line : m_objExcel.AutomationSecurity = msoAutomationSecurityForceDisable
to this m_objExcel.AutomationSecurity = msoAutomationSecurityByUI
it works but gets a warning message.
Also if I comment the line it works perfectly but with macros On.
Private Sub CopyFunction()
Set m_objExcel = New Excel.Application 'creare obiect
m_objExcel.DisplayAlerts = False
g_secAutomation = m_objExcel.AutomationSecurity
m_objExcel.AutomationSecurity = msoAutomationSecurityForceDisable
m_objExcel.Visible = True
Dim CopyFrom As Workbook
Dim CopyTo As Workbook
Dim CopyThis As Object
Set CopyFrom = m_objExcel.Workbooks.Open("D:\FromFile.xls")
Set CopyTo = m_objExcel.Workbooks.Open("D:\ToFile.xls")
Set CopyThis = CopyFrom.Sheets(1) ''Sheet number 1
CopyThis.Copy After:=CopyTo.Sheets(1)
m_objExcel.Workbooks(CopyTo.FullName).Save
CopyFrom.Close
CopyTo.Close
m_objExcel.Workbooks.Close
MsgBox "ok"
End Sub
I am using it from Access and work with a Excel file.
What is the problem?
Is there a way to still be able to copy a sheet from a workbook to another, and have the macros disabled?
That's what the disable macro is typically for: Security.
It is meant for your own protection; in case you receive a workbook from an unknown author, this person may want to send you harmful software.
Imagine for example that code starts deleting files as soon as you open the workbook.
Disabling macro's prevents this and allows you to look into code before you decide to execute it.
As a solution, the user can trust you as author while you sign your project as developer.
I suggest that you check out this link:
http://msdn.microsoft.com/en-us/library/aa190098(v=office.10)
(You can decide to turn off the security entirely (Enable macro's), but this is generally not recommended.)
I found that the problem is here:
m_objExcel.Workbooks(CopyTo.Name).Save
I have sales global sales data in very large files which I need to filter by country and product and then analyze. Since I will need to perform this same analysis over and over again with different country/product combinations I am trying to do this with a macro.
This is what the macro does:
Open the source files with global data;
Filters the data;
Copies it and pastes it into a workbook which houses the macro;
Recalculates and refreshes the workbook and;
Saves a copy of the file to another folder.
The macro appears to run fine and the files are being saved, however I am running into 2 problems on steps 4 and 5:
The pivot tables do not seem to be refreshing - this may be because the second problem:
All pivot tables in the saved copy still refer to the original file
I'd prefer to fix both problems by generating the copied file without links, but I'm also open to any bandaids that might allow me to force the copied file to link to itself (this doesn't seem to work when I do it manually).
I have the full code if you want to see it all, but because I suspect the issue is in how I'm saving the file I'll just paste that piece here. Let me know if you need to see another part of the macro. Any help would be much appreciated, thanks in advance.
Save Function:
Public Sub SaveAsCopy(filePath As String)
Dim updateStatus As Boolean
'Check current status of Alerts
updateStatus = Application.DisplayAlerts
'Turn off alerts
Application.DisplayAlerts = False
ThisWorkbook.Sheets.Copy 'creates new workbook without macros"
'The New workbook copy is now the Active workbook
'Delete Control Sheet
ActiveWorkbook.Sheets(1).Delete
'Save Macro free version and close
ActiveWorkbook.SaveAs Filename:=filePath, FileFormat:=51
ActiveWorkbook.Close
'Revert back to origional alert status
Application.DisplayAlerts = updateStatus
End Sub
Function Call:
Call SaveAsCopy(filePath)
Will share the workaround I developed since I didn't get any bites on a more elegant solution:
Public Sub SaveAsCopy(filePath As String)
Dim updateStatus As Boolean
'Check current status of Alerts
updateStatus = Application.DisplayAlerts
'Turn off alerts
Application.DisplayAlerts = False
'Hide Control Sheet
ActiveWorkbook.Sheets(1).Visible = False
'Save Macro free version and close
ActiveWorkbook.SaveAs Filename:=filePath, FileFormat:=52
'Unhide
ActiveWorkbook.Sheets(1).Visible = True
'Revert back to original alert status
Application.DisplayAlerts = updateStatus
End Sub
At the end of the parent function I close the current file, reopen the original, and loop through the new workbooks to remove macros.