|
|
Create a Multipage DWF File Using VB/VBA
15 Jan, 2005 By: Mike Tuersley CadalystIncluding more than one page is a bit complicated -- or is it?
A question that has crossed my desk a lot lately is how to create a multipage DWF file through VB/VBA programming. A single page DWF is simple to produce using the DWF plotter drivers inside AutoCAD or the free DWF printer driver, but the multipage DWF is a bit more complicated -- or is it?
Example Project Scope
To demonstrate how to create the multipage DWF file, I will present a form to the user with a list of all the layouts in the current drawing (figure 1). The user can select which of the layouts to include in the final DWF file. I will need a Userform with a ListBox and a CommandButton. The final version of the code that can be downloaded will include more material, but this is enough to demonstrate the functionality. I will leave all the default names for the controls, but I will set the ListBox to use checkboxes and enable multiple selections:
![]() Figure 1. Multipage DWF dialog box. |
Option Explicit Private Sub UserForm_Initialize() '+--- Startup Dim oLO as AcadLayout For Each oLO In ThisDrawing.Layouts ListBox1.AddItem oLO.Name Next 'setup controls CommandButton1.Caption = "Print" ListBox1.ListStyle = fmListStyleOption ListBox1.MultiSelect = fmMultiSelectMulti Me.Caption = "xPage DWF Print Example" End Sub
Private Sub CommandButton1_Click() '+--- user is printing Dim cLO As New Collection Dim iIndex As Integer For iIndex = 0 To Listbox1.ListCount - 1 If ListBox1.Selected(iIndex) = True Then cLO.Add ListBox1.List(iIndex) End If Next 'hide form so code can run Me.Hide 'call to printing MultiDWFPrint cLO 'show form again Me.Show End Sub
Note: The next-to-last line is the action call to print, which will be created shortly.
DWF Background Information
The DWF file format is just a compressed archive file similar to a ZIP file. If you have a DWF file handy, make a copy and rename its extension to .zip. When you try opening it using your ZIP software, you should see a series of folders and files within the ZIP, which consist of XML data structures, PNG graphics and Meta data information.
A file of particular interest to us is the DSD (Drawing Set Description) file located in the ePlotGlobal folder. The simplest explanation of a DSD file that it's a table of contents that tells AutoCAD's DWF engine what is required for the multipage DWF file. AutoCAD uses this file to process the Layout tabs needed. Here is an example of a DSD file:
[DWF6Version] Ver = 1 [DWF6Sheet:1st Layout Name] DWG=C: \Wilhome.dwg Layout = 1st Layout Name <?sheets between 1st and nth?> [DWF6Sheet:Nth Layout Name] DWG=C:\ Wilhome.dwg Layout = Nth layout Name [Target] Type=1 DWF=C:\Wilhome.dwf PWD=
Notice the DSD file is nothing more than a Windows INI file -- it is separated into sections and values. The first two lines are set in stone -- they give the version of the DWF file. The very last line is optional to allow password protection if desired. All the lines in between are descriptions of the layouts that comprise the multipage DWF file. Each layout requires a section stating the name of the layout. The following two values are the drawing file and its layout to process as part of the DWF file.
Also be aware that there may be more value keys within your DSD file. The structure presented above represents the minimum structure required in a DSD file. This is important because our next step is to create our own DSD file.
DSD File Creation
The DSD file is required to generate a multipage DWF file. Whether the DSD file is an existing one or a new one created as part of this project has to be determined by you. This wouldn't be a complete article if I didn't create my own on-the-fly, though!
I'll use very basic code for the file creation and add a loop that will write each layout name the user selected in the ListBox of our form. This is the code I will use:
Private Function CreateDSDFile(cLOs As Collection, _
sDWFFile As String) As Boolean
Dim iCntr As Integer 'generic counter
Dim sTemp As String 'generic temporary string
Dim LogNum As Integer 'reference to file object
On Error GoTo Exit_Early
'check to see if DSD file exists and delete it if it does
If FileLen(sDWFFile) > 0 Then Kill sDWFFile
'create the new dsd file
LogNum = FreeFile
'write to the file
Open sDWFFile For Append Access Write Lock Write As #LogNum
Print #LogNum, "[DWF6Version]"
Print #LogNum, "Ver = 1"
'iterate thru the layouts collection
For iCntr = 1 To cLOs.Count
'grab the next layout name in the collection
sTemp = cLOs.Item(iCntr)
Print #LogNum, "[DWF6Sheet:" & sTemp & "]"
Print #LogNum, "DWG=" & m_dwgName
Print #LogNum, "Layout = " & sTemp
Next
Print #LogNum, "[Target]"
Print #LogNum, "Type=1"
Print #LogNum, "DWF=" & sDWFFile
Print #LogNum, "PWD="
Close #LogNum
'send back success
CreateDSDFile = True
Exit Function
Exit_Early:
Err.Clear
'send back failure
CreateDSDFile = False
End Function
Here I have chosen to use a function that expects a collection and a string to be passed to it. The collection will contain the list of layout names the user selected in the dialog box, and the string will be the name of the DSD file. For this example, the DSD file will be located in the same directory as the current drawing and have the same name as the drawing with the DSD extension. The function itself passes back a Boolean value that will indicate whether it was successful in creating the DSD file.
DWF Printing
So far, so good! This isn't really that difficult, is it? Well, now comes the tricky part.
Unfortunately, the only way to generate the DWF file from AutoCAD is to use the Publish command, which presents a series of problems because Publish is not exposed through the AutoCAD API. The first problem is that Publish uses a dialog box that we cannot allow. If the Publish command does fire its dialog box, my program will stop because I have no way of interfacing with it. To get past this, I will use the command line version of Publish: _PUBLISH. To do this, I must suppress the display of file dialog boxes by turning off the system variable FILEDIA:
ThisDrawing.SetVariable "FILEDIA", 0
The next problem is actually calling the _PUBLISH command. To do this, I have to use the SendCommand method. The SendCommand method should always be reserved as the very last option because it introduces a whole can of worms to your programming efforts. Because the SendCommand is basically a method of forcing typed commands into AutoCAD's Command line, it is very easy for my program to lose focus because it has no way to determine when the SendCommand code has finished processing. VB/VBA code just passes the string to the SendCommand and continues on its merry way, which usually results in an error because it is running faster than the command it passed. So, if you have to use the SendCommand, always make it the very last command in the program.
The next problem I could have is due to the name of the file I am going to generate. If the DWF file has spaces in its name, SendCommand will see those spaces as Enters and basically split the file name apart, which will bomb my program. To eclipse this hurdle, I must pass the name of the DWF file surrounded by quotation marks without the VB/VBA command interpreter mistaking the extra quotation marks as VB string indicators. I will opt to pass a LISP command to SendCommand so I can concatenate character codes [CHR(#)] to my real string variables and fake out the interpreter.
Sub MultiDWFPrint (cLayOuts As Collection)
Dim dwgName As String
Dim dwfName As String
Dim dsdName As String
Dim sTxt As String
'grab the drawing variables we need
dwgName = ThisDrawing.FullName
'check to make sure we have layouts
If cLayOuts.Count > 0 Then
'build the DSD file name
dsdFile = Replace(dwgName, ".dwg", ".dsd")
'build the DWF file name
dwfFile = Replace(dwgName, ".dwg", ".dwf")
'create the DSD file
If CreateDSDFile(cLayOuts, dsdFile) = True Then
'publish our multipage DWF file
With ThisDrawing
sTxt = Replace(dsdFile, "\", "/")
'turn FILEDIA *OFF* to avoid dialog boxes
.SetVariable "FILEDIA", 0
.Regen acActiveViewport
'Publish layouts
.SendCommand "(command " & Chr(34) & _
"-PUBLISH" & Chr(34) & _
" " & Chr(34) & sTxt & _
Chr(34) & ")" & vbCr
End With
Else
MsgBox "Error creating DSD file: " & dsdFile
GoTo Leave_Now
End If
Else
MsgBox "There are no valid layouts within dwg file"
End If
Leave_Now:
'clean up before leaving
If Not cLayOuts Is Nothing Then Set cLayOuts = Nothing
'
End Sub
Note the line Replace(dsdFile, "\", "/") is required because LISP will interpret the forward slash as a noncharacter so it must be replaced with a backslash. This is a LISP requirement.
Wrapping Up
I have one final issue to resolve. If the program is successful, my AutoCAD session now has its file dialog support disabled! Remember how I said that if you use SendCommand, it must be the very last command? In the example so far, it is the next-to-last command, and you can see how the SendCommand is still running behind the VBA code because the Userform reappears before the _PUBLISH command has finished running.
I could forget that I thought of this problem and just wait for my end users to complain, or I could add code to the form close event that sets FILEDIA back to 1:
Private Sub UserForm_Terminate() ThisDrawing.SetVariable "FILEDIA", 1 End Sub
Kick It Up a Notch!
Okay, my Wrapping Up section is a little less substantial than usual because what if I am writing an application that does not contain a form? How will I turn FILEDIA back on if that is the case? Well, we have plenty of unique ways to handle that scenario, and I will leave you to explore them. For example, one workaround might be to add a loop that reads a USER variable:
Dim sTest As String
Do Until sTest = "DONE"
sTest = ThisDrawing.GetVariable("USERS2")
Loop
In this scenario, the USERS2 variable value could be set through code added to an event such as EndCommand or EndPlot. See what you can come up with to resolve this issue. If you think you have an ingenious solution, e-mail it to me. I just might publish it. Take care until next month!
|
|
AutoCAD Tips!
Autodesk Technical Evangelist Lynn Allen guides you through a different AutoCAD feature in every edition of her popular "Circles and Lines" tutorial series. For even more AutoCAD how-to, check out Lynn's quick tips in the Cadalyst Video Gallery. Subscribe to Cadalyst's Tips & Tricks Tuesdays free e-newsletter and we'll notify you every time a new video tip is available. All exclusively from Cadalyst! |
![]() | Feed
The Infinite Resource: the case for GMO instead of organic farming 22 May, 2013 |
![]() | Feed
TERA Semicon Drives Its Own Destiny with CAD and PDM 22 May, 2013 |
![]() | Feed
Excel Hyperlinks & Document Management Tricks 22 May, 2013 |
![]() | Feed
SolidWorks Simulation Tips: Parameters and Design Studies 22 May, 2013 |
![]() | Feed
Is This the All-in-One Bike Helmet of the Future? 22 May, 2013 |
|









