The HotDocs Computation Archive
Get Extra Help

0110 - Auto-Save Macros

Description:

Word and WordPerfect macros for automatically saving your document after assembly.


• Explanation •

The macros below will automatically save a document after assembly. The macros will work "as-is" (as-are?). Simply save the appropriate macro to the macro directory (WordPerfect) or to a global add-in template (Word). The WordPerfect macro is also available for download.

Quick Overview: These macros are all based on the same concept. The user is prompted for the document's filename by HotDocs during assembly. This is just a HotDocs text variable, called TextVar in the explanations below. This text variable is placed somewhere in the template surrounded by a bookmark. When assembly is complete, the macro looks for the bookmark, extracts the value of TextVar from within it, and saves the document using this value as the filename.

Directory: You should be able to add directory-selecting functionality fairly easily. One option is to create a HotDocs multiple choice variable for the directory and include that variable within the bookmark with TextVar:

[Bookmark]«Directory»«TextVar»[Bookmark]

The second Word macro below demonstrates how to have your macro determine the directory, and additionally how to add an entry for the document in a Lawbase database.

Invoking the Macro: The macros are all invoked in the same manner, regardless of whether you use Word or WordPerfect. To invoke the macro you must use a PLAY instruction at the end of the document. In other words, make sure that the PLAY is the very last thing in the document. Otherwise, the saved document will be incomplete. To create a PLAY instruction, follow the directions found in Computation #0108: Running a Macro During Assembly.


•  •  •  •  •  •  •


• Code •

WordPerfect:

DISPLAY( Off! )
ONERROR( Oops )
ONCANCEL( CheckStatus )

// Find and select the requested filename
BookmarkBlock( "AutoSave" )

// Extract the filename
vFile := ?SelectedText
SelectDelete
BookmarkDelete( "AutoSave" )

// Uncomment the next line of code to end the macro
// if the user did not give a filename (no-nag mode)
// IF (vFile = "") GO( CheckStatus ) ENDIF

