PDA

View Full Version : Save in two places



menteith
01-17-2016, 10:17 AM
Hi all,

I am very new to VBA so I would like to get some help with a macro I have created (some parts of it were found in the Internet). The macro should save make a backup (in a specified path) of a file that is currently being saved, a procedure that is often discussed since Word lacks of it. I will talk over what I think the macro does and should do.

1. FileSave procedure is intercepted.
2. The macro checks if an active document is saved. If it is, no extra action is required and the macro closes.
3. If an active document in not saved, the usual "Save As" dialog appears. If the user chooses to not save the file then the macro closes.
4. If document is not saved, the macros saves it.
5. The macro looks for a backup folder. If it is not found, the macro creates it and shows a message box.
6. Then the macro checks if the source folder is the same as the backup folder. If they are the same, the macro shows a message and closes.
7. The active (current) document is copied to the backup folder. If it fails, a message box is displayed.

I tested this macro and it seems to work. However, there is a huge imperfection. When document is modified and the user chooses to close it, a dialog appears asking if the document should be saved. If the user chooses to do so, the document is saved, but a backup copy is not created - and I would like to create a backup in this situation.

Could you check the macro against errors and suggest how to implement the above-mentioned feature? I am newbie so I am pretty sure that the macro is, to say the least, imperfect and it could be rewrirtten. I did my best to make it as elegant (e.g. I tried to avoid the GoTo procudure) and short as I could.

Please find the macro below.


Sub FileSave()
Dim source As String
Dim DocName As String
Dim objF As Object
Dim retVal As Long

backup = "C:\Users\" & Environ("UserName") & "\Documents\BackupWord\"

With ActiveDocument

If .Saved Then Exit Sub
If .Path = "" Then
If Application.Dialogs(wdDialogFileSaveAs).Show <> -1 Then Exit Sub
End If
'GoTo continue

If Not .Saved Then
ActiveDocument.Save
End If
'continue:
If Dir(backup, vbDirectory) = "" Then
MkDir backup
MsgBox "Backup folder has been created.", vbInformation
End If

source = .Path & "\"
DocName = .Name
If source = backup Then
MsgBox "WARNING! Backup folder is the same as the source folder."
Exit Sub
End If

Set objF = CreateObject("Scripting.FileSystemObject")
retVal = -1
On Error Resume Next
retVal = objF.CopyFile(source & DocName, _
backup & DocName, True)
On Error GoTo 0
Set objF = Nothing
If retVal <> 0 Then
MsgBox "Backup has not been copied to folder " & backup
End If
End With
End Sub

SamT
01-17-2016, 01:07 PM
Does this apply to

All Documents
Documents of a certain Template
Only certain Documents


In any case the code must be in a Class Module
If 1 , then it must be in Normal.dot
If 2, it must be in the Templae
If 3, it must be in the Document itself.

You will need two Event Procedures
For case 1, Private Sub appWord_DocumentBeforeClose and Private Sub appWord_DocumentBeforeSave
For cases 2 and 3, Private Sub appWord_Quit and Private Sub appWord_DocumentBeforeSave

The following is from the Help files

Private Sub App_Quit()


object An object of type Application declared with events in a class module. See using events with the Application object below


Private Sub App_DocumentBeforeClose(ByVal Doc As Document, Cancel As Boolean)


object An object of type Application declared with events in a class module. For more information about using events with the Application object see below.

Doc The document that's being closed.
Cancel False when the event occurs. If the event procedure sets this argument to True, the document doesn't close when the procedure is finished.


Private Sub App_DocumentBeforeSave(ByVal Doc As Document, ByVal SaveAsUI As Boolean, Cancel As Boolean)


object An object of type Application declared with events in a class module. For more information about using events with the Application object see below.

Doc The document that's being saved.

SaveAsUI True to display the Save As dialog box.
Cancel False when the event occurs. If the event procedure sets this argument to True, the document isn't saved when the procedure is finished.


Using Events with the Application Object See Also Specifics
To create an event handler for an event of the Application object, you need to complete the following three steps:



Declare an object variable in a class module to respond to the events.
Write the specific event procedures.
Initialize the declared object from another module.

Declare the Object Variable Before you can write procedures for the events of the Application object, you must create a new class module and declare an object of type Application with events. For example, assume that a new class module is created and called EventClassModule. The new class module contains the following code.
Public WithEvents App As Word.Application Write the Event Procedures After the new object has been declared with events, it appears in the Object drop-down list box in the class module, and you can write event procedures for the new object. (When you select the new object in the Object box, the valid events for that object are listed in the Procedure drop-down list box.) Select an event from the Procedure drop-down list box; an empty procedure is added to the class module.
Private Sub App_DocumentChange()

End Sub Initialize the Declared Object Before the procedure will run, you must connect the declared object in the class module (App in this example) with the Application object. You can do this with the following code from any module.
Dim X As New EventClassModule
Sub Register_Event_Handler()
Set X.App = Word.Application
End Sub Run the Register_Event_Handler procedure. After the procedure is run, the App object in the class module points to the Microsoft Word Application object, and the event procedures in the class module will run when the events occur.

SamT
01-17-2016, 01:08 PM
The code in the two Event Procedure should jut call the sub that does the actual savingl

gmayor
01-18-2016, 11:13 PM
http://www.gmayor.com/SaveInTwoPlacesAddIn.htm might save you a lot of effort.

menteith
01-19-2016, 09:41 AM
gmayor

I know your addin - it's great.Your is very user friendly with GUI, pop-ups and so on. I would like to have a macro to suit my needs - with almost no pop ups and son on.


Does this apply to

All Documents
Documents of a certain Template
Only certain Documents


In any case the code must be in a Class Module
If 1 , then it must be in Normal.dot
If 2, it must be in the Templae
If 3, it must be in the Document itself.

It seems that it applies to all document. The code is in normal.dot in Microsoft Word Object -> ThisDocument. For a starter, I would like to deal with a dialog when I close Word which shows if I want to save or not a document or to cancel. My macro fails to show a msgbox when I choose "Cancel". Could you help me with this? Your first reply was to complicated for me - I am really newbie in VBA.


Private Sub DocumentBeforeSave()

With ActiveDocument
If Application.Dialogs(wdDialogFileSaveAs).Show = 0 Then
MsgBox "The Cancel button."
End If

End With
End Sub