การสั่งพิมพ์แบบมีเงื่อนไข
กระทู้เก่าบอร์ด อ.Yeadram

 2,464   15
URL.หัวข้อ / URL
การสั่งพิมพ์แบบมีเงื่อนไข

สวัสดีครับ มีเรื่องรบกวนอีกแล้ว

สมมุติผมมี Table ที่เก็บ สินค้า ประเภทสินค้า และ ราคา

1. ดินสอ / เครื่องเขียน / 5
2. รถตักดิน / ของเล่น / 30
3. น้ำอัดลม / เครื่องดื่ม / 12

ผมมีรายงาน 3 แบบ ซึ่งแตกต่างกันตามแต่ละประเภทของสินค้าด้านบน

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

ตัวอย่าง
รายงาน A ใช้งานเฉพาะ เครื่องเขียน
รายงาน B ใช้งานเฉพาะ ของเล่น
รายงาน C ใช้งานเฉพาะ เครื่องดื่ม
ผมฟิลเตอร์เฉพาะ เครื่องเขียน และเครื่องดื่ม

โดยกดที่ปุ่ม cmd1 จำนวน 1 ครั้ง
จะได้รายงานของ เครื่องเขียน และ เครื่องดื่ม

ปล. ตอนนี้ผมสามารถฟิลเตอร์ได้แล้ว แต่ไม่สามารถพิมพ์ได้ภายในครั้งเดียว ตอนนี้ใช้วิธีให้ User ดูและเลือกพิมพ์เอาครับ ว่าจะพิมพ์แบบไหน ส่วนเมื่อ User เลือกรายงานที่ไม่มีประเภทสินค้านั้นๆ จะขึ้นว่า "ไม่พบข้อมูล" ครับ

ขอบพระคุณสำหรับคำตอบครับผม

15 Reply in this Topic. Dispaly 1 pages and you are on page number 1

1 @R23035
ถ้าหมายถึงคุณมีรายงานอยู่แล้ว 3 ตัว อยากกดปุ่มที่เดียวพิมพ์ทั้ง 3 รายงานเลยก็ใช้โค๊ดประมาณนี้ครับ
'Private Sub Command0_Click()
On Error GoTo ProcError
    
    DoCmd.OpenReport "ชื่อรายงาน 1", acNormal
    DoCmd.OpenReport "ชื่อรายงาน 2", acNormal
    DoCmd.OpenReport "ชื่อรายงาน 3", acNormal
    
ExitProc:
    Exit Sub
ProcError:
    MsgBox "Error " & Err.Number & ": " & Err.Description, _
    vbCritical, "Error in procedure cmdPrintReports_Click..."
    Resume ExitProc
'End Sub

ประมาณนี้ครับ
2 @R23042
ขอบพระคุณมากๆ ครับ พี่ TTT



3 @R23043
เอาไปลองใช้แล้ว ยังไม่ตรงตามความต้องการครับ

เช่น ผมต้องการพิมพ์รายงาน เครื่องดื่ม หลังจากกดปุ่มพิมพ์ไป รายงานออกมาทุกแบบเลยครับ (รายงานที่ไม่มีข้อมูลก็จะออกมาแต่ฟอร์มว่าง)
4 @R23044
อ่านแล้วไม่ค่อยเข้าใจแนวคิดนะครับ ตอบไม่ถูก
ปุ่มคุณอยู่ที่ไหน บนฟอร์มหรืออะไร แล้วใช้อะไรเป็นตัวเลือกว่าจะพิมพ์ รายงานเครื่องดื่ม หรืออะไร

จากโค๊ดเราก็ใส่เงื่อนไข หรือตัวแปรลงในคำสั่งพิมพ์ เช่น

if เครื่องดื่มอย่างเดียว Then
    DoCmd.OpenReport "ชื่อรายงาน เครื่องดื่ม", acNormal
Elseif ของเล่นอย่างเดียว Then
    DoCmd.OpenReport "ชื่อรายงาน ของเล่น", acNormal
Elseif เครื่องดื่ม AND ของเล่น Then
    DoCmd.OpenReport "ชื่อรายงาน เครื่องดื่ม", acNormal
    DoCmd.OpenReport "ชื่อรายงาน ของเล่น", acNormal
