私は ASP.NET MVC を使用しており、iTextSharp を使用して HTML ページを PDF にレンダリングしています。詳細には iTextSharp XMLWorkerHelper ツールです。縦向きの場合は解析して PDF にレンダリングする必要があるすべてのページで正常に動作しますが、横向きの場合は失敗します。
これは、横向きにレンダリングしたい HTML の非常に単純なサンプルです。
<table style="border:1px solid red; width:280mm;">
<tr>
<td>
In this cell there is a content that can be very large...
</td>
</tr>
</table>
テーブルの幅は 280 mm にする必要があることに注意してください (横モードで A4 の全幅より少し小さい)。
HTML から PDF への変換のコアは次のとおりです。
public override void ExecuteResult(ControllerContext context)
{
IView viewEngineResult;
ViewContext viewContext;
if (string.IsNullOrEmpty(ViewName))
ViewName = context.RouteData.GetRequiredString("action");
context.Controller.ViewData.Model = Model;
var workStream = new MemoryStream();
var sb = new StringBuilder();
Document document = new Document(new Rectangle(842f, 595f));
document.SetPageSize(PageSize.A4.Rotate());
TextWriter tr = new StringWriter(sb);
viewEngineResult = ViewEngines.Engines.FindView(context, ViewName, null).View;
viewContext = new ViewContext(context, viewEngineResult, context.Controller.ViewData,
context.Controller.TempData, tr);
viewEngineResult.Render(viewContext, tr);
Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(sb.ToString()));
PdfWriter pdfWriter = PdfWriter.GetInstance(document, workStream);
pdfWriter.CloseStream = false;
document.Open();
XMLWorkerHelper.GetInstance().ParseXHtml(pdfWriter, document, stream, (Stream)null);
document.Close();
new FileContentResult(workStream.ToArray(), "application/pdf").ExecuteResult(context);
}
その結果、横長のドキュメントが作成され、テーブルの境界線が赤くなりますが、幅が正しくありません。PDF でレンダリングされた幅は280 mm ではなく、縦長の A4 ドキュメントでテーブルが持つ最大幅であることは容易に理解できます。
私はさまざまな方法を試しました:
- PdfPTable を作成し、幅を 100% に設定しました。次に、テーブル内に PdfPCell を作成しました。最後に、ParseXHtml の結果をそのセルに入れます。その結果、完全な「A4横幅」セルが作成され、280mmの赤い枠線テーブルが内側にありましたが、通常は幅が間違っていました(縦長のA4ドキュメントの最大値)
- ParseXHtml を実行する前に document.NewPage() を挿入しようとしました。これは、さまざまな投稿で、ドキュメントに適切な寸法を持たせるために「NewPage」の呼び出しが必要であることがわかったためです...しかし、この操作からも良い結果は得られませんでした。
多分私は間違った方法に従おうとしているのかもしれません.この問題を解決するための非常に簡単で愚かな方法はありますか?
ご提案いただきありがとうございます。
更新しました
この問題を回避策で解決しようとしました。document.Open()
とdocument.Close()
メソッド
の間で、次のものを置き換えました。XMLWorkerHelper.GetInstance().ParseXHtml(pdfWriter, document, stream, (Stream)null);
次のもので:
var handler = new SampleHandler();
using (TextReader sr = new StringReader(sb.ToString()))
{
//Parse
XMLWorkerHelper.GetInstance().ParseXHtml(handler , sr);
}
foreach (var element in handler.elements)
{
document.Add(element);
}
新しいクラスを作成しました:
public class SampleHandler : IElementHandler
{
public List<IElement> elements = new List<IElement>();
public void Add(IWritable w)
{
if (w is WritableElement)
{
// Here all the logic useful to catch the PDFPTable and redefine
// its width or other tricks (such as nested tables redefining)
}
}
}
最初の問題で述べたように、もっと簡単な方法があるかどうかはわかりません。正直なところ、うまくいくかどうかはわかりませんが、この回避策が良いかどうかはわかりません...