www.oocities.org/pontipa001

หน้าแรก อุปกรณ์ที่ประกอบเป็นเครื่องคอมพิวเตอร์ เกาเหลาเทคนิคการใช้ HTML วิธีทำสร้าง Shortcut บน Desktop ปัญหาใหญ่ของ Data transfer

 เรื่องรายงาน

หัวข้อนี้จะแนะนำคำสั่งนำรายงานที่สร้างโดย Crystal Report มาพิมพ์ใน VB สำหรับการสร้างรายงานนั้นท่านผู้อ่านต้องไปศึกษาเพิ่มเติม แต่ไม่ค่อยยากเพราะมี Wizard ช่วย ในความจริงแล้วผมเองไม่ค่อยชอบ Crytal Report เท่าไหร่เนื่องจากว่าพิมพ์ลงในแบบฟอร์ม(Preprint Form) จะค่อนข้างยาก  แต่เท่าที่ทราบมาคือ Crystal Report Version 5.0 ได้สนับสนุนการพิมพ์ลงแบบฟอร์ม   ปัจจุบันนี้ (เมษายน 41) Crystal  Report เป็น Version 6   เนื่องจากว่า Crytal Report ที่มากับ VB4 เป็น Version 3 ซึ่งไม่ค่อยดีเท่าไหร่ ดังนั้นจึงอธิบายในส่วนที่เป็นของ VB5 ซึ่งเป็น Version 4.6 ซึ่งสามารถนำไปใน VB4 ได้ด้วย 

  เข้าใจโครงสร้างของรายงาน
  นำ รายงาน Crytal Report มาใช้ใน VB ได้อย่างไร
  เมื่อต้องการเรียงลำดับ Fields
  เมื่อต้องการเลือกเรคคอร์ดที่ต้องการพิมพ์
  เมื่อต้องการส่งค่าตัวแปรเข้าไปในรายงาน
  เกี่ยวกับการจัดกลุ่ม
  Properties อื่นๆ
  เมื่อต้องการพิมพ์รายงานเอง
  ถ้าคุณต้องการพิมพ์ทางเครื่องพิมพ์ในรูปแบบ TextMode

เข้าใจโครงสร้างของรายงาน

      ก่อนที่จะใช้ Crystal Report หรือ ทำรายงานเองก็ตามเราต้องเข้าใจโครงสร้างรายงานก่อน เรื่องโครงสร้างรายงานนั้นน่าน้อยใจอยู่มากก็คือ ไม่ค่อยมีการเรียน การสอนเลย แม้หนังสือไม่ค่อยจะมีเล่มใดกล่าวถึง คงถือว่าเป็นเรื่องเล็กน้อยมั้ง เมื่อก่อนที่จะมีโปรแกรมช่วยทำรายงานนั้นผม ต้องเขียนโปรแกรมตามรูปแบบตัวเอง แต่มาเจอหนังสือเล่มนึงอธิบายได้ดีมาก และเป็นพื้นฐานที่ใช้ในการทำรายงาน แม้กระทั่ง Crytal Report หรือ ใน Access หรือโปรแกรมอื่นที่ทำทางด้านรายงานก็มาจาก พื้นฐานนี้ ผมจึงต้องนำมากล่าวถึง ดังนี้
      โครงสร้างรายงานมีดังนี้
      Report  Header ------------------------------------------------------------
           Page Header ----------------------------------------------------------
                 Group Header --------------------------------------------------
                       Detail ---------------------------------------------------------
                 Group Footer ---------------------------------------------------
           Page Footer -----------------------------------------------------------
      Report Footer -------------------------------------------------------------
      อธิายโครงสร้างรายงาน
      Report Header / Title
       ใช้ในการพิมพ์หน้าแรกหน้าเดียว ปกติในการพิมพ์รายงานในระบบเครือข่าย จะมีรายงานพิมพ์ต่อเนื่องกัน ถ้าเราไม่พิมพ์หน้าแรก เวลาจะไปแยกรายงาน จะทำให้สับสนได้ แต่ถ้าเป็นรายงานแบบ Sigle User ไม่ต้องพิมพ์หน้านี้ก็ได้
      Page Header
       ใช้พิมพ์หัวรายงานในแต่ละหน้า ทุกรายงานจำเป็นมากที่จะต้องมีคำอธิบายที่หัวรายงาน เช่น ชื่อบริษัท ชื่อรายงาน วันที่ เวลา และหัวรายงานของแต่ละช่อง ดังตัวอย่าง
                                                      บริษัท สาธิต จำกัด                                    หน้า:    1
                                                    รายงานยอดขายตามวันที่                            พิมพ์:    11/04/1998
