Data Report
Visual Basic 6 เป็นเวอร์ชันแรกที่เพิ่ม report writer ภายใน IDE เมื่อเปรียบเทียบกับ Crystal report แล้ว DataReport designer ใช้ได้ง่ายกว่า แต่ส่วนประกอบหลายอย่างและไม่สามารถทำงานหนักได้ดีเท่ากับ Crystal report
การใช้ DataReport designer ต้องทำการเพิ่มเข้าไปใน IDE ด้วยการไปที่เมนู Project แล้วเลือกคำสั่ง Component เมื่อไดอะล๊อกบ๊อกซ์ Component เปิดขึ้นมา ให้คลิกแท็บ Designer แล้วเลือก check box ของ DataReport แล้วคลิกที่ ok เพื่อปิดไดอะล๊อกบ๊อกซ์ หรือสร้าง data project ใหม่ และให้ Visual Basic สร้าง instance ของ DataReport designer
DataReport designer ทำงานในโหมด bound อย่างเดียว ทำให้สามารถดึงข้อมูล และส่งไปยังเครื่องพิมพ์หรือแสดงรายการใน Preview window โดยอัตโนมัติ DataReport designer สามารถส่งออกรายงานเป็นไฟล์ข้อความ หรือไฟล์ HTML และสนับสนุนรูปแบบกำหนดเอง
DataReport designer มากับกลุ่มของตัว Control ที่ใช้ได้รูปถึง Lines, Shapes, Images และฟังก์ชันที่นำมาใช้การสร้างฟิลด์ผลรวมในรายงาน การส่งพิมพ์ไปเครื่องพิมพ์เป็นการส่งในโหมด Asynchronous ที่ทำให้ผู้ใช้สามารถพิมพ์งานขณะที่กำลังพิมพ์งาน
ไอคอน |
ชื่อ Class |
ชื่อ Class |
คำอธิบาย |
|
RptLabel |
RptLabel |
สร้างป้าย ข้อความ เหมือน Label |
|
RptTextBox |
RptTextBox |
ข้อความ หรือข้อมูลของฟิลด์ เหมือน Text box |
|
RptPicture |
RptPicture |
แสดงภาพ เหมือน Image |
|
RptLine |
RptLine |
เส้น |
|
RptShape |
RptShape |
รูปทรง เช่น สี่เหลี่ยม วงกลม |
|
RptFunction |
RptFunction |
ประยุกต์ฟังก์ชัน |
การทำงานเมื่อออกแบบ
วิธีง่ายที่สุดในการสร้างรายงานด้วย DataReport คือ ทำงานร่วมกับ DataEnvironment designer ซึ่ง DataReport designer สนับสนุนการ drag-and-drop ของอ๊อบเจค command ใน DataEnvironment designer รวมถึงอ๊อบเจค Hierarchical command ข้อจำกัดคือรายงานสามารถมี Recordset ลูกได้เพียง 1 ระดับ ในแต่ละระดับ nesting ตัวอย่างที่จะกล่าวถึงเป็นการใช้อ๊อบเจค Hierarchical command ที่มาจาก table "Orders" และ "Order Details" ในฐานข้อมูล NWind.mdb
การรวมกับอ๊อบเจค Command
การสร้างรายงานที่มาจากอ๊อบเจค Hierarchical command มีวิธีการดังนี้
1. สร้าง Hierarchical command "Orders" มี Command ลูก คือ "Order Details" และตรวจสอบค่าได้ถึงสารสนเทศที่สนใจ เช่น โดยการรวมกับ Hierarchical Flexgrid บนฟอร์มและเรียกใช้คำสั่งประยุกต์
2. สร้าง instance ของ DataReport designer หรือใช้ provider ที่เป็น provider เริ่มต้น ใน Data project ของ Visual Basic Project
3. เรียกตารางคุณสมบัติ ของ DataReport แล้วกำหนดให้คุณสมบัติ DataSource ชี้ที่ DataEnvironment1 (หรือชื่อที่ตั้งไว้) และตั้งค่าคุณสมบัติ DataMember เป็น Orders
4. คลิกเมาส์ปุ่มขวาบนส่วนหัวรายงาน(Report header) ของ DataReport designer และเลือกคำสั่ง Retrieve Structure เพื่อสร้างส่วนกลุ่มหัวและส่วนกลุ่มล่าง ซึ่งมีชื่อ Orders_header และ Orders_footer สำหรับส่วนรายละเอียด มีชื่อ Order_Details_detail
ส่วนที่เป็นบล็อกของข้อมูล ที่จะทำสำหรับแต่ละเรคคอร์ดในอ๊อบเจค Command แม่ ส่วนเรคคอร์ดตรงกับอ๊อบเจค Command แม่ ส่วนที่สองเป็น Command ลูก และมาถึงส่วนรายละเอียดซึ่งตรงกับอ๊อบเจค Command ชั้นในที่สุด ส่วนทั้งหมดยกเว้นส่วนรายละเอียดจะแบ่งเป็นส่วนหัวและส่วนล่าง ซึ่งจะพิมพ์ก่อนและหลังสารสนเทศที่สัมพันธ์กับส่วนของอ๊อบเจคที่ระดับชั้นใน
DataReport designer มีส่วนรายงาน (ซึ่งพิมพ์สารสนเทศที่ตอนต้นและท้ายของรายงาน) และส่วนหน้า (ซึ่งพิมพ์สารสนเทศที่ตอนต้นและตอนท้ายของแต่ละหน้า) ถ้าไม่เห็นสองส่วนนี้ให้เมาส์มุ่มขวา บน DataReport designer และเลือกคำสั่งที่ต้องการ
5. drag ฟิลด์ ที่ต้องการจากอ๊อบเจค Command "Orders" ใน DataEnvironment มายังส่วน Orders_header ของ DataReport เมื่อปล่อยปุ่มของเมาส์ ชุดของตัว control คือ RptLabel และ RptTextbox จะปรากฏใน DataReport ซึ่งภายใน RptLabel จะสร้างข้อความด้วยชื่อของฟิลด์ และ Rpttexbox จะถูกแทนที่โดยข้อความจาก ฟิลด์ฐานข้อมูล แล้วจัดตำแหน่งฟิลด์ให้เหมาะสม
6. คลิกบนอ๊อบเจค Command "Order Details" และ drag ไปที่ DataReport จากนั้น Visual Basic จะสร้างชุดตัว control คือ RptLabel และ RptTextbox สำหรับแต่ละฟิลด์ ใน Recordset สามารถลบฟิลด์ OrderID และจัดตำแหน่งตัว control ในแถว
7. จัดส่วนสูงเพื่อไม่ให้มีที่ว่างมากเกินไป ซึ่งมีความสำคัญมาก สำหรับส่วนรายละเอียด เพราะส่วนนี้จะแสดงเรคคอร์ดแต่ละเรดคอร์ดซ้ำ และสามารถลดส่วนทั้งหมดที่ไม่มีฟิลด์เป็นค่าว่าง
8. ถ้าสารสนเทศใน DataReport เพียงพอ ให้นำไดอะล๊อกบ๊อกซ์ของ Project properties pages เลือก Datareport1 เป็น Startup object และเรียกใช้โปรแกรม
Note: การวางตัว control ในส่วน สามารถวางให้ตรงกับอ๊อบเจค command และส่วนที่อยู่ระดับต่ำกว่า เช่น สามารถวางฟิลด์ OrderID จากอ๊อบเจค Command "Orders" ในส่วน Orders และ Order_Details แต่ไม่สามารถวางฟิลด์ UnitPrice จากส่วนชั้นใน Order_Details มายังส่วน Orders
การตั้งค่าคุณสมบัติ
การรวมตัว control ลงบน DataReport เหมือนกับตัว control มาตรฐานที่วางบนฟอร์ม แต่มีไลบรารีต่างกัน และไม่สามารถนำ intrinsic control มาวางบน DataReport หรือตัว control จากไลบรารี DataReport ไปตามวางบนฟอร์ม รวมถึงไม่สามารถใช้คำสั่งในเมนู Format ต้องใช้การคลิกเมาส์ปุ่มขวาบนตัว control และใช้คำสั่งจากเมนู popup
สำหรับคุณสมบัติเฉพาะ คือ คุณสมบัติ Control ถ้าตั้งค่าเป็น True ตัว control ยอมให้ขยายตามแนวตั้งเมื่อข้อมูล มากกว่าความกว้าง ค่าเริ่มต้นของคุณสมบัตินี้ คือ False ซึ่งจะตัดข้อความที่ยาวกว่าความกว้าง
การแสดงฟิลด์คำนวณ
วิธีการแสดงฟิลด์คำนวณมี 2 วิธีคือ
1. ใช้คำสั่ง SELECT คำนวณค่าของฟิลด์ต่าง ๆ ในเรคคอร์ดเดียวกัน เช่น
SELECT OrderID, ProductID, UnitPrice, Quantity, Discount,
((UnitPrice * Quantity) * (1 - Discount)) As Total FROM [Order Details]
แล้วเพิ่มฟิลด์ Total ในส่วนรายละเอียดเพื่อแสดงราคารวมของแต่เรคคอร์ด จาก Order Details แล้วจัดรูปแบบและตำแหน่งของฟิลด์ให้เหมาะสม
นอกจากนี้สามารถใช้คำสั่ง SQL ระดับสูง คือ การเชื่อม table ด้วย JOIN Clause เป็นประโยคคำสั่ง SELECT เพื่อดึงข้อมูลจาก table อื่น
SELECT [Order Details].OrderID, [Order Details].ProductID, [Order Details].UnitPrice,
[Order Details].Quantity, [Order Details].Discount, (([Order Details].UnitPrice *
[Order Details].Quantity) * (1 - [Order Details].Discount)) As Total,
Products.ProductName FROM [Order Details] INNER JOIN Products
ON [Order Details].ProductID = Products.ProduvtID
2. ใช้ RptFunction ในการหาผลรวมของเรคคอร์ด เช่น หาผลรวมฟิลด์ Total ของอ๊อบเจค Command "Order Details" ให้วาง RptFunction ลงในส่วน Order_Footer แล้วกำหนดค่าคุณสมบัติในตัว control ใหม่ ตั้งค่าคุณสมบัติ DataMember เป็น Order_Details คุณสมบัติ DataField เป็น Total คุณสมบัติ FunctioType เป็น 0-rptFuncSum และคุณสมบัติ DataFormat เป็น Currency ค่าที่หาได้เป็นผลรวมของแต่ละ OrderID
ถ้าต้องการหาผลรวมของรายงานทั้งหมด ให้วาง RptFunction ที่ส่วนรายงาน เช่น การหาผลรวมของค่าขนส่งทั้งหมด ให้วาง RptFunction ที่ส่วนรายงาน แล้วตั้งคุณสมบัติ DataMember เป็น Orders คุณสมบัติ DataField เป็น Freight คุณสมบัติ FunctioType เป็น 0-rptFuncSum และคุณสมบัติ DataFormat เป็น Currency เมื่อเรียกใช้โปรแกรม จะได้ผลรวมของทุก OrderID ที่หน้าสุดท้ายของรายงาน
การจัดการส่วนล่างของหน้าและตัวแบ่งหน้า
หน้าส่วนหัวและหน้าส่วนล่าง ใช้แสดงสารสนเทศเกี่ยวกับหมายเลขหน้า ,จำนวนหน้ารวม, วันที่และเวลาที่พิมพ์ เป็นต้น การกำหนดรายละเอียดเหล่านี้ที่ให้คลิกเมาส์ปุ่มขวาในส่วนที่สนใจ เลือกคำสั่ง Insert Control จากนั้นเลือกสารสนเทศที่ต้องการแสดง
ตัว control ที่ใช้คือ RptLabel แล้วกำหนดตัวอักษรตามตาราง 15.1 ในคุณสมบัติ Caption เช่น หน้า %p ของ %P
ในทุกส่วนของอ๊อบเจคมีคุณสมบัติ 2 อย่างที่มีผลต่อการแบ่งหน้า คือ คุณสมบัติ ForePageBreak เพื่อหากำหนดขึ้นหน้าใหม่
คุณสมบัติ KeepTogether เป็นค่า Boolean ถ้ากำหนดเป็น True การพิมพ์รายงาน DataReport จะเพิ่มตัวแบ่งหน้าหรือขึ้นหน้าใหม่โดยอัตโนมัติ ถ้าข้อมูลในหน้าต่อไปยาวกว่า 1 หน้ากระดาษ
คุณสมบัติอื่นของรายงาน
DataReport designer มีคุณสมบัติหลายอย่างที่สามารถปรับปรุงได้ในตารางคุณสมบัติ เหมือนกับ Designer อื่น เช่น Caption, Font, WindowState เป็นต้น
คุณสมบัติเฉพาะของ DataReport designer คือคุณสมบัติ LeftMargin, RightMargin, TopMargin และ ButtomMargin สำหรับการหาขนาดของระยะจากขอบกระดาษในการพิมพ์รายงาน ในขณะที่คุณสมบัติ ReportWidth หาความกว้างของหน้ารายงาน ส่วน GridX และ GridY เป็นระยะห่างของตารางตัว control ในเวลาออกแบบ
การทำงานเมื่อเรียกใช้
การเตรียมรายงาน อาจมีการเพิ่มตัว control บางตัวบน DataReport designer เพื่อใช้คุณสมบัติ เมธอด และ event ในการควบคุมผ่านคำสั่งเมื่อเรียกใช้ เพื่อทำให้สามารถสร้างรายงานที่ซับซ้อนได้
การพิมพ์รายงาน
การพิมพ์รายงานปกติทำได้ง่ายโดยการส่งพิมพ์ที่ปุ่มเครื่องพิมพ์บนแถบเครื่องมือใน Preview Window ของ DataReport ในการแสดง DataReport window ทำได้ด้วยเมธอด Show
DataReport1.WindowState = VbMaximzed
DataReport1.Show vbModal
ควบคุมการพิมพ์ด้วยคำสั่ง ต้องใช้เมธอด PrintReport ของ DataReport designer ตามไวยากรณ์นี้
Cookie = PrintReport [Show Dialog], [Range], [Page From], [Page To]
Show Dialog เป็นค่า Boolean สำหรับการแสดง Print dialog box
Range เป็นการกำหนดช่วงของการพิมพ์ ด้วยค่า 0-rptRangeAllPages (พิมพ์ทุกหน้า) หรือ 1-rptRangeFromTo (กำหนดช่วงพิมพ์)
Page Form และ Page To ระบุหลักแรกและหน้าสุดท้าย ของการพิมพ์
Dim Cookie As Long
Cookie = DataReport1. PrintReport (False, rptRangeFromTo,1,10)
การใช้ประโยชน์การประมวลผลแบบ Asynchronous
การสร้างรายงาน แบ่งเป็น 3 ขั้นตอนย่อย คือ การ query, การสร้างไฟล์ชั่วคราว และการพิมพ์ (รวมถึง Preview และการส่งออก) โดยการ query และการพิมพ์ไฟล์ชั่วคราว เป็น synchronous ส่วนการพิมพ์เป็น asynchronous เมื่อ DataReport designer กำลังทำงานแบบ asynchronous จะเกิด ProcessingTimeout เป็นระยะประมาณทุกวินาทีสามารถจับ event เพื่อให้ผู้ใช้ควบคุมการพิมพ์ได้ เช่น การยกเลิกการพิมพ์
Private Sub DataReport_ProcessingTimeout(ByVal Seconds As Long, Cancel As Boolean, _
ByVal JobType As MSDataReportLib.AsyncTypeConstants, ByVal Cookie As Long)
' แสดงข้อความทุกๆ 20 วินาที
Const TIMEOUT = 20
' ค่าของวินาทีเมื่อแสดงข้อความ
Static LastMessageSecs As Long
' ตั้งค่า LastMessage ใหม่ ถ้า มีการสั่งพิมพ์ใหม่
If Seconds < LastMessageSecs Then
LastMessageSecs = 0
ElseIf LastMessageSecs + TIMEOUT <= Seconds Then
LastMessageSecs = Seconds
' ถามผู้ใช้ ถ้าต้องการทำงานยกเลิกการทำงาน
If MsgBox("การทำงานนี้ได้เริ่มต้นมาแล้ว " & Seconds &
" วินาที " & vbCr & "ต้องการยกเลิกหรือไม่?", vbYesNo + vbExclamation) = vbYes Then
Cancel = True
End If
End If
End Sub
อากิวเมนต์ JopType เป็นประเภทการทำงานที่ค่าเป็น 0-rptAsynPreview, 1-rptAsyncPrint หรือ 2-rptAsyncExport ส่วน cookie ระบุการทำงานตามค่า Long ที่ส่งออกมาจาก เมธอด PrintReport หรือ ExportReport การแสดงความก้าวหน้าของการพิมพ์สามารถจับ Progress event ซึ่งเกิดขึ้นทุกครั้งที่พิมพ์หน้าใหม่
Private Sub DataReport_AsyncProgress(ByVal JobType As MSDataReportLib.AsyncTypeConstants, _
ByVal Cookie As Long, ByVal PageCompleted As Long, ByVal TotalPages As Long)
' แสดงสถานะพิเศษใน Label บนฟอร์มหลัก
frmMain.lblStatus = "พิมพ์ " & PageCompleted & " ของ " & TotalPages
End Sub
การส่งออกรายงาน
ผู้ใช้สามารถส่งออกรายงานด้วยการคลิกปุ่ม Export บน Preview window ของ DataReport ในไดอะล๊อกบ๊อกซ์ Export ให้เลือกชื่อไฟล์ ประเภทไฟล์ (เป็น html, htmltext , Unicode และ Unicode text) และช่วงของหน้า ซึ่งหน้าของการ Export มักจะไม่ตรงกับหน้าของการ Preview และไม่สามารถส่งออกกราฟฟิก โดย RptImage และ RptShape
การส่งออกด้วยคำสั่ง ใช้เมธอด ExportReport ตามไวยากรณ์นี้
Cookie = ExportReport ([Format Or Indexkey], [File Name], [Overwrite], [Show Dialog],
[Range], [PageFrom], [PageTo])
Format หรือ Indexkey เป็นดัชนีตัวเลข หรือ string key ที่ระบุรูปแบบการส่งออก
Overwrite เป็นค่า Boolean ในการหาว่าถ้ามีไฟล์อยู่แล้วจะทำการเขียนทับ (ค่าเริ่มต้นเป็น True)
Show Dialog เป็นค่า Boolean เพื่อระบุการแสดงไดอะล๊อกบ๊อกซ์มาตรฐานของการส่งออก
อากิวเมนต์อื่นมีความหมายเหมือนเมธอด PrintReport
เมธอด ExpoitReport ส่งออกค่า Long กำหนดได้เฉพาะใน ProcessingTimeout, AsyncProgress หรือ Error Event
ตัวอย่างคำสั่งการส่งออกไฟล์ html
cookie = DataReport1.ExportReport rptKeyHtml, App.Path & "\Orders", True
การเปลี่ยนผังรายงานเมื่อเรียกใช้
ในกรณีที่สร้างรายงาน หลายรายงานที่คล้ายกัน เช่น รายงานพนักงานที่แสดงสารสนเทศทั้งหมดและรายงานที่ซ่อนข้อมูลบางส่วน การสร้างรายงานประเภทคำได้สะดวกเนื่องจาก DataReport เป็นอ๊อบเจคแบบ programmable
การอ้างถึง อ๊อบเจค Section หรือส่วน ใช้ Sections collection และอ้างถึงตัว control ภายในส่วน
' ซ่อนส่วนล่าง (footer) ตามคำสั่ง
DataReport1.Sections ("Orders_Footer").Visible = False
' เปลี่ยน caption ของ lblTitle
DataReport1.Sections ("Section1").Controls ("lblTitle")
.Caption = "May 99"
การอ้างถึงส่วนสามารถใช้ดัชนีตัวเลข หรือชื่อ
ในเวลาเรียกใช้ การเพิ่มตัว control ในรายงานไม่สามารถทำได้ เนื่องจาก DataReport ไม่สนับสนุนเมธอด Add การทำงานลักษณะที่ให้เตรียมรายงานที่มีฟิลด์ทั้งหมด แล้วซ่อนฟิลด์ที่ไม่ต้องการในแต่ละเวอร์ชัน
' ตัวแปร member สำหรับคุณสมบัติ ShowDetails
Private m_ShowDetails As Boolean
Public Property Get ShowDetails() As Boolean
ShowDetails = m_ShowDetails
End Property
Public Property Let ShowDetails(ByVal newValue As Boolean)
Dim newTop As Single
m_ShowDetails = newValue
' สร้างหัวรายงาน
If m_ShowDetails Then
Sections("Section1").Controls("lblTitle").Caption = "รายละเอียดใบสั่งซื้อ"
Else
Sections("Section1").Controls("lblTitle").Caption = "สรุปใบสั่งซื้อ"
End If
' คุณสมบัติมีผลต่อการมองเห็นของส่วนในที่สุด
Sections("Order_Details_Detail").Visible = m_ShowDetails
' มีผลกระทบต่อการมองเห็นในส่วน Orders ถ้าต้องการลดความสูงของส่วน
' ที่ต้องสร้างทั้งหมดตัว control ที่ไม่จำเป็นมองไม่เห็น และย้ายขึ้น อื่นๆ กำหนดให้
' ค่าเล็กกว่าของความสูงของส่วนที่ไม่ต้องการทำงาน
newTop = IIf(m_ShowDetails, 2500, 0)
With Sections("Orders_Header")
.Controls("lblProduct").Visible = m_ShowDetails
.Controls("lblProduct").Top = newTop
.Controls("lblUnitPrice").Visible = m_ShowDetails
.Controls("lblUnitPrice").Top = newTop
.Controls("lblQty").Visible = m_ShowDetails
.Controls("lblQty").Top = newTop
.Controls("lblDiscount").Visible = m_ShowDetails
.Controls("lblDiscount").Top = newTop
.Controls("lblTotal").Visible = m_ShowDetails
.Controls("lblTotal").Top = newTop
.Controls("shaDetailHeader").Visible = m_ShowDetails
.Controls("shaDetailHeader").Top = newTop
' ตั้งค่าความสูงส่วนเป็น 0 เพื่อบีบให้มากที่สุดเท่าที่จะทำได้
.Height = IIf(m_ShowDetails, 2200, 0)
End With
End Property
การเพิ่มรูปแบบ dynamic และ ฟิลด์ lookup
เมื่อมีการรวม DataReport ด้วยกลไกการรวม ADO มาตรฐาน ทำให้ศักยภาพสูงขึ้น เช่น การจัดรูปแบบของฟิลด์ที่รวมข้อมูลแล้วสามารถควบคุมผ่าน Format event ของอ๊อบเจค StdDataFormat
Dim WithEvents DiscountFormat As StdDataFormat
Private Sub DataReport_Initialize()
' สร้างรูปแบบ DataFormat อื่น สำหรับฟิลด์ Discount
Set DiscountFormat = New StdDataFormat
Set Sections("Order_Details_Detail").Controls("txtDiscount").DataFormat = DiscountFormat
End Sub
Private Sub DiscountFormat_Format(ByVal DataValue As StdFormat.StdDataValue)
If CDbl(DataValue.Value) = 0 Then
DataValue.Value = Null
End If
End Sub
ดาวน์โหลดตัวอย่าง (DataRpt.vbp)
|