ตั้งค่าให้แสดงคำว่า continue ในรายงานที่ไม่ใช่หน้า
กระทู้เก่าบอร์ด อ.Yeadram

 4,344   16
URL.หัวข้อ / URL
ตั้งค่าให้แสดงคำว่า continue ในรายงานที่ไม่ใช่หน้า

สวัสดีครับ

ตอนนี้ผมมีข้อสงสัยเรื่องการนับจำนวนหน้าของรายงานครับ

เงื่อนไขที่ต้องการครับ
ถ้ารายงานมีเพียง 1 หน้าให้ label ที่แสดงข้อความ Continue visible = false ครับ
ถ้าหลายหน้าจะต้องดูว่า
    ถ้าไม่ใช่หน้าสุดท้ายให้ label ที่แสดงข้อความ Continue visible = True ครับ
    ถ้าเป็นหน้าสุดท้ายให้ label ที่แสดงข้อความ Continue visible = false ครับ

รบกวนด้วยครับ

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

1 @R18105
ได้แล้วครับ
ผมสร้าง textbox ที่ page footer
โดยกำหนด control source ตามนี้ครับ
=IIf([Pages]=1,"",IIf([Page]=[Pages],"","Continue"))
2 @R18106
มีเรื่องใหม่อีกเรื่องมาครับ

รายงานที่ต้องการจะมี Report Footer ที่เป็นชื่อ ลายเซ็น ซึ่งกรณีที่มีข้อมูลมากกว่า 1 หน้าจะเกิดกรณีที่ข้อมูลมีจำนวน 1 หน้าพอดี แต่มีส่วนที่เกินไปเฉพาะลายเซ็นทำให้ ลายเซ็นถูกดันไปหน้าสุดท้ายรวม Page header (หน้าสุดท้ามี page header กับลายเซ็นโดยไม่มีข้อมูล details)

ซึ่งที่ผมต้องการคือถ้าจำนวนรายการในรายงานที่เรียกมีพอดีที่ทำให้รายงานแสดงผลหน้าสุดท้ายเป็น page header กับ report footer ให้ย้าย details 2 รายการสุดท้ายมาอยู่ในหน้าสุดท้ายของรายงานแทนครับ
3 @R18107
ย้ายลายเซ็นต์ใน report footer มาใส่ page footer แทน แล้วให้แสดงเฉพาะเมื่อเป็นหน้าสุดท้ายเท่านั้น แต่ลายเซ็นต์มันจะแปะที่ด้านล่างของกระดาษเสมอ ไม่เหมือน report footer ที่จะเข้ามาต่อท้ายเรคอร์ดสุดท้าย
4 @R18108
ลองย้ายลายเซ็นต์มาไว้ใน page footer แล้วพบว่ามันจะกินหน้ากระดาษส่วนของลายเซ็นต์ทำให้จำนวนข้อมูลแต่ละหน้าลดลง
(ส่วนที่เป็นลายเซ็นจะว่างเวลาพิมออกมาจะดูโล่งๆ ด้านล่างกระดาษในหน้าที่ไม่มีลายเซ็นครับ)

ที่คิดไว้ประมาณว่า Count จำนวน details แต่ละหน้าในรายงาน ถ้าหน้าไหน Count = 0 ให้ไปตัดข้อมูล Details 2 รายการสุดท้ายหน้าก่อนหน้าเพื่อมาแสดงในหน้านี้ แต่ดูแล้วมันน่าจะเขียนยากครับ แต่ถ้าได้อย่าที่ต้องการ หน้าสุดท้ายจะกลายเป็นมีข้อมูล 2 บรรทัดและตามด้วยลายเซ็นครับ(หน้ารองสุดท้ายข้อมูลจะถูกร่นมาสองรายการครับ)

จะลองหาวิธีไปเรื่อยๆครับ
5 @R18109
คุณสามารถกำหนดจำนวนบรรทัดแต่ละหน้าได้ด้วยการสร้างเงื่อนไขในคุณสมบัติของ ForceNewPage ตัวอย่างเช่น

1. สร้าง Text Box เปล่าขึ้นใหม่บนพื้นที่ Detail section และกำหนด Property ดังนี้:
Other > Name: txtcounter
Data   > Control Source: =1
Data   > Running Sum: Over Group
Format > Visible: No