วันที่ : 11/04/1998
--------------------------------------------------------------------------------------------------------------------------------------------------
วันที่        เลขที่        ชื่อลูกค้า                                                           จำนวนเงิน
--------------------------------------------------------------------------------------------------------------------------------------------------
       
Group Header
        ใช้พิมพ์หัวกลุ่ม ซึ่งจะมีหลายกลุ่มก็ได้ เช่น ถ้าเราต้องการพิมพ์สรุปตาม หน่วยงาน และแผนก
       
Detail
        ใช้พิมพ์รายการแต่ละบรรทัด
        Group Footer
        ใช้พิมพ์สรุปยอดรวมของแต่ละกลุ่ม ปกติมักจะเป็นยอดรวมจำนวนเงิน หรือ จำนวนรายการ
        Page Footer
        ใช้พิมพ์ท้ายรายงานของแต่ละหน้า ใช้มากในทางธุรกิจเช่นพิมพ์ใบกำกับภาษี
        Report Footer / Summary
        ใช้พิมพ์สรุปยอดรวมทั้งหมดท้ายรายงาน ทุกรายงานส่วนใหญ่ต้องมีพิมพ์สรุป ดังนั้นสำคัญมาก

       เมื่อคุณเข้าใจโครงสร้างรายงานแล้ว เมื่อคุณไปใช้ Crytal Report ง่ายมากเลย เพียงคุณเลือกฟิลด์ไปใส่ตามแถบให้ถูกต้อง แต่ถ้าคุณหากคุณต้องเขียนโปรแกรมเอง ให้ดูตัวอย่างในหัวข้อ
เมื่อต้องการพิมพ์รายงานเอง


นำรายงาน Crytal Report มาใช้ใน VB ได้อย่างไร


      ต้องเพิ่ม Control ของ Crytal Report เพิ่มเติม โดยไปที่ เมนู Tool -> Componet (VB4) หรือ เมนู Project -> Componet (VB5) ลากลงบน Form แล้วกำหนดคุณสมบัติ Report File Name เลือกรายงานที่สร้างจาก Crytal Report (นามสกุล .rpt) และกำหนดคุณสมบัติ Destination เมื่อต้องการพิมพ์ให้กำหนด Action = 1
       ตัวอย่าง
          Private Sub Command1_Click()
            CrystalReport1.DataFiles(0) = "c:\vb32\biblio.mdb"   
'** กำหนดชื่อแฟ้มข้อมูล
             CrystalReport1.ReportFileName = "c:\vb32\author.rpt"
'** ใส่ชื่อรายงาน
            CrystalReport1.Destination = 0 
'** 0-ToWindow, 1-Printer, 2-File
            CrystalReport1.Action = 1
         End Sub


        แค่นี้สามารถที่จะพิมพ์รายงาน Crystal Report ได้แล้ว

เมื่อต้องการเรียงลำดับฟิลด์
  ในขั้นตอนออกแบบใน Crystal Report ท่านสามารถกำหนดให้เรียงลำดับได้เลย ในขั้นตอนของ Runtime ใช้ Sortfields
   ตัวอย่าง
      Private Sub Command1_Click()
        CrystalReport1.DataFiles(0) = "c:\vb32\biblio.mdb"
       CrystalReport1.ReportFileName = "c:\vb32\author.rpt"
        CrystalReport1.Destination = 0
        CrystalReport1.SortFields(0) = "+{authors.author}"
'**+คือเรียงน้อยไปมาก Table=authors, Field=author
        CrystalReport1.SortFields(1) = "-{authors.au_id}" '**-คือเรียงมากไปน้อย ของฟิลด์ที่ 2
        CrystalReport1.Action = 1
      End Sub