Elseif ทั้งหมด Then
    DoCmd.OpenReport "ชื่อรายงาน ...", acNormal
    DoCmd.OpenReport "ชื่อรายงาน ...", acNormal
    DoCmd.OpenReport "ชื่อรายงาน ...", acNormal
End if

อะไรประมาณนี้ครับ
5 @R23054
คือผมสร้าง Form 1 สำหรับค้นหาใบออเดอร์ครับ
โดยที่มีฟอร์มย่อย ในนี้ เพื่อแสดงผลลัพธ์จากการค้นหา โดย ฟอร์มย่อยนั้นจะมีข้อมูล

1. ชื่อสินค้า
2. ประเภทผลิตภัณฑ์
3. จำนวน

และแต่ละรายงานจะมีรูปแบบฟอร์มที่ไม่เหมือนกัน
A = ของเล่น
B = ขนม
C = เครื่องดื่ม

เมื่อ user พิมพ์ เลขที่ใบออเดอร์ 001 จะแสดงรายการมา เช่น

|    รายการ    |      ประเภท     |      จำนวน     |
รถของเล่น        ของเล่น               5
ข้าวโพดอบ          ขนม                 10
     ตุ๊กตา             ของเล่น               2


และเมื่อสั่งพิมพ์ ใบออเดอร์ 001 จะพิมพ์ รายงาน
A และ B
โดยที่ รายงาน A จะมี 2 รายการคือ รถของเล่น และ ตุ๊กตา
ส่วน รายงาน B จะมีแค่รายการของขนม

โดยตอนนี้ปัญหาคือ เมื่อผมสั่งพิมพ์ไปแล้ว จะมีรายงาน C ติดมาด้วยครับ
ซึ่งไม่มีข้อมูล

ประมาณนี้ครับ

ปล. ขออภัยด้วยครับพิมพ์ไม่ค่อยเข้าใจ
6 @R23055
ตรวจโค้ดดูจ้า (ไม่ได้รับเชิญจะมาได้ไง) เช็คดูดี ๆ นะ
7 @R23056
ลองทำใน Query ได้หรือไม่ครับ
กำหนดเงี่อนไขในส่วนของประเภทดังนี้ครับ
>=[ประเภท1] And <=[ประเภท2]

หรือ
>=[Forms]![ชื่อฟอร์ม]![ชื่อTexe Box1] And <=[Forms]![ชื่อฟอร์ม]![ชื่อTexe Box2]

ซึ่งQuery จะดึงข้อมูลเฉพาะประเภทที่เลือก
ลองดูครับ
8 @R23058
อื่ม อ่านแล้วก็ งง จริงๆนะครับ คือว่ามันอยู่ที่ว่าคุณกรองข้อมูลมาทำเป็น รายงานยังไงมากกว่า ที่ว่าคุณทำการกรองข้อมูลได้แล้ว กรองยังไง รายงานที่ไม่มีข้อมูลคืออะไร การสั่งพิมพ์เขียนแบบไหน แล้วถ้าไม่พิมพ์แต่เรียกดูรายงานแต่ละตัวได้ตรงตามความต้องการหรือเปล่า มีปัญหาเฉพาะตอนสั่งพิมพ์เท่านั้นจริงเหรอ ตอนเรียกดูรายงานเฉยๆดูได้ครบไม่เกิน?

คือยังนึกไม่ออกว่าคุณออกแบบรายงานการพิมพ์แบบไหน ทำเป็น Report แต่ละประเภทรอไว้ก่อนหรือเปล่า

ที่ว่า "ตอนนี้ผมสามารถฟิลเตอร์ได้แล้ว" ทำในส่วนของ Report หรือบนฟอร์ม ขอวิธีที่คุณทำคร่าวๆหน่อย

ปล. ถ้าฝากรูปหรือลงคลิปให้ดูได้ก็จะดีมาก
9 @R23059
แหะๆ งั้นผมอัพภาพมาแล้วครับ

อันนี้ภาพก่อนการค้นหาครับ (ด้านล่างคือ Sub form ครับ)


