Introduction
This article is for people who want to write Impact scripts and have at least a basic knowledge of Impact and of VB but find the Impact COM Documentation (ImpactCOM.chm) help file tricky to follow.
I hope that this difficulty doesn’t indicate anything fundamentally wrong with the document, rather that it is a big document with no obvious place to start. The help file is produced automatically, which means that we don’t have much control over its format, but it does mean that it should always contain all our objects and members. This allows us to concentrate on descriptions and examples to help you make sense of it all. As always, we welcome your comments on the clarity and helpfulness of the text.
In this document, I will try to go through the process of writing a script as if I had no prior knowledge of the Impact objects and members (methods and properties). I will try to explain how I use the documentation to get the information I need.
I strongly recommend that, as you read this document, you follow my path through the help file, ideally running the scripts in Impact too. Whenever I mention Contents, Index or Search, I mean the tabs in the help file (you might have them hidden).
For clarity, I’ll call all my objects My-Something. VB isn’t fussy about capitalisation and indentation, but I’ve tried to be clear and consistent.
Starting The Script
I have arbitrarily chosen to write a script to display the names of my working projects (as shown in the Working Projects node of the project browser). The first thing I might do is to look in the Index for working. This shows me an item called WorkingProject Property. If I view that topic, the description Indicates if the drawing that this object represents is being modified by the currently connected user. tells me that I could be on the right track. It doesn’t explicitly state which object this is a property of, but the See also section shows IDatabaseItem Object. Following that link tells me that this object Represents an item in the database, this may be a project, symbol, template, standard or standard part. So this isn’t really what I want (I don’t have any database item to start with). Next, I have a go at using Search for *working*. This finds 30 or so matches. I can see that a lot of them are examples, because they have (VBScript) in the title. I notice a GetWorkingProjects Method. Viewing this topic shows a description that matches what I want to do: Gets a list of IDatabaseItem objects representing the projects this user is currently working on. The See Also gives IUser Object which sounds right. (There is also an example there, but let’s ignore that for this exercise.)
So the starting point for my script is:
MyWorkingProjectItems = MyUser.GetWorkingProjects()
I won’t run this yet, because I don’t yet know how to create the MyUser object. If I did, it would produce the error: Script Error (Ln: 1 Pos: 0): 'Object required: 'MyUser'’. Note: the GetWorkingProjects method returns an array (not an object or collection), so I must not start the statement with a Set. However the Set is essential (in VBS) for objects and collections. (In VB.NET, this distinction is removed – there is no Set statement.) I need now to get an IUser object which represents my user. From experience I can guess that if there is an object called IUser then there is likely to be a collection called IUsers. Looking in the Index for IUsers confirms this, but doesn’t give me any useful info: A collection of IUser objects. Doing a Search for IUsers gives several matches. There are a few methods, but the names don’t sound relevant to what I’m doing. However IDatabase Object Members sounds useful, because what I’m after is a list of all users configured in the database. Following this link shows that IDatabase has a property called Users, so I can do this:
Set MyUsers = MyDatabase.Users
With a collection, you can usually use the Item method to find one item in the collection using a name string. This is the case for IUsers (you might expect the string to match the FullName property, but it matches the LoginID property, which is actually more useful in most cases). So, if I don’t mind a hard-coded name in the script, I can do this:
Set MyUsers = MyDatabase.Users
Set MyUser = MyUsers.Item(“JOHN”)
MyWorkingProjectItems = MyUser.GetWorkingProjects
The script still won’t run jut yet though. If I’m using VBS from within Impact, I can actually use a pre-defined object ActiveDatabase. However, if I’m not (or if I didn’t know that) then I need to work out how to get the MyDatabase object. Looking at the IDatabase Object documentation shows some examples. The first line of the first example includes the line Set db = Impact.ActiveDatabase. If I hadn’t spotted this, I would have had to Search for IDatabase and scanned the many matches for anything useful (ActiveDatabase Property is there). So now (omitting to check for null objects for the moment) I have:
Set MyUser = Impact.ActiveDatabase.Users.Item(“JOHN”)
MyWorkingProjectItems = MyUser. GetWorkingProjects()
Msgbox (Ubound(MyWorkingProjectItems) - Lbound(MyWorkingProjectItems) +1) & “ working projects”
This runs and gives the correct number. Nice.
The last line is standard VB – finding the number of items in an array by looking at the lower and upper bounds of the array (it works even for zero items in the array). The ampersand (&) is for string concatenation. I’m just making sure the script is returning sensible information before I go any further. Having hard-coded strings is not nice though - it would be much better if the script could get my username itself. Searching for IUser shows a match ConnectedUser Property. This is a property of IDatabase and returns an IUser object, so it is exactly what I need. Now my script is this:
Set MyUser = Impact.ActiveDatabase.ConnectedUser
MyWorkingProjectItems = MyUser.GetWorkingProjects
There are several ways of iterating through an array, but this is the easiest:
For Each MyWorkingItem In MyWorkingProjectItems
' do something
Next
Now the GetWorkingProjects method returns an array of IDatabaseItem objects. Unfortunately, there isn’t a link from this topic to IDatabaseItem, so I use the Index to find it. I follow the link to IDatabaseItem Object Members, because generally this is much more useful (I never find those Object Model diagrams very useful). There are plenty of useful properties here, but Reference (the project name) is the first one I want. Now I have:
Set MyUser = Impact.ActiveDatabase.ConnectedUser
MyWorkingProjectItems = MyUser.GetWorkingProjects()
WorkingCount = (Ubound(MyWorkingProjectItems) _
- Lbound(MyWorkingProjectItems) +1)
Gui.Outputtoolbox.Add WorkingCount & " working projects"
For Each MyWorkingItem In MyWorkingProjectItems
Gui.OutputToolbox.Add MyWorkingItem.Reference
Next
Note that I’ve changed the previous Msgbox to use the OutputToolbox object instead. Most of our examples use this, so it tends to be one of the first things you learn when writing scripts. The Gui object is one of several predefined objects, but I could just as easily have used Impact.Gui. Incidentally, the underscore is the VB line continuation character. The script runs fine (hopefully it does for you too).
Enhancing The Script
I’ve noticed that IDatabaseItem objects also have a property called Drawing: The IDrawing object that this item represents. Following this link to the Drawing Property topic shows the comment If the drawing is not currently open this method returns NULL. It can be used to test whether a drawing is still open , so I can test whether I have any of my working projects open at the moment, as follows:
If MyWorkingItem.Drawing Is Nothing Then
Str = ""
Else
Str = " (currently open)"
End if
Gui.OutputToolbox.Add MyWorkingItem.Reference & Str
This all works nicely. Finally, I haven’t done any validity checking yet, so adding this gives:
Set MyDb = Impact.ActiveDatabase
Set MyOutput = Impact.Gui.OutputToolbox
If Not MyDb Is Nothing Then
Set MyUser = MyDb.ConnectedUser
If Not MyUser Is Nothing Then
MyWorkingProjectItems = MyUser.GetWorkingProjects
If IsArray(MyWorkingProjectItems) Then
WorkingCount = (Ubound(MyWorkingProjectItems) _
- Lbound(MyWorkingProjectItems) +1)
MyOutput.Add WorkingCount & " working projects"
For Each MyWorkingItem In MyWorkingProjectItems
If MyWorkingItem.Drawing Is Nothing Then
Str = ""
Else
Str = " (currently open)"
End if
MyOutput.Add MyWorkingItem.Reference & Str
Next
Else
MsgBox "Unable to determine working projects"
End If
Else
MsgBox "Unable to determine current user"
End If
Else
MsgBox "No active database"
End If
The If Not obj Is Nothing syntax doesn’t look very elegant, but it seems to be the most common way of checking that I have a valid object.
Summary
I’ve never really thought about how I use the help file before, but it seems that I use Search a lot, Index a little bit and Contents rarely. I tend to work backwards from what I need (in this case, working projects) to what I’ve got (the Impact object). Most of the methods and properties have names which match the Impact tools, user-interface elements and data, so they’re quite guessable. In general, I find that the examples quite often address several of my questions at once, so I tend to look there first. If all that fails, you know where to find us!