Chapter 12
Communicating with Other Applications

Everything up until this point has been focused on learning VBA, automating tasks in the AutoCAD® drawing environment, and manipulating the AutoCAD program itself. The VBA programming language also supports features that can be used to get information from outside of the AutoCAD program.

Using VBA, you can read and write text files that are stored on disc and leverage other libraries registered on your workstation with the ActiveX technology. Microsoft Windows comes preinstalled with a number of libraries that can be used to parse the information stored in an XML file or manipulate the files and directories on the discs that are accessible from your workstation. If you have Microsoft Office installed, you can also access Microsoft Word, Excel, and Access to read and write information to DOC, DOCX, XLS, XLSX, ACCDB, or MDB files.

Referencing a Programming Library

When a new VBA project is created, the Microsoft VBA and AutoCAD Object libraries are referenced by default. You can reference other libraries that are installed and registered on your workstation using the References dialog box. Here are examples of other programming libraries:

  1. AutoCAD/ObjectDBX™ Common Type Library (axdb<version>enu.tlb) This library allows you to access the objects of a drawing without loading the drawing into the AutoCAD drawing environment first.
  2. AcSmComponents 1.0 Type Library (acsmcomponents<version>.tlb) Using this library, you can automate tasks related to the Sheet Set Manager in the AutoCAD drawing environment.
  3. Microsoft Excel Object Library (excel.exe) If you need to access the Excel application, use this library.
  4. Microsoft Word Object Library (msword<version>.olb) Using the Microsoft Word Object Library, you can access the Word application.

The following explains how to add a reference to a third-party library in a VBA project:

  1. In the VBA Editor, from the Project Explorer select a loaded project to set it as current.
  2. On the menu bar, click Tools arrow References.
  3. When the References dialog box opens, scroll to the library you want to reference.
  4. Click the check box next to the programming library to reference.

    If the programming library you want to load is not referenced, click Browse and select the library to load. Click Open.

  5. Click OK.

Creating and Getting an Instance of an Object

Most of the objects that you have learned to work with were created using an object method defined in the AutoCAD Object library or using the New keyword. I explained how to use the New keyword to create a new instance of an object in the “Working with Objects” section of Chapter 2, “Understanding Visual Basic for Applications.”

When using a library registered on your workstation, you can let VBA know that you want to use the library by referencing it first or simply creating an instance of an object that can be instantiated. Referencing a library as part of your VBA project is known as early binding. Early binding allows you to browse the objects and members of a library using the Object Browser in the VBA Editor as well as the IntelliSense (type-ahead) feature of the code editor windows. I mentioned how to reference a library in the “Referencing a Programming Library” section earlier.

The alternative to early binding is known as late binding. Late binding is when you use a programming library without first adding a reference to the library in your project. Early binding is the more popular approach when working with a programming library, but it does have a limitation.

Early binding forces your program to use a specific release of a programming library, whereas late binding allows you to work with any version of a programming library registered on your workstation. An example of when you might want to use late binding instead of early binding is when you want to create a program that can target and take advantage of the features in different releases of Word.

Creating a New Instance of an Object

The New keyword can only be used when you use early binding. To create a new instance of an object with early or later binding, you can use the CreateObject function. The CreateObject function expects a class ID for the object you want to create. Class ID values are defined in the Windows Registry, but the vendor of the library should have these documented as part of the library's documentation.

The following shows the syntax of the CreateObject function:

retObj = CreateObject(classID [, servername])

Its arguments are as follows:

  1. retObj The retObj argument represents the object that is returned.
  2. classID

    The classID argument is a string that represents the object to be created. The string is in the form of appname.objecttype[.version]. When the library has already been referenced in a project, the value of appname must match the name of the library you are calling exactly as it appears in the Libraries drop-down list in the Object Browser of the VBA Editor (see Figure 12.1). The value of objecttype specifies the type of object to be created, whereas version is an optional version number that could include a major and/or minor version number. Not all object types support a version number.

    An example of a major version number might be 19, and an example of a major and minor number might be 19.1. The AcadApplication object in the AutoCAD Object library supports both major and minor versions and is based on the release of AutoCAD. Table 12.1 lists some common class IDs for the Application object in the AutoCAD Object library.

    Be sure to refer to each library's documentation for object versioning information.

  3. servername The servername argument is an optional string that represents the name of the server on the network where the object should be created. If no value or a value of "" is provided, the object is created locally in memory on your workstation.
image

Figure 12.1 Check the Libraries drop-down list in the Object Browser and use the appname listed there.

Table 12.1 Common class IDs for the AutoCAD Object library Application object

Class ID Specifies
AutoCAD.Application Any version of AutoCAD
AutoCAD.Application.19 AutoCAD 2013 release
AutoCAD.Application.19.1 AutoCAD 2014 release
AutoCAD.Application.20 AutoCAD 2015 release

If the object specified by the classID argument can't be created, an error is generated. You will need to handle those errors. I show an example of how to handle the errors generated by the CreateObject function later in this chapter, and you can learn more about error handling in Chapter 13, “Handling Errors and Deploying VBA Projects.”

Two objects must be created using the CreateObject function before they can be used: the File System object (FileSystemObject) from the Scripting Object library and the Application object in the Word Object library. The FileSystemObject object provides access to the files and folders on a local or network drive and allows you to automate the file management tasks related to your projects. For example, you could use the Application object of the Word Object library to generate sections of a bid specification or a cost estimation document from the information in a drawing. I discuss more about the File System and Word application objects in the “Working with Microsoft Windows” and “Working with Microsoft Office Applications” sections later in this chapter.

Here are examples of creating new instances of a filesystem or the Word application object:

' Create a new instance of the FileSystemObject without
' referencing the Microsoft Scripting Runtime (scrrun.dll)
Dim ofsObj as Object
Set ofsObj = CreateObject("Scripting.FileSystemObject")
' Create a new instance of the Word application without
' referencing the Microsoft Word 15.0 Object Library (msword15.olb)
Dim oWordApp as Object
Set oWordApp = CreateObject("Word.Application")