// The following do not apply to directories or non-named files
IF (( vFile <> "" ) AND ( StrRight( vFile;1 ) <> "\" ))

   // Add a file extension if there is not one
   IF (StrPos( StrRight( vFile;4 ); "." ) < 1)
      vFile = vFile + ".wpd"
   ENDIF

   // See if the file already exists
   IF (StrPos( vFile; "\" ) > 0)
      vDir := ""
   ELSE
      vDir := ?PathDocument
   ENDIF
   FileExists( vExists; vDir + vFile )
   IF (vExists = True)
      MessageBox(;"Save Document"; """" + vFile + """ already exists.")
      vPos := StrPos( StrReverse( vFile ); "\" )
      IF (vPos > 0)
         vFile := StrLeft( vFile; StrLen( vFile ) - vPos + 1)
      ELSE
         vFile := ""
      ENDIF
   ENDIF

ENDIF

// Perform the Save operation
FileSave( Filename:vFile; Overwrite:Yes! )
GO( CheckStatus )

// Check whether the file was saved
LABEL( CheckStatus )
   IF (?Name <> "")
      MessageBox(;"Save Document"; "Saved as """ + ?Name + """")
   ELSE
      MessageBox(;"Save Document"; "Document was NOT saved.")
   ENDIF
GO( Away )

LABEL( Oops )
   MessageBox(;"Save Document"; "An unknown error has ocurred.")
GO( CheckStatus )

LABEL( Away )
// Instead of using QUIT, we GO( Away ).
// QUIT can kill HotDocs, so don't use it.

• Explanation •

(download the macro)

This macro looks for a filename located in a bookmark called AutoSave. To create this in your template, insert the HotDocs text variable which will contain the filename (TextVar). Next select the entire variable - chevrons and all. Now create the bookmark (generally: Tools or Insert > Bookmark > Create). Type AutoSave as the name of the bookmark, and make sure that Selected Bookmark is checked. Finally, create your PLAY instruction as directed above.

When your user assembles the document, your TextVar will ask them what the filename should be. If they give a unique filename with full path, the document will automatically be saved with that name. BUT: 1) If they give only a filename, but no directory, they will be presented with the "Save As" dialog with the filename filled in, where they can then choose the appropriate directory and "Save" the document. 2) If they do not include a file extension (such as ".wpd") one will be added automatically. 3) If they give only a directory (it must end in "\"), they will be presented with the "Save As" dialog with that directory preselected. 4) If the chosen filename already exists, they will be presented with the "Save As" dialog so that they can choose a different name. 5) And if they leave TextVar unanswered, they will be presented with the "Save As" dialog. This final behavior can be changed to "no-nag" mode (macro will simply end if the filename value is blank) by uncommenting the line noted in the macro.

Note that whenever the user gets the "Save As" dialog they can dismiss it without saving the document.

Contributor: LegalCS


•  •  •  •  •  •  •


• Code •

Word:

Option Explicit
Public Sub HDSaveasmsb()

   Dim Temp As String      'contents will be the filename
   Dim Temp1 As String     'selected text
   Dim Temp2 As String     'the final file name (with .doc) for comparison in error loop
   Dim Path As String      'path of caselog that will be saved
   Dim newname As String   'contents will be user input file name if temp is already a valid filename
   Dim message As String   'message for input box in error routine

   Path = "c:\"            '!! place the directory here; be sure it ends with "\"

   ' Find the marker ***zzz and delete it.
   ' Curser will now be at the beginning of the
   ' filename that was inserted by HD.
   Selection.Find.ClearFormatting
   Selection.Find.Replacement.ClearFormatting
   With Selection.Find
      .Text = "***zzz"
      .Replacement.Text = ""
      .Forward = True
      .Wrap = wdFindContinue
      .Format = False
      .MatchCase = False
      .MatchWholeWord = False
      .MatchWildcards = False
      .MatchSoundsLike = False
      .MatchAllWordForms = False
      .Execute
   End With
   With Selection
      If .Find.Forward = True Then
         .Collapse Direction:=wdCollapseStart
      Else
         .Collapse Direction:=wdCollapseEnd
      End If
      .Find.Execute Replace:=wdReplaceOne
      If .Find.Forward = True Then
         .Collapse Direction:=wdCollapseEnd
      Else
         .Collapse Direction:=wdCollapseStart
      End If
      .Find.Execute
   End With
    
   ' Select the rest of the line, i.e., the file name
   ' Then move left 1 character so the paragraph mark is not included in the selection
   Selection.EndKey Unit:=wdLine, Extend:=wdExtend
   Selection.MoveLeft Unit:=wdCharacter, Count:=1, Extend:=wdExtend
        
   Temp = Path & Selection.Text     ' "save to" path + file name taken from the bookmark
   Temp1 = Selection.Text
   Temp2 = Temp & ".doc"
    
   ' If filename is in use, keep prompting until a free name is given
   While Dir(Temp2) <> ""
      message = "There is already a Caselog file called " & Temp1 & ". Please choose another name for this file."
      newname = InputBox(message, "Choose a New File Name")
      Temp = Path & newname
      Temp1 = newname
      Temp2 = Temp & ".doc"
   Do Loop

   ' Save the file
   ActiveWindow.View.Type = wdNormalView     ' Optional
   ActiveDocument.SaveAs FileName:=Temp
   ActiveDocument.Close                      ' Optional
End Sub

• Explanation •

Rather than a bookmark, the template needs the label "***zzz" just before the HD text variable that holds the filename (TextVar). For example:

***zzz«TextVar»¶

The macro will take all text between this label and the paragraph mark as the filename.

Also, do not include a '.doc' extension! The macro adds it automatically.

The macro needs you to specify what the document path will be at the Path = "" line. Without this, the macro will fail.

The macro will make sure that the requested filename does not exist already. If there does happen to already be a file with that name, the macro will prompt the user for a different name.

Contributor: Mike Bernstein


•  •  •  •  •  •  •


• Code •

Word:

Sub SaveDoc()

   Dim DocNameStr As String
   Dim DocPathStr As String
   Dim DocNameChoppedStr As String
   Dim DocDriveLtr
   Dim nextSerial

   ' Find the bookmark called DocumentName to get the document's save name
   Selection.GoTo What:=wdGoToBookmark, Name:="DocumentName"

   ' Select all of the text in the DocumentName line
   Selection.EndKey Unit:=wdLine, Extend:=wdExtend

   ' Dump the searched text into a string for use in saving the file
   DocNameStr = Selection.Text
   DocNameChoppedStr = Selection.Text

   ' Use the last name of the person to whom the document is created to
   ' pick the directory where it will be stored
   DocDriveLtr = Left(DocNameChoppedStr, 1)

   ' Set the string of the drive and path to where the document will be saved
   ' !! MODIFY THIS TO MATCH YOUR DRIVE CONFIGURATION !!
   DocPathStr = "//SERVERNAME/SomePath/" & DocDriveLtr & "/"

   ' Delete the bookmark from the document
   Selection.Delete

   ' Save the file using the directory that was specified above and the name
   ' that is designated by DocNameStr
   With Dialogs(wdDialogFileSaveAs)
      .Name = DocPathStr & DocNameStr & "_"
      .Show
   End With

   ' Begin section to set office link and throw the link to the document
   ' in there as well
   Selection.GoTo What:=wdGoToBookmark, Name:="DocuSerial"

   ' Get the saved documents name and path
   DocNameStr = ""
   DocPathStr = ""
   DocNameStr = ActiveDocument.Name
   DocPathStr = ActiveDocument.Path

   Dim SerialNum
   Dim DBLawbase
   Dim dsSerialNum
   Dim dsAddOfficeLink

   SerialNum = Trim(Selection)

   ' Create connection object to connect to the database
   Set DBLawbase = CreateObject("ADODB.Connection")
   DBLawbase.connectionstring = "DSN=Lawbase;uid=sa;pwd=sa;"
   DBLawbase.Open

   ' Get last serial number so we can add one to it
   Set dsSerialNum = CreateObject("adodb.Recordset")
   nextSerial = "select max(serial) + 1 as newserial from office_link"
   dsSerialNum.Open nextSerial, DBLawbase, 3, 3

   ' Insert all values into the officelink table for the serial in question
   Set dsAddOfficeLink = CreateObject("ADODB.RecordSet")
   SQL = "insert into office_link values (" & dsSerialNum.Fields("newserial") & ", " & SerialNum & ", 0, 0, '" & DocPathStr & "/" & DocNameStr & "', '" & DocNameStr & "', getdate(), 'AUTO', 'Word')"
   dsAddOfficeLink.Open SQL, DBLawbase, 3, 3

   ' Kill serial number off of document
   Selection.Delete

   ' Resave after cleaning
   ActiveDocument.Save

   ' Cleanup
   dsSerialNum.Close
   Set dsSerialNum = Nothing
   'dsAddOfficeLink.Close
   Set dsAddOfficeLink = Nothing
   DBLawbase.Close
   Set DBLawbase = Nothing

   End

End Sub

• Explanation •

Our frim uses Lawbase as a frontend w/ a SQL Server backend. Since there is very little custom coding for Lawbase, I wrote this to simplify the ever-enthralling task of choosing the correct directory to save the document in and linking the document to the matter in our database. We use a directory with subdirectories of the alphabet. For example, documents involving John Doe would go in:

//SERVER/SomePath/D/...

I think it is eaisier to use DOS names instead of long file names.

First thing anyone wanting to use this code needs to do is insert two bookmarks into their document. The first is called DocumentName, and the second DocuSerial. Here is the format I use (you will want to use your own naming conventions):

DocumentName - [Bookmark]«lb_link_header_client_lname», «lb_link_header_client_fname», «lb_template», «TODAY:3 June 1990»[Bookmark]
DocuSerial - [Bookmark]  «lb_header_serial»  [Bookmark]

NOTE: «lb_header_serial» in DocuSerial must be padded with spaces on either side if it is not long enough to be a Bookmark.

I just make the text white so that it will not be visible in the document and will not confuse anyone.

Contributor: Joel Musheno

 

• Contributors •

LegalCS   Mike Bernstein   Joel Musheno
The Lawfirm of Malek & Malek
1227 South High St.
Columbus, OH 43206