เมื่อต้องการเลือกเรคคอร์ดที่ต้องการพิมพ์
  ในขั้นตอนออกแบบ ท่านสามารถกำหนดให้เลือกเรคคอร์ดได้แต่ไม่ค่อยเป็นที่นิยม เพราะควรจะให้ผู้ใช้เลือกพิมพ์ได้เอง ในขั้นตอนของ Runtime ใช้ SelectionFomula
   ตัวอย่าง

     Private Sub Command1_Click()
        CrystalReport1.DataFiles(0) = "c:\vb32\biblio.mdb"
        CrystalReport1.ReportFileName = "c:\vb32\author.rpt"
        CrystalReport1.Destination = 0
        CrystalReport1.SelectionFormula = " {authors.au_id} > 10 " 
'** เลือกฟิลด์ au_id ที่มากว่า 10
        CrystalReport1.Action = 1
     End Sub

   

เมื่อต้องการส่งค่าตัวแปรเข้าไปในรายงาน
     ในการส่งค่าตัวแปรเข้าไปในรายงานเป็นเรื่องที่สำคัญเหมือนกัน เพราะเราจะได้ไม่ต้องเข่้าไปแก้ในรายงาน เช่น หัวรายงานต้องพิมพ์ชื่อบริษัท ซึ่งต้องเปลี่ยนเมื่อนำไปใช้กับบริษัทอื่น ดังนั้นท่านจะระบุตายตัวในรายงานไม่ได้ ต้องกำหนดเป็นตัวแปรไว้ แล้วใช้วิธีส่งค่าจาก VB เข้าไป
     ในการส่งค่าตัวแปรนี้ท่านต้อง กำหนด Formulas ในรายงานก่อนแล้วใช้ Formulas
     ตัวอย่าง
     Private Sub Command1_Click()
       CrystalReport1.DataFiles(0) = "c:\vb32\biblio.mdb"
       CrystalReport1.ReportFileName = "c:\vb32\author.rpt"
       CrystalReport1.Destination = 0
       CrystalReport1.Formulas(0) = "Company = 'My Company' " 
'** กำหนด Company ไว้ในรายงาน
       'CrystalReport1.Formulas(1) = "Total = {Orders.Sales} + {Orders.Vat} "
       CrystalReport1.Action = 1
      End Sub

เกี่ยวกับการจัดกลุ่ม
   ปกติการจัดกลุ่มมักทำกัดที่ Design Time ใน Crytal Report เพราะว่าสามารถเห็นรายงานได้ทันที แต่ส่วนนี้อธิบายให้ทราบท่านนั้นเองว่าใช้อย่างไร มีใช้อยู่ 3 Properties คือ GroupCondition, GroupSelectionFormula และ GroupSortFields
   GroupCondition กำหนดกลุ่มมีรูปแบบ
      CrystalReport1.GroupCondition(0) = "Group;Field;Condition;SortDirection"
          Group = ชื่อ; Field = ชื่อฟิลด์; Condition= เงื่อนไขการเรียง;SortDirect = A-น้อยไปมาก D-มากไปน้อย
     เช่น
        CrystalReport1.GroupCondition(0) = "Group1;{OrderH.OrderNo;ANYCHANGE;A"
   GroupSelectionFormula ใช้เลือกกลุ่มที่จะใช้ในการพิมพ์รายงาน
   GroupSortFileds ใช้ระบุกลุ่มของฟิลด์ที่ต้องการเรียงลำดับในการพิมพ์

  

 