อันนี้โค้ดปุ่ม Search ครับ
image-not-found

หลังจากที่กด Search จะไปฟิลเตอร์ Query ตามภาพนี้เลยครับ


ผลที่ได้จะออกมาประมาณนี้

จากภาพนี้จะเห็นว่า "ประเภท" ของสินค้าเป็นชนิดเดียวกัน
แต่ถ้าเกิดกรณีว่าสินค้ามีหลายประเภท เช่น รายการที่ 1-3 เป็น AGM รายการที่ 4 เป็น CDB และ 5-6 เป็น AGM

เมื่อ User ทำการสั่งพิมพ์ จะไปเข้าเงื่อนไขตาม Query นี้ครับ (ตามจริงมีหลาย Query ประเภทสินค้าหลายชนิดมากๆ ครับ อันนี้ตัวอย่าง Query AGM )
image-not-found

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

>> ตอนนี้ผมหาทางเช็ค ข้อมูลใน Query ได้แล้วโดยใส่
if Me.sub_so.Form.product_type = "ประเภท" then
DoCmd.OpenReport "รายงานประเภทนั้นๆ", acNormal
แต่ผมคิดว่ายังไม่ถูกเพราะน่าจะต้องใส่ Loop เช็คแต่ละแถว ตรงนี้แหละครับ ที่ผมทำไม่ได้ T_T
10 @R23060
เหมือนที่คุณ ekkaphon แนะนำไว้ คุณสามารถใช้ Logical Operators (Not, And, Or, Xor, Eqv, Imp) เชื่อมต่อเงื่อนไขได้ทั้งในคิวรี่หรือการสั่งพิมพ์

if Me.sub_so.Form.product_type = "ประเภท1" then
    DoCmd.OpenReport "รายงานประเภท2", acNormal
Elseif Me.sub_so.Form.product_type = "ประเภท1" AND Me.sub_so.Form.product_type = "ประเภท2" then
    DoCmd.OpenReport "รายงานประเภท1", acNormal
    DoCmd.OpenReport "รายงานประเภท2", acNormal
Elseif ...
    ...
End if

ปรับใช้ดูครับ
11 @R23061
มีวิธีอื่นไหมครับ เช่น
สร้างตัวแปร i

ลูปให้เช็คทีแถว [i] ใน Query ว่าถ้าเจอ Type นี้ให้พิมพ์ แล้ว i+1
ไปแถวที่ [i] ฯลฯ
เพราะว่าถ้าใช้วิธีจับทีละคู่แบบด้านบน จะต้องเขียนเงื่อนไขเยอะมากๆ
ฟอร์มผมมี 10-15 แบบอะครับ

เช่น

แบบที่ 1 - 15
แบบที่ 1 และ 2 -9
แบบที่ 2 และ 3 - 9
.
.
.
12 @R23062
เอาเป็นเรื่องการสั่งพิมพ์อย่างเดียวใช่หรือเปล่าที่คุณติดปัญหา

1. ถ้าคุณค้นหาหมายเลข so แล้วแสดงเรคคอร์ดสมมุติเป็น

เลขที่ใบส่งสินค้า   รหัสินค้า     เลข          Heat        ประเภท
2020191692       AGM107506012   600205   AGM
2020191692       AGM107506012   600205   AGM
2020191692       AGM107506012   600205   AGM

คำถาม
แสดงว่าคุณต้องการพิมพ์รายงาน ชื่อ รายงานAGM ที่ซ้ำกันเพียงครั้งเดียว หรือ รายงานAGM 3 ครั้งตามเรคคอร์ด

โดยคุณก็จะใช้คำสั่ง
   DoCmd.OpenReport "รายงานประเภทAGM", acNormal
   DoCmd.OpenReport "รายงานประเภทAGM", acNormal
   DoCmd.OpenReport "รายงานประเภทAGM", acNormal
แบบนี้ได้หรือใช้เพียง
DoCmd.OpenReport "รายงานประเภทAGM", acNormal
ก็พอ

2. แต่ถ้าค้นหาหมายเลข so แล้วแสดงเรคคอร์ดเป็น

