Skip to main content
Bruno69
Participating Frequently
May 27, 2020
Answered

How to select items in listbox field from VBA

  • May 27, 2020
  • 2 replies
  • 4605 views

Good evening,

I’d be grateful if anyone could help in my problem.

I have to fill out the fields of a administrative pdf forms from Access (where I have my database), under VBA. I have no problems with the main part of the fields, except with listboxes having a multiple choice selection.

I put my code below, and the form for example is attached. Even if I send a sorted array of integers to set the currentValueIndices, I get the error code 13 : type incompatibility. The array type is 8194 (array 8192 + integer 2), and all my values are integer.

Could anyone help to understand how to pass the array to the pdf listbox field and set the selected items, please.

Many thanks

Bruno

from Adobe Acrobat SDK

«To set a multiple selection for a list box that allows it, pass an array as argument to this property, containing the indices (sorted in ascending order) of those strings in the options array. » 

    Dim apPDDoc, apVisuPDDoc, formAcrob, javscrobj As Object
    Dim champTravail As Object
    Dim nomFichOr, nomFichDest As String
    Dim Cpt, nbLangagesSel As Integer
    Dim valListBox() As Integer
    
    Dim chLangage As String
    chLangage = "PYT;JAV;CPP" ' Valeurs possibles PYT JAV PAS CPP VBA XML
    
    Dim langagesList As Object
    Set langagesList = CreateObject("Scripting.Dictionary")
    langagesList.Add "CPP", 0
    langagesList.Add "CPP_l", "C/C++"
    langagesList.Add "JAV", 1
    langagesList.Add "JAV_l", "Java"
    langagesList.Add "PAS", 2
    langagesList.Add "PAS_l", "Pascal"
    langagesList.Add "PYT", 3
    langagesList.Add "PYT_l", "Python"
    langagesList.Add "VBA", 4
    langagesList.Add "VBA_l", "VBA"
    langagesList.Add "XML", 5
    langagesList.Add "XML_l", "XML"
    
    nomFichOr = "C:\Bruno\ManipPdfAccess\Form_Travail_remplLstbox.pdf"
    nomFichDest = "C:\Bruno\ManipPdfAccess\Form_Travail_remplLstbox_rempli.pdf"
    
    Set apPDDoc = CreateObject("AcroExch.PDDoc")
    Set apVisuPDDoc = CreateObject("AcroExch.AVDoc")
        
    If apVisuPDDoc.Open(nomFichOr, "") Then
        Set formAcrobat = apVisuPDDoc.GetPDDoc()
        Set javscrobj = formAcrobat.getJSObject
    
        Set chTravail = javscrobj.getfield("chLangage")
        ' Extraction des langages sélectionnés
        ' Extraction of the selected values from chLangage
        nbLangagesSel = (Len(chLangage) + 1) / 4
        
        ReDim valListBox(0 To nbLangagesSel - 1)
        
        For Cpt = 0 To nbLangagesSel - 1
            ' Va chercher dans le dictionnaire l'indice de liste associé au langage à sélectionner
            ' Fills the array with selected items, through the dictionnary
            valListBox(Cpt) = CInt(langagesList.Item(Mid$(chLangage, 4 * Cpt + 1, 3)))
        Next
        
        ' Tri du tableau, en principe par une fonction appelée (array sort, done by a function)
        ' Sorting the array, normaly made by function call
        Dim i, temp As Integer
        Dim finTri, pasDeModif As Boolean
        finTri = False
        pasDeModif = True
        While Not finTri
            For i = 0 To UBound(valListBox) - 1
                If valListBox(i) > valListBox(i + 1) Then
                    temp = valListBox(i)
                    valListBox(i) = valListBox(i + 1)
                    valListBox(i + 1) = temp
                    pasDeModif = False
                End If
            Next i
            If pasDeModif Then finTri = True Else pasDeModif = True
        Wend
        
        ' Là, erreur 13, c'est pourtant tableau d'integer
        ' Here there is error code 13 type incompatibility
        chTravail.currentValueIndices = valListBox()
        formAcrobat.Save 1, nomFichDest
    Else
        MsgBox ("Pas de document de ce nom disponible")
    End If
    
    
    Set chTravail = Nothing
    Set javscrobj = Nothing
    Set formAcrobat = Nothing
    Set apVisuPDDoc = Nothing
    Set apPDDoc = Nothing