Properties อื่นๆ
  WIndowBorderStyle
      กำหนดประเภทกรอบหน้าต่างเมื่อพิมพ์ออกทางจอภาพ
  WindowControlBox
     กำหนดให้มี Control Menu หรือไม่
  WindowControl
     กำหนดให้มีแถบเครื่องมือกรณีพิมพ์ออกทางจอ หรือไม่
  WindowHeight
     กำหนดความสูงหน้าต่างกรณีพิมพ์ออกทางจอภาพ   ในหน่วย pixel
  WindowWidth
     กำหนดความกว้างหน้าต่างกรณีพิมพ์ออกทางจอภาพ   ในหน่วย pixel
  WindowLeft
    กำหนดตำแหน่งกรอบด้านซ้ายของหน้าต่าง ในหน่วย pixel
  WindowTop
    กำหนดตำแหน่งกรอบด้านบนของหน้าต่าง ในหน่วย pixel
  WindowState
    กำหนดสถานะกรอบหน้าต่างเป็น Normal, Minimize หรือ Maximize
  WindowParentHandle
    กำหนดให้เป็นฟอร์มลูกของหน้าต่างอื่น
  PrinterCopies
    กำหนดจำนวนชุดของรายงาน
  Printerฏพรอำพ
    กำหนด Driver ของเครื่องพิมพ์
  PrinterName
    กำหนดชื่อเครื่องพิมพ์
  PrinterPort
    กำหนด Port การพิมพ์ เช่น LPT1
  PrinterStartPage
    กำหนดหน้าเริ่มพิมพ์
  PrinterEndPage
    กำหนดหน้าสุดท้ายที่จะพิมพ์
  PrinterFileName
    กำหนดชื่อแฟ้มที่จะพิมพ์ กรณีพิมพ์ออกทาง File
  PrinterFileType
    กำหนดประเภทแฟ้มที่พิมพ์ กรณีพิมพ์ออกทาง File สามารถพิมพ์ออกได้หลาย Format
  ยังมีอีกหลาย Propperties ลองอ่านใน Help ดูละกัน

 

เมื่อต้องการพิมพ์รายงานเอง
เมื่อก่อนนี้เวลาเขียนรายงานผมมักจะเขียนตามรูปแบบตัวเอง แต่เมื่อทราบโครงสร้างรายงานแล้ว ทำให้ผมยึดรูปแบบนี้ไว้เป็นมาตรฐานเวลาแก้ไขปรับปรุงก็ง่าย และรูปแบบนี้จะใช้ได้ตลอดไม่ว่าจะเขียนด้วยภาษาใดก็ตาม

ดังนั้นผมจึงนำเสนอรูปแบบโครงสร้างรายงานให้ ถ้าจะนำไปใช้ต้องแก้ไขปรับปรุงอีกนิดนึง
ในตัวอย่างนี้ผมต้องการทำรายงานสรุปตามสาขา และ พนักงานขาย

Dim mDb As Database
Dim mRs As Recordset
Dim mLine As integer
Dim mPageLen as Integer
Dim mPageNo as Integer
Dim old_Branch As String
Dim old_SalesMan As String
DIm Sum_SalesMan as Currency
DIm Sum_Branch as Currency
DIm Sum_GrandTotal as Currency
'*** กำหนดค่าเริ่มต้น
mLine = 999
mPageLen = 40
mPageNo = 1
sum_GrandTotal = 0
'*** เปิดใช้ฐานข้อมูล
gSQL = " SELECT * FROM Order ORDER BY Order.Branch, Order.SalesMan; "
Set mDb = Workspaces(0).OpenDatabase("C:\Data\Data.MDB")
Set mRs = mDb.OpenRecordset(gSQL, dbOpenSnapshot)
'**** เริ่มพิมพ์
Printer.StartDoc
'***** Report Header
Do While Not mRs.EOF
   If mLine > mPageLen - 2 Then
      If mLine < 999 Then
         Printer.NewPage
'*** พิมพ์หน้าใหม่
         mPageNo = mPageNo + 1
      End If
      Call PageHeader
'*** พิมพ์หัวรายงาน  (PageHeader เป็นโปรแกรมย่อย)
      mLine = 1
   End If
   sum_Branch = 0
   old_Branch = mRs!Branch
   '***** Group Header
   '***** พิมพ์หัวกลุ่ม ในที่นี้คือ Branch (อย่าลืมบวก  mLine เพิ่ม)
   '*****

   Do While Not mRs.EOF And mRs!Branch = old_Branch
      If mLine > mPageLen - 1 Then
         Printer.NewPage
'*** พิมพ์หน้าใหม่
         mPageNo = mPageNo + 1
         Call PageHeader
'*** พิมพ์หัวรายงาน  (PageHeader เป็นโปรแกรมย่อย)
         mLine = 1
      End If
      sum_SalesMan = 0
      old_SalesMan = mRs!SalesMan
      '***** Group Header 2
        '*** พิมพ์หัวกลุ่มย่อย ในที่นี้คือ พนักงานขาย (อย๋าลืมบวก  mLine เพิ่ม)
      '*****

      Do While Not mRs.EOF And mRs!Branch = old_Branch And mRs!SalesMan = old_SalesMan
         If mLine > mPageLen Then
            Printer.NewPage 
