■VB.Netによる開発その4(印刷)
PostgreSQLのデータを読み込んで以下のような帳票(A4横)を印刷をしてみます。
印刷は自作のクラスを使います。
ここで公開しているソースをcls_Print_としてプログラムに組み込みます。
●Form1変数
'### 印刷用構造体
####################################################################
Private Structure P_Rec_
Public
P_Kubun As Integer
'区分
Public P_date As
Date
'日付
Public P_code As
String
'商品コード
Public P_name As
String
'商品名
Public P_quantity As Decimal
'数量
Public P_price As
Decimal '単価
Public P_money As Decimal '金額
End
Structure
'### 印刷データ保持用ジェネリックコレクション
###################################################
Private p_List As System.Collections.Generic.List(Of
P_Rec_)
'### 印刷開始フラグ ##############
Private Fl_Print_First As
Boolean
○PrintDocumentに直接データを渡せないのでForm変数を作成して参照する事とします。
DBのデータを読み込んでジェネリックコレクションに追加、ジェネリックコネクションから
データを取り出して印刷する事とします。
●印刷開始
'DBデータから印刷
Dim pPaperSz As
System.Drawing.Printing.PaperKind
Dim pkSize As
System.Drawing.Printing.PaperSize
'###
データベースから印刷用データを配列へセット
###############################
If
Print_data_make() = False
Then
Exit
Sub
End
If
'###
プリンター名を直接指定して印刷
############################################
PrintDocument3.PrinterSettings.PrinterName = "PrimoPDF"
'###
印刷用紙サイズ設定
#######################################################
pPaperSz =
Printing.PaperKind.A4
'A4 サイズの定数
'サポートされている用紙サイズの一覧を取得
For Each
pkSize In
PrintDocument3.PrinterSettings.PaperSizes
'指定の用紙サイズがサポートされているか
If pkSize.Kind = pPaperSz
Then
'指定の用紙サイズが見つかったら用紙サイズを設定する
PrintDocument3.DefaultPageSettings.PaperSize =
pkSize
End
If
Next
'###
用紙方向横向き/縦向きで印刷
################################################
PrintDocument3.DefaultPageSettings.Landscape =
True '横向き
'###
印刷ドキュメント名設定
######################################################
PrintDocument3.DocumentName = DateTime.Now.ToString("yyyyMMdd_HHmmss") &
"_TestPrint" '印刷ドキュメント名設定
'### 印刷開始フラグ
##############################################################
Fl_Print_First =
True
'### 印刷
########################################################################
PrintDocument3.Print()
○普通の印刷とほぼ同じです。Print_data_make()
がデータベースを読み込んで
ジェネリックコネクションへ追加するルーチンです。
●データベースを読み込んでジェネリックコネクションへ追加
Private Function Print_data_make() As
Boolean
'印刷データを作成する
Dim cn As New
NpgsqlConnection 'コネクション
Dim dr As
NpgsqlDataReader
'DataReadr
Dim cmd As New
NpgsqlCommand 'SQL発行用
Dim W_Sql As
String
'SQL作成用
Dim W_Rec As New
P_Rec_
'構造体(明細用)
Dim Fl_Open As Boolean =
False 'DBオープンフラグ
Dim W_Kei As
Decimal = 0
'金額合計ワーク
'### 接続設定
###
cn.ConnectionString = "Server=[サーバのIPアドレス];Port=[接続に使用するポート];User
Id=[ユーザー];Password=[パスワード];Database=[接続するDB名];Preload Reader = true;"
'### 処理開始
###
Try
'---
接続 ---
cn.Open()
Fl_Open = True
W_Sql = "SELECT sal.date AS date , sal.code AS code , item.name AS name " &
_
", sal.quantity AS quantity , sal.price AS price , sal.money AS money " &
_
"FROM ms_sales sal JOIN cm_item item on sal.code = item.code " &
_
"ORDER BY sal.date , sal.code , sal.id "
'--- DataReaderを使用したデータの読込
---
cmd =
New NpgsqlCommand(W_Sql,
cn)
dr =
cmd.ExecuteReader
p_List = New System.Collections.Generic.List(Of P_Rec_)
'印刷データ配列初期化
'--- データを読み込んで配列に追加
---
While
dr.Read
W_Rec = New
P_Rec_
W_Rec.P_Kubun =
0
W_Rec.P_date =
dr("date")
W_Rec.P_code =
dr("code")
W_Rec.P_name =
dr("name")
W_Rec.P_quantity =
dr("quantity")
W_Rec.P_price =
dr("price")
W_Rec.P_money = dr("money")
W_Kei = W_Kei +
dr("money")
p_List.Add(W_Rec)
End While
'--- 最終レコード(合計)追加
---
W_Rec.P_Kubun =
1
W_Rec.P_date =
DateTime.Now
W_Rec.P_code =
0
W_Rec.P_name =
""
W_Rec.P_quantity =
0
W_Rec.P_price =
0
W_Rec.P_money = W_Kei
p_List.Add(W_Rec)
dr.Close()
Return True
Catch ex As Exception
MessageBox.Show("エラーが発生しました" &
ex.Message)
Return True
Finally
'--- 切断
---
If
Fl_Open = True
Then
cn.Close()
End If
End
Try
End
Function
○データを取り出してジェネリックコネクションへ追加します。
VB.Netは印刷部が変わったので合計等はこちらでセットするのが良いのかなと思います。
●印刷実装部
Private Sub PrintDocument3_PrintPage(sender As System.Object, e As
System.Drawing.Printing.PrintPageEventArgs) Handles
PrintDocument3.PrintPage
'---
印刷・配列から
-----------------------------
Static W_Page As Long
'ページ数
Static W_Gyo As
Long
'行数
Static Data_Count As
Long
'配列のカウンタ
Dim clsPrt As
New cls_print_ '印刷クラス
'プリンタの初期設定を行う
clsPrt.Printer_Setting(e, Me.PrintDocument1, New Point(140, 50))
'印刷初回設定
If Fl_Print_First = True
Then
W_Page = 0
Data_Count =
0
Fl_Print_First = False
End If
'ヘッダー印刷
W_Page = W_Page
+ 1
clsPrt.Print_Moji(e, New PointF(20, 1),
"*** 売上一覧 ***")
clsPrt.Print_Moji(e, New PointF(57, 1), "Date:" &
DateTime.Now.ToString("yyyy/MM/dd
HH:mm"))
clsPrt.Print_Moji(e, New PointF(80, 1), "Page:" &
W_Page.ToString("###"))
clsPrt.Print_Moji(e, New PointF(8, 4),
"日 付")
clsPrt.Print_Moji(e, New
PointF(18, 4), "商品名")
clsPrt.Print_Moji(e, New PointF(56, 4),
"数量")
clsPrt.Print_Moji(e, New
PointF(69, 4), "単価")
clsPrt.Print_Moji(e, New PointF(84, 4), "金額")
'罫線印刷
'横
clsPrt.Draw_Line(e, New
PointF(5, 3), New PointF(89, 3))
For i10 As Integer = 6 To 26 Step
2
'太さ・破線の間隔を省略
clsPrt.Draw_Line(e, New PointF(5, i10), New PointF(89,
i10))
Next
'縦
clsPrt.Draw_Line(e, New
PointF(5, 3), New PointF(5, 26))
clsPrt.Draw_Line(e, New PointF(17, 3), New PointF(17,
26))
clsPrt.Draw_Line(e, New
PointF(49, 3), New PointF(49, 26))
clsPrt.Draw_Line(e, New PointF(61, 3), New PointF(61,
26))
clsPrt.Draw_Line(e, New
PointF(74, 3), New PointF(74, 26))
clsPrt.Draw_Line(e, New PointF(89, 3), New PointF(89, 26))
'明細印刷
'初期化
W_Gyo = 0
Do
If
p_List(Data_Count).P_Kubun = 0
Then
clsPrt.Print_Moji(e, New PointF(6, 6 + W_Gyo * 2),
p_List(Data_Count).P_date.ToString("yyyy/MM/dd"))
clsPrt.Print_Moji(e, New PointF(18, 6 + W_Gyo * 2),
p_List(Data_Count).P_name)
clsPrt.Print_Moji(e, New PointF(49, 6 + W_Gyo * 2),
p_List(Data_Count).P_quantity.ToString("#,###"), 11,
"R")
clsPrt.Print_Moji(e, New PointF(61, 6 + W_Gyo * 2),
p_List(Data_Count).P_price.ToString("#,###"), 12,
"R")
clsPrt.Print_Moji(e, New PointF(74, 6 + W_Gyo * 2),
p_List(Data_Count).P_money.ToString("#,###"), 14,
"R")
Else
clsPrt.Print_Moji(e, New PointF(18, 6 + W_Gyo * 2),
"●● 合 計 ●●")
clsPrt.Print_Moji(e, New PointF(74, 6 + W_Gyo * 2),
p_List(Data_Count).P_money.ToString("#,###"), 14,
"R")
End If
W_Gyo = W_Gyo +
1
Data_Count = Data_Count + 1
If Data_Count >= p_List.Count
Then
e.HasMorePages =
False
Exit Sub
End If
If
W_Gyo > 9
Then
e.HasMorePages =
True
Exit Sub
End If
Loop
End
Sub
○印刷実装部です。
・Fl_Print_First
による初回判定
変数宣言と同時に0クリアすると1回目の印刷は良い物の、2回目の印刷で初期化されません。
その為Form変数でフラグを持ち、他の初期化処理を含めて行っています。
・Data_Count
配列の何行目かを管理する変数です。上記フラグで印刷開始時にクリアされます。
※あとはさほど特別な処理は無いと思います。
改ページでルーチンを一旦抜ける事を考えると事前のデータである程度
出力する形にデータを整えておいて印刷側は簡単にすると良いと思います。
印刷はクラスで簡単になっているかな?市販の印刷用ソフトなんかを使ってみたいですね。
まだ思考錯誤中なので意見・アドバイス等あればブログまでお願いします。
トップへ戻る