合并表单后,iText字段将无法计算

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了合并表单后,iText字段将无法计算相关的知识,希望对你有一定的参考价值。

我正在使用此脚本循环访问用户文件并填写details.pdf模板的副本,并将它们作为一个文件合并在一起。

我的问题是tfTotalPrice字段不计算,直到我手动打开文档javascript并更改某些内容,如添加警报。我认为它可能与需要“/ CO”字典密钥有关,但我不明白为什么。我刚刚在ISO32000-1 doc中读到过。

static void Main(string[] args)
    {
        int i = 0;
        int partsTotal = args.Count();

        //template page
        string tempDetails = @"C:	empDetails.pdf";
        //final multi page quote
        string finishedQuote = @"C:	empQuote.pdf";

        DateTime processedDate = DateTime.Now;
        string dateProc = processedDate.ToString("MM/dd/yyyy");

        Console.WriteLine("Please Enter Your Customer Name and Press Enter");
        string customer = Console.ReadLine();

        //This will hold the memory streams and be used to merge them all
        List<byte[]> pagesToMerge = new List<byte[]>();

        Document doc = new Document();
        PdfSmartCopy copy = new PdfSmartCopy(doc, new FileStream(finishedQuote, FileMode.Create));

        doc.Open();
        copy.SetMergeFields();
        copy.SetPdfVersion(PdfWriter.PDF_VERSION_1_7);

        List<PdfReader> readers = new List<PdfReader>();

        for (i = 0; i < partsTotal; i++)
        {
            string partFile = args[i].ToString();
            string partFileName = partFile.Substring(partFile.LastIndexOf(@"") + 1);
            string partFileLocation = partFile.Substring(0, partFile.LastIndexOf(@""));
            Console.WriteLine("Processing : " + partFileName);

            PdfReader reader = new PdfReader(RenameFields(tempDetails, i));
            readers.Add(reader);
            copy.AddDocument(reader);

        }

        doc.Close();
        foreach (PdfReader reader in readers)
        {
            reader.Close();
        }


        //Should we open it up?
        bool response = GetYorN();
        if (response == true)
        {
            System.Diagnostics.Process.Start(finishedQuote);
        }

    }

    static byte[] RenameFields(string src, int i)
    {
        //This method creates a new document in memory with newly named unique fields
        MemoryStream baos = new MemoryStream();
        PdfReader reader = new PdfReader(src);
        PdfStamper stamper = new PdfStamper(reader, baos);
        stamper.Writer.SetPdfVersion(PdfWriter.PDF_VERSION_1_7);
        stamper.AcroFields.GenerateAppearances = true;
        stamper.FormFlattening = false;

        AcroFields form = stamper.AcroFields;
        //populate names with the dictionary keys for the current file(stream)
        string[] names = new string[stamper.AcroFields.Fields.Keys.Count];
        stamper.AcroFields.Fields.Keys.CopyTo(names, 0);

        //rename all fields in this file(stream)
        foreach (string name in names)
        {
            stamper.AcroFields.RenameField(name, name + i);
        }

        //Add the calculation action to totalPrice(i)
        AcroFields.Item newTotalField = form.GetFieldItem("tfTotalPrice" + i);
        PdfDictionary newTotalRefDict = (PdfDictionary)PdfReader.GetPdfObject(newTotalField.GetWidgetRef(0));
        PdfString newTotalP = newTotalRefDict.GetAsString(PdfName.T);

        AcroFields.Item newSetupField = stamper.AcroFields.GetFieldItem("tfSetupPrice" + i);
        PdfDictionary newSetupRefDict = (PdfDictionary)PdfReader.GetPdfObject(newSetupField.GetWidgetRef(0));
        PdfString newSetupP = newSetupRefDict.GetAsString(PdfName.T);

        AcroFields.Item newToolField = stamper.AcroFields.GetFieldItem("tfToolPrice" + i);
        PdfDictionary newToolRefDict = (PdfDictionary)PdfReader.GetPdfObject(newToolField.GetWidgetRef(0));
        PdfString newToolP = newToolRefDict.GetAsString(PdfName.T);

        AcroFields.Item newPieceField = stamper.AcroFields.GetFieldItem("tfPiecePrice" + i);
        PdfDictionary newPieceRefDict = (PdfDictionary)PdfReader.GetPdfObject(newPieceField.GetWidgetRef(0));
        PdfString newPieceP = newPieceRefDict.GetAsString(PdfName.T);

        AcroFields.Item newFixtureField = stamper.AcroFields.GetFieldItem("tfFixturePrice" + i);
        PdfDictionary newFixtureRefDict = (PdfDictionary)PdfReader.GetPdfObject(newFixtureField.GetWidgetRef(0));
        PdfString newFixtureP = newFixtureRefDict.GetAsString(PdfName.T);

        //Declare the sum action
        string newJS = "this.getField("" + newTotalP + "").value = (this.getField("" + newPieceP + "").value + this.getField("" + newToolP + "").value + this.getField("" + newFixtureP + "").value + this.getField("" + newSetupP + "").value);";
        PdfAction pdfAction = PdfAction.JavaScript(newJS, stamper.Writer);
        PdfDictionary widgetRefDict = (PdfDictionary)PdfReader.GetPdfObject(newTotalField.GetWidgetRef(0));
        //AA = Additional Action Annotation Dictionary
        PdfDictionary actionDict = widgetRefDict.GetAsDict(PdfName.AA);
        //C = Calculation that lives inside of the AA dictionary
        PdfDictionary calcDict = actionDict.GetAsDict(new PdfName("C"));

        //Plug in the js calc with the new form field names
        calcDict.Put(new PdfName("JS"), new PdfString(newJS));

        //stamper.SetPageAction(PdfWriter.PAGE_OPEN, PdfAction.JavaScript(newJS, stamper.Writer), 1);

        //close up shop and return the new doc in memory
        stamper.Close();
        reader.Close();
        return baos.ToArray();
    }

任何帮助将不胜感激,我一直坚持这个:(谢谢你

这是PDFs的链接

答案

因此,我能够正确计算的唯一方法是用新的字段替换现有字段:

static byte[] RenameFields(string src, int i, string imageName, string customer, string dateProc, string partFileName, string partFileLocation)
    {
        //This method creates a new document in memory with newly named unique fields
        MemoryStream baos = new MemoryStream();
        PdfReader reader = new PdfReader(src);
        PdfStamper stamper = new PdfStamper(reader, baos);
        stamper.Writer.SetPdfVersion(PdfWriter.PDF_VERSION_1_7);
        stamper.AcroFields.GenerateAppearances = true;
        stamper.FormFlattening = false;
        AcroFields form = stamper.AcroFields;

        //Set Fields that don't need to be recreated
        form.SetField("tfCustomer", customer);
        form.SetField("tfDate", dateProc);
        form.SetField("tfFileName", partFileName);
        form.SetField("tfFileLocation", partFileLocation);
        form.SetField("tfQuantity", "300");
        form.SetField("tfLeadTime", "-");
        form.SetField("tfMaterialType", "N/A");
        form.SetField("tfThickness", "N/A");

        //Place Image
        string imageField = "ifPart";
        iTextSharp.text.Rectangle imageRect = form.GetFieldPositions(imageField)[0].position;
        Bitmap imageBitmap = new Bitmap(imageName);
        iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(imageBitmap, System.Drawing.Imaging.ImageFormat.Jpeg);
        image.ScaleAbsolute(imageRect.Width, imageRect.Height);
        image.SetAbsolutePosition(imageRect.GetLeft(0), imageRect.GetBottom(0));
        PdfContentByte content = stamper.GetOverContent(1);
        content.AddImage(image);

        //populate names with the dictionary keys for the current file(stream)
        string[] names = new string[stamper.AcroFields.Fields.Keys.Count];
        stamper.AcroFields.Fields.Keys.CopyTo(names, 0);

        //rename all fields in this file(stream)
        foreach (string name in names)
        {
            stamper.AcroFields.RenameField(name, name + i);
        }



        //Add the calculation action to totalPrice(i)
        AcroFields.Item newTotalField = form.GetFieldItem("tfTotalPrice" + i);
        PdfDictionary newTotalRefDict = (PdfDictionary)PdfReader.GetPdfObject(newTotalField.GetWidgetRef(0));
        PdfString newTotalP = newTotalRefDict.GetAsString(PdfName.T);
        PdfArray totalRect = newTotalRefDict.GetAsArray(PdfName.RECT);

        AcroFields.Item newSetupField = stamper.AcroFields.GetFieldItem("tfSetupPrice" + i);
        PdfDictionary newSetupRefDict = (PdfDictionary)PdfReader.GetPdfObject(newSetupField.GetWidgetRef(0));
        PdfString newSetupP = newSetupRefDict.GetAsString(PdfName.T);
        PdfArray setupRect = newSetupRefDict.GetAsArray(PdfName.RECT);


        AcroFields.Item newToolField = stamper.AcroFields.GetFieldItem("tfToolPrice" + i);
        PdfDictionary newToolRefDict = (PdfDictionary)PdfReader.GetPdfObject(newToolField.GetWidgetRef(0));
        PdfString newToolP = newToolRefDict.GetAsString(PdfName.T);
        PdfArray toolRect = newToolRefDict.GetAsArray(PdfName.RECT);

        AcroFields.Item newPieceField = stamper.AcroFields.GetFieldItem("tfPiecePrice" + i);
        PdfDictionary newPieceRefDict = (PdfDictionary)PdfReader.GetPdfObject(newPieceField.GetWidgetRef(0));
        PdfString newPieceP = newPieceRefDict.GetAsString(PdfName.T);
        PdfArray pieceRect = newPieceRefDict.GetAsArray(PdfName.RECT);

        AcroFields.Item newFixtureField = stamper.AcroFields.GetFieldItem("tfFixturePrice" + i);
        PdfDictionary newFixtureRefDict = (PdfDictionary)PdfReader.GetPdfObject(newFixtureField.GetWidgetRef(0));
        PdfString newFixtureP = newFixtureRefDict.GetAsString(PdfName.T);
        PdfArray fixtureRect = newFixtureRefDict.GetAsArray(PdfName.RECT);

        //PiecePrice Field
        var llxPiece = Convert.ToDecimal(pieceRect[0].ToString());
        var llyPiece = Convert.ToDecimal(pieceRect[1].ToString());
        var urxPiece = Convert.ToDecimal(pieceRect[2].ToString());
        var uryPiece = Convert.ToDecimal(pieceRect[3].ToString());
        //Remove Old Price Field
        form.RemoveField(newPieceP.ToString());
        //In with the new
        TextField PieceField = new TextField(stamper.Writer, new iTextSharp.text.Rectangle((float)llxPiece, (float)llyPiece, (float)urxPiece, (float)uryPiece), newPieceP.ToString())
        {
            Alignment = 1,
            Text = "0.00"
        };
        PdfFormField fPiece = PieceField.GetTextField();
        fPiece.SetAdditionalActions(PdfName.BL, PdfAction.JavaScript("this.getField('" + newTotalP + "').value = (parseFloat(this.getField('" + newPieceP + "').value) + parseFloat(this.getField('" + newToolP + "').value) + parseFloat(this.getField('" + newFixtureP + "').value) + parseFloat(this.getField('" + newSetupP + "').value));", stamper.Writer));
        fPiece.SetAdditionalActions(PdfName.F, PdfAction.JavaScript("AFNumber_Format(2, 0, 0, 0, 'u0024', true);", stamper.Writer));
        fPiece.SetAdditionalActions(PdfName.K, PdfAction.JavaScript("AFNumber_Keystroke(2, 0, 0, 0, 'u0024', true);", stamper.Writer));
        stamper.AddAnnotation(fPiece, 1);

        //ToolPrice Field
        var llxTool = Convert.ToDecimal(toolRect[0].ToString());
        var llyTool = Convert.ToDecimal(toolRect[1].ToString());
        var urxTool = Convert.ToDecimal(toolRect[2].ToString());
        var uryTool = Convert.ToDecimal(toolRect[3].ToString());
        //Remove Old Price Field
        form.RemoveField(newToolP.ToString());
        //In with the new
        TextField ToolField = new TextField(stamper.Writer, new iTextSharp.text.Rectangle((float)llxTool, (float)llyTool, (float)urxTool, (float)uryTool), newToolP.ToString())
        {
            Alignment = 1,
            Text = "0.00"
        };
        PdfFormField fTool = ToolField.GetTextField();
        fTool.SetAdditionalActions(PdfName.BL, PdfAction.JavaScript("this.getField('" + newTotalP + "').value = (parseFloat(this.getField('" + newPieceP + "').value) + parseFloat(this.getField('" + newToolP + "').value) + parseFloat(this.getField('" + newFixtureP + "').value) + parseFloat(this.getField('" + newSetupP + "').value));", stamper.Writer));
        fTool.SetAdditionalActions(PdfName.F, PdfAction.JavaScript("AFNumber_Format(2, 0, 0, 0, 'u0024', true);", stamper.Writer));
        fTool.SetAdditionalActions(PdfName.K, PdfAction.JavaScript("AFNumber_Keystroke(2, 0, 0, 0, 'u0024', true);", stamper.Writer));
        stamper.AddAnnotation(fTool, 1);

        //FixturePrice Field
        var llxFixture = Convert.ToDecimal(fixtureRect[0].ToString());
        var llyFixture = Convert.ToDecimal(fixtureRect[1].ToString());
        var urxFixture = Convert.ToDecimal(fixtureRect[2].ToString());
        var uryFixture = Convert.ToDecimal(fixtureRect[3].ToString());
        //Remove Old Price Field
        form.RemoveField(newFixtureP.ToString());
        //In with the new
        TextField FixtureField = new TextField(stamper.Writer, new iTextSharp.text.Rectangle((float)llxFixture, (float)llyFixture, (float)urxFixture, (float)uryFixture), newFixtureP.ToString())
        {
            Alignment = 1,
            Text = "0.00"
        };
        PdfFormField fFixture = FixtureField.GetTextField();
        fFixture.SetAdditionalActions(PdfName.BL, PdfAction.JavaScript("this.getField('" + newTotalP + "').value = (parseFloat(this.getField('" + newPieceP + "').value) + parseFloat(this.getField('" + newToolP + "').value) + parseFloat(this.getField('" + newFixtureP + "').value) + parseFloat(this.getField('" + newSetupP + "').value));", stamper.Writer));
        fFixture.SetAdditionalActions(PdfName.F, PdfAction.JavaScript("AFNumber_Format(2, 0, 0, 0, 'u0024', true);", stamper.Writer));
        fFixture.SetAdditionalActions(PdfName.K, PdfAction.JavaScript("AFNumber_Keystroke(2, 0, 0, 0, 'u0024', true);", stamper.Writer));
        stamper.AddAnnotation(fFixture, 1);

        //SetupPri

以上是关于合并表单后,iText字段将无法计算的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 iText 获取 Pdf 表单字段的自定义格式脚本?

iText onchange事件未触发

编译itext提供的示例程序

pdf格式在itext7中为空

itext7 pdf与书签合并

使用iText 7(C#)创建删除线字体