Solved Write code from a string (1 Viewer)

NauticalGent

Ignore List Poster Boy
Local time
Today, 11:14
Joined
Apr 27, 2015
Messages
6,286
Hello SportsFans, I've got one that really has me scratching my bald head, there HAS to be a way to do this...

The concept is simple: I want to fill a PDF with data from an unbound form. Using code the DBG's website, I was able to determine what the names of the PDF fields were and also get the code to "push" the values to it (nice work DBG!)

The issue is I want to build the series of commands and then use it as an argument to a public sub:

Code:
Sub FillPDF(strData As String)
    Dim gApp As Acrobat.AcroApp
    Dim avDoc As Acrobat.AcroAVDoc
    Dim pdDoc As Object
    Dim jso As Object
    Dim FileNm2 As String

    FileNm = "\\Data\SubContractingPlan\Edit_DD2579_blank_form.pdf"
    FileNm2 = "\\Data\SubContractingPlan\DD2579-BuyerName.pdf"

    Set gApp = CreateObject("AcroExch.app")
    Set avDoc = CreateObject("AcroExch.AVDoc")

    If avDoc.Open(FileNm, "") Then
        Set pdDoc = avDoc.GetPDDoc()
        Set jso = pdDoc.GetJSObject
    'Here is where I want to write the contents of the argument (strData) so the sub can execute them - here is an example of what one line would              'look like
    'jso.getfield("form1[0].#subform[0].ctr_email[0]").Value = "john.clark@MyDomain.com"

        pdDoc.Save 1, FileNm2
        pdDoc.Close
    End If

    avDoc.Close (True)
    Set gApp = Nothing
    Set avDoc = Nothing
    Set pdDoc = Nothing
    Set jso = Nothing

End Sub

The reason I am not doing this within the Form's Class Module is that I want to make this dynamic for the many PDF forms the clients will be using.
Open to any suggestions here, I am not married to this concept, it is just the only way I cold think of.

Thanks in advance!
 

theDBguy

I’m here to help
Staff member
Local time
Today, 08:14
Joined
Oct 29, 2018
Messages
21,359
Thanks! What are you thinking the Sub might look like?

For the above example, it could be something like:
Code:
Public Sub FilloutPDF(FieldArg As String, FieldValue As String)
    'object setup here
    jso.getfield(FieldArg).Value = FieldValue
End Sub
Is that what you have in mind?
 

NauticalGent

Ignore List Poster Boy
Local time
Today, 11:14
Joined
Apr 27, 2015
Messages
6,286
Thanks! What are you thinking the Sub might look like?

For the above example, it could be something like:
Code:
Public Sub FilloutPDF(FieldArg As String, FieldValue As String)
    'object setup here
    jso.getfield(FieldArg).Value = FieldValue
End Sub
Is that what you have in mind?
Sort of, but there could be multiple lines of code that begin with the "jso.getField..."

I suppose I could call it out individually from the unbound form like you have shown...again, I got wrapped around the axle thinking about sending it all as a chunk of code...mostly because I need all the data to be written before the PDF is saved as a new name.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 10:14
Joined
Feb 28, 2001
Messages
27,003
You want to be able to place an instruction in-line and execute it, such as
Code:
     jso.getfield("form1[0].#subform[0].ctr_email[0]").Value = "john.clark@MyDomain.com"
The problem is that the kind of instruction you want to use has to be compiled to get the variable and property references right, but that only happens in form design mode. Further, the way that instructions operate in PCode (what the VBA compiler produces), they have to be compiled and saved in the order you want them executed, and there is an implied (hidden) line number for each line in a module. You would have to find the right line before or after which you would do the insertion.

The instructions can be input to a module because there are Module.Insertxxxx methods that could insert a line. It is totally possible to build code on lines in the module. It is the step of compiling the module to catch the new code that runs into that pesky little fact that you have to be in design mode to be able to trigger the compiler to run but to do this step from running VBA code, you CAN'T be in design mode. Unless you are running this code from another module so that the new code would be in a logically separate module from the code that would be driving this insertion and activation. In that case, it MIGHT be possible - but I don't advise holding your breath while trying to make this work.