This topic has been closed for replies.
Correct answer Thom Parker

Using "ExecuteThisJavaScript" is a very similar approach. It moves the main action into the JavaScript engine and passes parameters as a string. However, it is not as clean, robust, or flexible as using the same code in a Folder Level JavaScript function.   

 

The Folder level function approach allows you to refine the Acrobat side functionality separately, and within the Acrobat environment. I would place everything that needs to be done in Acrobat in this function (or functions) so that there is a clear separation between the Acrobat functionality, and the Access functionality. Only use the JSO to pass data into the Acrobat side folder level functions. 

2 replies

Thom Parker
Community Expert
Community Expert
May 30, 2020

Objects in VBA are different from objects in JavaScript. There is some level of compatibility provided by the JSO interface, but the fact is that you cannot reliably pass data in objects from VBA to the Acrobat JavaScript engine. Arrays are of course a type of object. But you also have the compound problem of assigning an object value (the index array) to a property of a JavaScript field object acquired through getField. Field objects are built-in JavaScript objects. it's hard enough to think about handling generic objects across the JSO boundary, But this is quite complex and I'm sure resolving the object compatibilities is way beyond the abilities of JSO. There are other inefficiencies with this interface as well.

 

As a general practice, when writing in .NET or VBA I keep interactions with the JSO to a minimum, and only pass arguments as strings or integers. 


For any kind of complex operation, or anything involving object related properties on the JavaScript side, I create folder level JavaScript functions to perform the majority of the work and then call the function from the JSO.  For example VBA code should never act directly on a built-in JavaScript object from within VBA.  

 

These techniques will fix your issue in the most robust and efficient way.  

 

 

Thom Parker - Software Developer at PDFScriptingUse the Acrobat JavaScript Reference early and often
Bruno69
Bruno69Author
Participating Frequently
May 30, 2020

Thanks Thom for your answer,

Do you mean that the technique I used finally with the .ExecuteThisJavaScript is not the right one ? I'm not a specialist of JS and have a lot to learn.

 

Thom Parker
Community Expert
Thom ParkerCommunity ExpertCorrect answer
Community Expert
May 30, 2020

Using "ExecuteThisJavaScript" is a very similar approach. It moves the main action into the JavaScript engine and passes parameters as a string. However, it is not as clean, robust, or flexible as using the same code in a Folder Level JavaScript function.   

 

The Folder level function approach allows you to refine the Acrobat side functionality separately, and within the Acrobat environment. I would place everything that needs to be done in Acrobat in this function (or functions) so that there is a clear separation between the Acrobat functionality, and the Access functionality. Only use the JSO to pass data into the Acrobat side folder level functions. 

Thom Parker - Software Developer at PDFScriptingUse the Acrobat JavaScript Reference early and often
Bruno69
Bruno69Author
Participating Frequently
May 28, 2020

I found a solution, using an ExecuteThisJavaScript on a Fields object from AFormAut.App, but its not a very elegant one.

Is it a possibility to pass the array directly through the jsobject getfield ?

Many thanks

Bruno

ls_rbls
Community Expert
Community Expert
May 29, 2020

From your code posted earlier, it is saying in French about the error with  the use of Integers in the array.

 

It fails to explain that you must not declare with your variables that will be processed with integer number values  using string values.

 

So it is possible to pass the array as long as you fix that with the following recommendations:

 

 

 

Bruno69
Bruno69Author
Participating Frequently
May 30, 2020

Thanks ls_rbls for your answer.

I'm not sure I understood all what you recommended, I tried to declare my array as an long values one, then declare it without any other indication (Dim valListBox() -> becomes an array of variant). Unfortunately, it didnt fix my problem.

Its written in Adobe Acrobat SDK that you must "pass an array as argument to this property, containing the indices (sorted in ascending order) of those strings in the options array" and "It accepts a single integer or array of integers as an argument".

I can understand where it does fail.

In another answer, I put the "solution" I found, not very elegant, but working.