[VB.NET] แจกฟรีโค้ด ActiveReports.NET การพิมพ์ใบแจ้งค่าใช้จ่าย สำหรับหอพัก ห้องเช่า อพาร์ทเมนท์ แบบกระดาษครึ่ง A4
http://www.g2gnet.com/webboard/images/vbnet/RentRoom.pngหลายวันก่อนก็แจกเป็นโปรแกรมไปเรียบร้อย (สามารถดาวน์โหลดได้ที่นี่) วันนี้มาแจกเป็นโค้ดเพื่อให้ได้นำไปศึกษาเรียนรู้กันครับผม โค้ด Visual Basic .Net ที่อ่านข้อมูลจาก Excel หรือการ Import ข้อมูลจากเวิร์คชีตของตาราง Excel เข้ามาสู่ตารางกริด จากนั้นก็นำผลไปพิมพ์เป็นใบแจ้งหนี้ หรือใบแจ้งค่าใช้จ่ายด้วย ActiveReports .Net (AR)...
สำหรับการพิมพ์รายงานแบบนี้ค่อนข้างจะแปลกประหลาดไปจากที่หลายๆคนอาจจะเคยเห็นๆมา เพราะว่าเป็นการนำเอาข้อมูลจากหลักมาพิมพ์ในแนวแถวแทน โดยพิจารณาจากภาพประกอบด้านบนซึ่งเป็น Excel เริ่มต้นจากหลักที่ 3 (Index = 2) หรือหลัก C เราเอาค่าในเซลล์ C1 มาพิมพ์ลง Detail ของ AR ในแถวแรก จากนั้นเลื่อนแถวถัดไปคือเซลล์ C2 (จำนวนเงิน) แต่กลับเอามาพิมพ์ต่อในแถวเดิม แต่เลื่อนหลักไป ... งงมั้ยครับ 5555+ ... คือต้องไปดูที่โค้ดในส่วนโปรแกรมย่อย Detail ของ AR แล้วต้องทำการ Debugger จะทำให้คุณเข้าใจได้ชัดเจนขึ้นครับ ...
หัวข้อที่เกี่ยวข้อง ...
การเรียกใช้งาน ActiveReports .NET แบบเบื้องต้น
ก้าวแรกกับการพิมพ์รายงานด้วย ActiveReports .NET
พื้นฐานการพิมพ์รายงานด้วย ActiveReports .NET ลงบนกระดาษขนาด A4
แอดมินได้อธิบายรายละเอียด ActiveReports (AR) ไล่เรียงกันมาตามหัวข้อด้านบนแล้ว ดังนั้นจึงจะไม่ขออธิบายเพิ่มเติมล่ะกันครับผม ... สำหรับบทความนี้เราจะไม่ใช้งาน Excel Object แต่เป็นการใช้ OLEDB เพื่อจัดการหรือติดต่อกับไฟล์ Excel file แทน
มาดูโค้ดในส่วนของการ Import ไฟล์ Excel ด้วยการติดต่อผ่าน ADO.NET ... นั่นคือเราจะมอง Excel เป็นเสมือนไฟล์ฐานข้อมูล
' / --------------------------------------------------------------------
' / เลือกไฟล์ Excel เข้ามา
Private Sub btnBrowse_Click(sender As System.Object, e As System.EventArgs) Handles btnBrowse.Click
' ประกาศใช้งาน Open File Dialog ในแบบ Run Time
Dim dlgOpenFile As OpenFileDialog = New OpenFileDialog()
' / ตั้งค่าการใช้งาน Open File Dialog
With dlgOpenFile
.InitialDirectory = MyPath(Application.StartupPath)
.Title = "เลือกไฟล์ MS Excel"
.Filter = "MS Excel Files (*.xlsx;*.xls)|*.xlsx;*xls"
.FilterIndex = 1
.RestoreDirectory = True
End With
' / หากเลือกปุ่ม OK หลังจากการ Browse ...
If dlgOpenFile.ShowDialog() = DialogResult.OK Then
txtFileName.Text = dlgOpenFile.FileName
Dim strConn As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & _
dlgOpenFile.FileName & "; Extended Properties=""Excel 12.0 Xml; HDR=YES"";"
Dim Conn As New OleDbConnection(strConn)
Conn.Open()
' / มอง WorkSheet ให้เป็นตารางข้อมูล (Table)
Dim dtSheets As DataTable = Conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, Nothing)
Dim drSheet As DataRow
cmbSheetName.Items.Clear()
' / นำรายชื่อ WorkSheet ทั้งหมด มาเก็บไว้ที่ ComboBox เพื่อรอให้ User เลือกนำไปใช้งาน
For Each drSheet In dtSheets.Rows
cmbSheetName.Items.Add(drSheet("TABLE_NAME").ToString())
Next
Conn.Close()
'//
dgvData.Columns.Clear()
End If
End Sub
โค้ดในการติดต่อกับ WorkSheet ... เรามองเวิร์คชีตเป็นเหมือนตารางข้อมูล (Table)
' / --------------------------------------------------------------------
' / เลือก WorkSheet เพื่อนำข้อมูลมาแสดงผลในตารางกริด
Private Sub cmbSheetName_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles cmbSheetName.SelectedIndexChanged
Dim Conn As OleDbConnection
Dim Cmd As OleDbCommand
Dim DAP As OleDbDataAdapter
Dim DS As DataSet
Dim strConn As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & _
txtFileName.Text & "; Extended Properties=""Excel 12.0 Xml; HDR=YES"";"
Try
Conn = New OleDbConnection
Conn.ConnectionString = strConn
Cmd = New OleDbCommand
'// เสมือน WorkSheet เป็น Table ในฐานข้อมูล
Cmd.CommandText = "Select * FROM [" & cmbSheetName.Text & "]"
Cmd.Connection = Conn
DAP = New OleDbDataAdapter(Cmd)
DS = New DataSet
Conn.Open()
DAP.Fill(DS, "MySheet")
'// ผูกข้อมูล (Bound Data)
dgvData.DataSource = DS.Tables("MySheet")
Call InitGrid()
Catch ex As Exception
MessageBox.Show(ex.Message)
Finally
Conn = Nothing
Cmd = Nothing
DAP = Nothing
DS = Nothing
End Try
End Sub
โค้ดในส่วนของการผูก ActiveReports Designer เข้ากับ ARViewer
' / --------------------------------------------------------------------
Private Sub dgvData_DoubleClick(sender As Object, e As System.EventArgs) Handles dgvData.DoubleClick
If dgvData.Rows.Count <= 0 Then Exit Sub
' Instance name ARDesigner มันจะชี้ไปที่ไฟล์ arRentRoomBill.vb
Dim rpt As New arRentRoomBill
' โหลดรายงาน document (arRentRoomBill) เข้าสู่ ActiveReports Viewer
'// Zoom 95%
Me.Viewer1.ReportViewer.Zoom = 0.95
Me.Viewer1.Document = rpt.Document
' Run Report
rpt.Run()
End Sub
โค้ดในการตั้งค่าการพิมพ์ให้กับ ActiveReports Designer ...
' / --------------------------------------------------------------------
' / ก่อนเริ่มการพิมพ์มาตั้งค่าให้ Report ก่อน
Private Sub arRentRoomBill_ReportStart(sender As Object, e As System.EventArgs) Handles Me.ReportStart
'/ การตั้งค่าหน้ากระดาษ
With PageSettings
' หน่วยวัดเป็นนิ้ว
.Margins.Left = CmToInch(1) ' แปลงค่า 1.0 ซม. เป็นนิ้ว
.Margins.Right = 0.1
.Margins.Top = 0.5
.Margins.Bottom = 0.2
' ตั้งค่ากระดาษแนวตั้ง
.Orientation = PageOrientation.Portrait
' กระดาษขนาด A4
'.PaperKind = Drawing.Printing.PaperKind.A4
' กรณีที่กำหนดขนาดกระดาษเอง
.PaperKind = Drawing.Printing.PaperKind.Custom
.PaperWidth = CmToInch(21) ' 21 ซม.
.PaperHeight = CmToInch(14.8)
End With
'/ ปกติต้องเคลียร์ค่าต่างๆของ TextBox ก่อนการพิมพ์
txtItem.Text = ""
txtDesc.Text = ""
txtHeader.Text = ""
txtUnitPrice.Text = ""
txtQTY.Text = ""
txtAmount.Text = ""
txtGrandTotal.Text = ""
'// แสดงกิจการและที่อยู่ โดยการอ่านค่าจาก INI (Initialized File)
Dim strFileINI As String = MyPath(Application.StartupPath) & "Config.ini"
If My.Computer.FileSystem.FileExists(strFileINI) Then
txtOwner.Text = ReadIni(strFileINI, "Config", "Owner", "")
txtAddress.Text = ReadIni(strFileINI, "Config", "Address", "")
txtHeader.Text = ReadIni(strFileINI, "Config", "Header", "")
lblRemark1.Text = ReadIni(strFileINI, "Config", "Remark1", "")
lblRemark2.Text = ReadIni(strFileINI, "Config", "Remark2", "")
'// กรณีไม่เจอ ให้เริ่มต้นค่าใหม่
Else
txtOwner.Text = "ทองก้อน ฮาเร็ม อพาร์ทเมนท์"
txtAddress.Text = "123/456 ถ.กลางเมือง ต.เมืองเก่า อ.เมือง จ.ขอนแก่น โทร.043-XXX-XXX"
txtHeader.Text = "- ใบแจ้งค่าใช้จ่าย -"
lblRemark1.Text = " กรุณาชำระเงินภายในวันที่ 32 ของทุกเดือน"
lblRemark2.Text = " การเงินมีปัญหา ใส่ชุดนักศึกษามาหาป๋าทองก้อนได้ตลอด 24 ชั่วโมง"
End If
txtDate.Text = FormatDateTime(Now(), DateFormat.GeneralDate)
'// อ่านค่าชื่อ WorkSheet มาพิมพ์ประจำเดือน (ตัวอย่าง "สิงหาคม 2560")
Dim strMonth As String = frmMainBill.cmbSheetName.Text
'// ตัดคำที่ไม่ต้องการคือ $
strMonth = strMonth.Replace("'", "").Replace("[ DISCUZ_CODE_3 ]quot;, "")
txtDateReciept.Text = strMonth
'// รับค่า "แถว" ที่ถูกเลือกในตารางกริด
sRow = frmMainBill.dgvData.CurrentRow.Index
'// หลักแรกกับหลักที่ 2
txtCname.Text = frmMainBill.dgvData.Rows(sRow).Cells(0).Value
txtRoomNo.Text = frmMainBill.dgvData.Rows(sRow).Cells(1).Value
End Sub
โค้ดในส่วนของการพิมพ์รายละเอียด ... ขอให้สังเกตว่า ข้อมูลการพิมพ์มันจัดเรียงต่อกันในแนวนอน แต่จริงๆเราจะต้องเอาทีละหลักมาพิมพ์
' / --------------------------------------------------------------------
Private Sub Detail1_Format(sender As Object, e As System.EventArgs) Handles Detail1.Format
'// ItemNo หรือลำดับที่ โดยจะเริ่มจาก 1
txtItem.Text = ItemNo
With frmMainBill
'// อ่านค่าเริ่มจากหลัก 2 ดังนั้น ItemNo จึงต้อง +1 เพื่ออ่านค่าจาก Header มาแสดงผล
'// โดยเรียงตามลำดับ --> ค่าเช่าห้อง(หลักที่ 2), ค่าไฟฟ้า(3), ค่าน้ำ(4), ค่าอินเทอร์เน็ต(5), ค่าเคเบิ้ลทีวี(6) และค่าเก็บขยะ(7)
txtDesc.Text = .dgvData.Columns(ItemNo + 1).HeaderText
txtQTY.Text = "1"
'// อ่านค่าข้อมูลจากแถวที่เลือกมา (sRow) และข้อมูลอยู่ในหลัก 2 (และเลื่อนหลักถัดๆไป)
txtUnitPrice.Text = Format(Val(.dgvData.Rows(sRow).Cells(ItemNo + 1).Value), "#,##0.00")
txtAmount.Text = txtUnitPrice.Text
End With
' รวมจำนวนเงินผ่านทางตัวแปร
GrandTotal = GrandTotal + CDbl(txtUnitPrice.Text)
txtGrandTotal.Text = "รวมเงิน: " & Format(GrandTotal, "#,##0.00") & " บาท."
End Subส่วนสำคัญ ... ต้องใจเย็นๆช้าๆในการไล่แกะและทำความเข้าใจกับโค้ดครับ เพราะเป็นการอ่านค่าจากแถวใดแถวหนึ่ง (sRow) ที่เลือกขึ้นมา แต่ข้อมูลที่จะพิมพ์จะไล่ไปทีละหลัก คืออ่านค่าข้อมูลในแนวนอนตั้งแต่หลักที่ 2 (ค่า Index) แต่เอาข้อมูลในหลักนั้นมาพิมพ์ทีละแถวเรียงลงไปแทน ...
โค้ดในส่วนของการตรวจสอบว่าหมดข้อมูล (จำนวนหลัก) ที่จะพิมพ์แล้วหรือยัง ...
' ตัวแปรนี้ต้องประกาศเป็นแบบ Public (เฉพาะ arRoomReciept) เพื่อให้ส่วนของ Detail1_Format และ FetchData มองเห็นด้วย
Private ItemNo As Integer
Private GrandTotal As Double
'// เลือกจากแถวในตารางกริด
Private sRow As Integer
' / --------------------------------------------------------------------
' / จะเกิดการนับตามจำนวนหลักคือ 6 หลัก ข้อมูลการพิมพ์ก็จะหมด eArgs.EOF = True
Private Sub arRentRoomBill_FetchData(sender As Object, eArgs As DataDynamics.ActiveReports.ActiveReport.FetchEventArgs) Handles Me.FetchData
ItemNo = ItemNo + 1
'/ ตรวจสอบจำนวนการพิมพ์ทั้งหมด ซึ่งจะมีทั้งหมด 6 หลัก
'/ 2 หลักแรกคือ ชื่อผู้เช่า (0) และ หมายเลขห้อง (1) เราพิมพ์ที่ PageHeader ไปแล้ว ก็ให้ข้ามไป
'/ หลักที่ต้องนำมาพิมพ์ตามแถวเรียงตามลำดับ --> ค่าเช่าห้อง(หลักที่ 2), ค่าไฟฟ้า(3), ค่าน้ำ(4), ค่าอินเทอร์เน็ต(5), ค่าเคเบิ้ลทีวี(6) และค่าเก็บขยะ(7)
If ItemNo > 6 Then
'/ หากหมดแล้วก็จบการพิมพ์
eArgs.EOF = True
Exit Sub
'/ ยังไม่หมดข้อมูล
Else
eArgs.EOF = False
End If
End Subกรณีที่จำนวนหลักในไฟล์ Excel เปลี่ยนแปลงไปไม่ตรงกับตัวอย่าง ... แอดมินวางยาเอาไว้แถวๆนี้แหละ หากเข้าใจในตัวโค้ดก็จะแก้ปัญหาได้ครับ อิอิอิอิ
สำหรับโค้ดเรื่องของ Initialize File หรือ INI แอดมินขอแยกมาอยู่อีกหัวข้อหนึ่งล่ะกันครับ การประยุกต์ใช้งานไฟล์ INI (Initialize File) มาทำการเก็บข้อมูลขนาดเล็ก
ดาวน์โหลดโค้ดต้นฉบับแบบเต็ม VB.NET (2010) ได้ที่นี่
ขอบคุณครับ ขอบคุณครับ ขอบคุณครับ เริ่ม VB.Net อีกครั้ง(ไม่รู้ครั้งที่เท่าไหร่ครับเฮีย 55555)
หน้า:
[1]