2. จากนั้นใส่โค๊ดที่ Event > On Format ในส่วนของ Detail section ดังนี้:

'Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
    If [txtcounter] Mod 9 = 0 Then ' กำหนดเงื่อนตัวเลขจำนวนเรคคอร์ดที่จะแสดงคือ 9 บรรทัด
        Me.Detail.ForceNewPage = 9
    Else
        Me.Detail.ForceNewPage = 0
    End If
'End Sub

- จากนั้นเมื่อ Print Preview ดู แต่ละหน้าของ Report ก็จะแสดงเพียง 9 เรคคอร์ดเท่านั้น หากเกินก็ขึ้นหน้าใหม่ โดยพื้นที่ใน Detail ก็ยังสูงเท่าเดิม

ปรับใช้ดูครับ

6 @R18113
ขอบคุณครับ

เรื่อง forcenewpage ผมลองใช่แล้วครับ(ที่ค้นหาเจอใน internet อย่างแรกก็เป็นตัวนี้ครับ)
แต่ปัญหาที่ยังเจอก็ยังเป็นเหมือนเดิมครับ คือกรณีที่จำนวน record มันพอดีกับหน้าสุดท้าย(คือพื้นที่เหลือในหน้านั้นไม่พอกับลายเซ็น(ที่อยู่ใน Report Footer) ) ลายเซ็นจะถูกดันไปหน้าถัดไป (จริงๆแล้วหน้าสุดท้ายที่มีลายเซ็นก็แสดง page header ด้วยแต่ page header ผมต้องการให้มีพอดี)

หน้าสุดท้ายตามกรณีที่เกิดขึ้นจะมี Page header กับ ลายเซ็นต์ โดยไม่มีข้อมูล Details ครับ

ที่จะเห็นได้ชัดก็ในกรณีที่ข้อมูลมีปริมาณ 12 - 16 record จะเกิดตามเคสที่กล่าวมาครับ(ไม่นับข้อมูลเยอะๆ หลายหน้าซึ่งสามารถเกิดได้เหมือนกัน)

ผมคิดไว้อีกวิธีคือสร้าง report เพิ่ม ไว้สำหรับกรณีที่กดเรียกรายงาน(ให้ count record ก่อนว่าเท่าไร) ถ้าเข้าเงื่อนไข 12-16 ก็ให้ไป report ที่สร้างตาม format เฉพาะ แต่การทำแบบนี้ก็ไม่ได้แก้ปัญหาสำหรับกรณีปริมาณข้อมูลเยอะๆ แต่ผมคิดไว้ว่าถ้าหาวิธีไม่ได้คงทำแบบนี้ไปก่อนครับ เพราะดูแล้วข้อมูลที่มี record เยอะๆ มีความถี่น้อยครับ
7 @R18115
ขออธิบายเพิ่มเติมครับ ผมไม่สามารถเว้นส่วนล่างของรายงานไว้สำหรับลายเซ็นที่จะแสดงหน้าสุดท้ายเพียงอย่างเดียวได้ครับ การ Forcenewpage เพื่อเว้นพื้นที่จึงไม่ตอบโจทย์ผมในเรื่องนี้ครับ

ขอบคุณครับ
8 @R18116
ForceNewPage ที่คุณ TTT แสดงเป็นตัวอย่างให้นั้น เป็นสิ่งที่ใช้แก้ปัญหาคุณได้แน่นอน เพราะมันจะถูก set หรือ reset ทุกครั้งที่จะพิมพ์แต่ละบรรทัด เพียงแต่เงื่อนไขในคำสั่ง If [txtcounter] Mod 9 = 0 Then คุณต้องไปปรับให้เหมาะสมเอง
9 @R18118
ขอบคุณครับ

เดี๋ยวผมจะไปลองดูใหม่อีกครั้งครับ
อันเก่าที่ลองใช้เป็น
    If [txtcounter] Mod 25 = 0 Then
        Me.Detail.ForceNewPage = 2 'เข้าใจว่ารายการถัดไปขึ้นหน้าใหม่ เลยใช้ 2 ครับ
    Else
        Me.Detail.ForceNewPage = 0
    End If
