- - PR -
動的なPDFファイルの作成
1
| 投稿者 | 投稿内容 | ||||
|---|---|---|---|---|---|
|
投稿日時: 2004-11-22 11:50
お世話になります。現在、ASP.Net、VisualStudio2003の環境で、C#を使用した
Webアプリを作成しております。今やりたいことは、クライアント側に表示されて いるWebフォーム上で、任意の検索条件を指定し、ボタンを押すことにより、検索 条件に合致するデータをDBから取得し、そのデータを元にPDFファイルをサーバー 上に作成し、その後すぐにクライアント側にダウンロードのダイアログを表示した いのですが、その方法が分かりません。DBから取得したデータを元にPDFを表示するだ けなら、現在FDFを使用して実現可能となっております。また、DBから取得したデ ータを元にExcelファイルをサーバーに作成し、クライアント側にダイアログを出 すことも実現可能となっております。サーバーにAcrobatを入れれば実現可能とい うことを聞きましたが、今回はなるべくサーバーにAcrobatを入れないで、かつ商 用のライブラリなどを使用しない(=お金を全くかけないで)PDFを作成する方法を調 査しております。FDFのみでは実現不可能といった話も耳にしました。どなたかご存 知の方がおりましたらご教示いただければと思います。 | ||||
|
投稿日時: 2004-11-22 20:23
はじめまして。
以前私もTottiさんと同じような開発を行いました。 そのときはiTextSharpを使用してブラウザ上で非同期にPDFファイルを生成させました。 罫線つきのテーブルも結構簡単に組めますよ。 http://homepage3.nifty.com/dotnetfan/tool/tool02.html http://itextsharp.sourceforge.net/index.html | ||||
|
投稿日時: 2004-11-26 16:21
とっちんさん、ご返答まことにありがとうございます。そして返信が遅くなり、大変申し訳ありませんでした。とっちんさんの言うように、iTextSharpで行うのがベストかなと思い、iTextSharpを使用してコーディングを行おうと思ったのですが、前回書き込みさせていただいた内容には記載しませんでしたが、今回行いたいのはフォーマットが決まっているPDFファイルに値を埋め込むといったことをやりたいのですが、iTextSharpのサイトなどに記載されておりますチュートリアルを見てもそれらしきことは載っていませんでした。(何分英文のチュートリアルなので、英語力のない私が見落としているだけかもしれませんが(^^ | ||||
|
投稿日時: 2004-11-26 16:33
どもです。がるです。
ちっと蛇足ちっくなお話で恐縮なのですが。
んっと。この手のは気をつけないとセキュリティホールになると 思います。 Tottiさんがおっしゃってる手順は データを入力-> DBから該当データを取得 PDFファイルを作成 <-PDFファイルを指し示す識別子を含むURLを返却 URLをクリック-> <-PDFファイルを出力 PDFファイルをゲット って感じだとおもうのですが。これだと、URLを適当に 偽装されたり総アタックかけられたりすると、他人のPDFが getできてしまう可能性があります。 可能なら データを入力-> DBから該当データを取得 PDFファイルを作成 <-PDFファイルを出力 PDFファイルをゲット という流れで、実ファイルを作らないようにしたほうがより 安全かなぁ、と思います。 蛇足ですが。 | ||||
|
投稿日時: 2004-11-26 20:52
こんにちは。
iTextSharpは基本的に動的にPDFを生成するもののようですね。 がるがるさんのご指摘ももっともですし、できればフォーマットも含め動的に生成する方がスマート(ではないかも?)ではないでしょうか。 Tottiさんのフォーマットとは複雑なものなのでしょうか? 例えば、 iTextSharp.textとiTextSharp.text.pdfをbinに配置しImportします。 DBから取得したデータはDataTable(tbl)に格納してあるものとします。 Dim ds As System.Data.DataSet ds = New System.Data.DataSet("pdfds") Dim tbl As System.Data.DataTable = ds.Tables.Add("pdftbl") Dim row As System.Data.DataRow '商品か何かのコード tbl.Columns.Add("id", System.Type.GetType("System.Int32")) '商品か何かの名前 tbl.Columns.Add("name", System.Type.GetType("System.String")) '売上年月(200412と200312) tbl.Columns.Add("yym", System.Type.GetType("System.Int32")) '売上週(1〜5) tbl.Columns.Add("week", System.Type.GetType("System.Int32")) '売上数量 tbl.Columns.Add("suryo", System.Type.GetType("System.Double")) 'データテーブルのソート処理 Dim resultrow() As System.Data.DataRow Dim rowx As System.Data.DataRow resultrow = tbl.Select("", "id") 'PDFドキュメント生成処理 Dim doc As new Document(PageSize.A3.rotate(), 30, 30, 30, 30) Dim strpdfpath As String = "c:\inetpub\wwwroot\test\test.pdf" Try Dim w As PdfWriter w = PdfWriter.getinstance(doc, new FileStream(strpdfpath, FileMode.Create)) Dim bf As BaseFont = BaseFont.CreateFont("c:\\windows\\fonts\\msgothic.ttc, 0", _ BaseFont.IDENTITY_H, _ BaseFont.EMBEDDED) Dim gtfont As Font = new Font(bf, 9, Font.NORMAL) Dim headertxt As String Dim dt As DateTime = DateTime.Now() Dim strdate As String = dt.ToString("yy/MM/dd") Dim strtime As String = dt.ToString("HH:mm:ss") headertxt = "【 タイトル2004年12月 前年対比 】" & _ strdate & " " & strtime & " Page : " Dim header As HeaderFooter = new HeaderFooter(new Phrase(headertxt, gtfont), true) header.Border = Rectangle.NO_BORDER doc.Header = header doc.Open() 'PDF出力用ワーク変数宣言 Dim dblsuryo(1, 5) As Double Dim intid As Integer Dim strname As String Dim strvalue As String Dim dblvalue As Double Dim dblp1 As Double Dim dblp2 As Double Dim intline As Integer = 0 Dim i As Integer = 0 Dim j As Integer Dim k As Integer 'PDFテーブル設定 Dim itbl As iTextSharp.text.Table itbl = new iTextSharp.text.Table(19) Dim headerwidth As Single() = _ {10, 5.5, 5.5, 4, 5.5, 5.5, 4, 5.5, 5.5, 4, 5.5, 5.5, 4, 5.5, 5.5, 4, 5.5, 5.5, 4} itbl.Widths = headerwidth itbl.WidthPercentage = 100 '※手動で罫線を引く場合には0を指定 itbl.DefaultCellBorderWidth = 1 itbl.Padding = 0 itbl.Spacing = 1 'データテーブルをループしPDF出力 For Each rowx In resultrow If i = 0 Then '配列初期化 For j = 0 To 1 For k = 0 To 5 dblsuryo(j, k) = 0 Next Next '比較用変数セット intid = CType(rowx("id"), Integer) strname = CType(rowx("name"), String) i = 1 End If 'idが変わった場合 If intid <> CType(rowx("id"), Integer) Then 'ヘダー出力 itbl.DefaultHorizontalAlignment = Element.ALIGN_CENTER itbl.DefaultColspan = 1 itbl.DefaultRowspan = 2 itbl.addCell(new Phrase("商品", gtfont)) itbl.DefaultColspan = 3 itbl.DefaultRowspan = 1 itbl.addCell(new Phrase("第1週", gtfont)) itbl.addCell(new Phrase("第2週", gtfont)) itbl.addCell(new Phrase("第3週", gtfont)) itbl.addCell(new Phrase("第4週", gtfont)) itbl.addCell(new Phrase("第5週", gtfont)) itbl.addCell(new Phrase("合計", gtfont)) itbl.DefaultColspan = 1 itbl.DefaultRowspan = 1 itbl.addCell(new Phrase("当年実績", gtfont)) itbl.addCell(new Phrase("前年実績", gtfont)) itbl.addCell(new Phrase("前年比", gtfont)) itbl.addCell(new Phrase("当年実績", gtfont)) itbl.addCell(new Phrase("前年実績", gtfont)) itbl.addCell(new Phrase("前年比", gtfont)) itbl.addCell(new Phrase("当年実績", gtfont)) itbl.addCell(new Phrase("前年実績", gtfont)) itbl.addCell(new Phrase("前年比", gtfont)) itbl.addCell(new Phrase("当年実績", gtfont)) itbl.addCell(new Phrase("前年実績", gtfont)) itbl.addCell(new Phrase("前年比", gtfont)) itbl.addCell(new Phrase("当年実績", gtfont)) itbl.addCell(new Phrase("前年実績", gtfont)) itbl.addCell(new Phrase("前年比", gtfont)) itbl.addCell(new Phrase("当年実績", gtfont)) itbl.addCell(new Phrase("前年実績", gtfont)) itbl.addCell(new Phrase("前年比", gtfont)) '明細出力 itbl.DefaultColspan = 1 itbl.DefaultRowspan = 1 strvalue = CType(intid, String) & " : " & strname itbl.DefaultHorizontalAlignment = Element.ALIGN_LEFT itbl.addCell(new Phrase(strvalue, gtfont)) itbl.DefaultHorizontalAlignment = Element.ALIGN_RIGHT For k = 0 To 5 For j = 0 To 1 strvalue = Format(dblsuryo(j, k), "#,##0") itbl.addCell(new Phrase(strvalue, gtfont)) Next dblp1 = 0 dblp2 = 0 '前年比 If dblsuryo(0, k) <> 0 and _ dblsuryo(1, k) <> 0 Then dblvalue = dblsuryo(0, k) / dblsuryo(1, k) * 100 dblp1 = Math.Floor(dblvalue * 10 + 0.5) dblp2 = dblp1 * 0.1 End If If dblp2 = 0 or dblp2 > 9999 Then strvalue = "-----" Else strvalue = Format(dblp2, "#,##0.0") & "%" End If itbl.addCell(new Phrase(strvalue, gtfont)) Next '配列初期化 For j = 0 To 1 For k = 0 To 5 dblsuryo(j, k) = 0 Next Next '比較用変数セット intid = CType(rowx("id"), Integer) strname = CType(rowx("name"), String) End If If intline >= 12 Then '改ページ処理 doc.Add(itbl) doc.newPage() intline = 0 'PDFテーブル設定 itbl = new iTextSharp.text.Table(19) itbl.Widths = headerwidth itbl.WidthPercentage = 100 '※手動で罫線を引く場合には0を指定 itbl.DefaultCellBorderWidth = 1 itbl.Padding = 0 itbl.Spacing = 1 End If '配列格納処理 If CType(rowx("yym"), Integer) = 200412 Then j = 0 Else j = 1 End If k = CType(rowx("week"), Integer) - 1 '数量集計処理 dblsuryo(j, k) += CType(rowx("suryo"), Integer) dblsuryo(j, 6) += CType(rowx("suryo"), Integer) Next 'idが変わった場合と同じ処理 '(中略) doc.Add(itbl) Catch de As DocumentException Return -1 Exit Function Catch ioe As IOException Return -1 Exit Function Catch ex As Exception Return -1 Exit Function Finally doc.Close() End Try こんな感じでDBから読み込んだデータを罫線つきで出力できます。 もっと複雑なフォーマットで罫線を自分で引きたい場合には、 Dim intx As Integer Dim inty As Integer Dim cb As PdfContentByte = w.DirectContent '縦外枠&区切り線出力 cb.LineWidth = 2 intx = 30 inty = 813 cb.moveTo(intx, inty) cb.lineTo(intx, 417) intx = 112 cb.moveTo(intx, inty) cb.lineTo(intx, 417) For i = 0 To 8 cb.moveTo(intx, inty) cb.lineTo(intx, 417) intx += 131 Next cb.stroke() '縦区切り線出力 cb.LineWidth = 1 intx = 164 inty = 813 cb.moveTo(intx, inty) cb.lineTo(intx, 417) For i = 0 To 7 cb.moveTo(intx, inty) cb.lineTo(intx, 417) intx += 39 cb.moveTo(intx, inty) cb.lineTo(intx, 417) intx += 92 Next cb.stroke() '横太枠区切り線出力 cb.LineWidth = 2 intx = 30 inty = 813 cb.moveTo(intx, inty) cb.lineTo(1160, inty) inty = inty - 11 For i = 0 To 35 If i = 0 or i = 1 or i = 4 or _ i = 5 or i = 13 or _ i = 20 or i = 24 or _ i = 27 or i = 35 Then cb.moveTo(intx, inty) cb.lineTo(1160, inty) End If inty = inty - 11 Next cb.stroke() '横明細区切り線 cb.LineWidth = 1 intx = 30 inty = 813 cb.moveTo(intx, inty) cb.lineTo(1160, inty) inty = inty - 11 For i = 0 To 35 If i <> 0 or i <> 1 or i <> 4 or _ i <> 5 or i <> 13 or _ i <> 20 or i <> 24 or _ i <> 27 or i <> 35 Then cb.moveTo(intx, inty) cb.lineTo(1160, inty) End If inty = inty - 11 Next cb.stroke() こんな感じでいかがでしょうか? フリーのソフトなので、このへんが限界かもしれませんね。 | ||||
1
