Questions similar to this appear on the Bentley Discussion Groups. These appeared in the VBA discussion group.
Q Level Libraries (DGNLIBs)
A MicroStation administrative facilities include level libraries, also known as DGNLIBs, as a way to provide consistent settings and symbology in your projects.
A level library has a predefined set of named levels, complete with line colour, weight, and style definitions. Your workspace may attach one or multiple level libraries. They make it easy for your MicroStation users to use consistent settings. A level library is attached to your DGN model as a special sort of reference model, whose settings you can see but can't modify. A level library differs from a normal reference model in that you can see its levels but you don't see any graphics elements.
A level library is a design file with a .dgnlib
extension. You can open a level library with MicroStation just like any other
DGN file. Typically, a system administrator would do just that when defining levels. Because a user never sees the
graphics in a level library, the administrator is free to include graphics in the DGNLIB such as, for example, a legend.
It's not a bad idea to include a legend in each DGNLIB, which displays an element for each level definition, maybe
with some annotation that describes the purpose of that level and its symbology.
That way, it's easy to see your symbology definitions and it becomes easier to publish your standards: just print the
DGNLIB to an Adobe PDF and put it in a public place on your Intranet.
Level libraries and DGNLIBs are synonymous. This can lead to some confusion because when you discuss DGNLIBs, your listener may not realise that you are talking about level libraries, and vice versa. In fact, there is already some confusion at Bentley Systems, evidenced by the names of configuration variables (CfgVars) used to define folders and files related to level libraries.
MS_LEVEL_LIB_DIR
is the CfgVar that defines the folder or folders that contain level libraries.
For example …
MS_LEVEL_LIB_DIR = //server/projects/standards/dgnlibs/
MS_DGNLIBLIST
is the CfgVar that defines a list of level libraries for a workspace.
For example …
MS_DGNLIBLIST = $(MS_LEVEL_LIB_DIR)electrical.dgnlib MS_DGNLIBLIST > $(MS_LEVEL_LIB_DIR)mechanical.dgnlib
You can see information about level libraries from the Configuration dialog that pops when you choose MicroStation's
Workspace|Configuration menu. The value of MS_LEVEL_LIB_DIR
is shown when you select the Levels category …
The value of MS_DGNLIBLIST
is shown when you select the Primary Search Paths category …
How do I find DGNLIBs with VBA? If you scan referenced models, you won't find them. The Attachments
collection
doesn't include level libraries.
As is usual, MDL provides ways to do things in MicroStation that are sometimes missing in VBA. In this case, there are MDL functions that work with DGNLIBs that have no direct VBA equivalent. Fortunately, it's possible to use MDL functions from a VBA macro.
In order to use an MDL function in VBA, it's necessary to Declare
the function, along with the
library (or DLL
) that contains its implementation. The following declarations should go at the beginning of your VBA code,
before any procedure (subroutine or function) definitions …
Declare PtrSafe Function mdlLevelLibrary_getFirst Lib "stdmdlbltin.dll" () As Long Declare PtrSafe Function mdlLevelLibrary_getName Lib "stdmdlbltin.dll" (ByVal pLibraryNameOut As Long, ByVal stringSizeIn As Long, ByVal pLibraryRefIn As Long) As Long Declare PtrSafe Function mdlLevelLibrary_getNext Lib "stdmdlbltin.dll" (ByVal pLibraryRefIn As Long) As Long
The following code snippet uses the MDL functions we've declared to iterate the list of level libraries attached to the current DGN model.
mdlLevelLibrary_getFirst
obtains a pointer to the first level library.
mdlLevelLibrary_getNext
uses the current value of that pointer to find the next library.
mdlLevelLibrary_getName
does what you expect, but it's camouflaged by some syntactic sugar we
have to sprinkle around it to convert the Unicode string it finds to something that VBA can understand …
Function IterateLevelLibs() As Long Dim iterator As Long Dim levelLib As Long Dim status As Long Const Length As Integer = 255 Dim lngLength As Long Dim fileName As String * Length Dim name As String Dim vtName As Variant fileName = String(Length, vbNull) levelLib = mdlLevelLibrary_getFirst() Do While 0 <> levelLib vtName = StrConv(fileName, vbFromUnicode) mdlLevelLibrary_getName StrPtr(vtName), Length, levelLib name = StrConv(vtName, vbUnicode) Debug.Print "Level Library '" & vtName & "'" levelLib = mdlLevelLibrary_getNext(levelLib) Loop End Function
In this example, we're doing nothing more useful than to trace the level library names with Debug.Print
…
Level Library 'X:\ … \Architectural\dgnlib\Architectural.dgnlib' Level Library 'X:\ … \Civil\dgnlib\Civil.dgnlib'