10 @R18126
ขอโทษด้วยครับที่อธิบายไม่หมดขอโพสรูปรายงานให้ดูด้วยนะครับ
จากที่ลองไปทำมาอีกรอบครับพบว่า

ถ้าผมกำหนด
If [txtcounter] Mod 28 = 0 Then
       Me.Detail.ForceNewPage = 2
    Else
        Me.Detail.ForceNewPage = 0
End If
สมมุติว่ารายการมีมากกว่า 100 รายการครับ
1. มันจะแสดงหน้าแรก 17 รายการ
2. หน้า 2 แสดงรายการที่เหลือ 11 รายการ
3. หน้า 3 แสดง 28 รายการ
4. หน้า 4 แสดง 28 รายการ
5. หน้าสุดท้ายจะแสดงตามจำนวนรายการที่เหลือ
ซึ่งถ้ารายการในหน้าสุดท้ายแสดงตั้งแต่ 25 -28 รายการ ลายเซ็นจะไม่มีที่ว่างเพียงพอในหน้านั้น ลายเซ็นก็จะถูกดันไปแสดงหน้าถัดไปครับ

ถ้าผมกำหนดให้แสดงที่ 24 รายการ ( If [txtcounter] Mod 24 = 0 Then )
1. หน้าแรกจะแสดง 17 รายการ
2. หน้า 2 แสดง 7 รายการ
3. หน้า 3 แสดง 24 รายการ
4. หน้า 4 แสดง 24 รายการ
5. หน้าสุดท้ายจะแสดงตามจำนวนรายการที่เหลือโดยที่สามารถแสดงลายเซ็นได้ในหน้านี้เลยครับ
แต่ถ้ากำหนดที่ 24 รายการหน้ากลางๆจะมีช่องว่างด้านล่างกระดาษเท่ากับขนาดความสูงของลายเซ็นครับ (ยกเว้นหน้าแรกที่แสดงได้เต็มพอดี)

ซึ่งถ้าผมกำหนดที่ 17 รายการ ( If [txtcounter] Mod 17 = 0 Then ) หน้ากลางๆก็จะมีช่องว่างด้านล่างกระดาษเพิ่มขึ้นอีก(แต่หน้า 2 จะแสดง 17 รายการพอดี)

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

ผมต้องขออภัยอาจารย์ทุกท่านด้วยครับที่ไม่ได้อธิบายรายละเอียดรายงานที่ต้องการ ตอนนี้ผมCap ภาพรายงานที่ต้องการมาให้แล้วครับ

หน้าแรกของรายงานครับ จะมีหัวรายงานก่อนที่จะเริ่มขึ้นข้อมูลครับ


หน้าสุดท้ายรายงานครับ


ซึ่งกรณีที่เป็นปัญหาจะออกมาแค่บรรทัด Instrument NO กับลายเซ็นครับ

ขอบคุณครับ
11 @R18127
เพิ่มเติมนิดครับ สำหรับกรณีกำหนดที่ 17 รายการ ( If [txtcounter] Mod 17 = 0 Then )

หน้าที่ 2 จะออกมาแบบนี้ครับ (ด้านล่างจะว่าง)
12 @R18130
รอค่ำๆ แล้วจะตอบให้ครับ ตอนนี้ยังไม่ว่าง
13 @R18132
ลองเอาโค้ดนี้ไปใช้ดูว่าใช้ได้หรือไม่ ลองอ่านที่ผม comment ไว้ว่าพอจะเข้าใจหรือไม่ ไม่เข้าใจยังไงก็มาถามแล้วกัน และเนื่องจากจำนวนบรรทัดในหน้าแรกและหน้าอื่นๆแตกต่างกัน เพราะหน้าแรกมี report header section (หรือจะ section อะไรอื่นๆอีกก็แล้วแต่) ให้แก้ค่าคงที่ของ FirstPageLine และ OtherPageLine ให้เป็นไปตามที่นับได้ ส่วน ReservedLine ตอนนี้เป็น 2 ตรงตามที่บอกความต้องการมาให้อยู่แล้ว (จะเปลี่ยนเป็นค่าอื่นก็ได้)

