Perform Macro on Close Event IF File was Saved - vba

I want to run a macro "ExportToExcel" automatically when I close my .mpp file, BUT only if the Project was saved.
Reason: we only save this after we make changes; however, we are constantly opening the files to review. If this ran every time we closed, it would not be efficient.
I toyed with projectaftersave and could not make it work. I can make the following code work, but it runs EVERY time I close the file.
Sub Auto_Close()
Call ExportToExcel
End Sub
Expectations are to run my code when I close the .mpp ONLY if it was saved (not 'Save As') prior to closing.

Try the before_save event in the "ThisProject" project objects ( Microsoft Help Page )
Something along the lines of:
Option Explicit
Private Sub Project_BeforeClose(ByVal pj As Project)
~~ Your code for doing things in excel ~~
End Sub

Related

How to change default path in save on close prompt?

I'm trying to create a template that automatically changes folder suggested by the save prompt to a specified location. I've managed to get it partially working using the following code (modified from here):
Sub FileSave()
Dim UserSaveDialog As Dialog
Set UserSaveDialog = Dialogs(wdDialogFileSaveAs)
'save changes if doc has been saved previously
If ActiveDocument.Path <> "" Then
ActiveDocument.Save
Exit Sub
End If
With UserSaveDialog
.Name = "C:\Users\david\Downloads"
If .Display Then
UserSaveDialog.Execute
End If
End With
End Sub
Using this code, my macro correctly intercepts the default save behaviour (or Ctrl+S), however it doesn't intercept the save dialog when closing the file. I've tried basically copying this code to a new Sub called Document_BeforeSave, FileExit, FileCloseEx and FileCloseAllEx (yes, I am having difficulty with all the different objects and what they do :) all to no avail.
I'm not sure the same code will even work in this event, but I don't even get any indication that it has failed to work, so it seems I'm using the wrong event.
Turns out I somehow missed AutoClose (MS Docs), which does what I want.

Disable Save As but not Save in Word 2010

I am looking to disable Save As in a Word 2010 file but still allow save. In other words I want users to be able to update the existing file but not create copies. I realize that this is impossible to truly do for people who know workarounds but for the general user I have successfully done this in Excel but am pretty new to word VBA.
When I add the following to a brand new document everything works as intended:
Sub FileSaveAs()
MsgBox "Copies of this file cannot be created. Please save changes in the original document." & _
, , "Copy Cannot be Created"
End Sub
My document has other macros for various command buttons but none of them involve saving the document (under original name or save as). There is also a macro running on open but that is 1 line going to a bookmark. When I try to "save as" in this document I get the message box as intended. When I try to "save" though things get strange: I get the save as dialogue (problem 1). Whether I try to save either under same name or other name the dialogue behaves as it normally would except it doesn't save and the dialogue box opens again automatically essentially creating an endless loop until I hit cancel (problem 2). I also intermittently get a "disk is full" warning pop-up after trying to save which I can dismiss but appears a few minutes later as long as he file is open (perhaps related to autosave?)
Since the macro works in the test file I assumed this strange behavior must be something elsewhere in my code but my document with the other macros saves normally as long as I don't include the save as code above so now I'm totally confused. Before I put up the rest of my code which is lengthy and for the reasons stated above I would not think impact things, I figured I'd ask this:
1. Is there any place other than my other command button macros that could be causing this behavior?
2. Is there a better method people recommend to achieve my ultimate goal of disabling save as but not save?
Thanks in advance for any advice you can provide.
The Word application has a DocumentBeforeSave event. To enable application events I suggest to create a class module by the name of ThisApplication and paste the following code into it.
Option Explicit
Private WithEvents App As Application
Private Sub Class_Initialize()
Set App = Word.Application
End Sub
Private Sub App_DocumentBeforeSave(ByVal Doc As Document, _
SaveAsUI As Boolean, _
Cancel As Boolean)
If SaveAsUI Then
MsgBox "Please always use the ""Save"" command" & vbCr & _
"to save this file.", _
vbExclamation, "SaveAs is not allowed"
Cancel = True
End If
End Sub
Add the following code to your ThisDocument module.
Dim WdApp As ThisApplication
Private Sub Document_Open()
Set WdApp = New ThisApplication
End Sub
You may add the Set App = ... line to your existing Document_Open procedure. After the WdApp variable has been initialised all application events will be received by the ThisApplication class where the DocumentBeforeSave event procedure is programmed not to allow SaveAs.
Of course, this is a blanket refusal for all documents. Therefore you may wish to add code to the procedure to limit the restriction to certain documents only. The proc receives the entire document object with all its properties, including Name, Path, FullName and built-in as well as custom properties. You can identify the files you wish to be affected by any of these.
Note that the WdApp variable will be erased in case of a program crash. If this happens the application events will no longer fire. It may be useful to know that application events occur before document events. This is if you wish to use the application's DocumentOpen event as well as or instead of the document's Document_Open event.

