Problem Using the ProjectWise SDK with VBA in Microsoft Access

When I want to connect to PW in Access with aaApi_LoginDlg (0, 0, 0, 0, 0, 0), no Datasource is displayed.

Identical VBA code works perfectly with Excel. it's amazing that this external dll doesn't work the same with Excel and Access.

My IT thinks it's because the SDK doesn't know where the data source server is, but it doesn't have the solution.

Parents
  • Didier,

    This function has been deprecated, but it should still work.

    Take a look at MostOfDavesClasses to see how it is used in C#.

    As for not getting a list of datasources, that's something you can check with ProjectWise Explorer.  If the machine you are running your code on isn't configured to query specific sources for datasources, ProjectWise Explore (and the API functions), won't "see" any datasources (unless UDP is enabled and the ProjectWise server machine and client are on the same network).

  • Hello, thank you
    Touching UDP does not change anything.

    So I tried to search the data sources to choose the user, then log it.

    Call :

    Option Explicit
    
    Public Declare Function aaApi_SelectDatasourcesByServer2 Lib "dmscli.dll" ( _
                                                                        ByVal ulFlags As Long, _
                                                                        ByVal strServerAddr As Long, _
                                                                        ByVal ulType As Long) As Long
    
    Public Declare Function aaApi_GetDatasourceName Lib "dmscli.dll" (ByVal lIndex As Long) As Long
    
    Public Declare Function aaApi_Login Lib "dmscli.dll" (ByVal lDsType As Long, _
                                                        ByVal lpctstrDSource As Long, _
                                                        ByVal lpctstrUser As Long, _
                                                        ByVal lpctstrPassword As Long, _
                                                        ByVal lpctstrSchema As Long _
                                                        ) As Long
    
    Global oDocument As clsPWDocument
    
    'Public Const ServeurPW = "projectwise-ss4.egis.fr" error DNS
    Public Const ServeurPW = "10.129.20.5"
    
    Sub Lancement()
    
    Dim Result As Boolean
    
        Set oDataSource = New clsPWDataSource
        Result = oDataSource.LoginDataSource()
        Stop
    
    End Sub

    And in the class module

    Public Function LoginDataSource() As Boolean
    Dim Nombre As Long
    Dim lOk As Long
    Dim strptrNomServeur As Long
    Dim NomServeur As String
    Dim strptrDataSource As Long
    Dim NomDataSource(1000) As String
    Dim NbDataSource As Long
    Dim NumDataSource As Long
    Dim lpctstrDSource As Long
    Dim lIndex As Long
    
        ' Récupère le nom des DataSources
        NomServeur = ServeurPW ' C'est une constante, donc intégrée au code : StrPtr ne peux pas la trouver
        strptrNomServeur = StrPtr(NomServeur)
        LoginDataSource = True
        Nombre = aaApi_SelectDatasourcesByServer2(0, strptrNomServeur, 0)
        Select Case Nombre
        Case Is = 0
            MsgBox "Pas de DataSource trouvée"
            Stop
            LoginDataSource = False
            Exit Function
        Case Is = -1
            lOk = aaApi_ShowLastErrorMessageBox ' renvoie un strptr sur le message de l'erreur
            Stop
            LoginDataSource = False
            Exit Function
        End Select
    
        NbDataSource = Nombre
        For lIndex = 0 To Nombre - 1
            strptrDataSource = aaApi_GetDatasourceName(lIndex)
            NomDataSource(lIndex + 1) = VBStringFromPtrW(strptrDataSource)
        Next lIndex
    
        ' Ecran de choix
        ' resultat NumDataSource
    
        ' Connect
        lpctstrDSource = StrPtr(NomDataSource(NumDataSource))
        lOk = aaApi_Login(0, lpctstrDSource, 0, 0, 0)
        If lOk = 0 Then
            MsgBox "Erreur login"
            Stop
            LoginDataSource = False
        End If
            
    End Function

    aaApi_SelectDatasourcesByServer2  answer "File not found C:\program Files\Bentley\ProjectWise\bin\dmscli.dll"

    I checked, dmscli is present and contains the called function.

    It looks like dmscli is calling another function that is not found.

    But where it is very strange is that the same code works under excel. How is it possible ?

  • Didier,

    I'm not sure why the file wasn't found assuming that the path is correct, but there is a mismatch on the signature of the function compared to how you declared it.

    The actual signature looks like this:

    You declared the function to have a three signed longs as parameters, which doesn't match the documentation, so perhaps Windows doesn't recognize the entry point and can't "find" the function?

    Here's how you would declare it using C#:

    Now, I'm not an expert in "VBA", so perhaps three longs will work, but since the second long is really a pointer to a "string", your code would have to take that into account so that the ProjectWise API function interprets it as a string, and from what I can tell, it looks like you are doing that with a call to StrPtr.

    I can't really help you with VBA to WIN32 issues as VBA isn't something I have any "real" experience with.  The ProjectWise API works from C, C++, and can be made to work with other languages such as C# if you correctly "map" the API function signatures.  Perhaps someone else can help you with using VBA interacting with unmangaged code.  Sorry I can't help you more on this part.

  • Dan,

    VBA is much simpler than C, it does not intrinsically know the subtleties such as unsigned integer, memory pointer, or even what UNICODE is.

    LONG, ULONG, PLONG, LPWSTR and even BOOLEAN, which occupy four bytes in memory are seen by VBA as Long. In VBA, Null represents absolutely nothing, while the NULL of C is a zero on 4 bytes.

    To process UNICODE, you must call Kernel32 functions, being careful to reserve memory for the aaAapi functions which return strptr (UNICODE occupies ANSI * 2 +1 bytes).

    The kernel of my code, almost 2,000 lines, is in four class modules that call almost 80 aaAapi, and in Excel everything works.

    To write my code, I was largely inspired by what is here: using-the-projectwise-api-in-vba, although this code has a lot of bugs and logic errors.

    I think there is a bug in dmscli (I'm pointing to the 64-bit version), which crashes when called from Access. It's incomprehensible.

  • Hi ,

    To get to the bottom of this issue quickly I think 2 checks are in order to confirm first, then 1 very specific need justified after.

    Two checks

    1. Unless COM is used and called from EXE to EXE (or having a system driver), bitness of DLLs is required to match by Microsoft calling and comparability conventions.  Can you verify both Access and ProjectWise DLLs being references are definitely both 64-bit dlls?  An easy way to do this is to open each application and confirm next to the Application Name "(32 bit)" being present or not.  Otherwise use Visual Studio's dumpbin tool like this to confirm each DLL's bitness. e.g. dumpbin /all BMakedll.dll | findstr -c:"word machine" 
    2. Microsoft Office applications can have different VBA permissions.  Can you confirm both Access and Excel are configured accordingly? See: Enable or Disable macros in Office files.

    One need

    If the above cannot help resolve the issue(s), it is recommended to reduce code and data to the minimum and zip provide a "test case" for review/proof (w/o guessing - portable and hopefully reproducible).

    Although not our domain and support expertise, we do provide these Microsoft support topics/articles that may also provide more insights to help resolve the issue(s): Debugging VBA and Troubleshooting.

    HTH,
    Bob



  • Office is fine in 32 bits. Excel and Access have the necessary permissions, the problem is not there.

    I attach an Excel file and an access file, stripped down, comprising exactly the same code

    You will see for yourself that aaAPI works in Excel and not in Access.

    You may need to go to options / security to allow macros.

    Test login with Excel ans Access.zip

    Thanks for your help.

  • Here is the full code:

    Option Explicit
    
    ' Kernel *************************************************************
    
    Public Declare Function lstrlenW Lib "kernel32" (lpString As Any) As Long
    
    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
    
    ' Standart login ***************************************************************
    
    Public Declare Function aaApi_GetActiveDatasource Lib "dmscli.dll" () As Long
    
    Public Declare Function aaApi_LoginDlg Lib "dmawin.dll" (ByVal lDsType As Long, _
                                                            ByRef dsName As Long, _
                                                            ByVal lDSLength As Long, _
                                                            ByVal user As Long, _
                                                            ByVal pwd As Long, _
                                                            ByVal Schema As Long) As Long
    
    Public Declare Function aaApi_ShowLastErrorMessageBox Lib "DMACTRL.dll" () As Long
    
    ' Alternative login ***************************************************************
    
    Public Declare Function aaApi_SelectDatasourcesByServer2 Lib "dmscli.dll" ( _
                                                                        ByVal ulFlags As Long, _
                                                                        ByVal strServerAddr As Long, _
                                                                        ByVal ulType As Long) As Long
    
    Public Declare Function aaApi_GetDatasourceName Lib "dmscli.dll" (ByVal lIndex As Long) As Long
    
    Public Declare Function aaApi_Login Lib "dmscli.dll" (ByVal lDsType As Long, _
                                                        ByVal lpctstrDSource As Long, _
                                                        ByVal lpctstrUser As Long, _
                                                        ByVal lpctstrPassword As Long, _
                                                        ByVal lpctstrSchema As Long _
                                                        ) As Long
    
    ' Project to check ********************************************************************
    
    Public Declare Function aaApi_SelectProjectDlg Lib "dmawin.dll" (ByVal hWndParent As Long, _
                                                                     ByVal lpctstrTitle As Long, _
                                                                     ByVal lProjectId As Long _
                                                                     ) As Long
    
    Public Declare Function aaApi_SelectProject Lib "dmscli.dll" (ByVal lProjectId As Long) As Long
    
    Public Declare Function aaApi_GetProjectStringProperty Lib "dmscli.dll" ( _
                                                                ByVal lPropertyId As Long, _
                                                                ByVal lIndex As Long _
                                                                ) As Long
    
    ' Divers ***********************************************************************************
    
    Public Const PROJ_PROP_NAME As Long = 12  ' String property.
    
    ' Retour de boite de dialogue
    Public Const DLG_OK As Long = 1 ' Tout c'est bien passé
    Public Const DLG_CANCEL As Long = 2 ' L'action a été annulée par l'utilisateur.
    Public Const DLG_ABORT As Long = 3 ' Ca s'est planté
    
    Public Const ID_OK As Long = 1 ' Tout c'est bien passé (n'est pas toujours en retour)
    Public Const ID_NONE As Long = 0 ' L'objet demandé n'existe pas
    Public Const ID_ABORT As Long = -1 ' Ca s'est planté (n'est pas toujours en retour
    
    Public Const CP_ACP = 0
    Public Const MAX_STRINGLEN As Long = 1024 ' Au pif, pas trouvé dans la doc
    
    
    'Public Const ServeurPW = "projectwise-ss4.egis.fr" d'ont work, error DNS
    Public Const ServeurPW = "10.129.20.5" ' Internal Egis
    
    ' ****************************************************************************
    
    ' Pour l'écran de choix
    Global strDataSourceName2(20) As String
    Global strDataBaseDesigned As String
    
    ' **************************************************************************
    
    Sub ClassicalLogin()
    ' Standart method
    
    Dim lngPointeurDataSource As Long
    Dim lOk As Long
    Dim strLen As Long
    Dim ptrDataSourceName As Long
    Dim strDataSourceName As String
    
    Dim strTitre As String
    Dim ptrTitre As Long
    Dim lProjectId As Long
    Dim strProjectName As String
    Dim ptrProjectName As Long
    
        Stop ' Here is the code entry point
             ' Press F8 to advance step by step
             ' Press F5 to execute the code directly
    '<-- To the right of any instruction, click in the vertical bar here to set a breakpoint
    '    (display of a red circle)
    
        lngPointeurDataSource = aaApi_GetActiveDatasource()
        If lngPointeurDataSource <> 0 Then
            ' If you're still connected, don't ask again
        Else
            lOk = aaApi_LoginDlg(0, 0, 0, 0, 0, 0) ' Default datasource
            Select Case lOk
            Case Is = DLG_OK
                ' On est toujours connecté
            Case Is = DLG_ABORT
                lOk = aaApi_ShowLastErrorMessageBox
                MsgBox "Echec login"
                Stop
                End
            Case Is = DLG_CANCEL
                MsgBox "Cancel login"
                Stop
                End
            Case Else
                Stop
                End
            End Select
        End If
    
        strTitre = "Designate a directory"
        ptrTitre = StrPtr(strTitre)
        lProjectId = 0 ' Default
        lOk = aaApi_SelectProjectDlg(0, ptrTitre, lProjectId)
        Select Case lOk
        Case Is > 0
            lProjectId = lOk
        Case Is = ID_ABORT
            lOk = aaApi_ShowLastErrorMessageBox
            Stop
            End
        Case Else
            MsgBox "Echec du répertoire"
            Stop
            End
        End Select
    
        ' Put the project in the static buffer
        lOk = aaApi_SelectProject(lProjectId)
        Select Case lOk
        Case Is = ID_OK
        Case Is = ID_ABORT
            lOk = aaApi_ShowLastErrorMessageBox
            Stop
            End
        Case Is = ID_NONE
            MsgBox "No project sélected"
            Stop
            End
        Case Else
            Stop
            End
        End Select
    
        ' Get the pointer to the UNICODE name of the directory
        ptrProjectName = aaApi_GetProjectStringProperty(PROJ_PROP_NAME, 0)
        ' Get the ANSI string which is there
        strProjectName = VBStringFromPtrW(ptrProjectName)
        
        MsgBox "Project number : " & lProjectId & vbCrLf & _
               "Project name : " & strProjectName
    
    End Sub
    
    ' *************************************************************************
    
    Sub AltenativeLogin()
    
    Dim Nombre As Long
    Dim lOk As Long
    Dim ptrNomServeur As Long
    Dim strNomServeur As String
    Dim ptrDataSourceName2 As Long
    Dim lIndex As Long
    
        Stop ' Here is the code entry point
             ' Press F8 to advance step by step
             ' Press F5 to execute the code directly
    '<-- To the right of any instruction, click in the vertical bar here to set a breakpoint
    '    (display of a red circle)
    
        strNomServeur = ServeurPW ' It's a constant, so it's built into the code: StrPtr can't find it
        ptrNomServeur = StrPtr(strNomServeur)
        Nombre = aaApi_SelectDatasourcesByServer2(0, ptrNomServeur, 0)
        Select Case Nombre
        Case Is = 0
            MsgBox "Pas de DataSource trouvée"
            Stop
            End
        Case Is = -1
            lOk = aaApi_ShowLastErrorMessageBox
            Stop
            End
        End Select
    
        If Nombre > 21 Then Nombre = 21
    
        For lIndex = 0 To Nombre - 1
            ptrDataSourceName2 = aaApi_GetDatasourceName(lIndex)
            strDataSourceName2(lIndex) = VBStringFromPtrW(ptrDataSourceName2)
        Next lIndex
    
        strDataBaseDesigned = ""
        ChooseDataBase.Show ' Waiting for user
    
    End Sub
        
    Sub ReplyComboBox()
    
    Dim ptrDataBaseDesigned As Long
    Dim lOk As Long
    
    Dim strTitre As String
    Dim ptrTitre As Long
    Dim lProjectId As Long
    Dim strProjectName As String
    Dim ptrProjectName As Long
    
        Stop ' Here is the second code entry point
             ' Press F8 to advance step by step
             ' Press F5 to execute the code directly
    '<-- To the right of any instruction, click in the vertical bar here to set a breakpoint
    '    (display of a red circle)
    
        If strDataBaseDesigned = "" Then
            MsgBox "La DataBase n'a pas été désignée"
            Stop
            End
        End If
    
        ptrDataBaseDesigned = StrPtr(strDataBaseDesigned)
        lOk = aaApi_Login(0, ptrDataBaseDesigned, 0, 0, 0)
        If lOk = ID_NONE Then
            lOk = aaApi_ShowLastErrorMessageBox
            Stop
            End
        End If
    
        strTitre = "Designate a directory"
        ptrTitre = StrPtr(strTitre)
        lProjectId = 0 ' Default
        lOk = aaApi_SelectProjectDlg(0, ptrTitre, lProjectId)
        Select Case lOk
        Case Is > 0
            lProjectId = lOk
        Case Is = ID_ABORT
            lOk = aaApi_ShowLastErrorMessageBox
            Stop
            End
        Case Else
            MsgBox "Echec du répertoire"
            Stop
            End
        End Select
    
        lOk = aaApi_SelectProject(lProjectId)
        Select Case lOk
        Case Is = ID_OK
        Case Is = ID_ABORT
            lOk = aaApi_ShowLastErrorMessageBox
            Stop
            End
        Case Is = ID_NONE
            MsgBox "No project sélected"
            Stop
            End
        Case Else
            Stop
            End
        End Select
    
        ptrProjectName = aaApi_GetProjectStringProperty(PROJ_PROP_NAME, 0)
        strProjectName = VBStringFromPtrW(ptrProjectName)
        
        MsgBox "Project number : " & lProjectId & vbCrLf & _
               "Project name : " & strProjectName
    
    End Sub
    
    
    ' *************************************************************************
    
    Public Function VBStringFromPtrW(ptrstrW As Long) As String
    ' Returns an ANSI string from a ptrstrW pointer to a Unicode string
    
    Dim strRtn As String
    Dim Len_ptrstrW As Long
    
        If ptrstrW = 0 Then
            Stop
            VBStringFromPtrW = ""
            Exit Function
        End If
        
        Len_ptrstrW = lstrlenW(ByVal ptrstrW) ' Longueur de la chaîne associée au pointeur, exprimé en caractères
        strRtn = String$(Len_ptrstrW * 2 + 1, 0) ' On réserve la mémoire pour accueillir le résultat (2 bytes/char)
    
        ' Demande à Kernel32 de faire la conversion et de donner le résultat dans strRtn
        ' WideCharToMultiByte retourne également la longueur de chaîne Unicode
        Call WideCharToMultiByte(CP_ACP, 0, ByVal ptrstrW, -1, ByVal strRtn, Len(strRtn), 0, 0)
    
        If InStr(strRtn, vbNullChar) Then
            ' On ne prends que ce qui est avant le NULL
            VBStringFromPtrW = Left$(strRtn, InStr(strRtn, vbNullChar) - 1)
        Else
            ' Si strRtn n'a pas de caractère null, la fonction Left$ ci-dessus renvoit une
            ' chaîne de longueur nulle ("").
            VBStringFromPtrW = strRtn
        End If
    
    End Function
    
    

    To test Excel and Access, simply designate your ProjectWise server in the PWServer constant

Reply
  • Here is the full code:

    Option Explicit
    
    ' Kernel *************************************************************
    
    Public Declare Function lstrlenW Lib "kernel32" (lpString As Any) As Long
    
    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
    
    ' Standart login ***************************************************************
    
    Public Declare Function aaApi_GetActiveDatasource Lib "dmscli.dll" () As Long
    
    Public Declare Function aaApi_LoginDlg Lib "dmawin.dll" (ByVal lDsType As Long, _
                                                            ByRef dsName As Long, _
                                                            ByVal lDSLength As Long, _
                                                            ByVal user As Long, _
                                                            ByVal pwd As Long, _
                                                            ByVal Schema As Long) As Long
    
    Public Declare Function aaApi_ShowLastErrorMessageBox Lib "DMACTRL.dll" () As Long
    
    ' Alternative login ***************************************************************
    
    Public Declare Function aaApi_SelectDatasourcesByServer2 Lib "dmscli.dll" ( _
                                                                        ByVal ulFlags As Long, _
                                                                        ByVal strServerAddr As Long, _
                                                                        ByVal ulType As Long) As Long
    
    Public Declare Function aaApi_GetDatasourceName Lib "dmscli.dll" (ByVal lIndex As Long) As Long
    
    Public Declare Function aaApi_Login Lib "dmscli.dll" (ByVal lDsType As Long, _
                                                        ByVal lpctstrDSource As Long, _
                                                        ByVal lpctstrUser As Long, _
                                                        ByVal lpctstrPassword As Long, _
                                                        ByVal lpctstrSchema As Long _
                                                        ) As Long
    
    ' Project to check ********************************************************************
    
    Public Declare Function aaApi_SelectProjectDlg Lib "dmawin.dll" (ByVal hWndParent As Long, _
                                                                     ByVal lpctstrTitle As Long, _
                                                                     ByVal lProjectId As Long _
                                                                     ) As Long
    
    Public Declare Function aaApi_SelectProject Lib "dmscli.dll" (ByVal lProjectId As Long) As Long
    
    Public Declare Function aaApi_GetProjectStringProperty Lib "dmscli.dll" ( _
                                                                ByVal lPropertyId As Long, _
                                                                ByVal lIndex As Long _
                                                                ) As Long
    
    ' Divers ***********************************************************************************
    
    Public Const PROJ_PROP_NAME As Long = 12  ' String property.
    
    ' Retour de boite de dialogue
    Public Const DLG_OK As Long = 1 ' Tout c'est bien passé
    Public Const DLG_CANCEL As Long = 2 ' L'action a été annulée par l'utilisateur.
    Public Const DLG_ABORT As Long = 3 ' Ca s'est planté
    
    Public Const ID_OK As Long = 1 ' Tout c'est bien passé (n'est pas toujours en retour)
    Public Const ID_NONE As Long = 0 ' L'objet demandé n'existe pas
    Public Const ID_ABORT As Long = -1 ' Ca s'est planté (n'est pas toujours en retour
    
    Public Const CP_ACP = 0
    Public Const MAX_STRINGLEN As Long = 1024 ' Au pif, pas trouvé dans la doc
    
    
    'Public Const ServeurPW = "projectwise-ss4.egis.fr" d'ont work, error DNS
    Public Const ServeurPW = "10.129.20.5" ' Internal Egis
    
    ' ****************************************************************************
    
    ' Pour l'écran de choix
    Global strDataSourceName2(20) As String
    Global strDataBaseDesigned As String
    
    ' **************************************************************************
    
    Sub ClassicalLogin()
    ' Standart method
    
    Dim lngPointeurDataSource As Long
    Dim lOk As Long
    Dim strLen As Long
    Dim ptrDataSourceName As Long
    Dim strDataSourceName As String
    
    Dim strTitre As String
    Dim ptrTitre As Long
    Dim lProjectId As Long
    Dim strProjectName As String
    Dim ptrProjectName As Long
    
        Stop ' Here is the code entry point
             ' Press F8 to advance step by step
             ' Press F5 to execute the code directly
    '<-- To the right of any instruction, click in the vertical bar here to set a breakpoint
    '    (display of a red circle)
    
        lngPointeurDataSource = aaApi_GetActiveDatasource()
        If lngPointeurDataSource <> 0 Then
            ' If you're still connected, don't ask again
        Else
            lOk = aaApi_LoginDlg(0, 0, 0, 0, 0, 0) ' Default datasource
            Select Case lOk
            Case Is = DLG_OK
                ' On est toujours connecté
            Case Is = DLG_ABORT
                lOk = aaApi_ShowLastErrorMessageBox
                MsgBox "Echec login"
                Stop
                End
            Case Is = DLG_CANCEL
                MsgBox "Cancel login"
                Stop
                End
            Case Else
                Stop
                End
            End Select
        End If
    
        strTitre = "Designate a directory"
        ptrTitre = StrPtr(strTitre)
        lProjectId = 0 ' Default
        lOk = aaApi_SelectProjectDlg(0, ptrTitre, lProjectId)
        Select Case lOk
        Case Is > 0
            lProjectId = lOk
        Case Is = ID_ABORT
            lOk = aaApi_ShowLastErrorMessageBox
            Stop
            End
        Case Else
            MsgBox "Echec du répertoire"
            Stop
            End
        End Select
    
        ' Put the project in the static buffer
        lOk = aaApi_SelectProject(lProjectId)
        Select Case lOk
        Case Is = ID_OK
        Case Is = ID_ABORT
            lOk = aaApi_ShowLastErrorMessageBox
            Stop
            End
        Case Is = ID_NONE
            MsgBox "No project sélected"
            Stop
            End
        Case Else
            Stop
            End
        End Select
    
        ' Get the pointer to the UNICODE name of the directory
        ptrProjectName = aaApi_GetProjectStringProperty(PROJ_PROP_NAME, 0)
        ' Get the ANSI string which is there
        strProjectName = VBStringFromPtrW(ptrProjectName)
        
        MsgBox "Project number : " & lProjectId & vbCrLf & _
               "Project name : " & strProjectName
    
    End Sub
    
    ' *************************************************************************
    
    Sub AltenativeLogin()
    
    Dim Nombre As Long
    Dim lOk As Long
    Dim ptrNomServeur As Long
    Dim strNomServeur As String
    Dim ptrDataSourceName2 As Long
    Dim lIndex As Long
    
        Stop ' Here is the code entry point
             ' Press F8 to advance step by step
             ' Press F5 to execute the code directly
    '<-- To the right of any instruction, click in the vertical bar here to set a breakpoint
    '    (display of a red circle)
    
        strNomServeur = ServeurPW ' It's a constant, so it's built into the code: StrPtr can't find it
        ptrNomServeur = StrPtr(strNomServeur)
        Nombre = aaApi_SelectDatasourcesByServer2(0, ptrNomServeur, 0)
        Select Case Nombre
        Case Is = 0
            MsgBox "Pas de DataSource trouvée"
            Stop
            End
        Case Is = -1
            lOk = aaApi_ShowLastErrorMessageBox
            Stop
            End
        End Select
    
        If Nombre > 21 Then Nombre = 21
    
        For lIndex = 0 To Nombre - 1
            ptrDataSourceName2 = aaApi_GetDatasourceName(lIndex)
            strDataSourceName2(lIndex) = VBStringFromPtrW(ptrDataSourceName2)
        Next lIndex
    
        strDataBaseDesigned = ""
        ChooseDataBase.Show ' Waiting for user
    
    End Sub
        
    Sub ReplyComboBox()
    
    Dim ptrDataBaseDesigned As Long
    Dim lOk As Long
    
    Dim strTitre As String
    Dim ptrTitre As Long
    Dim lProjectId As Long
    Dim strProjectName As String
    Dim ptrProjectName As Long
    
        Stop ' Here is the second code entry point
             ' Press F8 to advance step by step
             ' Press F5 to execute the code directly
    '<-- To the right of any instruction, click in the vertical bar here to set a breakpoint
    '    (display of a red circle)
    
        If strDataBaseDesigned = "" Then
            MsgBox "La DataBase n'a pas été désignée"
            Stop
            End
        End If
    
        ptrDataBaseDesigned = StrPtr(strDataBaseDesigned)
        lOk = aaApi_Login(0, ptrDataBaseDesigned, 0, 0, 0)
        If lOk = ID_NONE Then
            lOk = aaApi_ShowLastErrorMessageBox
            Stop
            End
        End If
    
        strTitre = "Designate a directory"
        ptrTitre = StrPtr(strTitre)
        lProjectId = 0 ' Default
        lOk = aaApi_SelectProjectDlg(0, ptrTitre, lProjectId)
        Select Case lOk
        Case Is > 0
            lProjectId = lOk
        Case Is = ID_ABORT
            lOk = aaApi_ShowLastErrorMessageBox
            Stop
            End
        Case Else
            MsgBox "Echec du répertoire"
            Stop
            End
        End Select
    
        lOk = aaApi_SelectProject(lProjectId)
        Select Case lOk
        Case Is = ID_OK
        Case Is = ID_ABORT
            lOk = aaApi_ShowLastErrorMessageBox
            Stop
            End
        Case Is = ID_NONE
            MsgBox "No project sélected"
            Stop
            End
        Case Else
            Stop
            End
        End Select
    
        ptrProjectName = aaApi_GetProjectStringProperty(PROJ_PROP_NAME, 0)
        strProjectName = VBStringFromPtrW(ptrProjectName)
        
        MsgBox "Project number : " & lProjectId & vbCrLf & _
               "Project name : " & strProjectName
    
    End Sub
    
    
    ' *************************************************************************
    
    Public Function VBStringFromPtrW(ptrstrW As Long) As String
    ' Returns an ANSI string from a ptrstrW pointer to a Unicode string
    
    Dim strRtn As String
    Dim Len_ptrstrW As Long
    
        If ptrstrW = 0 Then
            Stop
            VBStringFromPtrW = ""
            Exit Function
        End If
        
        Len_ptrstrW = lstrlenW(ByVal ptrstrW) ' Longueur de la chaîne associée au pointeur, exprimé en caractères
        strRtn = String$(Len_ptrstrW * 2 + 1, 0) ' On réserve la mémoire pour accueillir le résultat (2 bytes/char)
    
        ' Demande à Kernel32 de faire la conversion et de donner le résultat dans strRtn
        ' WideCharToMultiByte retourne également la longueur de chaîne Unicode
        Call WideCharToMultiByte(CP_ACP, 0, ByVal ptrstrW, -1, ByVal strRtn, Len(strRtn), 0, 0)
    
        If InStr(strRtn, vbNullChar) Then
            ' On ne prends que ce qui est avant le NULL
            VBStringFromPtrW = Left$(strRtn, InStr(strRtn, vbNullChar) - 1)
        Else
            ' Si strRtn n'a pas de caractère null, la fonction Left$ ci-dessus renvoit une
            ' chaîne de longueur nulle ("").
            VBStringFromPtrW = strRtn
        End If
    
    End Function
    
    

    To test Excel and Access, simply designate your ProjectWise server in the PWServer constant

Children
No Data