หมายเหตุ : โค้ดนี้ใช้ได้ก็ต่อเมื่อทุกๆหน้าจะต้องมีจำนวนบรรทัดที่พิมพ์ตามที่ระบุใน FirstPageLine หรือ OtherPageLine เท่านั้น ถ้ามี group footer section เพิ่มเข้ามา จะทำให้จำนวนบรรทัดที่จะพิมพ์ในแต่ละหน้าอาจไม่แน่นอนได้ โค้ดนี้จะใช้ไม่ได้ครับ
Option Compare Database
Option Explicit

Dim TotalRecord     As Integer ' จำนวนบรรทัดทั้งหมดที่แสดงในรายงาน

Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
    Const FirstPageLine = 10    ' จำนวนบรรทัดที่แสดงรายการพิมพ์ในหน้าแรก
    Const OtherPageLine = 17    ' จำนวนบรรทัดที่แสดงรายการพิมพ์ในหน้าอื่นๆ
    Const ReservedLine = 2      ' จำนวนบรรทัดที่สำรองไว้เพื่อยกไปพิมพ์ในหน้าถัดไป

    Dim PageLine    As Integer ' จำนวนบรรทัดต่อหน้าที่ใช้ระหว่างการคำนวน
    Dim CurrentLine As Integer ' บรรทัดปัจจุบันที่ใช้ระหว่างการคำนวน

    Me.Detail.ForceNewPage = 0

    ' อยู่ในลูปแรกของการจัดหน้ารายงาน (ยังไม่พิมพจริง)
    ' ซึ่งเกิดเพราะมีการใส่ฟังก์ชั่น [Pages] ลงในเท็กซ์บ็อกซ์บนหน้ารายงาน
    ' ความหมายของ Pages = 0 ให้ไปอ่านใน http://access.mvps.org/access/reports/rpt0013.htm
    If Me.Pages = 0 Then
        If Me.txtcounter > TotalRecord Then
            TotalRecord = Me.txtcounter     ' เก็บจำนวนบรรทัดสูงสุดที่นับได้
        End If
    Else
        ' ถ้าเป็นบรรทัดที่ต้องพิจารณาว่าบรรทัดถัดไปควรยกไปพิมพ์หน้าใหม่
        ' เช่น ตอนนี้เป็นบรรทัดที่ 25 จากทั้งหมด 27 บรรทัด
        If Me.txtcounter + ReservedLine = TotalRecord Then
            ' เนื่องจากหน้าแรกมี report header ซึ่งทำให้จำนวนบรรทัดที่พิมพ์ได้แตกต่างจากหน้าอื่น
            ' จึงต้องหาค่าที่ใช้ในการคำนวนแตกต่างกัน
            If Page = 1 Then
               PageLine = FirstPageLine
               CurrentLine = Me.txtcounter
            Else
               PageLine = OtherPageLine
               CurrentLine = Me.txtcounter - FirstPageLine     ' หักจำนวนบรรทัดในหน้าแรกออกไป
            End If
            
            ' ถ้าอีกจำนวน ReservedLine บรรทัดจะแสดงเต็มหน้านี้พอดี ก็ยกบรรทัดต่อไปพิมพ์ในหน้าใหม่
            If (CurrentLine Mod PageLine) + ReservedLine = PageLine Then
               Me.Detail.ForceNewPage = 1
            End If
        End If
    End If
End Sub


14 @R18135
ขอบคุณมากครับอาจารย์สันติสุข

