1

「MyDocument」のコンテンツを入力しようとしている PDF テンプレート ファイルがあります。すべてのフィールドに問題なく入力されますが、問題は、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();
    }
}
4

2 に答える 2

4

そこで、iText を使用して次の投稿に基づいて .NET でそれを行う方法を考え出しました (ITextSharp の Java バージョン - 手順は .net ではわずかに異なります)。iText での同じ問題の完全な説明と議論については、次のスレッドを自由に読んでください。

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

2 つの方法があります。

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

}

そして、Adobe が (上記のコードを使用して) 呼び出す JavaScript スクリプトを知っていれば、データのタイプがわかるので、データを「ダーティ」にすることができます。以下に、いくつかの Adob​​e データ型と、これらのデータ型の背後にある 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); 
                    } 
                } 
            } 
} 
于 2013-06-03T18:46:59.550 に答える