c# - 如何刷新非计算字段的格式并刷新可填写 PDF 表单中的计算字段

标签 c# vb.net itext

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

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();
    }
}

最佳答案

因此,我根据以下帖子使用 iText(ITextSharp 的 Java 版本 - .net 的过程略有不同)找出了如何在 .NET 中执行此操作。请随意阅读以下线程以获取对 iText 中相同问题的完整解释和讨论:

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

有两种方法:

(1) 提供如下显示值:

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

如:

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

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

(2) 为“DIRTY”值提供 javascript,以便对其进行格式化和计算:

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

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):

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();
    }

}

然后,如果您知道 Adob​​e 将调用的 javascript 脚本(使用上面的代码),您就会知道数据的类型,因此您可以“弄脏”数据。以下是一些 adobe 数据类型和这些数据类型背后的 javascript:

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); 
                    } 
                } 
            } 
} 

关于c# - 如何刷新非计算字段的格式并刷新可填写 PDF 表单中的计算字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16093162/

相关文章:

c# - 计算机关闭时 Windows 服务 OnStop

c# - 自定义 .net azure 数据工厂事件

css - XMLWorker:单元格的垂直对齐不起作用

asp.net - iTextSharp生成PDF并直接在浏览器上显示

c# - Monodevelop:嵌入式资源行尾 CRLF 转换为 LF?

C# 将数据表与计数器合并

vb.net - 从另一种形式 vb.net 运行函数

c# - 如何返回 Visual Studio 当前打开的 sotion 目录

wpf - 如何确定我的 WPF(xbap) 应用程序是从哪个文件夹启动的?

java - 如何在 java servlet 中将图像转换为 pdf?