|
หลายวันก่อนก็แจกเป็นโปรแกรมไปเรียบร้อย (สามารถดาวน์โหลดได้ที่นี่) วันนี้มาแจกเป็นโค้ดเพื่อให้ได้นำไปศึกษาเรียนรู้กันครับผม โค้ด Visual Basic .Net ที่อ่านข้อมูลจาก Excel หรือการ Import ข้อมูลจากเวิร์คชีตของตาราง Excel เข้ามาสู่ตารางกริด จากนั้นก็นำผลไปพิมพ์เป็นใบแจ้งหนี้ หรือใบแจ้งค่าใช้จ่ายด้วย ActiveReports .Net (AR) ...
สำหรับการพิมพ์รายงานแบบนี้ค่อนข้างจะแปลกประหลาดไปจากที่หลายๆคนอาจจะเคยเห็นๆมา เพราะว่าเป็นการนำเอาข้อมูลจากหลักมาพิมพ์ในแนวแถวแทน โดยพิจารณาจากภาพประกอบด้านบนซึ่งเป็น Excel เริ่มต้นจากหลักที่ 3 (Index = 2) หรือหลัก C เราเอาค่าในเซลล์ C1 มาพิมพ์ลง Detail ของ AR ในแถวแรก จากนั้นเลื่อนแถวถัดไปคือเซลล์ C2 (จำนวนเงิน) แต่กลับเอามาพิมพ์ต่อในแถวเดิม แต่เลื่อนหลักไป ... งงมั้ยครับ 5555+ ... คือต้องไปดูที่โค้ดในส่วนโปรแกรมย่อย Detail ของ AR แล้วต้องทำการ Debugger จะทำให้คุณเข้าใจได้ชัดเจนขึ้นครับ ...
หัวข้อที่เกี่ยวข้อง ...
การเรียกใช้งาน ActiveReports .NET แบบเบื้องต้น
[VB.NET] ก้าวแรกกับการพิมพ์รายงานด้วย ActiveReports .NET
[VB.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 = "[1] กรุณาชำระเงินภายในวันที่ 32 ของทุกเดือน"
- lblRemark2.Text = "[2] การเงินมีปัญหา ใส่ชุดนักศึกษามาหาป๋าทองก้อนได้ตลอด 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) ได้ที่นี่
|
ขออภัย! โพสต์นี้มีไฟล์แนบหรือรูปภาพที่ไม่ได้รับอนุญาตให้คุณเข้าถึง
คุณจำเป็นต้อง ลงชื่อเข้าใช้ เพื่อดาวน์โหลดหรือดูไฟล์แนบนี้ คุณยังไม่มีบัญชีใช่ไหม? ลงทะเบียน
x
|