If you have both Word 2003 and Word 2013 installed on the same machine (a fair number of tech writers and editors have those two versions available for compatibility with client files or because they have an extensive macro set that was developed with 2003 and didn't translate smoothly to 2010 and later versions), you can specify which version of the application to work with by adding the version number to the class ID. Here are examples of creating a new instance of an Application object from the Word 2003 Object library and Word 2013 Object library with the CreateObject function:

' Create a new instance of the Word 2003 application
Dim oWordApp2003 as Object
Set oWordApp2003 = CreateObject("Word.Application.11")
' Create a new instance of the Word 2013 application
Dim oWordApp2013 as Object
Set oWordApp2013 = CreateObject("Word.Application.15")

When you create a new object, whether with the New keyword or the CreateObject function, you should consider whether the object should be removed from memory when you are done with it or left resident. Remove the object from memory if you don't plan to use it again or want the user to interact with the object; such is the case if you create an instance of the Word application. Some objects support a method such as Close or Quit that removes the object from memory, whereas some require you to set the object to Nothing.

For example, the following example creates a new instance of the File System object and gets the filesystem type of the C: drive.

Dim ofsObj As Object
Set ofsObj = CreateObject("Scripting.FileSystemObject")
' Display the file system type of the C: drive
Dim oDrv As Object
Set oDrv = ofsObj.Drives("C")
MsgBox oDrv.FileSystem
' Release the object
Set ofsObj = Nothing

I discuss more about the File System object in the “Accessing the Filesystem” section later in this chapter.

Getting an In-Memory Instance of an Object

In some cases, you don't need to create a new instance of an object but can work with an instance of an object that is already running in memory. The GetObject function returns an instance of an object that is running in memory or can create an object that is representative of a file. For example, you can get an instance of the Word Application object running in memory or create a Word Document object based on a DOC or DOCX file that is stored on disc.

The following shows the syntax of the GetObject function:

retObj = GetObject([pathName] [, classID])

Its arguments are as follows:

  1. retObj The retObj argument represents the object that is returned.
  2. pathName The pathName argument is an optional string that represents the filename containing the type of object to create and return. The filename could be an executable or a file created by an application, but the filename must correspond to a valid class ID in a registered programming library.
  3. classID The classID argument is an optional string that represents the type of object in memory to be returned. For information on the structure of the class ID value, review the syntax of the CreateObject function in the “Creating a New Instance of an Object” section earlier in this chapter.

Here are two examples of the GetObject function:

' Gets an instance of the Word application running in memory
Dim oWordApp as Word.Application
Set oWordApp = GetObject("Word.Application")
' Creates an instance of a Document object of the
' Word Object library based on a file
Dim oWordApp as Word.Document
Set oWordApp = GetObject("c:UsersLeeDocumentsMyCustomFilesch12_circles.doc")

Listing 12.1 shows a custom function named GetCreateObject that tries to get an instance of an object in memory before attempting to create a new instance of the object. This function can be helpful when creating a new instance of the AutoCAD or Word application. The code in Listing 12.1 can be found in the ch12_code_listings.dvb file that is available for download from www.sybex.com/go/autocadcustomization.

If Microsoft Word isn't installed on the workstation, a message box with the text MS Word couldn't be started. is displayed when the previous example is executed.

Accessing a Drawing File from outside of AutoCAD

There are times when you want to get information from a drawing file that isn't opened in the current instance of AutoCAD. Although you could use the Open method of the AcadDocument or AcadDocuments objects, it takes time to open the drawing because you have to wait for the AutoCAD program to create a new document window and regenerate the drawing as it is being opened in the AutoCAD user interface.

Using the AutoCAD/ObjectDBX Common Type Library that comes with the AutoCAD program, you can access and modify graphical and nongraphical objects stored in a DWG file. Although there are limitations—such as not being able to allow the user to select objects to work with or use AutoCAD commands—it is much faster if you need to work with several to several hundreds of drawings quickly.

To use the AutoCAD/ObjectDBX Common Type Library in a VBA project, follow these steps:

  1. Create a new or open an existing VBA project.
  2. In the VBA Editor, click Tools arrow References.
  3. When the References dialog box opens, scroll to and check AutoCAD/ObjectDBX Common <version> Type Library.

    You typically want to always work with the latest version on your workstation, but if you need to work with a specific version make sure you choose that one. Version 18 represents AutoCAD 2010 through 2012, 19 represents AutoCAD 2013 and 2014, and 20 represents AutoCAD 2015. If you have more than one instance of the library registered, be sure to reference the one in <drive>:Program FilesCommon FilesAutodesk Shared.

  4. Click OK.

The following example shows how to open a DWG file in memory and list the number of layers and objects in model space that are present in the drawing. Figure 12.2 shows the resulting message box when the example code is executed.

Sub ReadDrawingEx()
  Dim sFlrPath As String, sDWGName As String
  sFlrPath = ThisDrawing.GetVariable("MyDocumentsPrefix") & _
             "MyCustomFiles"
  sDWGName = "Ch12_Building_Plan.dwg"
  Dim oDWGFile As New AxDbDocument
  oDWGFile.Open sFlrPath & sDWGName
  MsgBox sDWGName & " contains:" & vbLf & _
         "Layers - " & CStr(oDWGFile.Layers.Count) & vbLf & _
         "Objects - " & CStr(oDWGFile.ModelSpace.Count)
  ' Close the drawing file
  Set oDWGFile = Nothing
End Sub
image

Figure 12.2 Information from an externally opened drawing file.

If you make changes to the DWG file, be sure to save the changes with the SaveAs method. Because there is no Close method, you simply set the variable that contains the Document object that represents the DWG file to Nothing, as shown in the previous example.

Working with Microsoft Windows

Microsoft provides a number of programming libraries that allow you to access and use some of the features defined in the Windows operating system with your own programs. These programming libraries can save you time and help to implement user experiences in your custom programs that are found in many other Windows-based programs. Although it isn't possible to introduce all of the Windows programming libraries that are available in this book, I will show you examples from a few of my favorite libraries.

Here are some Windows programming libraries that I suggest you take a look at:

  • Microsoft Scripting Runtime
  • Windows Script Host Object Model
  • Microsoft Shell Controls and Automation
  • Windows 32-bit API

For additional information on these libraries, use your favorite Internet search engine and do a search of the library names with VB6 as one of the keywords.

Accessing the Filesystem

The Microsoft Scripting Runtime library is your gateway to the Windows filesystem. The library allows you to access information about the files, folders, and drives on your workstation. To use the Microsoft Scripting Runtime library, reference the library as part of your VBA project or use late binding with the class ID Scripting.FileSystemObject.

You can use the Microsoft Scripting Runtime library to perform the following tasks:

  • List the names and types of drives attached to a workstation
  • Create and manage the folders on a drive
  • Check to see if a file exists
  • Get information about a file or folder, including the extension of a file, parent folder of a folder, or name of a special folder

Here is how to create an instance of a File System object (FileSystemObject):

Dim ofsObj As New FileSystemObject

or

Dim ofsObj As Object
Set ofsObj = CreateObject("Scripting.FileSystemObject")

Getting the Drives Attached to a Workstation

When you first begin to work with the filesystem, it is a common tendency to want to work with a file. After all, a file is typically what you are creating with AutoCAD or any other application. Files are the lowest item in the filesystem hierarchy; drives are the very top.

The FileSystemObject object allows you to access all the drives attached to a workstation using the Drives collection object. Information about a drive can be obtained using the properties and methods of a Drive object.

The following example steps through the Drives collection object and displays a message box containing a drive's letter designation and the filesystem used to format it:

Sub ListDrives()
  Dim ofsObj As Object
  Set ofsObj = CreateObject("Scripting.FileSystemObject")
  ' Display the drive letter and file system
  Dim oDrv As Object
  For Each oDrv In ofsObj.Drives
    ' Check to see if the drive is ready
    If oDrv.IsReady Then
      MsgBox "Letter: " & oDrv.DriveLetter & vbLf & _
             "File System: " & oDrv.FileSystem
    Else
      MsgBox "Letter: " & oDrv.DriveLetter & vbLf & _
             "File System: *Drive not ready*"
    End If
  Next oDrv
  ' Release the object
  Set ofsObj = Nothing
End Sub

Table 12.2 lists the methods of the FileSystemObject object that can be helpful when working with the drives attached to a workstation.

Table 12.2 Drive-related methods of the FileSystemObject object

Method Description
DriveExists Returns True if the drive specified exists
GetDrive Returns a Drive object based on a drive letter or UNC path
GetDriveName Returns the drive name in a file path

Working with Folders and Special Folders

Folders are used to organize the files on a drive. You can use folders to organize your custom programs or all the drawing files related to a client project. The Folder object is used to get information about a folder on a drive, whereas the Folders collection object is used to access all the subfolders contained in a folder or drive. The FileSystemObject object can also be used to get the folders Microsoft has designated as special folders. There are three special folders: Windows, System, and Temp. Special folders are obtained using the GetSpecialFolder function and an integer value of 0 to 2. Pass the GetSpecialFolder function a value of 0 to get the Windows folder. Use a value of 1 to get the System folder or 2 to get the Temp folder.

The following example lists the subfolders in the AutoCAD installation folder and the location of the Windows folder:

Sub ListFolders()
  Dim ofsObj As New FileSystemObject
  ' Get the AutoCAD install folder
  Dim oAcadFldr As Folder
  Set oAcadFldr = ofsObj.GetFolder(ofsObj. _
                  GetFile(ThisDrawing.Application.FullName).ParentFolder.Path)
  ' Get the subfolders of the AutoCAD install folder
  Dim oFldr As Folder
  Dim sFldrs As String
  For Each oFldr In oAcadFldr.SubFolders
    sFldrs = sFldrs & vbLf & "  " & oFldr.Name
  Next oFldr
  ' Output the names of the AutoCAD install subfolders
  ThisDrawing.Utility.Prompt vbLf & oAcadFldr & sFldrs
  ' Get the Windows folder
  Dim oWinFldr As Folder
  Set oWinFldr = ofsObj.GetSpecialFolder(0)
  ' Get information about the Windows folder
  ThisDrawing.Utility.Prompt vbLf & "Windows install folder: " & _
                             vbLf & "  " & oWinFldr.Path
  ' Release the object
  Set ofsObj = Nothing
End Sub

The following shows an example of the output from the previous example:

C:Program FilesAutodeskAutoCAD 2015
  AcWebBrowser
  AdExchange
  AdlmRes
  CER
  Content Explorer
  Drv
Windows install folder:
  C:Windows

Table 12.3 lists some of the other methods of the FileSystemObject object that can be helpful when working with the folders on a drive.

Table 12.3 Folder-related methods of the FileSystemObject object

Method Description
CopyFolder Copies the folder and its files from a source to a destination location
CreateFolder Creates a new folder and returns a Folder object
DeleteFolder Removes a folder
FolderExists Returns True if the folder specified exists
GetAbsolutePathName Returns a string that represents the absolute path of a file
GetBaseName Returns a string that represents the base path of a file
GetParentFolderName Returns a string that represents the parent path of a file
MoveFolder Moves a folder and its files from a source to a destination location

Getting Information about a File

Files are the lowest item in the file hierarchy, but they are also the most important because they hold the information created by an application or the Windows operating system. The File object is used to get information about a file stored in a folder, whereas the Files collection object is used to access all the files in a folder.

The following example lists the files in the Fonts folder in the AutoCAD installation folder:

Sub ListFiles()
  Dim ofsObj As Object
  Set ofsObj = CreateObject("Scripting.FileSystemObject")
  Dim sAcadFontsFldr As String
  sAcadFontsFldr = ofsObj.GetParentFolderName( _
                          ThisDrawing.Application.FullName)
  ' Get the AutoCAD Fonts folder
  Dim oAcadFontsFldr As Object
  Set oAcadFontsFldr = ofsObj.GetFolder(sAcadFontsFldr & "Fonts")
  ' Get the Files of the Fonts folder
  Dim oFile As Object
  Dim sFiles As String
  For Each oFile In oAcadFontsFldr.Files
    sFiles = sFiles & vbLf & "  " & oFile.Name
  Next oFile
  ' Output the names of the files
  ThisDrawing.Utility.Prompt vbLf & oAcadFontsFldr.Path & sFiles
  ' Release the object
  Set ofsObj = Nothing
End Sub

The following shows an example of the output from the previous example:

C:Program FilesAutodeskAutoCAD 2015Fonts
  @extfont2.shx
  AcadEref.shx
  aehalf.shx
  AMDTSymbols.shx
  amgdt.shx
  amgdtans.shx
  bigfont.shx

Table 12.4 lists some of the other methods of the FileSystemObject object that can be helpful when working with the files on a drive or in a folder.

Table 12.4 File-related methods of the FileSystemObject object

Method Description
CopyFile Copies a file from a source to a destination location
DeleteFile Removes a file
FileExists Returns True if the file specified exists
GetExtension Returns a string that represents the extension of the file based on the specified path
GetFile Returns the File object based on the specified path
GetFileName Returns a string that represents the name of the file based on the specified path
GetFileVersion Returns a string that represents the version of the file based on the specified path
MoveFile Moves a file from a source to a destination location

Manipulating the Windows Shell

The Windows Script Host Object Model library can be helpful in manipulating some of the features found in the Windows shell. To use this library, reference it as part of your VBA project or use a late bind to the class ID WScript.Shell.

You can use the Windows Script Host Object Model library to perform the following tasks:

  • Create a desktop shortcut
  • Get and set environment variables

Here is how to create an instance of the Windows Scripting Shell object:

Dim ofsObj As New WshShell

or

Dim ofsObj As Object
Set ofsObj = CreateObject("WScript.Shell")

The following shows an example of creating a desktop shortcut:

Sub CreateDesktopShortcut()
  Dim oWshObj As New WshShell
  ' Get the Desktop and Documents folder locations
  Dim sDskFldr As String, sDocsFldr As String
  sDskFldr = oWshObj.SpecialFolders("Desktop")
  sDocsFldr = oWshObj.SpecialFolders("MyDocuments")
  ' Create the shortcut file
  Dim oShrtObj As WshShortcut
  Set oShrtObj = oWshObj.CreateShortcut(sDskFldr & "My AutoCAD.lnk")
  ' Set the target and properties of the shortcut
  oShrtObj.TargetPath = ThisDrawing.Application.FullName
  oShrtObj.Arguments = "/w ""3D Modeling"""
  oShrtObj.Description = "Custom AutoCAD Desktop Shortcut"
  oShrtObj.WindowStyle = WshNormalFocus
  oShrtObj.Hotkey = "Ctrl+Alt+A"
  oShrtObj.WorkingDirectory = sDocsFldr
  oShrtObj.IconLocation = ThisDrawing.Application.FullName & ",0"
  ' Save the shortcut
  oShrtObj.Save
  ' Release the object
  Set oShrtObj = Nothing
End Sub

The following custom procedures demonstrate how to get and set the values of environment variables in the Windows operating system:

' Shows how to use expanding environment strings
' Usage: ExpEnvStr "%TEMP%\MYDATA"
' Results of sample: "C:\DOCUME˜1\Lee\LOCALS˜1\Temp\MYDATA"
Public Function ExpEnvStr(strToExpand As String) As String
  Dim oWshObj As New WshShell
  ' Expand the string and any variables in the string
  ExpEnvStr = oWshObj.ExpandEnvironmentStrings(strToExpand)
  ' Release the object
  Set oWshObj = Nothing
End Function
' Retrieve the value of the environment variable
' Usage: GetEnvStr "SYSTEM", "PROCESSOR_ARCHITECTURE"
' Results of sample: "AMD64"
' Alt Usage: GetEnvStr "SYSTEM", "USERID"
' Results of sample: "L123"
Public Function GetEnvStr(VarType As String, VarName As String) As String
  Dim oWshObj As New WshShell
  ' Get a reference to the Environment
  Dim envVars As WshEnvironment
  Set envVars = oWshObj.Environment(VarType)
  ' Get the value of the variable
  GetEnvStr = envVars(VarName)
  ' Release the object
  Set oWshObj = Nothing
End Function
' Set the value to an environment variable
' Usage: SetEnvStr "SYSTEM", "USERID", "L123"
Public Function SetEnvStr(VarType As String, VarName As String, _
                          VarValue As String) As String
  Dim oWshObj As New WshShell
  ' Get a reference to the Environment
  Dim envVars As WshEnvironment
  Set envVars = oWshObj.Environment(VarType)
  ' Set the variable to the provided value
  oWshObj.Environment(VarType) = VarValue
  ' Release the object
  Set oWshObj = Nothing
End Function

Using the Win32 API

Buried deep in the Windows operating system lies a powerful programming library known as the Win32 API (or the Windows API in recent years). This programming library was introduced with Windows 95 but was still present in the latest release of Windows (Windows 8.1) available when this book was written. Although the Win32 API was originally introduced with Windows 95 (the first 32-bit release of Windows), the Win32 library contains functions that were introduced with Windows 3.1 (a 16-bit release) and later 64-bit releases of Windows.

Much of the information around using the Win32 API has gone dormant over the years since the introduction of VB.NET and its rebranding as the Windows API, but there are resources on the Internet that you will find useful. You can use the following resources to learn how to implement the Win32 API in your VBA programs:

  1. Using the Win32 API This tutorial (available at www.vb6.us/tutorials/using-win32-api) provides an overview for using the Win32 API.
  2. Visual Basic Win32 API Declarations This download (available from www.microsoft.com/en-gb/download/details.aspx?id=12427) installs a TXT file that contains the declarations of the functions and data types in the Win32 API.

If you prefer a book to electronic references, I suggest tracking down a copy of the Visual Basic Programmer's Guide to the Win32 API written by Dan Appleman (Sams, 1999). Other Win32 books also were written in the late 1990s, so you should be able to find something.

Although the Win32 API can take a while to learn and understand, it does offer many great functions that can be used to implement familiar interfaces and access features in the depths of the Windows operating system from your VBA programs. You will use the GetOpenFileName and GetSaveFileName functions from the Win32 API later in the “Exercise: Reading and Writing Data” section to prompt the user to select a file or specify a filename using a dialog box. The Ch26_ExSamples.dvb sample file that comes with this book also shows an example of the GetSaveFileName function, which allows the user to specify a location and filename in which to save a file using a standard file navigation dialog box.

Reading and Writing Text Files

VBA supports the ability to read and write ASCII or Unicode text files. You can read a text file and use the contents of the file to create general notes and disclaimers for known building conditions, or even populate project information in a title block. In addition to reading the contents of a file, you can write data to a text file, which is useful for exporting a bill of materials (BOM) containing the quantity and parts in a drawing or listing the properties of nongraphical objects or system variables to help identify CAD standard violations in a drawing.

Text files can be used to define a number of file types, such as CSV, text (TXT), HTM/HTML, or even XML. The File System (FileSystemObject) object, which I introduced in the “Accessing the Filesystem” section earlier in this chapter, can also be used to read and write a text file.

Opening and Creating a File

Content can be read or written to an existing text file stored on a local or network drive, or a text file can be created to store new content. The OpenTextFile function of the FileSystemObject object is used to open an existing file, whereas the CreateTextFile function can be used to create a new file. Whether you use the OpenTextFile or CreateTextFile function, both functions return a TextStream object. The TextStream object is then used to read and write the contents of a text file in memory.

The following shows the syntax of the OpenTextFile function:

retObj = OpenTextFile(filename [, mode] [, create] [, format])

Its arguments are as follows:

  1. retObj The retObj argument represents the TextStream object that is returned.
  2. filename The filename argument is a string that represents the file you want to open or create when the create argument is set to True and the file wasn't found.
  3. mode The mode argument is an optional integer value that represents how the file should be opened. By default, the file is open for read only. Table 12.5 provides a basic description of the supported integer values and the corresponding constants that can be used in their place.
  4. create The create argument is an optional Boolean that determines whether the file specified by the filename argument should be created if it wasn't found. A value of True creates the file if it wasn't found.
  5. format The format argument is an optional integer value that determines the format of the file: ASCII or Unicode. By default, the file is opened as an ASCII file. Table 12.6 provides a basic description of the supported integer values and the corresponding constants that can be used in their place.

Table 12.5 File modes available for the OpenTextFile statement

Mode Description
1 or ForReading Content of the file can only be read.
2 or ForWriting Content of the file can be read or written.
8 or ForAppending New content added to the file is appended to the end of the file. Content cannot be read.

Table 12.6 File formats available for the OpenTextFile statement

Mode Description
-2 or TriStateUseDefault File format is set to the system default; ASCII or Unicode.
-1 or TriStateTrue File format is indicated as Unicode.
0 or TriStateFalse File format is indicated as ASCII.

The following shows the syntax of the CreateTextFile function:

retObj = CreateTextFile(filename [, overwrite] [, unicode])

Its arguments are as follows:

  1. retObj The retObj argument represents the TextStream object that is returned.
  2. filename The filename argument is a string that specifies the name of the file you want to create.
  3. overwrite The overwrite argument is an optional Boolean that determines whether the file specified by the filename argument should be overwritten if it already exists. A value of True results in the existing file being overwritten by the newly created file.
  4. unicode The unicode argument is an optional Boolean that determines whether the file specified by the filename argument should be created with the ASCII or Unicode format. A value of True results in the file being created with the Unicode format.

Here are a few examples of opening and creating a text file:

' Create an instance of the File System object
Dim ofsObj As New FileSystemObject
' Open the text file Data.txt for read
Dim oTxtStreamData As TextStream
Set oTxtStreamData = ofsObj.OpenTextFile("c:DatasetData.txt")
' Create the text file BOM.txt, and overwrite if found
Dim oTxtStreamBOM As TextStream
Set oTxtStreamBOM = ofsObj.CreateTextFile("c:DatasetBOM.txt", True)

As the filename argument can specify any text file on a local or network drive, the name of the file and path you choose can affect the sustainability of your custom program. When you specify the filename argument for the open function, consider the following:

  1. Static Filenames When you need to read the contents from a file, using a static filename might be ideal, but static filenames don't work well when you want to write data to a file. When creating a file, allow the user to specify a filename either using the AutoCAD Command prompt or a file-navigation dialog box, or as part of a user form.
  2. Hard-Coded Paths I recommend against placing specific file paths in a custom program. Rather than hard-coding (typing the actual path to a particular file) a path or drive as part of a filename, use paths stored in system or environment variables related to the operating system or returned by the File object. For example, you can get the paths to My Documents (or Documents) or the temporary files folder with the AutoCAD system variables mydocumentsprefix and tempprefix.

If you just want to create a temporary file, you can use the GetTempName function of the File System object to generate a unique filename. Then, use the CreateTextFile function to create the TextStream object for that file. If you want to keep the temporary file, you can use the MoveFile function of the File object to keep the file and give it a more meaningful name.

Reading Content from a File

Once a TextStream object has been obtained, you can use its various read methods to step through the content. You can choose to read a specific number of characters at a time, read one line, or read all content into a string. The Read function allows you to specify a number of characters to read from the text stream into a string. Each successive call to the function gets the next characters in the text stream.

Reading a specific number of characters at a time until you reach the end of the text stream can be helpful in some situations, such as when you are reading a space-delimited file, but in most cases you want to read an entire line in the text stream. A line is defined as a text string that ends with a new linefeed character, which has an ASCII code value of 10. Use the ReadLine function to read a line of text from a text stream. Similar to the Read function, each successive call to the ReadLine function gets the next line in the text stream.

When using the Read or ReadLine function, an Input Past End of File error will be generated when there are no additional characters or lines to be read from the text stream. You should check the AtEndOfStream property of the TextStream object to see if the end of the file has been reached before you continue to read the content of the text stream. If you want to read all the content from a text stream, use the ReadAll function to get a string containing all the content.

The Read function expects a single integer value that represents the number of characters to be read from the text stream, whereas the ReadLine and ReadAll functions don't accept any values. The Read, ReadLine, and ReadAll functions all return a string value.

Here are examples of reading content from a text stream with the Read, ReadLine, and ReadAll functions:

' Create an instance of the File System object
Dim ofsObj As New FileSystemObject
' Open the text file Data.txt for reading
Dim oTxtStreamData As TextStream
Set oTxtStreamData = ofsObj.OpenTextFile("c:DatasetData.txt")
' Read the first 10 chracters of the content
ThisDrawing.Utility.Prompt vbLf & oTxtStreamData.Read(10) & vbLf
' Read the next line or remainder of the current line
ThisDrawing.Utility.Prompt vbLf & oTxtStreamData.ReadLine & vbLf
' Read the rest of the file
ThisDrawing.Utility.Prompt vbLf & oTxtStreamData.ReadAll & vbLf

As you read content from the text stream, you can get your current location using the Columns or Line property. The Columns property lets you know how many characters from the left you have read in the current line, and the Line property lets you know which line you are on in the file. You can use the AtEndOfStream property to see if you have reached the end of the text stream, and when reading characters with the Read function, you can use the AtEndOfLine property to see if you have reached the end of the current line when reading one character at a time.

Writing Content to a File

Writing data to a text stream is similar to reading data from a text stream. You can write a string with or without using the ASCII code value of 10 (the linefeed character). The linefeed character is used to indicate the end of a line in the text stream. A line can be created with content or blank lines can be written.

The Write and WriteLine functions are used to write a string to a text stream. The difference between the two functions is that the WriteLine function adds the linefeed character to the end of the string and forces a new line in the text stream. The WriteBlankLines function is used (just as its name indicates) to write blank lines to a text stream. Both the Write and WriteLine functions expect a string value that represents the content that should be written to the file, whereas the WriteBlankLines function expects a single integer value that represents the number of blank lines that should be written.

Here are examples of writing content to a text stream with the Write, WriteLine, and WriteBlankLine functions:

' Create an instance of the File System object
Dim ofsObj As New FileSystemObject
' Create a new text file named Data.txt
Dim oTxtStreamData As TextStream
Set oTxtStreamData = ofsObj.CreateTextFile("c:DatasetData.txt")
' Write a content to the file without adding the new linefeed character
oTxtStreamData.Write "BLOCK" & vbTab & "TAG" & vbTab
' Append to the current line and add the new linefeed character
oTxtStreamData.WriteLine "PART" & vbTab & "DESCRIPTION"
' Write a blank line
oTxtStreamData.WriteBlankLine 1

Closing a File

Each text stream that represents an opened or new text file created with the OpenTextFile or CreateTextFile function must be closed using the Close function. Closing the text stream saves the changes to the file and removes the text stream from memory to free up system resources. Text streams that aren't closed might remain open in memory, and that memory is not available to other applications until AutoCAD is closed or the VBA project is unloaded.

Typically, when the procedure ends and the Close function hasn't been called, the text stream is closed automatically, but I wouldn't rely on this approach. It is always good practice to close the text stream when it is no longer needed and not to rely on the system. The Close function doesn't accept any values.

Here is an example of the Close function:

' Close the text stream
oTxtStreamData.Close

Parsing Content in an XML File

XML files were once used primarily for working with data on the Internet, but today they are used by many applications and are a way to transfer information between different applications. Although text files can be nice for generating basic reports that can be printed or for storing content, they aren't really designed as a data repository or for working with large amounts of data. XML files are readable both by humans (when not compiled) and by applications without specialized software, but unlike a text file, they can help to enforce a data structure. You can create an XML file using the functions I mentioned in the “Reading and Writing Text Files” section earlier, but reading an XML file can be simplified using the Microsoft XML library.

The following is an example of an XML file that contains the contents of three general notes that could be found in a drawing or on a title sheet of a drawing set:

<?xml version="1.0"?>
<catalog>
   <note id="n001">
      <updated_date>2014-09-01</updated_date>
      <name>ADA Turn Radius</name>
      <description>ADA REQUIRES A MINIMUM TURN RADIUS OF 60" (1525MM) FOR
WHEELCHAIRS.</description>
</note>
   <note id="n002">
      <updated_date>2014-05-14</updated_date>
      <name>Dimension Reference</name>
      <description>ALL DIMENSIONS INDICATED ARE FOR REFERENCE AND
COORDINATION PURPOSES ONLY.</description>
</note>
   <note id="n003">
      <updated_date>2014-04-14</updated_date>
      <name>Electrical Contractor</name>
      <description>ALL ELECTRICAL WORK SHALL BE COMPLETED WITH NEW
MATERIALS AND CONDUCTED BY THE ELECTRICAL CONTRACTOR UNLESS
NOTED.</description>
</note>
</catalog>

A note is represented by the Note element and is a child of the root element Catalog. Each Note element has an attribute named id, which is used to uniquely identify the note in the XML file and three children nodes that describe the Note element. The three children nodes are named updated_date, name, and description.

The following shows an example VBA procedure that reads each Note element in an XML file, and then outputs the values of the attribute and children nodes of the Note element to the AutoCAD Command prompt:

Sub ReadXML()
  ' Specify the XML file to open
  Dim sXMLFile As String
  sXMLFile = ThisDrawing.GetVariable("MyDocumentsPrefix") & _
             "MyCustomFilesch12_notes.xml"
  ' Open the XML file
  Dim oXMLDoc As New MSXML2.DOMDocument
  oXMLDoc.async = False
  oXMLDoc.validateOnParse = False
  oXMLDoc.Load sXMLFile
  ' Get the root node of the XML file
  ' In the ch12_notes.xml file, the root node is Catalog
  Dim oNodeCatalog As MSXML2.IXMLDOMNode
  Set oNodeCatalog = oXMLDoc.documentElement
  Dim oNote As MSXML2.IXMLDOMNode
  Dim oNoteChild As MSXML2.IXMLDOMNode
  ' Get the nodes under the catalog node
  ' In the ch12_notes.xml file, the children nodes are Note
  For Each oNote In oNodeCatalog.ChildNodes
    ' Get and output the first attribute of the Note
    ' In the ch12_notes.xml file, the first attribute is ID
    ThisDrawing.Utility.Prompt vbLf & "ID: " & _
                               oNote.Attributes(0).Text & vbLf
    ' Get and output the children nodes of the Note node
    ' In the ch12_notes.xml file, the children nodes are updated_date,
    ' name, and description.
    For Each oNoteChild In oNote.ChildNodes
      ThisDrawing.Utility.Prompt vbLf & "  " & UCase(oNoteChild.BaseName) & _
                                 ": " & oNoteChild.Text & vbLf
    Next oNoteChild
  Next oNote
  ThisDrawing.Utility.Prompt vbLf
  ' Release the object
  Set oXMLDoc = Nothing
End Sub

The following shows what the output looks like in the AutoCAD Command Line history after executing the previous example:

ID: n001
  UPDATED_DATE: 2014-09-01
  NAME: ADA Turn Radius
  DESCRIPTION: ADA REQUIRES A MINIMUM TURN RADIUS OF 60" (1525MM)
               FOR WHEELCHAIRS.
ID: n002
  UPDATED_DATE: 2014-05-14
  NAME: Dimension Reference
  DESCRIPTION: ALL DIMENSIONS INDICATED ARE FOR REFERENCE AND COORDINATION
               PURPOSES ONLY.
ID: n003
  UPDATED_DATE: 2014-04-14
  NAME: Electrical Contractor
  DESCRIPTION: ALL ELECTRICAL WORK SHALL BE COMPLETED WITH NEW MATERIALS AND
               CONDUCTED BY THE ELECTRICAL CONTRACTOR UNLESS NOTED.

Before using the previous example, be sure to reference the Microsoft XML Library. There might be several versions of the Microsoft XML Library registered on your workstation; reference the latest version on your workstation. If you reference the Microsoft XML 6.0v library, you will need to change the code statement Dim oXMLDoc As New MSXML2.DOMDocument to Dim oXMLDoc As New MSXML2.DOMDocument60.

For more information on parsing an XML file and using the Microsoft XML library, I recommend starting with the “A Beginner's Guide to the XML DOM” topic on the Microsoft Developer Network site (http://msdn.microsoft.com/en-us/library/aa468547.aspx). You can also use your Internet browser to locate additional resources on working with XML files, or buy a book from your favorite retailer.

Working with Microsoft Office Applications

The Microsoft Office suite installs a number of programming libraries that allow you to manipulate the contents in the files that the applications of the suite can create and access the application's settings. For example, you can create an instance of the Microsoft Word application, and then create or open a DOC or DOCX file. Once a document has been created or opened, you can step through and manipulate the content of the document or print the document to an available system printer.

The following libraries allow you to create an instance of an application and work with the files that can be created or modified using the Microsoft Office suite:

  • Microsoft Word <version>.0 Object Library (msword.olb)
  • Microsoft Excel <version>.0 Object Library (excel.exe)
  • Microsoft Outlook <version>.0 Object Library (msoutl.olb)
  • Microsoft PowerPoint <version>.0 Object Library (msppt.olb)
  • Microsoft Access <version>.0 Object Library (msacc.olb)
  • Microsoft Publisher <version>.0 Object Library (mspub.tlb)

The Microsoft Access Object library can be used to manipulate information in a database file, but you can also access the tables and queries of an Access database file without having Access installed. You can use the following programming libraries when you want to work with an Access database file without having Access installed:

  • Microsoft ActiveX Data Objects 2.8 Library (msado28.tlb)
  • Microsoft DAO 3.6 Object Library (dao360.dll)

The object libraries for each of the applications in the Microsoft Office suite are very extensive, and it would take an entire book to do them justice. If you want to learn more about creating VBA programs that interact with the applications in the Microsoft Office suite, I recommend checking out Mastering VBA for Microsoft Office 2013, by Richard Mansfield (John Wiley & Sons, 2013). You can also use your favorite Internet browser and search engine to access resources online for learning to use VBA with the applications in the Microsoft Office suite.

I have created several examples for this book that demonstrate how you can connect information from an AutoCAD drawing to Microsoft Word and Excel. You can find these custom procedures in the ch12_mswin_office.dvb file that can be downloaded from www.sybex.com/go/autocadcustomization.

The DVB file contains the following custom procedures:

  1. Createmsworddoc The createmsworddoc procedure creates a new Word document and saves it with the name ch12_apc_word_sample.doc to the MyCustomFiles folder. The new Word document file is populated with information about some of the nongraphical objects in the current drawing.
  2. printmsworddoc The printmsworddoc procedure opens the ch12_apc_word_sample.doc file that was created with the createmsworddoc procedure and placed in the MyCustomFiles folder. The Word document file is then printed using the default system printer.
  3. extractattributestoexcel The extractattributestoexcel function creates a new spreadsheet file named ch12_attributes.xls in the MyCustomFiles folder. The handle, tag, and text string for each attribute in the block references of the current drawing are extracted to columns and rows in the spreadsheet. Open the ch12_building_plan.dwg file in AutoCAD before executing the function.
  4. updateattributesfromexcel The updateattributesfromexcel function reads the information from the spreadsheet file named ch12_attributes.xls in the MyCustomFiles folder. The extracted handle in the spreadsheet is used to get the attribute reference and then update the tag and text string value that are present in the spreadsheet. Since handles are unique by drawing, you must open the original drawing that the attributes were extracted from. Make changes to the third column in the spreadsheet file, such as C2436 to CC2436, before opening the ch12_building_plan.dwg file in AutoCAD before executing the function.

Along with the custom procedures that demonstrate how to work with Microsoft Word and Excel files, there are a few functions that demonstrate how to connect to an Access database (MDB) file using Database Access Object (DAO) and ActiveX Data Object (ADO). The database library you use depends on which release of Windows you are using or the Microsoft Office version installed. You can find these custom procedures in the ch12_mswin_office.dvb file that can be downloaded from www.sybex.com/go/autocadcustomization.

The DVB file contains the following custom functions:

  1. Accessdatabasedao The accessdatabasedao procedure makes a connection to the Access database ch12_employees.mdb located in the MyCustomFiles folder. Once a connection to the database is made, the records in the Employees table are read and modified. Use this function when working with Access 2007 and earlier.
  2. accessdatabaseado The accessdatabaseado function makes a connection to the Access database ch12_employees.mdb located in the MyCustomFiles folder. Once a connection to the database is made, the records in the Employees table are read and modified. Use this function when working with Access 2007 and later.

Exercise: Reading and Writing Data

In this section, you will create a new VBA project and modify the FurnTools project to introduce several new procedures that read data from and write data to text files. The first main procedure reads information from a text file and uses that information to add new layers to a drawing. The second main procedure is an extension of the BOM program in the FurnTools project that you created in Chapter 7. Instead of adding a table grid to a drawing, this new procedure exports the BOM content to a comma-delimited (CSV) file that can be imported into a database or spreadsheet program.

The key concepts I cover in this exercise are as follows:

  1. Referencing a Programming Library Programming libraries allow you to access additional features and utilities that are not part of the core VBA programming language.
  2. Locating and Prompting for External Files Files that a custom program might rely on can be located in the AutoCAD support file search paths before they are used, or the user can be prompted for a filename and location.
  3. Opening, Reading, and Writing Data in External Files Data files can be opened before the data in the file can be read or data can be written to. Once file access is no longer needed, the file should be closed.

Creating Layers Based on Data Stored in a Text File

Often you start a drawing from a drawing template that contains a default set of layers, but any layers that are not used can accidentally be removed with the purge or -purge command. To restore the missing layers, you could create a drawing that contains your default layers and insert it into your drawing. As an alternative on Windows, you could restore the layers using the Content ExplorerTM palette or the DesignCenter TM palette. An additional approach to restoring layers (or other named standards) is through the use of external data files and VBA.

The ch12_layers.dat file (part of the sample files supplied with this book) contains information that can be used to create layers in a drawing. The DAT file is tab-delimited and contains three pieces of information about each layer—layer name, color, and linetype:

; AutoCAD Customization Platform
; Layer data file used to setup layers
Plan_Cabinets       6     Continuous
Plan_Dimensions     3     Continuous

You will use the createlayer function defined in the ch12_clsUtilities.cls file (exported as part of the exercise in Chapter 4, “Creating and Modifying Drawing Objects”) to create the new layers. In addition to using the ch12_clsUtilities.cls file, you will use a function defined in the ch12_clsDialogs.cls file to let the user select a file on their local or network drive. The functions in the ch12_clsDialogs.cls file use the Win32 API.

In these steps, you'll create a new VBA project named LayerTools with a custom procedure named LoadLayers that will read and use the data stored in the file named layers.dat to create new layers in a drawing:

  1. Create a new VBA project with the name LayerTools. Make sure to also change the default project name (ACADProject) to LayerTools in the VBA Editor.
  2. In the VBA Editor, in the Project Explorer, right-click the new project and choose Import File.
  3. When the Import File dialog box opens, browse to and select the ch12_clsUtilities.cls file in the MyCustomFiles folder. Click Open.

    The ch12_clsUtilities.cls file contains the utility procedures that you created as part of the DrawPlate and the FurnTools projects.

  4. Import the ch12_clsDialogs.cls file into the new project from the MyCustomFiles folder.
  5. In the Project Explorer, right-click the new project and choose Insert arrow Module. Change the name of the new module to basLayerTools.
  6. In the text editor area of the basLayerTools component, type the following; the comments are here for your information and don't need to be typed:
    Private myUtilities As New clsUtilities
    Private myDialogs As New clsDialogs
    ' Creates layers based on the values in the ch12_layers.dat file.
    Sub LoadLayers()
      ' Select the layer data file, if not found
      ' in the AutoCAD support file search paths
      Dim sLayerDataFile As String
      sLayerDataFile = myUtilities.FindFile("ch12_layers.dat")
      ' If the file wasn't found then prompt the user
      If sLayerDataFile = "" Then
        ' Check to see if a previous file name is in the Windows Registry
        Dim sLastLoc As String
        sLastLoc = GetSetting("Sybex", "ACP", "LastLayerDataFile")
        ' Make sure the value in the Windows Registry is valid
        If sLastLoc <> "" Then
           sLastLoc = myUtilities.FindFile(sLastLoc)
        End If
        ' If the file is not valid, prompt for the file
        If sLastLoc = "" Then
          sLayerDataFile = myDialogs.SelectOpenFile( _
                "Select Layer Data File", "", "ch12_layers.dat", _
                "Data File (*.dat)" & Chr(0) & "*.dat")
        Else
          sLayerDataFile = sLastLoc
        End If
        ' Store the last location to the Windows Registry
        If sLayerDataFile <> "" Then
          SaveSetting "Sybex", "ACP", "LastLayerDataFile", sLayerDataFile
        End If
      End If
      ' Check to see if the user selected a file
      If sLayerDataFile <> "" Then
        On Error Resume Next
        ' Create a new instance of the File System object
        Dim ofsObj As New FileSystemObject
        ' Check to see if the value passed was a file or not
        Dim oFile As File
        Set oFile = ofsObj.GetFile(sLayerDataFile)
        Dim oTextStream As TextStream
        Set oTextStream = oFile.OpenAsTextStream(ForReading)
        ' Skip the first two lines in the text stream as they are comments
        oTextStream.SkipLine
        oTextStream.SkipLine
        ' Read the text from the stream
        Dim vLineData As Variant
        While Not oTextStream.AtEndOfStream
          ' Split the line into elements based on tab characters
          vLineData = Split(oTextStream.ReadLine, vbTab)
          ' Create the new layer
          Dim oLayer As AcadLayer
          Set oLayer = myUtilities.CreateLayer(CStr(vLineData(0)), _
                                              CInt(vLineData(1)))
          ' Assign the linetype to the layer
          oLayer.Linetype = vLineData(2)
        Wend
      End If
    End Sub
  7. Click File arrow Save.

    The procedure can't be executed yet, because you need to define a new utility procedure named FindFile in the imported clsUtilities component. You will do so in the next section.

Searching for a File in the AutoCAD Support Paths

The files that a custom program relies on should be found within the AutoCAD support search file paths or in a location that the custom program can always find, such as the ProgramData folder. The AutoCAD Object library doesn't have a native function that can be used to check to see if a file is found in the AutoCAD support file search paths, but you can use the SupportPaths property of the AcadPreferencesFiles object to get a list of the support paths and then use the FileExists function of the File System object to check for the existence of the file.

In these steps, you'll add the FindFile function to the imported version of the ch12_clsUtilities.cls file:

  1. On the menu bar, click Tools arrow References.
  2. When the References dialog box opens, scroll to the Microsoft Scripting Runtime library and click the check box next to it. The library should now be checked.
  3. Click OK.
  4. In the Project Explorer, double-click the clsUtilities component.
  5. In the text editor area of the clsUtilities component, scroll to the bottom of the last procedure and press Enter a few times. Then, type the following. (The comments are here for your information and don't need to be typed.)
    ' Returns a string containing the full path to the file if it is found
    ' in the AutoCAD support file search path.
    ' Function expects a string representing the name of
    ' the file you want to find.
    Function FindFile(sFileName As String) As String
      On Error Resume Next
      ' Create a new instance of the File System object
      Dim ofsObj As FileSystemObject
      Set ofsObj = CreateObject("Scripting.FileSystemObject")
      ' Check to see if the value passed was a file or not
      Dim oFile As File
      Set oFile = ofsObj.GetFile(sFileName)
      If Err Then
        Err.Clear
        Dim sSupportPaths As String, sPath As Variant
        ' Get the Support File paths
        sSupportPaths = ThisDrawing.Application.Preferences.Files.SupportPath
        ' Split the support paths delimited by a semicolon
        For Each sPath In Split(sSupportPaths, ";")
          ' Check to see if the file exists in the path
          If ofsObj.FileExists(CStr(sPath) & "" & sFileName) Then
            ' Return the full path to the file
            FindFile = CStr(sPath) & "" & sFileName
            ' Exit the For statement
            Exit Function
          End If
        Next
      Else
        ' Return the file name as it is a full path
        FindFile = sFileName
        Exit Function
      End If
      FindFile = ""
    End Function
  6. Click File arrow Save.
  7. In the Project Explorer, right-click the clsUtilities component and choose Export File.
  8. When the Export File dialog box opens, browse to the MyCustomFiles folder and click Save. The name in the File Name text box should be clsUtilities.cls; if it isn't, enter clsUtilities and then click Save. If you have a previous version of this file, be sure you want to overwrite that file.

    Now when you import the clsUtilities.cls file into a future project, the FindFile function will be available in that project. If you need this function in an existing project, you will need to remove the existing clsUtilities component and import this file.

Adding Layers to a Drawing with the LoadLayers Procedure

The LayerTools.dvb file now contains the LoadLayers procedure, which uses the createlayer function defined in the clsUtilities component and the SelectOpenFile function defined in the clsDialogs component.

The following steps explain how to use the LoadLayers procedure in the LayerTools.dvb file:

  1. Create a new drawing.
  2. At the Command prompt, type vbarun and press Enter.
  3. When the Macros dialog box opens, select the LayerTools.dvb!basLayerTools.LoadLayers macro from the list and click Run.
  4. If the Select Layer Data File dialog box opens, browse to and select the ch12_layers.dat file, which you should have copied to the MyCustomFiles folder under the Documents (or My Documents) folder. Click Open.

    The Select Layer Data File dialog box is only displayed if the VBA program couldn't locate the ch12_layers.dat file in the AutoCAD support search file paths.

  5. On the ribbon, click Home tab arrow Layers panel arrow Layer Properties.
  6. Open the ch12_layers.dat file in Notepad.
  7. Click at the end of the last line; the line starts with Plan_Walls.
  8. In the text editor area, type the following. (Press the Tab key rather than typing the text <tab>.)
    Title_Block<tab>7<tab>Continuous
  9. Save the changes to the ch12_layers.dat file.
  10. In AutoCAD, execute the LoadLayers macro again with the vbarun command; notice that the layer Title_Block is now added to the drawing.

Writing Bill of Materials to an External File

In Chapter 7 you created a VBA project that allowed you to extract the attributes of a block and then quantify the results before creating the BOM in the drawing. Here you will create a procedure named FurnBOMExport that allows you to export the BOM data generated with the ExtAttsFurnBOM procedure output to a comma-delimited text (CSV) file instead of adding it to the drawing as a table grid as you did with the FurnBOM procedure. You could then use the CSV file and import the BOM into a costing or ordering system.

Using these steps, you will create the custom procedure named FurnBOMExport in the FurnTools.dvb file, which you created in Chapter 7.

  1. Load the FurnTools.dvb file into the AutoCAD drawing environment and display the VBA Editor.
  2. In the VBA Editor, in the Project Explorer, right-click the FurnTools project and choose Import File.
  3. When the Import File dialog box opens, browse to the MyCustomFiles folder and select the ch12_clsDialogs.cls file (or the clsDialogs.cls file you exported in the previous section). Click Open.
  4. On the menu bar, click Tools arrow References.
  5. When the References dialog box opens, scroll to the Microsoft Scripting Runtime library in the list and click the check box next to it. The library should now be checked.
  6. Click OK.
  7. In the Project Explorer, double-click the basFurnTools component to edit the code in the code editor window.
  8. In the code editor window, scroll to the top of the window and after the code statement Private myUtilities As New clsUtilities press Enter.
  9. Type the following:
    Private myDialogs As New clsDialogs
  10. Scroll to the bottom of the code editor window, click after the End statement of the last procedure, and press Enter twice.
  11. In the code editor window, type the following:
    ' Exports the extracted attribute information to an external data file
    Sub FurnBOMExport()
      On Error Resume Next
      ' Get the blocks to extract
      Dim oSSFurn As AcadSelectionSet
      Set oSSFurn = ThisDrawing.SelectionSets.Add("SSFurn")
      ' If an error is generated, selection set already exists
      If Err Then
        Err.Clear
        Set oSSFurn = ThisDrawing.SelectionSets("SSFurn")
      End If
      ' Define the selection set filter to select only blocks
      Dim nDXFCodes(0) As Integer, nValue(0) As Variant
      nDXFCodes(0) = 0
      nValue(0) = "INSERT"
      Dim vDXFCodes As Variant, vValues As Variant
      vDXFCodes = nDXFCodes
      vValues = nValue
      ' Allow the user to select objects in the drawing
      oSSFurn.SelectOnScreen vDXFCodes, vValues
      ' Proceed if oSSFurn is greater than 0
      If oSSFurn.Count > 0 Then
        Dim sBOMDataFile As String
        sBOMDataFile = myDialogs.SelectSaveFile("Create CSV File", "", "", _
                            "Comma-delimited File (*.csv)" & Chr(0) & "*.csv")
        ' Check to see if the user selected a file
        If sBOMDataFile <> "" Then
          ' Extract and quantify the parts in the drawing
          Dim vAttList As Variant
          vAttList = ExtAttsFurnBOM(oSSFurn)
          On Error Resume Next
          ' Create a new instance of the File System object
          Dim ofsObj As New FileSystemObject
          ' Check for a file extension, if not present append one
          If ofsObj.GetExtensionName(sBOMDataFile) = "" Then
            sBOMDataFile = sBOMDataFile & ".csv"
          End If
          ' Create a new text file based on the selected file
          Dim oTextStream As TextStream
          Set oTextStream = ofsObj.CreateTextFile(sBOMDataFile)
          ' Write the header line to the file
          oTextStream.WriteLine "QTY,LABELS,PARTS"
          ' Step through the list
          Dim vItem As Variant
          For Each vItem In vAttList
            vItem = Split(vItem, vbTab)
            oTextStream.WriteLine CStr(vItem(0)) & "," & _
                                  CStr(vItem(1)) & "," & _
                                  CStr(vItem(2))
          Next vItem
          ' Close the file
          oTextStream.Close
        End If
        ' Remove the selection set
        oSSFurn.Delete
      End If
    End Sub
  12. Click File arrow Save.

Using the FurnBOMExport Procedure

The following steps explain how to use the FurnBOMExport procedure that is defined in the FurnTools.dvb file. Before starting the steps, download the sample ch12_building_plan.dwg from www.sybex.com/go/autocadcustomization. Place the sample file in the MyCustomFiles folder under the Documents (or My Documents) folder.

  1. Open ch12_building_plan.dwg.
  2. At the Command prompt, type vbarun and press Enter.
  3. When the Macros dialog box opens, select the FurnTools.dvb!basFurnTools.FurnBOMExport macro from the list and click Run.
  4. At the Select objects: prompt, select the furniture blocks in the plan and press Enter.
  5. When the Create CSV File dialog box opens, browse to the MyCustomFiles folder or the folder in which you want to create the CSV file.
  6. In the File Name text box, type furnbom and click Save.
  7. Open Windows Explorer or File Explorer, and browse to the location of the furnbom.csv file.
  8. Open the file in Notepad or even an application like Microsoft Excel.

    Figure 12.3 shows the results of opening the furnbom.csv file in Excel.

image

Figure 12.3 BOM content in Excel.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.204.0