如何刷新非计算字段上的格式并刷新可填写PDF表单中的计算字段 [英] How to refresh Formatting on Non-Calculated field and refresh Calculated fields in Fillable PDF form

查看:112
本文介绍了如何刷新非计算字段上的格式并刷新可填写PDF表单中的计算字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个PDF模板文件,我试图填充MyDocument的内容。所有字段都填充正常,但问题是我的PDF中的计算字段没有刷新,也没有在其他字段上设置格式。如何使用ITextSharp使计算字段刷新和格式化? (我不在乎我是否得到C#或VB.NET答案)

I have a PDF Template file that I am trying to populate with contents of "MyDocument". All the fields populate fine but the problem is that the "Calculated" fields in my PDF are not refreshed nor is the formatting set on other fields. How do I make the calculated fields refresh and formatting to work using ITextSharp? (I do not care if I get a C# or VB.NET answer)

VB.NET:

  Public Shared Sub Serialize(ByVal stmt As MyDocument, ByVal file As FileInfo)
                    Dim reader As New PdfReader(TemplateFilePath.FullName)
                    Dim pdfStamper As New PdfStamper(reader, New FileStream(file.FullName, FileMode.Open))
                    Try
                        With itsDaDetailFields
                            .MoveFirst()
                            While Not .EOF
                                Dim pdfFieldName As String = NsT(Of String)(!PDFFieldName, Nothing)
                                If Not String.IsNullOrEmpty(pdfFieldName) Then
                                    Dim value As String = NsT(Of String)(stmt.GetValueFromPDFField(pdfFieldName), Nothing)
                                    If Not String.IsNullOrEmpty(value) Then
                                        pdfStamper.AcroFields.SetField(pdfFieldName, value)
                                    End If
                                End If
                                .MoveNext()
                            End While
                        End With

                    Finally
                        pdfStamper.FormFlattening = False
                        reader.Close()
                        pdfStamper.Close()
                    End Try
                End Sub

C#:

public static void Serialize(MyDocument stmt, FileInfo file)
{
    PdfReader reader = new PdfReader(TemplateFilePath.FullName);
    PdfStamper pdfStamper = new PdfStamper(reader, new FileStream(file.FullName, FileMode.Open));
    try {
        var _with1 = itsDaDetailFields;
        _with1.MoveFirst();
        while (!_with1.EOF) {
            string pdfFieldName = NsT<string>(_with1["PDFFieldName"], null);
            if (!string.IsNullOrEmpty(pdfFieldName)) {
                string value = NsT<string>(stmt.GetValueFromPDFField(pdfFieldName), null);
                if (!string.IsNullOrEmpty(value)) {
                    pdfStamper.AcroFields.SetField(pdfFieldName, value);
                }
            }
            _with1.MoveNext();
        }

    } finally {
        pdfStamper.FormFlattening = false;
        reader.Close();
        pdfStamper.Close();
    }
}


推荐答案

所以我想知道如何在.NET中基于以下帖子使用iText(ITextSharp的java版本 - 这个过程与.net略有不同)。请随意阅读以下主题,以获得有关iText中同一问题的完整解释和讨论:

So I figured out how to do it in .NET based on the following post using iText (the java version of ITextSharp - the procedure is just slightly different for .net). Feel free to read the following thread for a complete explanation and discussion of the same problem in iText:

http://itext-general.2136553.n4.nabble.com/设置 - acroform-value-via-iText-messes-with-acrofield-formating-td2167101.html

有两种方法可以做到:

(1)提供如下显示值:

pdfStamper.AcroFields.SetField(pdfFieldName, value, <formatted value>)

in :

pdfStamper.AcroFields.SetField(pdfFieldName, 1000, "1,000")

这对我来说不是最理想的,因为我无法从我的PDF文件中以编程方式弄清楚哪些文本框正在以哪种格式格式化其内容。有些格式略有不同(有些有2个小数位,有些有0,有些有很多)所以如果你能跟踪文本框如何格式化数据,或者它们都做同样的事情,那么这可能有效。这也没有解决计算字段问题,只是似乎修复了格式问题。

This wasn't optimal for me because I couldn't figure out programattically from my PDF file which textboxes were formatting their contents in which format. Some had slightly different formats (some had 2 decimal places, some had 0, some had many) so if you could keep track of how a textbox formats its data or if they all do the same thing then this might work. This also didn't fix the calculated fields problem, just seemed to fix the formatting problem.

(2)提供javascript到DIRTY的值,以便它格式化&计算:

我的代码变成了类似下面的内容,因为我只需要格式化数值,但这可以扩展为处理其他类型(请参阅下面的讨论) )。

My code turned into something like the following since I only needed to format numeric values but this can be expanded to handle other types (see discussion below).

Dim reader As New PdfReader(TemplateFilePath.FullName)
Dim pdfStamper As New PdfStamper(reader, New FileStream(file.FullName, FileMode.Open))

 With pdfStamper.AcroFields
     If IsNumeric(value) Then
        Dim js As String = String.Format("var f = this.getField('{0}'); f.value = 1 * f.value;", pdfFieldName)
        pdfStamper.JavaScript = js
     End If
     .SetField(pdfFieldName, value)
End With

reader.Close()
pdfStamper.Close()

所以诀窍是你需要使用JavaScript来获取值脏,然后Reader将应用格式。你可以更多地概括它并根据下面提供的完整解决方案处理更多的值类型(对不起,它在java中,但可以适应.net):

So the trick is that you need to use JavaScript to get the value dirty, then Reader will apply the formatting. You can generalize this more and handle more value types based on the complete solution provided below (sorry it is in java but can be adapted to .net):

import java.io.IOException;
import java.util.ArrayList;

import com.lowagie.text.pdf.PRStream;
import com.lowagie.text.pdf.PdfDictionary;
import com.lowagie.text.pdf.PdfName;
import com.lowagie.text.pdf.PdfObject;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfString;
import com.lowagie.text.pdf.AcroFields.Item;

public class AcroFieldJSScanner {

    protected ArrayList<String> functions = null;


    public void getFieldFunctions(Item item) throws IOException{

        PdfDictionary dict;

        for (int i = 0; i < item.size(); i++) {
            dict = item.getMerged(i);

            scanPdfDictionary(dict);

//          dict = item.getWidget(i);
//          
//          scanPdfDictionary(dict);
        }
    }

    protected void scanPdfDictionary(PdfDictionary dict) throws IOException{

        PdfObject objJS = null;
        String func = null;

        objJS = dict.get(PdfName.JS);
        if (dict.get(PdfName.S) != null &&  objJS != null && objJS.isString()){

            PdfString strJS = (PdfString)objJS;
            if (functions == null){
                functions = new ArrayList<String>();
            }

            func = strJS.toString();
            functions.add(func);
        }else if (dict.get(PdfName.S) != null &&  objJS != null){

            for(Object obj : dict.getKeys()){
                PdfName pdfName = (PdfName)obj;

                PdfObject pdfObj = dict.get(pdfName);

                if (pdfObj.isIndirect()){
                    PdfObject pdfIndirectObject = PdfReader.getPdfObject(pdfObj);

                    func = new String(PdfReader.getStreamBytes((PRStream)pdfIndirectObject));

                    if (functions == null){
                        functions = new ArrayList<String>();
                    }

                    functions.add(func);
                }else{
                    scanPdfObject(pdfObj);
                }

            }


        }else{
            for(Object obj : dict.getKeys()){
                PdfName pdfName = (PdfName)obj;

                PdfObject pdfObj = dict.get(pdfName);
                scanPdfObject(pdfObj);
            }
        }

    }

    protected void scanPdfObject(PdfObject parentPdfObject) throws IOException{

        if (parentPdfObject.isDictionary()){
            scanPdfDictionary((PdfDictionary)parentPdfObject);
        }else if (parentPdfObject.isIndirect()){
            PdfObject pdfObject = PdfReader.getPdfObject(parentPdfObject);
            scanPdfObject(pdfObject);
        }
    }

    public ArrayList<String> getFunctions() {
        return functions;
    }

    public String toString(){

        StringBuilder sb = null;

        if (getFunctions() != null){
            sb = new StringBuilder();

            for (int i =0; i< getFunctions().size();i++) {

                sb.append(getFunctions().get(i)).append("\n");      
            } 
        }else{
            return "No functions found";
        }

        return sb.toString();
    }

}

然后如果你知道javascript Adobe将调用的脚本(使用上面的代码),您知道数据的类型是什么,这样您就可以DIRTY数据。以下是一些adobe数据类型以及这些数据类型背后的javascript:

And then if you know the javascript scripts that Adobe will call (using the above code) you know what type the data is so you can "DIRTY" the data. Here are some adobe data types and the javascript that is behind those data types:

public String getFieldFormat(Item item){ 

       PdfDictionary aa = (PdfDictionary) item.getMerged(0).get(PdfName.AA); 
        if (null != aa) 
            { 
                PdfDictionary f = (PdfDictionary)PdfReader.getPdfObject(aa.get(PdfName.F));
                 if (null != f) 
                { 
                    PdfString js = (PdfString)PdfReader.getPdfObject(f.get(PdfName.JS));
                     if (null != js) 
                    { 
                        String sScriptName = js.toString(); 
                        if (sScriptName.contains("AFNumber_Format")) 
                            System.out.println("Format : Number"); 
                        else if (sScriptName.contains("AFDate_Format")) 
                        System.out.println("Format : Date"); 
                        else if (sScriptName.contains("AFTime_Format")) 
                        System.out.println("Format : Time"); 
                        else if (sScriptName.contains("AFSpecial_Format")) 
                        System.out.println("Format : Special"); 
                        else if (sScriptName.contains("AFPercent_Format")) 
                        System.out.println("Format : Percent"); 
                        else 
                        System.out.println("Format : Custom");; 

                        System.out.println("JS: "); 
                        System.out.println(js); 
                    } 
                } 
            } 
} 

这篇关于如何刷新非计算字段上的格式并刷新可填写PDF表单中的计算字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