iTextSharp(C#):在位置添加文本(在所有内容上)

时间:2016-02-28 23:58:56

标签: c# wpf text itextsharp positioning

我正在尝试在WPF项目中使用iTextSharp将文本添加到现有PDF上,而不是在其他任何地方和给定点上。基本上数字相当于在纸质文档上书写

我尝试了多种方法,似乎没有任何东西真正将文本写入新PDF。我的代码在测试各种各样的东西时很乱(留下来,所以我知道我尝试了什么 - 是的,我会在解决后清除它),所以我会尝试获得所有重要的部分。

var stream = new FileStream(targetFilePath, FileMode.Create);
var doc = new iTextSharp.text.Document();
var target = new PdfCopy(doc, stream);

doc.Open();

var baseFont = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, false);

foreach (var vm in Pages) // Cycles through pages in WPF object...
{
    var srcDoc = vm.DocTmpFName;

    if (Path.GetExtension(srcDoc).ToUpperInvariant() == ".PDF")
    {
        var reader = new iTextSharp.text.pdf.PdfReader(srcDoc);
        var page = reader.GetPageN(vm.Number);
        var stamper = new PdfStamper(reader, stream);

        target.AddPage(target.GetImportedPage(reader, vm.Number));

        page.Put(PdfName.ROTATE, new PdfNumber(vm.Rotation % 360f));

        // Inside this 'foreach' loop is what isn't working.  The rest works fine.
        foreach(var str in vm.Strings) // str is a container class (just a string and two 'double' vars for positioning)
        {
            // This isn't writing to new PDF even though it gets run (verified with breakpoints)
            var contentByte = stamper.GetOverContent(vm.Number);

            contentByte.BeginText();
            contentByte.SetTextMatrix((float)str.X, (float)str.Y);
            contentByte.SetFontAndSize(baseFont, 72f); //Making it stupid-big so I don't miss it
            contentByte.ShowText(str.String);
            contentByte.EndText();
        }

        target.FreeReader(reader);
        reader.Close();

    }
}

target.Close();
doc.Close();
stream.Close();

如果你觉得我错过了什么让我知道。我试图保留问题区域的背景,所以希望它不是一个黑客工作太可怕。

- 修改了正确的代码 -

修改

我重命名了一些变量,以便更容易辨别出它们的用途。此外,我已经包含了新的固定(尽管有错误)代码,可以在某个位置添加文本 - 对于后来遇到这种情况的人来说。 =)

@ mkl回答后的工作代码:

var stream = new FileStream(targetFilePath, FileMode.Create);
var doc = new iTextSharp.text.Document();
var targetPdf = new PdfCopy(doc, stream);

doc.Open();

foreach (ViewModels.PageViewModel vm in document.Pages)
{
    var srcDocPath = FileIO.ToTempFileName(vm.DocName);

    // Copy pageDict from source...
    if (Path.GetExtension(srcDocPath).ToUpperInvariant() == ".PDF")
    {
        var srcReader = new iTextSharp.text.pdf.PdfReader(srcDocPath);
        var pageDict = srcReader.GetPageN(vm.Number);
        var importedPage = targetPdf.GetImportedPage(srcReader, vm.Number);
        var pageStamp = targetPdf.CreatePageStamp(importedPage);

        foreach(var str in vm.Strings)
        {
            ColumnText.ShowTextAligned(pageStamp.GetOverContent(),
                iTextSharp.text.Element.ALIGN_LEFT,
                new iTextSharp.text.Phrase(str.String),
                (float) str.X,
                // pdf-origin is bottom-left, not top-left
                (float)(importedPage.Height - str.Y),
                0);
        }

        pageDict.Put(PdfName.ROTATE, new PdfNumber(vm.Rotation % 360f));
        pageStamp.AlterContents();
        targetPdf.AddPage(importedPage);

        targetPdf.FreeReader(srcReader);
        srcReader.Close();
    }
}
targetPdf.Close();
doc.Close();
stream.Close();

2 个答案:

答案 0 :(得分:2)

你的代码有很多问题,其中一些@Übercoder已在他的回答中提到过。

此外,您有一个PdfCopy和多个PdfStamper个实体写入同一个流。这将导致流输出完全混乱。如果您要标记页面复制,则应使用PdfCopy.PageStamp,例如像这样:

using (PdfCopy copy = new PdfCopy(document, OUTPUT_STREAM)) {
    document.Open();
    PdfReader reader1 = new PdfReader(r1);
    int n1 = reader1.NumberOfPages;
    PdfImportedPage page;
    PdfCopy.PageStamp stamp;
    for (int i = 0; i < n1; ) {
        page = copy.GetImportedPage(reader1, ++i);
        stamp = copy.CreatePageStamp(page);
        // CHANGE THE PAGE,
        // e.g. by manipulating stamp.GetOverContent()
        ...
        //
        stamp.AlterContents();
        copy.AddPage(page);
    }
}

(摘自官方iTextSharp示例ConcatenateStamp.cs

答案 1 :(得分:0)

你不能在foreach循环中关闭阅读器。也不(我怀疑)你应该进行target.FreeReader电话:

foreach(var str in vm.Strings) // str is a container class (just a string and two 'double' vars for positioning)
{
    // This isn't writing to new PDF even though it gets run (verified with breakpoints)
    var contentByte = stamper.GetOverContent(vm.Number);

    contentByte.BeginText();
    contentByte.SetTextMatrix((float)str.X, (float)str.Y);
    contentByte.SetFontAndSize(baseFont, 72f); //Making it stupid-big so I don't miss it
    contentByte.ShowText(str.String);
    contentByte.EndText();
}
//moved the next two lines out of the foreach loop
target.FreeReader(reader);
reader.Close();

这三行的相同摘要:

target.Close();
doc.Close();
stream.Close();

它们也应该移出当前包含它们的foreach (var vm in Pages)循环。