iTextSharp 中文字型解決方案

0 comments
iTextSharp 是由 iText(for Java)移植到 .NET 平台的開放原始碼專案。它是一個完全使用 C# 語言所撰寫的 PDF APIs,可以讓你即時建立 PDF 文件。然而,當你要使用 iTextSharp 來建立包含中文字型的文件時,就會面臨無法正常顯示中文的問題。這是因為 iTextSharp 只支援 14 個標準的 Type 1 英文字型,並沒有直接支援中文字型的顯示,取而代之的是你必須自行指定中文字型來源才能獲得解決,所以在此整理顯示中文字的幾種解決方案。

Windows 內建的中文字型
中文版 Windows 內建的中文字型檔可分為 True Type、True Type Collection 及 Open Type 三種字型格式。你可以在 %WINDIR%\Fonts 目錄下找到以 .ttf、.ttc 為延伸檔名的中文字型檔。以下範例將會使用標楷體字型來顯示文字:
Document document = new Document();
PdfWriter.GetInstance(
document,
new FileStream(@"cjk.pdf", FileMode.Create)
);
document.Open();

string fontPath = Environment.GetFolderPath(Environment.SpecialFolder.System) +
@"\..\Fonts\kaiu.ttf";
BaseFont bfChinese = BaseFont.CreateFont(
fontPath,
BaseFont.IDENTITY_H, //橫式中文
BaseFont.NOT_EMBEDDED
);
Font fontChinese = new Font(bfChinese, 16f, Font.NORMAL);
document.Add(new Paragraph(
"難得糊塗",
fontChinese
));
document.Close();

在上例中,你也可以使用 FontFactory 代替 BaseFont 來取得中文字型:
FontFactory.Register(fontPath);
Font fontChinese = FontFactory.GetFont("標楷體", BaseFont.IDENTITY_H, 16f);
document.Add(new Paragraph(
"吃虧是福",
fontChinese
));

CID 字型(Character Identity-keyed Fonts)
CID 字型格式通常被應用到中日韓(Chinese Japanese Korean, CJK)字元集。如果要使用 CJK 字型,你就必須搭配額外的亞洲語言包 iTextAsian-1.0.dll
Document document = new Document();
BaseFont.AddToResourceSearch("iTextAsian.dll");

PdfWriter.GetInstance(
document,
new FileStream(@"cjk.pdf", FileMode.Create)
);
document.Open();

BaseFont bfChinese = BaseFont.CreateFont(
"MHei-Medium",
"UniCNS-UCS2-H", // 橫式中文
BaseFont.NOT_EMBEDDED
);
Font fontChinese = new Font(bfChinese, 8);
document.Add(new Paragraph(
@"聰明難,糊塗難,
由聰明而轉入糊塗更難,
放一著,退一步,當下心安,非圖後來福報也。",
fontChinese
));
document.Close();

Download sample code

參考資料:
iText Tutorial: Getting fonts

繼續閱讀...

Printing PDF Documents using C#

0 comments
在報表應用中,PDF 是常被使用的文件格式,透過 iTextSharp 可以讓你即時(On-The-Fly)建立 PDF 文件。然而,如果你想自動將建立的文件內容輸出至印表機時,可能就會面臨苦無對策的窘境。因為,iTextSharp 並未提供實際的列印文件功能。所幸,這個問題可以藉由動態資料交換(Dynamic Data Exchange, DDE)技術獲得解決,也就是透過 DDE 從 Adobe Reader 來要求列印指定的文件檔案。在 .NET 中,我們可以使用 NDde 這個開放源碼專案,來輕鬆撰寫 DDE 連結的功能。

在接下來的程式碼範例中,除了參考「Printing PDF documents in C#」的做法外,同時亦採用 Clifton Nock 所著「Data Access Patterns」一書中的 Retryer Pattern。以下程式碼是實作 IRetryable 介面的類別,用來執行列印 PDF 文件的工作:
using System;
using System.Diagnostics;
using NDde;
using NDde.Client;

namespace PdfPrintExample
{
class PdfPrintOperation : IRetryable
{
private DdeClient _client;
private string _filePath;

public PdfPrintOperation(string filePath)
{
_filePath = filePath;
_client = new DdeClient("acroview", "control");
}

public bool Attemp()
{
try
{
_client.Connect();
return true;
}
catch (DdeException)
{
// ignore exception
}

return false;
}

public void Recover()
{
// try running Adobe Reader
Process p = new Process();
p.StartInfo.FileName = "AcroRd32.exe";
p.Start();
p.WaitForInputIdle();
}

public void Print()
{
_client.Execute("[DocOpen(\"" + _filePath + "\")]", 60000);
_client.Execute("[FilePrintSilent(\"" + _filePath + "\")]", 60000);
_client.Execute("[DocClose(\"" + _filePath + "\")]", 60000);
_client.Execute("[AppExit]", 60000);
}
}
}

以下是簡單的使用範例:
namespace PdfPrintExample
{
class Program
{
static void Main(string[] args)
{
PdfPrintOperation operation = new PdfPrintOperation(@"C:\sample.pdf");
Retryer retryer = new Retryer(operation);
retryer.Perform(10, 5000);
// print the file
operation.Print();
}
}
}

使用 Retryer Pattern 的好處在於連結 DDE Server 發生 DDEException 例外狀況時,可以自動嘗試重新連線,直到連接成功或是達到最大重試次數為止。

Download source code

參考資料:
Printing PDF documents in C#

繼續閱讀...