vb.net MS Word crash cleanup

I have a program that takes a template .docx file and populates it with data, saving a copy afterwards. The program itself works fine and I got a nice try..catch in main sub in case something fails, so the file is closed regardless.
The problem is that if it crashes completely, i.e. is forced to close (or manually force closed if it hangs), it will keep the process running with the opened template, so next time it;s launched, you'll get the read only error when trying to open it.
So the question: Is there a way to clean up afterwards, without having to end process via task manager? Or maybe a way of opening it without locking it out? Making a temp copy maybe?
Fixed with this:
Sub KillUnusedWordProcess()
Dim oXlProcess As Process() = Process.GetProcessesByName("Winword")
For Each oXLP As Process In oXlProcess
If Len(oXLP.MainWindowTitle) = 0 Then
oXLP.Kill()
End If
Next
End Sub

How to use "ReSharper.ReSharper_SilentCleanupCode" in a vs2010 macro?

I am trying to build a macro that formats all modified files before saving them.
Public Module ReformatAndSave
Sub SingleFile()
DTE.ExecuteCommand("ReSharper.ReSharper_SilentCleanupCode")
DTE.ActiveDocument.Save()
End Sub
Sub AllFiles()
For Each doc As Document In DTE.Documents
If Not doc.Saved Then
doc.Activate()
DTE.ExecuteCommand("ReSharper.ReSharper_SilentCleanupCode")
DTE.ActiveDocument.Save()
End If
Next
End Sub
End Module
This results in an error
Error HRESULT E_FAIL has been returned from a call to a COM component.
It works when I use this instead:
DTE.ExecuteCommand("ReSharper.ReSharper_CleanupCode")
I could live with this solution for a single file but choosing the profile when saving all files is annoying.
I use ReSharper 6.1.1000.82. This bug seems to be rather old: http://youtrack.jetbrains.com/issue/RSRP-179846
Is it possible to work around this bug by collecting all modified files and the execute the working CleanUpCode command once for all the files.
I can manually select many files and execute CleanUp on these files, manually. I would like to do this automatically on all modified files when saving them.
The solution is so simple.
All I had to do is replacing this
DTE.ExecuteCommand("ReSharper.ReSharper_CleanupCode")
with this
DTE.ExecuteCommand("ReSharper_SilentCleanupCode")
This doesn't work!
DTE.ExecuteCommand("ReSharper.ReSharper_SilentCleanupCode")

Leaving a Project file open after retrieving it with GetObject

What is the right way to leave an MS Project file opened with GetObject() open and visible to the user after the end of a macro in a different app?
The information I found online suggests that setting the Application.UserControl property to True before the objects go out of scope should allow the user to continue using the opened file. However, for MS Project at least, the Application.UserControl property appears to be read-only. Is there a way to work around this?
A simplified example showing the problem:
Sub AddTasks()
Dim proj As Object
' Already have the file path from another part of the workflow
Set proj = GetObject("C:\projtest.mpp")
' perform some calculations and add new tasks to project
proj.Tasks.Add "additional task"
' Leave Project open and visible for the user
proj.Application.Visible = True
proj.Application.UserControl = True ' Gives "Type Mismatch" error
' without the UserControl line, runs ok, but Project closes after the end of the macro
End Sub
Instead of using GetObject, could you create an instance of the application and open the project file in the instance?
Sub AddTasks()
Dim msProj as Object
Set msProj = CreateObject("Project.Application")
msProj.FileOpen "C:\projtest.mpp"
'do stuff to project file here
msProj.Visible = True
End Sub
Something like the above (I can't test the above code because I don't have MSProject, but similar code works for MSWord)
For Project UserControl just indicates if the user started the application or not; it appears to be read-only because it is. I've not done what you're asking for with Project, although here is a similar example for Word trying to see and find running instances of Excel. Perhaps this helps a little:
can-vba-reach-across-instances-of-excel