If all that you are doing is a function call involving jso.getfield, you could write a function or sub that takes the arguments to be placed into arg list and calls jso.getfield with the pass-thru values. That is NOT the same as passing through an instruction. However, if these arguments require further evaluation, I don't know enough about the .GetField function to know if that input would resolve correctly.
 

Isaac

Lifelong Learner
Local time
Today, 08:14
Joined
Mar 14, 2017
Messages
8,738
Hello SportsFans, I've got one that really has me scratching my bald head, there HAS to be a way to do this...

The concept is simple: I want to fill a PDF with data from an unbound form. Using code the DBG's website, I was able to determine what the names of the PDF fields were and also get the code to "push" the values to it (nice work DBG!)

The issue is I want to build the series of commands and then use it as an argument to a public sub:

Code:
Sub FillPDF(strData As String)
    Dim gApp As Acrobat.AcroApp
    Dim avDoc As Acrobat.AcroAVDoc
    Dim pdDoc As Object
    Dim jso As Object
    Dim FileNm2 As String

    FileNm = "\\Data\SubContractingPlan\Edit_DD2579_blank_form.pdf"
    FileNm2 = "\\Data\SubContractingPlan\DD2579-BuyerName.pdf"

    Set gApp = CreateObject("AcroExch.app")
    Set avDoc = CreateObject("AcroExch.AVDoc")

    If avDoc.Open(FileNm, "") Then
        Set pdDoc = avDoc.GetPDDoc()
        Set jso = pdDoc.GetJSObject
    'Here is where I want to write the contents of the argument (strData) so the sub can execute them - here is an example of what one line would              'look like
    'jso.getfield("form1[0].#subform[0].ctr_email[0]").Value = "john.clark@MyDomain.com"

        pdDoc.Save 1, FileNm2
        pdDoc.Close
    End If

    avDoc.Close (True)
    Set gApp = Nothing
    Set avDoc = Nothing
    Set pdDoc = Nothing
    Set jso = Nothing

End Sub

The reason I am not doing this within the Form's Class Module is that I want to make this dynamic for the many PDF forms the clients will be using.
Open to any suggestions here, I am not married to this concept, it is just the only way I cold think of.

