How do I select multiple files from ProjectWise?

I am trying to get a list of files to process on from the user but I have not been able to figure out how to do this.  I can get one file fine via the mdlDialog_fileOpen inside the stdmdlbltin.dll, but as far as I can tell, there is no way to allow the user to select multiple files.

What I'm looking for is the dialog you get when you try to attach a reference to a file.  It has a single "tab" at the top that says Select.  Inside there, you can select multiple documents by hitting control or shift.  Or alternatively, hitting the Add button, which adds to the bottom panel.

I've tried using the mdlFileList_Edit, but that appears to allow me to open a folder, which is not what I'm looking for.

My backup plan is to use the batch processor, but I'd prefer not to do that.

Any help would be greatly appreciated.

Thanks,

Parents
  • Essential Information

    Please follow the Forum guidelines.

    • What version (e.g. v10.x.y.z) of MicroStation are you using?  Include that information when you start a new post on any Forum.
    • What programming language (C++, C#, VBA) are you using? Include that information when you start a new post on a Programming Forum.

    ProjectWise Overview

    ProjectWise is a Document Management System (DMS).  It uses an Oracle database (DB) to manage projects.  Put simply, a project is a list of files.  PW stores the files somewhere, usually on a server.  Unless you're a PW administrator, you don't know where those files are stored, and don't need to know.  When a user requests a file from PW, she's querying that DB. If she has permission and the file is available, PW copies the file to a local folder so she can work on it.  The files on the PW server folder are protected, secure and probably not even visible to normal users, which is why I ask the question below.

    PW handles any type of file, not just DGN files.  It has a list of the app required to open each file type (e.g. MicroStation opens DGN files, Word opens .docx files, etc).

    Programming ProjectWise

    I am trying to get a list of files from ProjectWise (PW). I can get one file fine via the mdlDialog_fileOpen

    I don't know that mdlDialog_fileOpen is the right function to open a PW file. How does that work?

    The best way to interact with PW as a user is by installing PW Explorer, these days called PW Design Integration.  The best way to interact with PW as a developer is to install the PW Design Integration SDK.

    There's a dedicated ProjectWise Programming Forum.

     
    Regards, Jon Summers
    LA Solutions

  • Jon,

        [CONNECT Update 14 VBA]   MSCE version 10.14.00.19

    So the User will have the PW Explorer installed.  

    When I call the mdlDialog_fileOpen, it is like the user opening a file and getting the PW interface (not the local).  It initializes the open file dialog, the user navigates to the file they need, select and open it.  Unfortunately, it appears to only work on one file.

    I am technically an Admin in PW, but I have others managing that, so I don't fully understand how it all works.  Thanks for the explanation.  So much to learn...

    This project was supposed to be pretty basic, hence using VBA, so I don't know that I want to go through the PW SDK.

    I also checked on the PW programming forum, but couldn't find much.  I believe this is more a MicroStation issue, and I happen to be using PW.

    So, after poking around more, it looks like the mdlFileList_edit command is the one i'm looking for!  I found another post that detailed how to send the attributes in correctly.  Turns out it defaults to folder mode if you don't pass the attributes in correctly.  Here's where i'm at so far:

    Declare PtrSafe Function mdlFileList_edit Lib "stdmdlbltin.dll" ( _
    ByRef lastInfoP As FileListInfo, _
    ByRef StringListP As String, _
    ByVal attributes As Long, _
    ByVal dialogTitle As String, _
    ByVal listLabel As String, _
    ByVal fileFilter As String, _
    ByVal defaultDirectory As String) As Long
    
    Type FileListInfo
        lastAction As Long
        lastDirectory As String
        lastFilter As String
    End Type
    
    Sub MultipleFiles()
    
    Const FILELISTATTR_SORT = &H1
    Const FILELISTATTR_MULTIPLE = &H8
    Const FILELISTATTR_FILES = &H100
    
    Dim sList As String
    Dim info As FileListInfo
    Dim attributes As Long
    Dim retVal As Long
    
    attributes = FILELISTATTR_FILES + FILELISTATTR_SORT + FILELISTATTR_MULTIPLE
    
    'This opens the select dialog file box.  I can select multiple files from PW and hit OK and it doesn't crash.
    retVal = mdlFileList_edit(info, sList, attributes, "This is the title", "This is the list label", "*.dgn", "")
    
    'Need to figure out how to get the information out and do stuff with it.
    
    end sub

    So if you look at the definition of mdlFileList_edit, it uses a structure called StringListP.  I cannot find a way to use this structure, and I believe it's my problem.  The function 'returns' a StringListP.  I put return in quotes, because I'm not sure it actually returns anything or if it tries to write it directly to the first passed variable "info" (it lists "info" as [out]).  I cannot get anything out of "info".

    I tried setting the function declaration to return anything else (tried String, Object, 'nothing', etc...) but they all cause MSCE to crash with no error handling.  If I set the function as Long, it 'works' but, I get nothing usable out of it.  Or nothing I currently know how to use.

    StringListP mdlFileList_edit ( FileListInfo lastInfoP,
    StringListP  stringListP,
    long  attributes,
    WCharCP  dialogTitle,
    WCharCP  listLabel,
    WCharCP  fileFilter,
    WCharCP  defaultDirectory 
    )

    Thanks.

  • When I call the mdlDialog_fileOpen, it is like the user opening a file and getting the PW interface

    When PW Explorer is installed, it adds an app mcm to MicroStation's app folder (..\MicroStation\mdlapps).  That app is automatically loaded when you start MicroStation.  Amongst other things, it hijacks MicroStation's user interface.

    mdlDialog_fileOpen is intended for the user to open a single DGN file.

    mdlFileList_edit uses a structure called StringListP.  I cannot find a way to use this structure

    A StringList dates from the earliest days of MDL, when VBA wasn't even  a glint in Microsoft's eye.  It uses dynamic memory allocation both for the list it manages and the strings contained in that list.  VBA is bad at dynamic memory and doesn't understand C++ pointers.  It would not be easy to attempt to use a StringList from VBA.

    You get a MicroStation crash because you must deallocate memory used by the StringList.  VBA has no way to deallocate memory.

    PW lacks a VBA API.

    You can write PW Explorer code using C++ or C#.  Visit the PW Programming Forum I mentioned above.

     
    Regards, Jon Summers
    LA Solutions

  • I agree, the mdlDialog_fileOpen is not the way to go.

    So after replying, I found a post from you on this a few years ago:

    https://communities.bentley.com/products/programming/microstation_programming/f/microstation-programming---forum/125209/v8i-vba-mdl-is-it-possible-to-use-mdlstringlist_getmember-with-vba

    Which you implemented in an example working with LineStyles:

    http://www.la-solutions.co.uk/content/V8/MVBA/MVBA-LineStyles.htm

    When trying to implement the code from the post or your article, I keep getting errors where it states that it can't find the function call in the MDL.

    "Can't find DLL entry point mdlStringList_getMember in stdmdlbltin.dll"

    I also get this error for mdlDialog_fileOpenExt.  I mention this because both mdlDialog_fileOpen and mdlDialog_fileOpenExt say they require the mdlbltin.lib.  One works but the other doesn't?

    I don't understand how stdmdlbltin.dll relates to mdlbltin.lib.

    StringList states that it requires "RmgrTools<ApiNumber>.lib i.e. RmgrTools3.lib"  I found the lib, but I don't know how to load a lib.

    I feel like I'm really close and if I can figure out why it can't find the DLL entry point, I might be able to get something working...

    Thanks again for taking the time to help on this.  I really appreciate this.  I have a basic understanding of C++ but languages like C and Objective C escape me...  I've gotten used to managed code.

  • I found a post from you on this

    I told you it wasn't easy!

    When trying to implement the code from the post or your article, I keep getting errors where it states that it can't find the function call

    Here's an updated version of that article about StringLists.  Note each function declaration where I've changed Long to LongPtr to match 64-bit VBA.

    StringList states that it requires "RmgrTools<ApiNumber>.lib i.e. RmgrTools3.lib"  I found the lib, but I don't know how to load a lib.

    You don't have to load a library.  Once you have the correct function declaration in VBA, the VBA run-time finds the library for you.

    I don't understand how stdmdlbltin.dll relates to mdlbltin.lib

    The CONNECT SDK delivers mdlbltin.lib.  The V8 SDK delivers stdmdlbltin.lib.

    I've gotten used to managed code

    The MicroStation CONNECT SDK delivers a first-class .NET API.  The PW SDK is C++, but MostOfDavesClasses.cs provides wrappers around the C functions.

     
    Regards, Jon Summers
    LA Solutions

  • I tried this one quick and noticed two things:

    1) the Download link to get the mvba is broken on your site.

    2) I copy and pasted the code from the example you posted, but it cannot find the dll file.  I searched through the folder that contained the stdmdlbltin.dll and mdlbltin.dll is not there.  I was able to find the mdlbltin.lib, but that does not help. I was looking through the SDK information to see if there was a way to create the dll from the lib but haven't seen anything yet.

    I'll search around tomorrow morning, any idea why the mdlbltin.dll isn't in the same folder?  Or where it is?

    I'll dig in to this one tomorrow morning.

  • I'm not Jon, and I can't help overall, but I can answer one of your questions.

    stdmdlbltin is part of the V8i SDK

    mdlbltin is part of the CONNECT SDK

    They are not the same because they are developed for different MicroStation versions. They are similar in that they are the same TYPE of file for their respective versions, but they are not directly related. You will use one or the other, depending on which MicroStation version your are writing for

    MaryB

    Power GeoPak 08.11.09.918
    Power InRoads 08.11.09.918
    OpenRoads Designer 2021 R2

        

  • the Download link to get the mvba is broken on your site

    I haven't had time to rewrite the VBA for CONNECT.  Download the V8 version and modify it.

    I searched through the folder that contained the stdmdlbltin.dll and mdlbltin.dll is not there

    Read the responses to your questions.  Both  and I have informed you about stdmdlbltin.lib and mdlbltin.lib.  The library (*.lib) files are delivered with the MicroStation SDK for the use of native code (C++) developers.  They are of no use with any other language.

    I can see stdmdlbltin.dll in the CONNECT ..\MicroStation folder.  I mistakenly changed the DLL name in the function declarations, which I've corrected.

    I was looking through the SDK information to see if there was a way to create the dll from the lib but haven't seen anything

    When Bentley Systems build MicroStation, the DLLs in the ..\MicroStation folder are created from those *.lib files.

     
    Regards, Jon Summers
    LA Solutions

  • Jon / MaryB,

        I apologize for my ignorance and thank you for your patience!

    Maybe I wasn't clear enough, but when I could not download the mvba, I tried editing the code manually.

    Declare PtrSafe Function mdlStringList_getMember Lib "stdmdlbltin.dll" ( _
            ByRef pString As LongPtr, _
            ByRef pInfo As LongPtr, _
            ByVal list As LongPtr, _
            ByVal n As Long) As Long

    The only difference from your code and mine for the function call is the PtrSafe, which VBA yells at me about.  Throws a Compile error saying that the code must be updated for 64-bit systems.

    When I run this, I get the error that it cannot find it:

    "Can't find DLL entry point mdlStringList_getMember in stdmdlbltin.dll"

    This is why I thought I was missing the mdlbltin.dll, hence the other questions about the .lib files.

    So, why is it saying that this function (and others) are not in the stdmdlbltin?  I have checked the spelling multiple times.

    Declare PtrSafe Function mdlFileList_edit Lib "stdmdlbltin.dll" ( _
        ByRef lastInfoP As FileListInfo, _
        ByRef StringListP As String, _
        ByVal attributes As Long, _
        ByVal dialogTitle As String, _
        ByVal listLabel As String, _
        ByVal fileFilter As String, _
        ByVal defaultDirectory As String) As Long
    
    
    Declare PtrSafe Function mdlStringList_getMember Lib "stdmdlbltin.dll" ( _
            ByRef pString As LongPtr, _
            ByRef pInfo As LongPtr, _
            ByVal list As LongPtr, _
            ByVal n As Long) As Long
            
    Declare PtrSafe Function SysAllocString Lib "oleaut32" (ByVal CharPtr As Long) As String
    
    Function CharPtrToString(CharPtr As LongPtr) As String
        If CharPtr = 0 Then
            CharPtrToString = ""
        Else
            CharPtrToString = SysAllocString(CharPtr)
        End If
    End Function
    
    Sub MultipleFiles()
        Stop
        
        Const FILELISTATTR_SORT = &H1
        Const FILELISTATTR_MULTIPLE = &H8
        Const FILELISTATTR_FILES = &H100
        
        Dim temp As Long
        Dim sList As String
        Dim info As FileListInfo
        Dim attributes As Long
        Dim retVal As Long
        
        Dim i As Long
        Dim j As Long
        Dim l As Long
        Dim s As String
        
        Dim lStringlist As LongPtr
        Dim ppstring As LongPtr
        Dim ppinfofields As LongPtr
    
        attributes = FILELISTATTR_FILES + FILELISTATTR_SORT + FILELISTATTR_MULTIPLE
        
        'So this gives me the dialog, but I cant seem to get anything out of it.  not sure how to deal with the StringListP structure...
        lStringlist = mdlFileList_edit(info, sList, attributes, "This is the title", "This is the list label", "*.dgn", "")
        
        Stop
        
        i = 0
        Do While (0 = mdlStringList_getMember(ppstring, ppinfofields, lStringlist, i))
            s = CharPtrToString(ppstring)
            j = InStr(1, s, vbNullChar)
            If j > 0 Then s = Left$(s, InStr(1, s, vbNullChar) - 1)
            Debug.Print s
            i = i + 1
        Loop

  • Why is it saying that this function (and others) are not in the stdmdlbltin?

    The only documentation we have about declarations of MDL functions for use in VBA is in the MicroStation V8 SDK help MDL Function Reference.  The VBA declarations there are not available in the equivalent MicroStation Help for the MicroStationAPI.

    For each VBA declaration we have to make the appropriate edits:

    • Add PtrSafe before each function
    • Change pointer data from Long to LongPtr
    • Find the DLL where the function is defined

    Feel free to post an Idea asking for VBA declarations to be included once again in MicroStationAPI help.  From what you've told us, it looks like mdlStringList_getMember is implemented in another DLL.

    If VBA complains (errors at run time) about a DLL, then you have to find it.  Here are some suggestions.

     
    Regards, Jon Summers
    LA Solutions

Reply
  • Why is it saying that this function (and others) are not in the stdmdlbltin?

    The only documentation we have about declarations of MDL functions for use in VBA is in the MicroStation V8 SDK help MDL Function Reference.  The VBA declarations there are not available in the equivalent MicroStation Help for the MicroStationAPI.

    For each VBA declaration we have to make the appropriate edits:

    • Add PtrSafe before each function
    • Change pointer data from Long to LongPtr
    • Find the DLL where the function is defined

    Feel free to post an Idea asking for VBA declarations to be included once again in MicroStationAPI help.  From what you've told us, it looks like mdlStringList_getMember is implemented in another DLL.

    If VBA complains (errors at run time) about a DLL, then you have to find it.  Here are some suggestions.

     
    Regards, Jon Summers
    LA Solutions

Children