ProjectWise's API can be accessed via VBA, allowing you to extend applications beyond the desktop. If you need to work with data that is stored in ProjectWise in your corporate environment, you can automate many tasks just by using VBA and the ProjectWise API. To use the API, you need to declare the functions that you plan to use. By encapsulating these calls, you can reuse them in many applications. In this article, we will use the simple process of logging in, checking out, allowing processing, and checking in of multiple documents in a ProjectWise document store. We need to declare the functions that will be used, then organize the application into reusable parts, and finally test the application.
First, set up the calls that need to be exposed to VBA from the ProjectWise API. The aaAPI class module is used to expose the C-based functions of the ProjectWise API to VBA. They are kept in one module to allow them to be reused in the application. There is also a Utility module to expose other functions that are necessary for both this and future projects.
The next phase is to build a set of classes that encapsulate the parts of ProjectWise that we will be working with. First is the datasource, which is in the clsPWDataSource class. This will be the point of the login and contain a reference to the collection of Projects that make up a datasource. Next, define the clsPWProject, which represents the Project information and contains a collection of documents. Next, define the clsPWDocument, which is the document class. Finally, there is the clsPWAttribute, which contains the document attributes.
The datasource class has the following properties and methods:
This method is called when a new reference to a datasource is created and contains the aaApi_initialize function call, which enables the rest of the aaApi calls to work.
This method calls the aaApi_login function to connect to the datasource.
'---------------------------------------------------------------------------------------+'' Copyright: (c) 2006 Bentley Systems, Incorporated. All rights reserved.''---------------------------------------------------------------------------------------+'---------------------------------------------------------------------------------------+' Module: clsPWDataSource.cls' Status:' Date:' Author:' Version: 1.0'' This class is a Connection to ProjectWise Datasource''---------------------------------------------------------------------------------------+Option Explicit'---------------------------------------------------------------------------------------+'' Private Members''---------------------------------------------------------------------------------------+' User InformationPrivate strUserName As StringPrivate strPassword As StringPrivate strDataSource As StringPrivate blIsLoggedIn As BooleanPrivate blIsMCMLoaded As Boolean'Document InformationPrivate lngDocID As LongPrivate lngProjectID As LongPrivate strDocumentName As StringPrivate lngSetID As LongPrivate lngAttibuteCount As LongPrivate strAttributes(0, 0) As StringPrivate strGUID As String'---------------------------------------------------------------------------------------+'' Public Members''---------------------------------------------------------------------------------------+Public Documents As CollectionPublic Projects As Collection'---------------------------------------------------------------------------------------+'' Public Properties''---------------------------------------------------------------------------------------+'User NamePublic Property Get UserName() As String UserName = StrConv(strUserName, vbFromUnicode)End PropertyPublic Property Let UserName(ByVal strNewUserName As String) strUserName = StrConv(strNewUserName, vbUnicode)End Property'PasswordPublic Property Let UserPassword(ByVal strNewPassword As String) strPassword = StrConv(strNewPassword, vbUnicode)End Property'DatasourcePublic Property Get datasource() As String datasource = StrConv(strDataSource, vbFromUnicode)End PropertyPublic Property Let datasource(ByVal strNewDataSource As String) strDataSource = StrConv(strNewDataSource, vbUnicode)End Property'SystemPublic Property Get IsMCMLoaded() As Boolean IsMCMLoaded = blIsMCMLoadedEnd Property'---------------------------------------------------------------------------------------+'' Login Properties and Methods''---------------------------------------------------------------------------------------+Public Property Get IsloggedIn() As Boolean IsloggedIn = blIsLoggedInEnd Property'*---------------------------------------------------------------------------------**''**' @description Logs a user into ProjectWise' @param lngDataSourceType IN Datasource type to log into' @param strLoginDataSourceName IN Datasource to log into' @param strLoginUserName IN User name' @param strLoginPassword IN User password' @return' @version 1.0' @dependencies' @example' @remarks' @alinkjoin' @group'---------------+---------------+---------------+---------------+---------------+------''Public Sub Login(lngDataSourceType As DataSourceTypes, strLoginDataSourceName As String, strLoginUserName As String, strLoginPassword As String) Dim lOK As Long UserName = strLoginUserName UserPassword = strLoginPassword datasource = strLoginDataSourceName lOK = aaApi_Login(lngDataSourceType, StrConv(strLoginDataSourceName, vbUnicode), StrConv(strLoginUserName, vbUnicode), StrConv(strLoginPassword, vbUnicode), "") If lOK <> 1 Then blIsLoggedIn = False Else blIsLoggedIn = True BuildDataSourceInfo End If End Sub'*---------------------------------------------------------------------------------**''**' @description Logs a user into ProjectWise' @param lngDataSourceType IN Datasource type to log into' @param strLoginDataSourceName IN Datasource to log into' @param strLoginUserName IN User name' @param strLoginPassword IN User password' @return' @version 1.0' @dependencies' @example' @remarks' @alinkjoin' @group'---------------+---------------+---------------+---------------+---------------+------''Public Sub LoginDlg(lngDataSourceType As DataSourceTypes, strLoginDataSourceName As String, strLoginUserName As String, strLoginPassword As String) Dim lOK As Long UserName = strLoginUserName UserPassword = strLoginPassword datasource = strLoginDataSourceName lOK = aaApi_LoginDlg(lngDataSourceType, "", Len(strLoginDataSourceName), "", "", "") If lOK <> 1 Then blIsLoggedIn = False Else blIsLoggedIn = True BuildDataSourceInfo End If End Sub'---------------------------------------------------------------------------------------+'' Project Properties and Methods''---------------------------------------------------------------------------------------+Sub NavigateHierarchy(lngPID As Long)Dim projectDatabuffer As LongDim numDocuments As LongDim iCount As LongDim oProject As clsPWProjectprojectDatabuffer = aaApi_SelectProjectDataBuffer(lngPID)numDocuments = aaApi_SelectDocumentsByProjectId(lngPID)'Process top level only.For iCount = 0 To numDocuments - 1 Set oProject = New clsPWProject oProject.ProjectID = aaApi_DmsDataBufferGetNumericProperty(projectDatabuffer, PROJ_PROP_ID, iCount) oProject.ProjectName = VBStringFromPtrW(aaApi_DmsDataBufferGetStringProperty(projectDatabuffer, PROJ_PROP_NAME, iCount)) oProject.Description = VBStringFromPtrW(aaApi_DmsDataBufferGetStringProperty(projectDatabuffer, PROJ_PROP_DESC, iCount)) oProject.BuildDocumentCollection Projects.Add oProjectNext iCountDim subProjectDataBuffer As LongDim numChildren As LongDim iSubCount As LongDim childProjID As LongsubProjectDataBuffer = aaApi_SelectProjectDataBufferChilds(lngPID)numChildren = aaApi_DmsDataBufferGetCount(subProjectDataBuffer)For iSubCount = 0 To numChildren - 1childProjID = aaApi_DmsDataBufferGetNumericProperty(subProjectDataBuffer, PROJ_PROP_ID, iSubCount) Call NavigateHierarchy(childProjID)Next iSubCountaaApi_DmsDataBufferFree subProjectDataBufferaaApi_DmsDataBufferFree projectDatabufferEnd SubSub BuildProjectCollection2()Dim projectDatabuffer As LongDim iTopLevelProjects As LongDim iCount As LongDim lngPID As LongiTopLevelProjects = aaApi_SelectTopLevelProjects()If iTopLevelProjects < 0 Then MsgBox "error on projects collection" & GetLastErrorMessage & GetLastErrorDetail Exit SubEnd IfFor iCount = 0 To iTopLevelProjects lngPID = aaApi_GetProjectId(iCount) Call NavigateHierarchy(lngPID)Next iCountEnd SubSub BuildProjectCollection()Dim projectDatabuffer As LongDim iTopLevelProjects As LongprojectDatabuffer = aaApi_DmsDataBufferSelect(AADMSBUFFER_PROJECT)If projectDatabuffer = 0 Then MsgBox "error on projects collection" & GetLastErrorMessage & GetLastErrorDetail Exit SubEnd IfDim numberOfProjects As LongDim oProject As clsPWProjectDim iCount As LongnumberOfProjects = aaApi_DmsDataBufferGetCount(projectDatabuffer)For iCount = 0 To numberOfProjects - 1 Set oProject = New clsPWProject oProject.ProjectID = aaApi_DmsDataBufferGetNumericProperty(projectDatabuffer, PROJ_PROP_ID, iCount) oProject.ProjectName = VBStringFromPtrW(aaApi_DmsDataBufferGetStringProperty(projectDatabuffer, PROJ_PROP_NAME, iCount)) oProject.Description = VBStringFromPtrW(aaApi_DmsDataBufferGetStringProperty(projectDatabuffer, PROJ_PROP_DESC, iCount)) oProject.BuildDocumentCollection Projects.Add oProjectNext iCountaaApi_DmsDataBufferFree (projectDatabuffer)End SubPrivate Sub BuildDataSourceInfo() Set Documents = New Collection Set Projects = New Collection BuildProjectCollectionEnd SubPrivate Sub Class_Initialize() ' See if MCM is loaded If Utility.MDLIsLoaded("MCM") <> True Then aaApi_Initialize AAMODULE_ALL blIsLoggedIn = False blIsMCMLoaded = False Else blIsMCMLoaded = True blIsLoggedIn = True End If End SubPrivate Sub Class_Terminate() 'Logout If datasource <> "" Then aaApi_Logout datasource End If Call aaApi_Uninitialize blIsLoggedIn = False End Sub
The project class has the following properties and methods:
This method iterates through the Documents in the project and creates a collection of clsPWDocuments.
This method allows a new document to be inserted into the project
'---------------------------------------------------------------------------------------+'' Copyright: (c) 2006 Bentley Systems, Incorporated. All rights reserved.''---------------------------------------------------------------------------------------+'---------------------------------------------------------------------------------------+' Module: clsPWProject.cls' Status:' Date:' Author:' Version: 1.0'' This class is a Connection to ProjectWise DataSource''---------------------------------------------------------------------------------------+Option ExplicitPrivate lngDataSource As LongPublic lngProjectID As LongPublic strName As StringPublic strDescription As StringPrivate Documents As CollectionPublic Property Let ProjectID(id As Long)lngProjectID = idEnd PropertyPublic Property Get ProjectID() As LongProjectID = lngProjectIDEnd PropertyPublic Property Get ProjectName() As StringProjectName = strNameEnd PropertyPublic Property Let ProjectName(strNameIn As String)strName = strNameInEnd PropertyPublic Property Let DataSourceID(datasource As Long)lngDataSource = datasourceEnd PropertyPublic Property Get DataSourceID() As LongDataSourceID = lngDataSourceEnd PropertyPublic Property Let Description(strDesc As String)strDescription = strDescEnd PropertyPublic Property Get Description() As StringDescription = strDescriptionEnd PropertyPublic Sub BuildDocumentCollection()Dim oDocument As clsPWDocumentDim numberOfDocuments As LongDim projectDocumentsBuffer As LongDim pAADocSelect As AADOCSELECT_ITEMpAADocSelect.lProjectId = lngProjectID'numberOfDocuments = aaApi_SelectDocumentsByProjectId(lngProjectID)numberOfDocuments = aaApi_SelectDocuments(VarPtr(pAADocSelect), 0, 0)If numberOfDocuments < 0 Then MsgBox "error building doc list " & GetLastErrorMessage & GetLastErrorDetailExit SubEnd IfDim iCount As LongDim id As LongDim lngDocType As LongFor iCount = 0 To numberOfDocuments - 1id = aaApi_GetDocumentNumericProperty(DOC_PROP_ID, iCount)If id <> 0 ThenSet oDocument = New clsPWDocument oDocument.DocumentID = id oDocument.ProjectID = lngProjectID oDocument.name = VBStringFromPtrW(aaApi_GetDocumentStringProperty(DOC_PROP_NAME, iCount)) lngDocType = aaApi_GetDocumentNumericProperty(DOC_PROP_ITEMTYPE, iCount) oDocument.DocType = lngDocType Documents.Add oDocumentEnd IfNext iCount'aaApi_DmsDataBufferFree projectDocumentsBufferEnd SubProperty Get DocumentsCollection() As CollectionSet DocumentsCollection = DocumentsEnd PropertyPrivate Sub Class_Initialize()Set Documents = New CollectionEnd Sub''*---------------------------------------------------------------------------------**''**'' @description Create a document in the ProjectWise database'' @param lngProjectID IN Project ID to create the document'' @param strDocument IN Path and name of the document'' @return True if the document was created successfully else False'' @version 1.0'' @dependencies'' @example'' @remarks'' @alinkjoin'' @group''---------------+---------------+---------------+---------------+---------------+------''Public Function CreateDocument(lngProjectID As Long, strDocument As String) As Long Dim lngAppID As Long Dim lngWorkSpceID As Long Dim lngAttID As Long Dim strFileName As String Dim strFileExt As String Dim strWorkingDir As String Dim status As Long Dim oDocument As clsPWDocument lngAppID = 1 strWorkingDir = Space(MAX_STRINGLEN) ' Parse file strFileName = fileNameParse(strDocument, FileNameOnlyType) strFileExt = fileNameParse(strDocument, FileExtOnlyType) strFileName = strFileName + "." + strFileExt ' Get IDs lngWorkSpceID = aaApi_GetWorkspaceProfileId(lngProjectID, 0) strFileExt = StrConv(strFileExt, vbUnicode) lngAppID = aaApi_GetFExtensionApplication(strFileExt) status = aaApi_CreateDocument(lngDocID, lngProjectID, 0, AADMS_FTYPE_UNKNOWN, AADMS_ITYPE, lngAppID, 0, _ lngWorkSpceID, StrConv(strDocument, vbUnicode), _ StrConv(strFileName, vbUnicode), _ StrConv(strFileName, vbUnicode), _ vbNullChar, vbNullChar, False, _ AADMSDOCCREF_DEFAULT, strWorkingDir, MAX_STRINGLEN, lngAttID) If status <> 0 Then oDocument = New clsPWDocument oDocument.Initialize lngProjectID, lngDocID oDocument.DocType = aaApi_GetDocumentNumericProperty(DOC_PROP_ITEMTYPE, iCount) Documents.Add oDocument End If CreateDocument = lngDocIDEnd Function
The Documents collection holds the documents in this project. To add a document, the CreateDocument method is called on the project that holds the document.
The document class has the following properties and methods: CheckIn and CheckOut methods.
The document is checked in and out using the
'---------------------------------------------------------------------------------------+'' Copyright: (c) 2006 Bentley Systems, Incorporated. All rights reserved.''---------------------------------------------------------------------------------------+'---------------------------------------------------------------------------------------+' Module: clsPWDocument.cls'' This class contains information about a document from ProjectWise''---------------------------------------------------------------------------------------+Option Explicit'---------------------------------------------------------------------------------------+'' Private Members''---------------------------------------------------------------------------------------+'Document InformationPrivate blnIsCheckOut As BooleanPrivate lngDocID As LongPrivate lngProjID As LongPrivate strDocumentName As StringPrivate strFullDocumentName As StringPrivate strCheckedOutName As StringPrivate lngDocItemType As LongPrivate lngSetID As LongPrivate lngAttibuteCount As LongPrivate strPathToCheckedOutFile As StringPrivate strGUID As String'---------------------------------------------------------------------------------------+'' Public Property''---------------------------------------------------------------------------------------+Public Attributes As CollectionPublic Property Get FullFileName() As String FullFileName = strFullDocumentNameEnd PropertyPublic Property Let FullFileName(name As String) FullFileName = nameEnd Property'DatasourcePublic Property Get DocumentID() As Long DocumentID = lngDocIDEnd PropertyPublic Property Let DocumentID(id As Long) lngDocID = idEnd PropertyPublic Property Get ProjectID() As Long ProjectID = lngProjIDEnd PropertyPublic Property Let ProjectID(id As Long) lngProjID = idEnd PropertyPublic Property Get name() As String name = strDocumentNameEnd PropertyPublic Property Let name(strName As String) strDocumentName = strNameEnd PropertyPublic Property Let DocType(DocType As Long)lngDocItemType = DocTypeEnd PropertyPublic Property Get DocType() As Long DocType = lngDocItemTypeEnd PropertyPublic Property Get CheckedOutName() As String CheckedOutName = strCheckedOutNameEnd PropertyPublic Property Get IsCheckOut() As Boolean IsCheckOut = blnIsCheckOutEnd PropertyPublic Property Get AttributeCount() As Long AttributeCount = lngAttibuteCountEnd Property'*---------------------------------------------------------------------------------**''**' @description Checks in the document with the provided ProjectID and DocumentID' @param lngProjectID IN Project ID of the document' @param lngDocumentID IN Document ID' @return True if the document was checked in successfully else False' @version 1.0' @dependencies' @example' @remarks' @alinkjoin' @group'---------------+---------------+---------------+---------------+---------------+------''Public Function CheckIn() As Long CheckIn = 0 If IsCheckOut Then CheckIn = aaApi_CheckInDocument(lngProjID, lngDocID) End If blnIsCheckOut = FalseEnd Function'*---------------------------------------------------------------------------------**''**' @description Retrieves the documents attributes and add them to the collection' @param' @return' @version 1.0' @dependencies' @example' @remarks' @alinkjoin' @group'---------------+---------------+---------------+---------------+---------------+------''Private Function PopulateAttributes() If aaApi_SelectEnvByProjectId(lngProjID) > 0 Then Dim lngEnvID As Long Dim lngTabNo As Long Dim count As Long Dim attributeDataBuffer As Long lngEnvID = aaApi_GetEnvId(0) lngTabNo = aaApi_GetEnvNumericProperty(ENV_PROP_TABLEID, 0) attributeDataBuffer = aaApi_SelectLinkDataDataBuffer(lngTabNo, AADMSLDT_DOCUMENT, lngProjID, lngDocID, vbNullChar, 0, 0, 0) If attributeDataBuffer <> 0 Then Dim i As Long count = aaApi_GetLinkDataDataBufferColumnCount(attributeDataBuffer) lngAttibuteCount = count For i = 0 To count - 1 Dim docAtt As clsAttribute Set docAtt = New clsAttribute docAtt.ColumName = VBStringFromPtrW(aaApi_DmsDataBufferGetStringProperty(attributeDataBuffer, LINKDATA_PROP_COLUMN_NAME, i)) docAtt.RowValue = VBStringFromPtrW(aaApi_GetLinkDataDataBufferColumnValue(attributeDataBuffer, 0, i)) Attributes.Add docAtt Next aaApi_DmsDataBufferFree attributeDataBuffer End If End IfEnd Function'*---------------------------------------------------------------------------------**''**' @description Checks out the document with the provided ProjectID and DocumentID' @param lngProjectID IN Project ID of the document' @param lngDocumentID IN Document ID' @return Nothing' @version 1.0' @dependencies' @example' @remarks' @alinkjoin' @group'---------------+---------------+---------------+---------------+---------------+------''Public Function CheckOut() As LongDim status As LongDim strName As StringDim strSize As LongDim strWorkingDir As StringstrWorkingDir = "d:\data\PWStuff\"strSize = 512 CheckOut = aaApi_CheckOutDocument(lngProjID, lngDocID, StrPtr(strWorkingDir), strFullDocumentName, MAX_STRINGLEN) If CheckOut = 1 Then lngProjID = lngProjID lngDocID = lngDocID blnIsCheckOut = True ' status = aaApi_GetDocumentCheckedOutFileName(lngProjID, lngDocID, StrPtr(strName), strSize)' If status = 0 Then' 'strCheckedOutName = VBStringFromPtrW()' End If End If End Function'*---------------------------------------------------------------------------------**''**' @description Initialize the document object.' @param' @return Returns 1 if the document was selected successfully.' @version 1.0' @dependencies' @example' @remarks' @alinkjoin' @group'---------------+---------------+---------------+---------------+---------------+------''Public Function Initialize(lngProjectID As Long, lngDocumentID As Long) As Long lngProjID = lngProjectID lngDocID = lngDocumentID blnIsCheckOut = True aaApi_SelectDocument lngProjectID, lngDocumentID strDocumentName = VBStringFromPtrW(aaApi_GetDocumentStringProperty(DOC_PROP_FILENAME, 0)) aaApi_GetDocumentFileName lngProjectID, lngDocumentID, strFullDocumentName, MAX_STRINGLEN PopulateAttributesEnd Function'*---------------------------------------------------------------------------------**''**' @description Copy out the document with the provided ProjectID and DocumentID.' @param' @return Returns 1 if the document was copied out successfully.' @version 1.0' @dependencies' @example' @remarks' @alinkjoin' @group'---------------+---------------+---------------+---------------+---------------+------''Public Function CopyOut() As Long CopyOut = aaApi_CopyOutDocument(lngProjID, lngProjID, "d:\data\pwstuff\", strDocumentName, MAX_STRINGLEN) If CopyOut = 1 Then lngProjID = lngProjectID lngDocID = lngDocumentID blnIsCheckOut = True PopulateAttributes End IfEnd FunctionPrivate Sub Class_Initialize() strDocumentName = Space$(MAX_STRINGLEN) strFullDocumentName = Space$(MAX_STRINGLEN) Set Attributes = New Collection End SubPrivate Sub Class_Terminate() Set Attributes = Nothing End SubThe main objects are supported by two helper modules that wrap functions for common and future use. First is the Utility module that contains some calls to get error reporting and process string data passed from VBA to MDL (or the ProjectWise API). Also included are calls to MDL functions that are used to work with MicroStation. The next module is the aaApi module, which contains definitions for all the ProjectWise API functions that are used in the Objects. This is done to allow the expansion of the ProjectWise API exposed without having to rebuild the Objects. These modules can also be referenced from other VBA projects, allowing for reuse of the code.
'---------------------------------------------------------------------------------------+'' Copyright: (c) 2006 Bentley Systems, Incorporated. All rights reserved.''---------------------------------------------------------------------------------------+'---------------------------------------------------------------------------------------+' Module: clsPWDocument.cls'' This class contains information about a document from ProjectWise''---------------------------------------------------------------------------------------+Option Explicit'---------------------------------------------------------------------------------------+'' Private Members''---------------------------------------------------------------------------------------+'Document InformationPrivate blnIsCheckOut As BooleanPrivate lngDocID As LongPrivate lngProjID As LongPrivate strDocumentName As StringPrivate strFullDocumentName As StringPrivate strCheckedOutName As StringPrivate lngDocItemType As LongPrivate lngSetID As LongPrivate lngAttibuteCount As LongPrivate strPathToCheckedOutFile As StringPrivate strGUID As String'---------------------------------------------------------------------------------------+'' Public Property''---------------------------------------------------------------------------------------+Public Attributes As CollectionPublic Property Get FullFileName() As String FullFileName = strFullDocumentNameEnd PropertyPublic Property Let FullFileName(name As String) FullFileName = nameEnd Property'DatasourcePublic Property Get DocumentID() As Long DocumentID = lngDocIDEnd PropertyPublic Property Let DocumentID(id As Long) lngDocID = idEnd PropertyPublic Property Get ProjectID() As Long ProjectID = lngProjIDEnd PropertyPublic Property Let ProjectID(id As Long) lngProjID = idEnd PropertyPublic Property Get name() As String name = strDocumentNameEnd PropertyPublic Property Let name(strName As String) strDocumentName = strNameEnd PropertyPublic Property Let DocType(DocType As Long)lngDocItemType = DocTypeEnd PropertyPublic Property Get DocType() As Long DocType = lngDocItemTypeEnd PropertyPublic Property Get CheckedOutName() As String CheckedOutName = strCheckedOutNameEnd PropertyPublic Property Get IsCheckOut() As Boolean IsCheckOut = blnIsCheckOutEnd PropertyPublic Property Get AttributeCount() As Long AttributeCount = lngAttibuteCountEnd Property'*---------------------------------------------------------------------------------**''**' @description Checks in the document with the provided ProjectID and DocumentID' @param lngProjectID IN Project ID of the document' @param lngDocumentID IN Document ID' @return True if the document was checked in successfully else False' @version 1.0' @dependencies' @example' @remarks' @alinkjoin' @group'---------------+---------------+---------------+---------------+---------------+------''Public Function CheckIn() As Long CheckIn = 0 If IsCheckOut Then CheckIn = aaApi_CheckInDocument(lngProjID, lngDocID) End If blnIsCheckOut = FalseEnd Function'*---------------------------------------------------------------------------------**''**' @description Retrieves the documents attributes and add them to the collection' @param' @return' @version 1.0' @dependencies' @example' @remarks' @alinkjoin' @group'---------------+---------------+---------------+---------------+---------------+------''Private Function PopulateAttributes() If aaApi_SelectEnvByProjectId(lngProjID) > 0 Then Dim lngEnvID As Long Dim lngTabNo As Long Dim count As Long Dim attributeDataBuffer As Long lngEnvID = aaApi_GetEnvId(0) lngTabNo = aaApi_GetEnvNumericProperty(ENV_PROP_TABLEID, 0) attributeDataBuffer = aaApi_SelectLinkDataDataBuffer(lngTabNo, AADMSLDT_DOCUMENT, lngProjID, lngDocID, vbNullChar, 0, 0, 0) If attributeDataBuffer <> 0 Then Dim i As Long count = aaApi_GetLinkDataDataBufferColumnCount(attributeDataBuffer) lngAttibuteCount = count For i = 0 To count - 1 Dim docAtt As clsAttribute Set docAtt = New clsAttribute docAtt.ColumName = VBStringFromPtrW(aaApi_DmsDataBufferGetStringProperty(attributeDataBuffer, LINKDATA_PROP_COLUMN_NAME, i)) docAtt.RowValue = VBStringFromPtrW(aaApi_GetLinkDataDataBufferColumnValue(attributeDataBuffer, 0, i)) Attributes.Add docAtt Next aaApi_DmsDataBufferFree attributeDataBuffer End If End IfEnd Function'*---------------------------------------------------------------------------------**''**' @description Checks out the document with the provided ProjectID and DocumentID' @param lngProjectID IN Project ID of the document' @param lngDocumentID IN Document ID' @return Nothing' @version 1.0' @dependencies' @example' @remarks' @alinkjoin' @group'---------------+---------------+---------------+---------------+---------------+------''Public Function CheckOut() As LongDim status As LongDim strName As StringDim strSize As LongDim strWorkingDir As StringstrWorkingDir = "d:\data\PWStuff\"strSize = 512 CheckOut = aaApi_CheckOutDocument(lngProjID, lngDocID, StrPtr(strWorkingDir), strFullDocumentName, MAX_STRINGLEN) If CheckOut = 1 Then lngProjID = lngProjID lngDocID = lngDocID blnIsCheckOut = True ' status = aaApi_GetDocumentCheckedOutFileName(lngProjID, lngDocID, StrPtr(strName), strSize)' If status = 0 Then' 'strCheckedOutName = VBStringFromPtrW()' End If End If End Function'*---------------------------------------------------------------------------------**''**' @description Initialize the document object.' @param' @return Returns 1 if the document was selected successfully.' @version 1.0' @dependencies' @example' @remarks' @alinkjoin' @group'---------------+---------------+---------------+---------------+---------------+------''Public Function Initialize(lngProjectID As Long, lngDocumentID As Long) As Long lngProjID = lngProjectID lngDocID = lngDocumentID blnIsCheckOut = True aaApi_SelectDocument lngProjectID, lngDocumentID strDocumentName = VBStringFromPtrW(aaApi_GetDocumentStringProperty(DOC_PROP_FILENAME, 0)) aaApi_GetDocumentFileName lngProjectID, lngDocumentID, strFullDocumentName, MAX_STRINGLEN PopulateAttributesEnd Function'*---------------------------------------------------------------------------------**''**' @description Copy out the document with the provided ProjectID and DocumentID.' @param' @return Returns 1 if the document was copied out successfully.' @version 1.0' @dependencies' @example' @remarks' @alinkjoin' @group'---------------+---------------+---------------+---------------+---------------+------''Public Function CopyOut() As Long CopyOut = aaApi_CopyOutDocument(lngProjID, lngProjID, "d:\data\pwstuff\", strDocumentName, MAX_STRINGLEN) If CopyOut = 1 Then lngProjID = lngProjectID lngDocID = lngDocumentID blnIsCheckOut = True PopulateAttributes End IfEnd FunctionPrivate Sub Class_Initialize() strDocumentName = Space$(MAX_STRINGLEN) strFullDocumentName = Space$(MAX_STRINGLEN) Set Attributes = New Collection End SubPrivate Sub Class_Terminate() Set Attributes = Nothing End Sub
To start, create an instance of the datasource object, which in its initialization initializes the ProjectWise API. Next, we need to be able to explore the datasource hierarchy, which is made up of Projects and Documents. The datasource allows us to build the collection of Projects, each of which having a collection of Documents. The Document object has the properties and methods necessary for working with the document in the ProjectWise context.
In the sample application, we build the objects and then process the datasource to find each design file, subsequently allowing the application to open each one and process the file. This application uses the non-interactive login, which means that we have to hardcode the login information directly into the application. First, the code creates the clsPWConnection object and after we have a connection, the application then can login. The project and document collections are created when the login is complete and finally, the sample application iterates through the collection of projects. Within each project, it iterates through the documents.
'---------------------------------------------------------------------------------------+'' Copyright: (c) 2006 Bentley Systems, Incorporated. All rights reserved.''---------------------------------------------------------------------------------------+'---------------------------------------------------------------------------------------+' Module: BDNzineExample' Status:' Date:' Author:' Version: 1.0'' This module demonstrates a simple connection to ProjectWise''---------------------------------------------------------------------------------------+Option ExplicitSub BDNzineCheckOutAndProcessFiles()Dim oPW As clsPWDataSourceDim oDocItem As clsPWDocumentDim lngProjectID As LongDim lngDocumentID As LongDim oProject As clsPWProjectDim oDocument As clsPWDocumentDim extString As StringDim lStatus As LongDim oview As ViewDim oDesignFile As DesignFileDim pOriginalDGNFileName As String'Save off the original file name to allow reopening the file at the end of the process.pOriginalDGNFileName = ActiveDesignFile.FullName ' Create an instance of the clsPWDataSource class. Set oPW = New clsPWDataSource oPW.Login AAAPIDB_UNKNOWN, "computername:PWSample", "john.public", "a1b2c3d4" Debug.Print "Datasource : " + oPW.datasource Debug.Print "User Logged in : " + oPW.UserName If oPW.IsloggedIn Then oPW.BuildProjectCollection If Not oPW.Projects Is Nothing Then For Each oProject In oPW.Projects Debug.Print "the project id is " & oProject.ProjectID & " the Project name is " & oProject.ProjectName If Not oProject.DocumentsCollection Is Nothing Then For Each oDocument In oProject.DocumentsCollection Debug.Print "the document id is " & oDocument.DocumentID & " the file name is " & oDocument.name extString = InStrRev(oDocument.name, ".dgn") If extString > 0 Then oDocument.CheckOut Set oDesignFile = OpenDesignFile(StrConv(oDocument.FullFileName, vbFromUnicode), True) For Each oview In oDesignFile.Views If oview.IsOpen Then oview.Fit True End If Next oview oDesignFile.Close oDocument.CheckIn End If Next oDocument End If Next oProject End If Else MsgBox "Error on login " & GetLastErrorMessage & " " & GetLastErrorDetail End If 'You don't need to logout since the destructor for the PWConnection class will do that for you. Set oPW = Nothing 'This is done to leave us in a file, not in a blank MicroStation session. If oPW Is Nothing Then OpenDesignFile pOriginalDGNFileName, False End IfEnd Sub
Lastly, the code above refers to a utility method VBStringFromPtrW that takes in the address of a WideChar Unicode string and returns an ANSI C MultiByte string: The code for the utility function is provided below. Make sure to place your constants and declare statements near the top of an appropriate "utility" source code module so it can be easily be shared among any VBA project needing such a conversion.
'---------------------------------------------------------------------------------------+ ' ' Public constant definitions ' '---------------------------------------------------------------------------------------+ Public Const CP_ACP = 0 Public Declare Function WideCharToMultiByte Lib "kernel32" (ByVal codepage As Long, ByVal dwFlags As Long, lpWideCharStr As Any, ByVal cchWideChar As Long, lpMultiByteStr As Any, ByVal cchMultiByte As Long, ByVal lpDefaultChar As String, ByVal lpUsedDefaultChar As Long) As Long Public Declare Function lstrlenW Lib "kernel32" (lpString As Any) As Long '*---------------------------------------------------------------------------------**''** ' @description Returns the string before first null char encountered (if any) ' from an ANSII string. ' @param ' @return Returns the string ' @version 1.0 ' @dependencies VBIDE, IWshRuntimeLibrary ' @example ' @remarks ' @alinkjoin ' @group ' @bsimethod BSI-DEVSPT 06/04 '---------------+---------------+---------------+---------------+---------------+------'' ' Returns the string before first null char encountered (if any) from an ANSII string. Public Function GetStrFromBufferA(sz As String) As String If InStr(sz, vbNullChar) Then GetStrFromBufferA = Left$(sz, InStr(sz, vbNullChar) - 1) Else ' If sz had no null char, the Left$ function ' above would return a zero length string (""). GetStrFromBufferA = sz End If End Function '*---------------------------------------------------------------------------------**''** ' @description Returns an ANSI string from a pointer to a Unicode string ' @param ' @return Returns an ANSI string from a pointer to a Unicode string ' @version 1.0 ' @dependencies ' @example ' @remarks ' @alinkjoin ' @group ' @bsimethod BSI-DEVSPT 06/04 '---------------+---------------+---------------+---------------+---------------+------'' Public Function VBStringFromPtrW(lpszW As Long) As String Dim sRtn As String sRtn = String$(lstrlenW(ByVal lpszW) * 2, 0) ' 2 bytes/char ' WideCharToMultiByte also returns Unicode string length Call WideCharToMultiByte(CP_ACP, 0, ByVal lpszW, -1, ByVal sRtn, Len(sRtn), 0, 0) VBStringFromPtrW = GetStrFromBufferA(sRtn) End Function