Visual Basic

Home

Visual Basic Tutorial
Knowledge Developer Database Internet Resource
Database Contol
1. DataCombo และ Data List
2. DataGrid
3. Hierachical FlexGrid
4. Data Report
 
Visual Basic Tutorial
1. Visual Basic 6
2. ฟอร์ม
3. Intrinsic Control
4. ตัวแปรและ Procedure
5. Class
6. Common Control1
7. Common Control2
8. ActiveX Control
9. Interface
10. ฐานข้อมูล
11. Database Control
 
Developer
Visual Basic
Microsoft Access
Microsoft Excel
 

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)

 

  

สงวนลิขสิทธิ (C) widebase