Thanks in advance!
So the variables would be 1) form1[#], 2) subform[#], 3) email[#], and the final value / email address?
Or maybe the subform# and email#'s are always zero..

Either way, you could change FillPDF to accept several arrays (one for each of those elements).
Then change FillPDF to loop through the arrays (sized identically, one-dimensional) and execute those jsfo.getfield lines.....IF .GetField method accepts strings as arguments, which I haven't seen as you haven't posted pdDoc.GetJSObject class, but you can verify if that's the case.

If I was more familiar with 2 and 3-dimensional arrays I would just suggest that, but I'm not so I didn't; maybe you can just use that.

That, to me, is the "mechanics" of it - along with the assumptions I made as noted and the need to verify them as appropriate.

Or, alternately, just make the calling code dump stuff in a table - then have FillPDF loop through it and execute one line per record in the whole recordset...constructing strings made-to-order for jso.GetFields' consumption
 
Last edited:

MajP

You've got your good things, and you've got mine.
Local time
Today, 11:14
Joined
May 21, 2018
Messages
8,463
Put data in table so it can be easily updated. Select file to run.

tblData tblData

IDFileNameFieldNameFieldValue
1​
\\Data\SubContractingPlan\Edit_DD2579_blank_form.pdfform1[0].#subform[0].ctr_email[0]john.clark@MyDomain.com
2​
\\Data\SubContractingPlan\Edit_DD2579_blank_form.pdfform1[0].#subform[0].ctr_Name[0]John Clark
3​
\\Data\SubContractingPlan\Edit_DD2579_blank_form.pdfform1[0].#subform[0].ctr_Phon[0]123-456-7890
Code:
Public Sub TestRunFill()
  RunFill "\\Data\SubContractingPlan\Edit_DD2579_blank_form.pdf"
End Sub

Public Sub RunFill(fileName As String)
  Dim Data() As String
  Dim rs As DAO.Recordset
  Dim recordCount As Integer
  Dim i As Integer
  Set rs = CurrentDb.OpenRecordset("Select * from tblData where fileName = '" & fileName & "'")
  If Not rs.EOF Then
    rs.MoveLast
    rs.MoveFirst
    recordCount = rs.recordCount
  End If
  ReDim Data(recordCount - 1, recordCount - 1)
 
  Do While Not rs.EOF
    
    Data(i, 0) = rs!FieldName
    Data(i, 1) = rs!fieldValue
    i = i + 1
    rs.MoveNext
  Loop
  FillPDF fileName, Data
End Sub

Public Sub FillPDF(fileNm As String, Data As Variant)
   'Dim gApp As Acrobat.AcroApp
   ' Dim avDoc As Acrobat.AcroAVDoc
   ' Dim pdDoc As Object
   ' Dim jso As Object
    Dim i As Integer
  
    'Set gApp = CreateObject("AcroExch.app")
    'Set avDoc = CreateObject("AcroExch.AVDoc")

    'If avDoc.Open(FileNm, "") Then
    '    Set pdDoc = avDoc.GetPDDoc()
    '    Set jso = pdDoc.GetJSObject
    'Here is where I want to write the contents of the argument (strData) so the sub can execute them - here is an example of what one line would              'look like
    'jso.getfield("form1[0].#subform[0].ctr_email[0]").Value = "john.clark@MyDomain.com"
        For i = 0 To UBound(Data)
           'jso.getfield(data(i,0)).Value = data(i,1)
           Debug.Print Data(i, 0) & " " & Data(i, 1)
        Next i
        
        'pdDoc.Save 1, FileNm2
        'pdDoc.Close
    'End If

    'avDoc.Close (True)
    'Set gApp = Nothing
    'Set avDoc = Nothing
    'Set pdDoc = Nothing
    'Set jso = Nothing

End Sub
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 11:14
Joined
May 21, 2018
Messages
8,463
I want to fill a PDF with data from an unbound form
If you want to use a form then you probably need another field. "Display Name"
So
form1[0].#subform[0].ctr_email[0] would have Display name of Contractor Email
Your continuous form would have every display name and you fill in the values.
 

NauticalGent

Ignore List Poster Boy
Local time
Today, 11:14
Joined
Apr 27, 2015
Messages
6,286
To make things a little more clear, below is a screen shot of what DBG's utility can do. I modified it so it would show the field PDF field type and the current value. Adding the value allowed me to positively identify each field as there are over a hundred - DoD forms are a study in confusion and inefficiency.

I delimited it with the pipe symbol so that importing it as a text file was easy.

If you want to use a form then you probably need another field. "Display Name"
So
form1[0].#subform[0].ctr_email[0] would have Display name of Contractor Email
Your continuous form would have every display name and you fill in the values.
I use the filed name (e.g. form1[0].#subform[0].ctr_email[0] ) as the Tag property for each corresponding form control so that once everything is ready, it would loop through the controls and write and add each jso.getfield("PDFFieldName").Value line into a string in hopes I could send the completed string to my sub for execution.

But as Doc explained in his "this is super geeky but I dumbed it down for you" way (thanks Doc for the explanation!), this is simply not possible.

MajP, thanks so much for the suggestion and the code. I am going to use my loop sequence to write the info to a temp table and then use your code to populate and save the document. Excellent feedback and I want to be just like you when I grow up - but then I have said the same thing to just about everyone here so take that for what its worth! I dont know how to mark your post as the Answer, once I figure it out I will do so...

Thanks again to everyone who chipped in, You guys make life real easy for me...

image001 (2).png
 

Users who are viewing this thread

Top Bottom