GetTablePages.cs
//
// このコードは、DioDocs for PDF のサンプルの一部として提供されています。
// © MESCIUS inc. All rights reserved.
//
using System;
using System.IO;
using System.Drawing;
using System.Linq;
using System.Collections.Generic;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Pdf.Recognition;
using GrapeCity.Documents.Text;
using GrapeCity.Documents.Common;
using GCTEXT = GrapeCity.Documents.Text;
using GCDRAW = GrapeCity.Documents.Drawing;
namespace DsPdfWeb.Demos
{
// テーブルからデータを抽出します。
public class GetTablePages
{
public int CreatePDF(Stream stream)
{
const float DPI = 72;
const float margin = 36;
var doc = new GcPdfDocument();
var tf = new TextFormat()
{
Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "ipag.ttc")),
FontSize = 9,
ForeColor = Color.Black
};
var tfHdr = new TextFormat(tf)
{
FontBold = true,
FontSize = 11,
ForeColor = Color.DarkBlue
};
var tfRed = new TextFormat(tf) { ForeColor = Color.Red };
using (var fs = File.OpenRead(Path.Combine("Resources", "PDFs", "product-list.pdf")))
{
var page = doc.NewPage();
page.Landscape = true;
var g = page.Graphics;
var rc = Common.Util.AddNote(
"このサンプルでは、複数のページに分割されたテーブル(商品価格表)を含むPDFを読み込み、" +
"Page.GetTable()メソッドを用いて全ページのテーブルを抽出しています。" +
"抽出されたデータは、行とセルのリストとして出力されます。" +
"テーブルを含む元のPDFも、参照用に生成されるPDFに追加されます。",
page,
new RectangleF(margin, margin, page.Bounds.Width - margin * 2, page.Bounds.Height - margin * 2));
var tl = g.CreateTextLayout();
tl.MaxWidth = page.Bounds.Width;
tl.MaxHeight = page.Bounds.Height;
tl.MarginAll = margin;
tl.MarginTop = rc.Bottom;
tl.DefaultTabStops = 165;
var docSrc = new GcPdfDocument();
docSrc.Load(fs);
for (int i = 0; i < docSrc.Pages.Count; ++i)
{
// TableExtractOptionsを使用すると、テーブルのフォーマットの特殊性を考慮して、
// テーブルの認識を微調整することができます。
var teo = new TableExtractOptions();
var GetMinimumDistanceBetweenRows = teo.GetMinimumDistanceBetweenRows;
// ここでは、行間の最小距離をわずかに長くして、テキストが折り返されているセルが
// 2つのセルであると誤認識されないようにしています。
teo.GetMinimumDistanceBetweenRows = (list) => {
var res = GetMinimumDistanceBetweenRows(list);
return res * 1.2f;
};
var top = i == 0 ? DPI * 2 : DPI;
// 指定された範囲にあるテーブルを取得します。
var itable = docSrc.Pages[i].GetTable(new RectangleF(DPI * 0.25f, top, DPI * 8, DPI * 10.5f - top), teo);
// テキストレイアウトにテーブルデータを追加します。
tl.Append($"\n元のドキュメントの {i + 1} ページ目のテーブルには、列が {itable.Cols.Count} 列と、行が {itable.Rows.Count} 行あります。データは以下のとおりです。", tfHdr);
tl.AppendParagraphBreak();
for (int row = 0; row < itable.Rows.Count; ++row)
{
var tfmt = row == 0 ? tfHdr : tf;
for (int col = 0; col < itable.Cols.Count; ++col)
{
var cell = itable.GetCell(row, col);
if (col > 0)
tl.Append("\t", tfmt);
if (cell == null)
tl.Append("<セルなし>", tfRed);
else
tl.Append(cell.Text, tfmt);
}
tl.AppendLine();
}
}
// 抽出したデータを出力します。
TextSplitOptions to = new TextSplitOptions(tl) { RestMarginTop = margin, MinLinesInFirstParagraph = 2, MinLinesInLastParagraph = 2 };
tl.PerformLayout(true);
while (true)
{
var splitResult = tl.Split(to, out TextLayout rest);
doc.Pages.Last.Graphics.DrawTextLayout(tl, PointF.Empty);
if (splitResult != SplitResult.Split)
break;
tl = rest;
doc.NewPage().Landscape = true;
}
// 参照のため元のドキュメントを追加します。
doc.MergeWithDocument(docSrc);
doc.Save(stream);
return doc.Pages.Count;
}
}
}
}