'*** พิมพ์หน้าใหม่
            mPageNo = mPageNo + 1
            Call PageHeader
'*** พิมพ์หัวรายงาน  (PageHeader เป็นโปรแกรมย่อย)
            mLine = 1
         End If
         '*** Detail
         '*** พิมพ์ส่วนที่เป็นรายการ Detail
         '***
         '***
รวมยอดสะสม
         sum_SalesMan = sum_SalesMan + mRs!Amount
         sum_Branch = sum_Branch + mRs!Amount
         sum_GrandTotal = sum_GrandTotal + mRs!Amount
         '*** เพิ่มบรรทัด และ เลื่อนเรคคอร์ด
         mLine = mLine + 1
         mRs.MoveNext
         If mRs.EOF Then Exit Do
'*** แก้ไขกรณี Error เมื่อถึง Eof
      Loop
      '**** Group Footer 2
      '**** พิมพ์สรุปยอดตามกลุ่มย่อย ในที่นี้คือ SalesMan อย่าลืมบวก mLine เพิ่ม
      '****

      If mRs.EOF Then Exit Do
'*** แก้ไขกรณี Error เมื่อถึง Eof
   Loop
   '**** Group Footer
   '**** พิมพ์สรุปยอดตามกลุ่ม ในที่นี้คือ Branch (อย่าลืมบวก mLine เพิ่ม)
   '****

Loop
'**** Report Footer / Summary
'**** พิมพ์สรุปยอดทั้งสิ้น
'****

Printer.EndDoc
mRs.Close
mDb.Close

โครงสร้างนี้ถ้ามีพิมพ์สรุปยอดรวมในแต่ละหน้า ให้พิมพ์ ก่อนที่จะเรียก NewPage
ท่านผู้อ่านสามารถนำโครงสร้างนี้ไปปรับปรุงเพื่อพิมพ์รายงานได้ตามต้องการ และหวังว่าโครงสร้างนี้คงมีประโยช์นกับท่านไม่มากก็น้อย
 

ถ้าคุณต้องการพิมพ์ทางเครื่องพิมพ์ในรูปแบบ Text Mode
ใครที่เคยใช้ VB มาคงนึกไม่ถึง เพราะว่า VB เป็นโปรแกรมที่เขียนอยู่บน Windows คงพิมพ์ Text Mode ไม่ได้มั้ง ผมเองยังนึกไม่ถึงเลย มีคนถามนานแล้วว่า พิมพ์ Text Mode ได้หรือไม่ ? จนกระทั่งคุณ วรุตร์ Mail มาถามอีก ผมเลยต้องหาวิธึ จนได้ เลยมาแถลงให้คนอื่นได้ทราบกันทั่วหน้าเลย   สำหรับการพิมพ์ใน Text Mode นั้นข้อดีคือเร็ว ดังนั้นถ้ารายงานใดยาวๆ ควรพิมพ์ใน Text Mode ก็จะดีมาก

Open "LPT1:" For Output As #1
   Print #1, "This is the line No.1..."
   Print #1, "This is the line No.2..."
   Print #1, "This is the line No.3..."
Close #1

การใช้แบบนี้จะส่งอักษรไปที่เครื่องพิมพ์ตรงๆ ดังนั้นคุณสามารถส่ง Control Code เพื่อควบคุม Printer ได้ในรูปแบบที่ต้องการ เหมือนกับที่สั่งจากโปรแกรมบน Dos แต่มีข้อเสียคือการพิมพ์ภาษาไทย คุณจะต้องจัดระดับเอง ผมเคยเขียนโปรแกรมจัดระดับบน Dbase แต่ว่าไม่รู้โปรแกรมหายไปไหนแล้ว หากใครเขียน ถ้้าส่ง Code มาบ้างจะขอบคุณมาก

หน้าแรก อุปกรณ์ที่ประกอบเป็นเครื่องคอมพิวเตอร์ เกาเหลาเทคนิคการใช้ HTML วิธีทำสร้าง Shortcut บน Desktop ปัญหาใหญ่ของ Data transfer