โค้ดตัวนี้ใช้ได้เลยครับสำหรับรายงานนี้(ผมเปลี่ยนเอา Sum ที่อยู่ใน group footer section มาไว้ใน Report Footer เนื่องจากรายงานนี้มี Sum รายการเดียว)

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ขอสอบถามความเข้าใจหน่อยครับอ. เรื่องความหมายของ Pages = 0

        ผมเข้าใจในภาษาบ้านๆว่าเมื่อเรียกรายงาน Access จะยังไม่รู้ว่ามีจำนวนหน้าทั้งหมดกี่หน้าจนกว่าจะจัด Format ของรายงานตามที่กำหนดเสร็จสิ้นค่า Pages เริ่มต้นจึงยังไม่มี จากนั้น Access จะทำการจัด Format ของรายงานซึ่งจะทำให้ทราบจำนวนหน้าทั้งหมด ในกรณีที่มีการใช้คำสั่งให้แสดงค่า pages ในรายงาน {ในกรณีผมสร้าง textbox โดยกำหนด Control Source =IIf([Pages]=1,"",IIf([Page]=[Pages],"","Continue")) } ซึ่งทำให้ Access ถูกบังคับให้ ทำการ Format Report 2 ครั้ง (ผมเข้าใจว่าปกติถ้าไม่มีการเรียกใช้ [Pages] Access จะทำการ Format รายงานเพียงครั้งเดียวแล้วจึงพิมพ์รายงานออกมา แต่ถ้ามีการใช้ [Pages] Access จะต้องจัด Format รายงานเพื่อหาค่าจำนวนหน้าทั้งหมดก่อน แล้วจึงนำมาจัด Format รายงานอีกครั้งก่อนพิมพ์รายงานเหมือนต้องจัด format 2 ครั้ง

ผมเข้าใจถูกต้องมั้ยครับ
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

ส่วนโค้ด
    If Me.Pages = 0 Then
        If Me.txtcounter > TotalRecord Then
            TotalRecord = Me.txtcounter   
        End If
    Else
    ...
    End If

txtcounter เมื่อ Me.Pages = 0 จะนับรวมข้อมูลทั้งหมดที่ดึงมา (โดยยังไม่ได้แบ่งหน้าตอนนี้)

txtcounter เมื่อ Me.Pages <> 0   (ผมไม่เข้าใจว่า ณ จุดนี้ txtcounter จะเป็นแบบไหน ถ้าตามผลจาก Code ของอาจารย์ผมคิดว่า txtcounter ตอนนี้มีค่าตาม loop คือ running sum ไปเรื่อยๆ จนเข้าเงื่อนไข Me.txtcounter + ReservedLine = TotalRecord (ตามตัวอย่าง 25+2 = 27)

สอบถามเพิ่มเติมครับ
1. ถ้าในรายงานผมไม่ได้มีการดึงค่า Page & Pages มาใช้ ผมจะหา TotalRecord ได้อย่างไรบ้างครับ
(ที่คิดไว้คือผมต้อง select Count(*) จากตารางและเงื่อนไขเดียวกับตอนเรียกรายงานใช่มั้ยครับ หรือเรียกแบบอื่น).

2. ถ้าในรายงานผมไม่ได้มีการดึงค่า Page & Pages มาใช้ ผมไม่จำเป็นต้องเขียน Code Check me.pages ใช่มั้ยครับ (ใช้ Code ด้านในได้เลย)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ขอบคุณครับ
15 @R18136
- event โดยทั่วไปที่เกิดขึ้นคือ
format บรรทัดแรก ในลูปแรก
format บรรทัดที่ 2 ในลูปแรก
...
format บรรทัดสุดท้าย ในลูปแรก

format บรรทัดแรก ในลูปที่ 2
print บรรทัดแรก ในลูปที่ 2

format บรรทัดที่ 2 ในลูปที่ 2
print บรรทัดที่ 2 ในลูปที่ 2
...
format บรรทัดสุดท้าย ในลูปที่ 2
print บรรทัดสุดท้าย ในลูปที่ 2

ที่บอกปกติก็เพราะ microsoft เขียนว่าในบางกรณี ในบรรทัดเดียวกันอาจมีการเกิด format event ได้เกินกว่า 1 ครั้ง (ตัวเลขในพารามิเตอร์ FormatCount ของ On Format event procedure จะเป็นตัวบอก)

- ใช่ครับ ก็คงต้องใช้ select count(*) from ... เพื่อหาจำนวนเรคอร์ดทั้งหมดที่จะพิมพ์แทนการใช้ Me.txtcounter

- ใช่ครับ ไม่จำเป็นต้องเช็ค Me.Pages
16 @R18145
ขอบคุณมากครับอาจารย์ ได้อ่านแล้วกระจ่างขึ้นครับ
@ ประกาศใช้งานเว็บบอร์ดใหม่ => บอร์ดเรียนรู้ Access สำหรับคนไทย
แล้วจะใส่ลิ้งอ้างอิงมาที่โพสต์เก่านี้หรือไม่ก็ตามสะดวกครับ
Time: 0.2988s