【问题标题】:Acrobat cannot read .FDF written with Excel VBAAcrobat 无法读取使用 Excel VBA 编写的 .FDF
【发布时间】:2017-04-06 14:32:38
【问题描述】:

我在 FDF 中导出了一个带有表单域的 PDF,并编写了一个子程序以逐字输出另一个 FDF,其中包含表单域值的单元格值。如果我在文本编辑器中编辑 FDF 并更改值,Acrobat 可以正常读取文件,但使用 VBA 输出的文件会引发错误:

Adobe 无法打开 whatever.fdf,因为它不是受支持的文件类型或文件已损坏

我尝试了两种不同类型的换行符,我尝试了一个类似的带有 xfdf 格式的 sub,但结果略有不同。

Sub something()

Dim sht As Worksheet
Set sht = Sheets("owssvr")

Dim lastrow As Integer
lastrow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row

Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Dim Fileout As Object

Dim x As Integer
For x = 2 To lastrow
    Set Fileout = fso.CreateTextFile("C:\Users\blabla\" & x & ".fdf", True, True)
                Fileout.Write "%FDF-1.2" & vbCrLf & _
                "%âãÏÓ" & vbCrLf & _
                "1 0 obj" & vbCrLf & _
                "<</FDF<</F(MyDocument.pdf)/Fields[<</T(Adobe Form Field)/V(" & sht.Range("U" & x) & ")>>]/ID[<4ED54800AC4A3D41ABE4F4C7B12A3D23><609E705B7532334B8F914CFF4C09F2A0>]/UF(MyDocument.pdf)>>/Type/Catalog>>" & vbCrLf & _
                "endobj" & vbCrLf & _
                "trailer" & vbCrLf & _
                "<</Root 1 0 R>>" & vbCrLf & _
                "%%EOF" & vbCrLf
Fileout.Close

Next x

End Sub

【问题讨论】:

  • 我怀疑存在编码问题。考虑使用StrConv 函数来确保正确编码 (vbUnicode?)
  • 很好的标注,但使用 vbunicode 无效
  • "%âãÏÓ" 是 ANSI 编码的字符串文字 - 如果它是 unicode,vbUnicode-encoding "%âãÏÓ" 可能不会神奇地将其转换为 unicode 等价物;您可能需要将它与ChrW 结合使用以发出实际 unicode 字符。
  • 恐怕我从来没有使用过 Chr 或 Chrw,你能举个例子吗?
  • Debug.Print Chr(65) 打印 ASCII 65,大写 AChrW(1024) 输出位置 1024 处的任何 unicode 字符;请注意,VBE 使用的是 ANSI 编码,因此您不能使用 Debug.Print 输出 unicode(所有内容都将显示为 ?)。 MSDN 有 VB.NET 等效函数的文档(VBA 函数的文档在 Google 上很难找到)。

标签: vba excel acrobat fdf


【解决方案1】:

只需省略以下行:“%âãÏÓ” & vbCrLf & _"。/ID 和 /UF 键并不真正需要。

这样的事情应该可以工作:

Fileout.Write "%FDF-1.2" & vbCrLf & _
            "1 0 obj<</FDF<<" & vbCrLf & _
            "/F(MyDocument.pdf)" & vbCrLf & _
            "/Fields" & vbCrLf & _
            "[<</T(Adobe Form Field)/V(xyValue)>>]" & vbCrLf & _            
            ">>>>" & vbCrLf & _
            "endobj" & vbCrLf & _
            "trailer" & vbCrLf & _
            "<</Root 1 0 R>>" & vbCrLf & _
            "%%EOF" & vbCrLf

【讨论】:

  • 不幸的是同样的错误。我只是不明白。如果我在 NP++ 中并排查看文件,它们看起来是相同的。我可以编辑原始导出,它仍然可以工作。地狱,如果我从原始文件复制并粘贴到新文件,它就可以工作。 VBA 正在编写的东西使它变得无用。我想我可以在原版上尝试一个长字符串替换循环,但我之前没有真正这样做过,所以可能需要一些时间。
  • 在德国有点晚了。如果你不明白,我明天给你一个vbs。
【解决方案2】:

您可以在 Acrobat IAC 文档中找到它。这是一个快速的 vbs(vba) 示例。你只需要两行:jso.getField 和 f.value =...祝你好运。

  '//-> Set a value for a form field via JSO
  '//-> Settings
FileNm = "d:\TestInput.pdf"
FieldNm= "Input1"
FieldValue= "50"
  '//-> let's start
Set App = CreateObject("Acroexch.app")
app.show
Set AVDoc = CreateObject("AcroExch.AVDoc")
    '//-> open the file and put the value in
If AVDoc.Open(FileNM,"") Then
    Set PDDoc = AVDoc.GetPDDoc()
    Set jso = PDDoc.GetJSObject
  '//-> Get the field and put a value in
    set f = jso.getField(FieldNm)
    f.value = FieldValue
end if

【讨论】:

    【解决方案3】:

    尽管我想保持这个开放状态,希望有人弄清楚为什么 VBA 搞砸了 unicode,但我的问题可以在根本不调用 fso 的情况下解决,只需在原始 FDF 上使用 FreeFile 和字符串替换

    Sub blabla()
    
    Dim objAcroApp As Acrobat.AcroApp
    Dim objAcroAVDoc As Acrobat.AcroAVDoc
    Dim objAcroPDDoc As Acrobat.AcroPDDoc
    Dim jsObj As Object
    Dim boResult As Boolean
    Dim oldPDF As String
    Dim NewFilePath As String
    
        Dim sTemp As String
        Dim iFileNum As Integer
        Dim oldFDF As String
        Dim i As Integer
        Dim lastRow As Integer
        Dim sht As Worksheet
        Set sht = Sheets("owssvr")
    
        With sht
            lastRow = .Range("A" & .Rows.Count).End(xlUp).Row
        End With
    
        For i = 2 To lastRow
    
        oldPDF = "\mydoc.pdf"
        oldFDF = "\mydoc_data.fdf"
        newPDF = "\" & i & ".pdf"
    
        iFileNum = FreeFile
        Open oldFDF For Input As iFileNum
    
        Do Until EOF(iFileNum)
        Line Input #iFileNum, sBuf
        sTemp = sTemp & vbCrLf
        Loop
        Close iFileNum
    
        sTemp = Replace(sTemp, "<</T(some form field)/V( )>>", "<</T(some form field)/V(" & sht.Range("E" & i) & ")>>")
    
        iFileNum = FreeFile
        oldFDF = "\" & i & ".fdf"
        Open oldFDF For Output As iFileNum
    
        Print #iFileNum, sTemp
    
        Close iFileNum
    
                Set objAcroApp = CreateObject("AcroExch.App")
                Set objAcroAVDoc = CreateObject("AcroExch.AVDoc")
                boResult = objAcroAVDoc.Open(oldPDF, "")
                Set objAcroPDDoc = objAcroAVDoc.GetPDDoc
                Set jsObj = objAcroPDDoc.GetJSObject
                jsObj.ImportAnFDF oldFDF
                jsObj.SaveAs newPDF
                boResult = objAcroAVDoc.Close(True)
                boResult = objAcroApp.Exit
    
    Next i
    
    
    End Sub
    

    【讨论】:

    • 现在我真的很想知道您使用 FDF 来填写表格。使用 Acrobat,您可以使用 JSObject 直接填充它。
    • facepalm 哇,我没有意识到这一点。我会再看一遍 API 手册,看看我需要做什么
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多