如果ABCPDF中已存在TextField,如何添加TextField?

时间:2014-07-02 15:10:11

标签: c# pdf abcpdf

使用ABCPDF添加TextField非常简单:

public FormField AddTextField(string inRect, string inName, string inText)
{
    int fieldId = mDoc.AddObject("<</Type /Annot /Subtype /Widget /F 4 /FT /Tx /Ff 4096 /Q 1>>");
    mDoc.SetInfo(fieldId, "/V:Text", inText);
    RegisterField(fieldId, inName, inRect);
    return new FormField(fieldId, mDoc);
}

以此为实施:

FormField text = AddTextField("40 530 300 580", "TextField1", "Hello World!");
text.DefaultAppearance = "/TimesRoman 36 Tf 0 0 1 rg";
text.BorderColor = "0 0 0";
text.FillColor = "220 220 220";
text.TextAlign = "Left";

如果我需要添加两个具有相同名称的字段,它会更复杂一些:

public int AddGroupField(FormField[] inKids, string inName, string inValue)
{
    if (inKids.Length == 0)
        throw new Exception("Cannot have a group field with no kids");
    string ft = null, dv = null;
    int fieldId = mDoc.AddObject("<< /Kids [] >>");
    foreach (FormField kid in inKids)
    {
        mDoc.SetInfo(fieldId, "/Kids[]:Ref", kid.Id.ToString());
        mDoc.SetInfo(kid.Id, "/Parent:Ref", fieldId);
        if (ft == null)
            ft = mDoc.GetInfo(kid.Id, "/FT");
        if (dv == null)
            dv = mDoc.GetInfo(kid.Id, "/DV");
        mDoc.SetInfo(kid.Id, "/FT:Del", "");
        mDoc.SetInfo(kid.Id, "/V:Del", "");
        mDoc.SetInfo(kid.Id, "/DV:Del", "");
    }
    mDoc.SetInfo(fieldId, "/FT", ft);
    mDoc.SetInfo(fieldId, "/T:Text", inName);
    mDoc.SetInfo(fieldId, "/V:Text", inValue);
    if (dv != null)
        mDoc.SetInfo(fieldId, "/DV:Text", dv);
    int eid = mDoc.GetInfoInt(mDoc.Root, "/AcroForm:Ref");
    mDoc.SetInfo(eid, "/Fields*[]:Ref", fieldId);
    return fieldId;
}

以此为实施:

FormField[] kids = new FormField[2];
kids[0] = AddTextField("40 230 300 280", null, null);
kids[1] = AddTextField("40 170 300 220", null, null);
int id = AddGroupField(kids, "TextField1", "Hello World!");

但是,我在将TextField添加到PDF中时遇到问题,其中TextField已存在同名。因此,例如,如果我的PDF已经有一个名为&#34; TextField1&#34;然后我想添加另一个具有相同名称的字段,上述任何实现都不起作用。

1 个答案:

答案 0 :(得分:3)

我能够从ABCPDF支持中得到答案。正如您所看到的,这不是一个简单的过程。我不确定任何人都可以自己解决这个问题,而无需花费数月和数月对PDF规范和ABCPDF产品进行研究。

public FormField AddTextField(string inRect, string inName, string inText)
{
    bool fieldAlreadyExists = mDoc.Form[inName] != null;

    int fieldId = mDoc.AddObject("<</Type /Annot /Subtype /Widget /F 4 /FT /Tx /Ff 4096 /Q 1>>");
    mDoc.SetInfo(fieldId, "/V:Text", inText);
    RegisterField(fieldId, inName, inRect);
    var field = new FormField(fieldId, mDoc);

    if (fieldAlreadyExists)
    {
        InteractiveForm form = new InteractiveForm(mDoc);
        form.AddFieldIntoExistingGroup(field, true);
    }

    return field;
}


private bool AddFieldIntoExistingGroup(FormField field, bool refreshForm)
{
    bool duplicatesFound = false;
    int acroFormID = mDoc.GetInfoInt(mDoc.Root, "/AcroForm:Ref");
    int parentID = mDoc.GetInfoInt(field.Id, "/Parent:Ref");
    ArrayAtom kids;
    if (parentID > 0)
    {
        kids = mDoc.ObjectSoup.Catalog.Resolve(Atom.GetItem(mDoc.ObjectSoup[parentID].Atom, "Kids")) as ArrayAtom;
    }
    else
    {
        kids = mDoc.ObjectSoup.Catalog.Resolve(Atom.GetItem(mDoc.ObjectSoup[acroFormID].Atom, "Fields")) as ArrayAtom;
    }
    Dictionary<string, List<IndirectObject>> items = new Dictionary<string, List<IndirectObject>>();
    for (int i = 0; i < kids.Count; i++)
    {
        IndirectObject io = mDoc.ObjectSoup.Catalog.ResolveObj(kids[i]);
        if (io == null)
        {
            continue; // shouldn't really happen
        }
        string name = mDoc.GetInfo(io.ID, "/T:Text");
        if (!items.ContainsKey(name))
        {
            items[name] = new List<IndirectObject>();
        }
        items[name].Add(io);
    }
    foreach (KeyValuePair<string, List<IndirectObject>> pair in items)
    {
        if (pair.Value.Count > 1)
        {
            duplicatesFound = true;
            // shift field down to be a child of a new field node
            int id = mDoc.AddObject("<< >>");
            if (parentID > 0)
            {
                mDoc.SetInfo(parentID, "/Kids[]:Ref", id);
                mDoc.SetInfo(id, "/Parent:Ref", parentID);
            }
            else
            {
                mDoc.SetInfo(acroFormID, "/Fields[]:Ref", id);
            }
            string[] dictEntries = new[] { "/FT", "/T", "/TU", "/Ff", "/V", "/DV" };
            foreach (IndirectObject io in pair.Value)
            {
                foreach (string dictEntry in dictEntries)
                {
                    string val = mDoc.GetInfo(io.ID, dictEntry);
                    if (!string.IsNullOrEmpty(val))
                    {
                        mDoc.SetInfo(id, dictEntry, val);
                        mDoc.SetInfo(io.ID, dictEntry + ":Del", "");
                    }
                }
                ArrayRemoveOneRefAtom(kids, io.ID);
                mDoc.SetInfo(id, "/Kids[]:Ref", io.ID);
                mDoc.SetInfo(io.ID, "/Parent:Ref", id);
            }
        }
    }
    if ((refreshForm) && (duplicatesFound))
    {
        mDoc.Form.Refresh();
    }
    return duplicatesFound;
}

private static bool ArrayRemoveOneRefAtom(ArrayAtom array, int id)
{
    if (array != null)
    {
        for (int i = 0; i < array.Count; i++)
        {
            RefAtom refAtom = array[i] as RefAtom;
            if ((refAtom != null) && (refAtom.ID == id))
            {
                ArrayRemoveAt(array, i);
                return true;
            }
        }
    }
    return false;
}

private static void ArrayRemoveAt(ArrayAtom array, int index)
{
    if (index == 0)
    { // Workaround for bug in some versions of ABCpdf
        Atom[] copy = new Atom[array.Count];
        array.CopyTo(copy, 0);
        array.Clear();
        for (int i = 1; i < copy.Length; i++)
            array.Add(copy[i]);
    }
    else
    {
        array.RemoveAt(index);
    }
}