繁体   English   中英

使用iTextSharp,c#将空的AcroField展平后,从PDF模板中删除空白(空白)空间

[英]Remove blank (empty) space from PDF template after flattenning an empty AcroField using iTextSharp, c#

我正在通过Windows Forms应用程序使用iTextSharp填充包含AcroFieldsPDF模板。 数据通过带有多个comboBoxes接口填充,如下所示:

string template = path1 + @"\Template1.pdf";
PdfReader pdfreader = new PdfReader(template);
StringBuilder sb = new StringBuilder();

foreach (KeyValuePair<string, iTextSharp.text.pdf.AcroFields.Item> de in
pdfreader.AcroFields.Fields)
    {
       sb.Append(de.Key.ToString() + Environment.NewLine);
    }

string newPDF = path + @"\"name".pdf";
PdfStamper pdfstamper = new PdfStamper(pdfreader, new FileStream(newPDF,
FileMode.Create));
AcroFields pdffields = pdfstamper.AcroFields;
pdffields.SetField("ProductText", product.SelectedItem.ToString());
pdffields.SetField("indexText", index.SelectedItem.ToString());
 .
 .
 .

pdfstamper.FormFlattening = true;
pdfstamper.Close();

PDF的结果如下图所示:

生成PDF

但是问题是:如果未选择“ Grade (如上图所示),我可以删除“ Grade的整行,但这将在PDF保留空白空间,如下图所示:

带有空白展开字段空白的PDF

有什么可能的方法来移除展平的空白字段的空白空间? 是通过向上移动紧随其后的内容吗? 谢谢。

OP在对该问题的评论中指出

我可以处理标签问题,但是如何移动下面的字段?

因此,以下代码仅处理字段。

将所有字段上移到空白字段下方

因此,假设您在将字段设置为该字段之前检查该字段的值。 如果为空,则不设置字段值,而是调用如下方法将该字段下的每个字段上移:

void MoveUp(PdfStamper stamper, String fieldName, int pageNumber)
{
    AcroFields fields = stamper.AcroFields;
    IList<AcroFields.FieldPosition> positions = fields.GetFieldPositions(fieldName);
    foreach (AcroFields.FieldPosition position in positions)
    {
        if (position.page == pageNumber)
        {
            IList<float> fieldYsBelowField = new List<float>();
            PdfDictionary pageDict = stamper.Reader.GetPageN(pageNumber);
            PdfArray annots = pageDict.GetAsArray(PdfName.ANNOTS);
            for (int i = 0; i < annots.Size; i++)
            {
                PdfDictionary annot = annots.GetAsDict(i);
                PdfArray rect = annot.GetAsArray(PdfName.RECT);
                if (((PdfNumber)rect[1]).FloatValue < position.position.Bottom)
                {
                    fieldYsBelowField.Add(((PdfNumber)rect[1]).FloatValue);
                }
            }
            if (fieldYsBelowField.Count > 0)
            {
                float offset = position.position.Bottom - fieldYsBelowField.Max();
                for (int i = 0; i < annots.Size; i++)
                {
                    PdfDictionary annot = annots.GetAsDict(i);
                    PdfArray rect = annot.GetAsArray(PdfName.RECT);
                    if (((PdfNumber)rect[1]).FloatValue < position.position.Bottom)
                    {
                        rect[1] = new PdfNumber(((PdfNumber)rect[1]).FloatValue + offset);
                        rect[3] = new PdfNumber(((PdfNumber)rect[3]).FloatValue + offset);
                    }
                }
            }
        }
    }
}

您会得到想要的。

例如,对于某些单页,形成以下代码

AcroFields fields = stamper.AcroFields;
fields.SetField("Product", "Product1");
fields.SetField("Index", "XQAA-0000-000");
fields.SetField("Quality", "USP,");
fields.SetField("Grade", "SomeGrade");
fields.SetField("Customer", "Customer1");
fields.SetField("Market", "England, Germany");

结果是

屏幕截图全部填充

AcroFields fields = stamper.AcroFields;
fields.SetField("Product", "Product1");
fields.SetField("Index", "XQAA-0000-000");
fields.SetField("Quality", "USP,");
fields.SetField("Customer", "Customer1");
fields.SetField("Market", "England, Germany");

结果是

屏幕截图为空成绩

然后

AcroFields fields = stamper.AcroFields;
fields.SetField("Product", "Product1");
fields.SetField("Index", "XQAA-0000-000");
fields.SetField("Quality", "USP,");
MoveUp(stamper, "Grade", 1);
fields.SetField("Customer", "Customer1");
fields.SetField("Market", "England, Germany");

结果是

屏幕截图,其中空等级和以下字段向上移动

仅向上移动一个字段

在对问题的评论中,OP问

我可以指定要移动的字段,而不是移动所有下面的字段吗? [...]假设我只希望将Customer1移到SomeGrade的位置。

这样的帮助程序更加简单:

void MoveUp(PdfStamper stamper, String fieldName, String moveFieldName, int pageNumber)
{
    AcroFields fields = stamper.AcroFields;
    IList<AcroFields.FieldPosition> positions = fields.GetFieldPositions(fieldName);
    foreach (AcroFields.FieldPosition position in positions)
    {
        if (position.page == pageNumber)
        {
            Item moveFieldItem = fields.GetFieldItem(moveFieldName);
            for (int i = 0; i < moveFieldItem.Size; i++)
            {
                if (moveFieldItem.GetPage(i) == pageNumber)
                {
                    PdfDictionary annot = moveFieldItem.GetWidget(i);
                    PdfArray rect = annot.GetAsArray(PdfName.RECT);
                    float offset = position.position.Bottom - ((PdfNumber)rect[1]).FloatValue;
                    rect[1] = new PdfNumber(((PdfNumber)rect[1]).FloatValue + offset);
                    rect[3] = new PdfNumber(((PdfNumber)rect[3]).FloatValue + offset);
                    break;
                }
            }
        }
    }
}

使用这种方法

AcroFields fields = stamper.AcroFields;
fields.SetField("Product", "Product1");
fields.SetField("Index", "XQAA-0000-000");
fields.SetField("Quality", "USP,");
MoveUp(stamper, "Grade", "Customer", 1);
fields.SetField("Customer", "Customer1");
fields.SetField("Market", "England, Germany");

结果是

空等级和“客户”字段为空的屏幕截图

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM