2017年2月19日日曜日

C#で直接印刷

C#で直接印刷

C#の直接印刷で手こずっていましたが、ghostscript.net で解決。

つかうもの。itextsharp, ghostscript.net そして、Adobe Illustrator cs2です。
itextsharp,ghostscript.net はそれぞれ NuGet にあるのでインストールしておきます。

1 Illustratorでテンプレートを作成


Adobe Illustratorで下地となるテンプレートを作成。
単位、座標をitextsharpと一致させます。
単位:ポイント
座標:左下 (「定規」を表示して左下に座標設定)
    Illustratorなのでかなり意匠の凝った印刷物が作成可。
    レイヤーでプログラムに使う座標なども作成しておくと便利。
最後に不必要なレイヤーを非表示にして「複製を保存」でpdfファイルを作成。

2 itextsharp


作成されたpdfファイルにコンテンツを追加していきます。
文字もグリッド用の線もすべて PdfContentByte で位置固定。

サンプル

using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

{

string filePaht="";
var template1 = new PdfReader(filePath);
var doc = new Document(PageSize.A4.Rotate());
FileStream fs = null;
fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
var writer = PdfWriter.GetInstance(doc, fs);
doc.Open();

//row.Count枚数の印刷物
foreach(DataRow row in table)

{
var page1 = writer.GetImportedPage(template1, 1);
doc.NewPage();
var pcd1 = writer.DirectContent;
pcd1.AddTemplate(page1, 0, 0);
AddContents(writer, row);
}
doc.Close();
fs.Close();
template1.Close();
}

//DataRowのコンテンツを追加します

private void AddContents(PdfWriter writer, DataRow row)
{
var cb = writer.DirectContent;
var bf = BaseFont.CreateFont(@"c:\windows\fonts\msgothic.ttc,0", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
//
float x0=***f,y0=***f;
float w0=***f,h0=***f;
DrawTextAligned(cb, bf, 11f, row.Field<string>(1), new PointF(x0, y0), Element.ALIGN_LEFT);
//
DrawTextCell(cb, bf, 10f, r1[2].ToString(), new PointF(x0,y0), new SizeF(w0, h0), Element.ALIGN_LEFT);
//直線
DrawLine(cb, new PointF(x0, y0), new SizeF(w0, 0.0f), 0.5f, Color.Black.ToArgb());
}
//文字列一行
private static void DrawTextAligned(PdfContentByte cb, BaseFont bf, float fSize, string s, PointF xy, int alignment = Element.ALIGN_LEFT, int argb = -16777216)
{
if (s == "") return;
cb.BeginText();
BaseColor bc = new BaseColor(argb);
cb.SetColorFill(bc);
cb.SetFontAndSize(bf, fSize);
cb.ShowTextAligned(alignment, s, xy.X, xy.Y,0.0f);
cb.EndText();
}

//文字列 複数行
private static void DrawTextCell(PdfContentByte cb, BaseFont bf, float fontSize, string s, PointF xy, SizeF wh, int alignment = Element.ALIGN_LEFT,int arb=-16777216)
{
ColumnText col = new ColumnText(cb);
var font = new iTextSharp.text.Font(bf, fontSize);
Color color = Color.FromArgb(argb);
font.SetColor(color.R, color.G, color.B);
col.SetSimpleColumn(new Phrase(s, font), xy.X, xy.Y, xy.X + wh.Width, xy.Y + wh.Height, fontSize, alignment);
col.Go();
}
//直線
private static void DrawLine(PdfContentByte cb, PointF xy, SizeF wh, float lineWidth = 0.5f, int argb = -16777216)
{
BaseColor bc = new BaseColor(argb);
cb.MoveTo(xy.X, xy.Y);
cb.LineTo(xy.X + wh.Width, xy.Y+ wh.Height);
cb.SetLineWidth(lineWidth);
cb.SetColorStroke(bc);
cb.ClosePathStroke();
}
//塗りつぶし矩形
private static void DrawFillRect(PdfContentByte cb, PointF xy,SizeF wh, int argb)
{
BaseColor c=new BaseColor(argb);
cb.SetColorFill(c);
cb.Rectangle( xy.X, xy.Y,wh.Width,wh.Height);
cb.Fill();
}

ライン、文字列の関数はすべて ( x=左 y=下 w=幅, h=高さ )を変数に作成してありますが、これはIllastrator の「ウィンドウ> 変形」のXYWHと一致させるためです。Illastratorの「変形」の値を参照しながら位置を設定していきます。もし、Illastratorのオブジェクトの名前と位置をテキストにエクスポート出来ることができれば、もっと簡便に設定できるのですが。。

また、Illastrator「変形」の基準ポイント(9点)の 左、中央、右はitextsharpのElement.ALIGN_LEFT,Element.ALIGN_CENTER,Element.ALIGN_RIGHTに相当します。たとえば、Element.ALIGN_RIGHTだと xは右側が基準です。同様にElement.ALIGN_CENTERの場合は中央が基準です。

3 ghostscript.net


ghostscript.netで直接印刷します。
ghostscript.netにはプレビュー用のフォームのサンプルもあるのでビュアーも作成可能。 Acrobat Readerよりはずっと早い。

サンプルコード

using Ghostscript.NET;
using Ghostscript.NET.Viewer;
using Ghostscript.NET.Processor;

var pd = new System.Drawing.Printing.PrintDocument();
string printerName = pd.PrinterSettings.PrinterName;
string inputFile = ””;

using (GhostscriptProcessor processor = new GhostscriptProcessor())
{
List<string> switches = new List<string>();
switches.Add("-empty");
switches.Add("-dPrinted");
switches.Add("-dBATCH");
switches.Add("-dNOPAUSE");
switches.Add("-dNOSAFER");
switches.Add("-dNumCopies=1"); //部数
switches.Add("-sDEVICE=mswinpr2");
switches.Add("-sPAPERSIZE=a4");
//横指定A4
//switches.Add("-dDEVICEWIDTHPOINTS=842");
//switches.Add("-dDEVICEHEIGHTPOINTS=595");
//両面印刷
//switches.Add("-dDuplex");//TrueON,false=off
//switches.Add("-dTumble=true");//True=短辺綴じ false=長辺綴じ
switches.Add("-sOutputFile=%printer%" + printerName);
switches.Add("-f");
switches.Add(inputFile);
processor.StartProcessing(switches.ToArray(), null);
}

いままで印刷は、PrintDocumentクラスを使用したり、xpsを用いたりと四苦八苦していたのですが、Ghostscriptで簡単に行けそうです。あぁ無料。