เลขที่ใบส่งสินค้า   รหัสินค้า     เลข          Heat        ประเภท
2020191692       AGM107506012   600205   AGM
2020191692       AGM107506012   600205   AGM
2020191692       AGM107506012   600205   CDB

หมายถึงคุณจะคำสั่งพิมพ์
   DoCmd.OpenReport "รายงานประเภทAGM", acNormal
   DoCmd.OpenReport "รายงานประเภทAGM", acNormal
   DoCmd.OpenReport "รายงานประเภทCDB", acNormal
หรือ
   DoCmd.OpenReport "รายงานประเภทAGM", acNormal
   DoCmd.OpenReport "รายงานประเภทCDB", acNormal

ไม่รู้ผมเข้าใจถูกเปล่า ถ้าถูก หากประเภทในฟอร์มค้นหาซ้ำกันคุณต้องการนับครั้งเดียวหรือไม่
13 @R23063
ใช่ครับ หากประเภทในฟอร์มค้นหาซ้ำกันต้องการนับครั้งเดียว ใช้โค้ด

DoCmd.OpenReport "รายงานประเภทAGM", acNormal
DoCmd.OpenReport "รายงานประเภทCDB", acNormal

ในปุ่ม prt_btn

แต่ สมมุติเลข SO อื่น ที่มี ประเภท AGM อย่างเดียว โค้ดนี้จะไม่สามารถใช้ได้ครับ เนื่องจากจะพิมพ์ "รายงานประเภทCDB" ออกมาด้วย ซึ่งเป็นรายงานเปล่า ไม่มีข้อมูล

ดังนั้นผมจะใส่เงื่อนไขที่สามารถเช็คแถว "ประเภท" ไปด้วยน่ะครับ ว่าแต่ละแถวมีประเภทใดบ้าง และให้พิมพ์ตามรายงานนั้นๆ แต่มันมีหลายประเภทครับ ตอนนี้และมีโอกาสเพิ่มในภายหลังสูงมาก ดังนั้นใช้โค้ดจับคู่ทีละเงื่อนไขไม่ได้อะครับ
เลยจะใช้ลูปเช็ค "ประเภท" วนทุกๆ Row ในแต่ละการค้นหาแทนครับ
14 @R23064
    Dim db As DAO.Database
    Dim rs As DAO.Recordset
    Set db = CurrentDb
    Set rs = Me.RecordsetClone
    Dim i As String
    rs.MoveFirst
    Do Until rs.EOF
        If i = "" Then
            i = rs!product_type
        Else
            If Not i Like "*" & rs!product_type & "*" Then 'หากชื่อประเภทซ้ำก็ไม่ต้องเก็บเข้าตัวแปรอีก
               i = i & "," & rs!product_type
            End If
        End If
        rs.MoveNext
    Loop
    rs.Close: Set rs = Nothing
    Set db = Nothing

'นำตัวแปร i ที่เก็นชื่อประเภทมาสั่งพิมพ์

    Dim ary() As String, intLoop As Integer
    ary = Split(i, ",")
    For intLoop = 0 To UBound(ary)
On Error Resume Next ' จะใส่โค๊ดดัก Error ยังไงเช่นหากเครื่องพิมพ์ไม่พร้อม อะไรก็ว่าไปครับ
        DoCmd.OpenReport "รายงาน" & ary(intLoop), acNormal ' คำสั่งพิมพ์ โดยเราต้องตั้งชื่อรายงานสอดคล้องกับประเภท เช่น ชื่อ รายงาน_AGM, รายงาน_CDB, รายงาน_..., เป็นต้น
    Next intLoop


ประมาณนี้ครับ ลองปรับใช้ดูครับ
15 @R23067
ขอบคุณครับผม

ขออภัยอีกครั้งเรื่องการพิมพ์อีกครั้งครับ ทำให้เข้าใจยาก ฮ่าๆ
@ ประกาศใช้งานเว็บบอร์ดใหม่ => บอร์ดเรียนรู้ Access สำหรับคนไทย
แล้วจะใส่ลิ้งอ้างอิงมาที่โพสต์เก่านี้หรือไม่ก็ตามสะดวกครับ
Time: 0.2767s