Wypełnianie formularza tekstem z polskimi znakami przy pomocy iTextSharp

06.06.2011

Przez ostatnie dwa dni pracowałem nad projektem, w którym przy pomocy biblioteki iTextSharp generowałem dokumenty PDF z szablonu (pustego dokumentu PDF) i programowo wypełniałem pola formularzy. Jak to zwykle bywa w przypadku języka polskiego pojawiły się problemy z kodowaniem znaków w tekście wprowadzanym do formularzy. Jak się okazało czcionka zastosowana w formularzu niestety nie obsługuje odpowiedniego kodowania, więc wszelkie próby programowego wpisania Ą,Ę,Ł czy Ć kończyły się niepowodzeniem (w miejscach występowania polskich liter pojawiały się różne dziwne znaki). Początkowo myślałem, że problemem jest samo kodowanie tekstu w momencie wypełniania pól formularza, jednak szybko okazało się, że zastosowanie metody Encode.Convert(…) nie daje rezultatów. To czego brakowało do poprawnego wyświetlenia polskiego tekstu to czcionka, którą należy dodać do każdego wypełnianego pola w formularzu. Wycinek z programu:

public void Generate(Dictionary<string, string> formData, byte[] emptyForm, string filePath)
{
    if (formData == null || formData.Keys.Count == 0)
    {
        return;
    }

    var reader = new PdfReader(emptyForm);
    var stamper = new PdfStamper(reader, new FileStream(filePath, FileMode.Create));
    var fields = stamper.AcroFields;

    var baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1250, true);

    foreach (var pair in formData)
    {
        var s = pair.Value.Convert(Encoding.Default, Encoding.GetEncoding(1250));
        fields.SetFieldProperty(pair.Key, "textfont", baseFont, null);
        fields.SetField(pair.Key, s);
    }

    stamper.Close();
}

Najważniejsze są dwie linie. Ta, w której tworzony jest obiekt baseFont (strona kodowa 1250). Oraz linia, w której ustawiana jest właściwość pola formy (czcionka) – SetFieldProperty(). Dodatkowo tekst konwertowany jest z domyślnego kodowania do kodowania zgodnego z numerem strony 1250 przy pomocy extension method.

public static class StringExtensions
{
    public static string Convert(this string @this, Encoding src, Encoding dst) 
    {
        return dst.GetString(Encoding.Convert(src, dst, src.GetBytes(@this)));
    }
}