Level 1: Core Fundamentals

Sub-topic 1.2: Report Bands Architecture & Coordinate Engine

สถาปัตยกรรม 11 Bands Execution Flow, ระบบพิกัดเฉพาะส่วน (Band Coordinates), จุดตาย Infinite Page Loop และ Hands-on Engineering Labs

Step 1: Deep Dive (11 Bands Execution Timing & Printable Coordinates)

ในกระบวนการ Fill Stage ตัวประมวลผล JRVerticalFiller จะแบ่งพื้นที่เอกสาร A4 ออกเป็นระบบพิกัดเฉพาะส่วน (Band Coordinate System) โดยพิกัด $Y=0$ จะเริ่มต้นใหม่เสมอที่ขอบบนของแต่ละ Band ไม่ใช่พิกัดสะสมจากหัวกระดาษแผ่นใหญ่

11 Bands Execution Flowchart
รูปที่ 1: สถาปัตยกรรม 11 Bands Execution Lifecycle ตามแกนเวลาของ JRVerticalFiller

สูตรคำนวณพื้นที่พิมพ์จริง (Printable Area):

Printable Height = pageHeight - (topMargin + bottomMargin)
Printable Width  = pageWidth  - (leftMargin + rightMargin)

// ตัวอย่างมาตรฐาน A4:
// 842pt - (20pt + 20pt) = 802pt (ความสูงสุทธิ)
// 595pt - (20pt + 20pt) = 555pt (ความกว้างสุทธิ)

ลักษณะการกระตุ้นทำงาน (Trigger Timing) ของ Bands หลัก:

  • <background>: วาดลงบนเลเยอร์ล่างสุดของทุกหน้า เหมาะสำหรับ Watermark / ลายเซ็นต์ดิจิทัล
  • <title>: ประมวลผลครั้งเดียวที่จุดเริ่มต้นของเอกสาร (ควบคุมการขึ้นหน้าใหม่ด้วย isTitleNewPage)
  • <pageHeader> / <pageFooter>: วาดที่หัวและท้ายกระดาษของทุกๆ หน้า
  • <lastPageFooter>: หากประกาศไว้ จะถูกนำมาวาดแทนที่ pageFooter ปกติบนหน้าสุดท้าย
  • <summary>: พิมพ์ปิดท้ายเอกสารเพียงครั้งเดียว (ควบคุมให้เกาะต่อท้ายแถวสุดท้ายด้วย isSummaryNewPage="false")
  • whenNoDataType="AllSectionsNoDetail": บังคับให้โครงสร้าง Header/Footer วาดออกมาแม้ไม่มีแถวข้อมูลจาก DataSource
จุดตายบน Production (The Infinite Page Loop Crash):
หาก Band ใดๆ (เช่น Detail Band) ถูกกำหนดค่า height หรือยืดขยายด้วย StretchHeight จนมีความสูงรวมมากกว่าพื้นที่ Printable Height ($> 802\text{ pt}$) เครื่องยนต์จะไม่สามารถวาด Band นั้นลงในหน้าเดียวได้สำเร็จ ส่งผลให้เกิดการ Trigger ตัดขึ้นหน้าใหม่ไปเรื่อยๆ ซ้ำซากไม่รู้จบ จนกระทั่งหน่วยความจำ JVM พังทลายด้วย OutOfMemoryError: Java heap space

Step 2: Real-world 7.0.x Architecture Example

Invoice Preview Mockup
รูปที่ 2: Visual Materialization เอกสารใบแจ้งหนี้จริง จัดวางโครงสร้าง Band ตามสถาปัตยกรรม 7.0.x
<!-- JRXML 7.0.x Schema: Tax Invoice Architecture -->
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports"
              name="TaxInvoice" pageWidth="595" pageHeight="842"
              columnWidth="555" leftMargin="20" rightMargin="20"
              topMargin="20" bottomMargin="20"
              whenNoDataType="AllSectionsNoDetail">

    <background>
        <band height="802">
            <element kind="staticText" x="100" y="350" width="355" height="60">
                <text><![CDATA[ORIGINAL]]></text>
            </element>
        </band>
    </background>

    <title>
        <band height="60">
            <element kind="staticText" x="0" y="10" width="250" height="30">
                <text><![CDATA[TAX INVOICE / RECEIPT]]></text>
            </element>
        </band>
    </title>

    <detail>
        <band height="25" splitType="Prevent">
            <element kind="textField" x="0" y="2" width="400" height="20">
                <expression><![CDATA[$F{item_description}]]></expression>
            </element>
            <element kind="textField" x="410" y="2" width="145" height="20">
                <expression><![CDATA[$F{unit_price}]]></expression>
            </element>
        </band>
    </detail>

    <summary>
        <band height="40">
            <element kind="staticText" x="300" y="10" width="100" height="20">
                <text><![CDATA[Grand Total:]></text>
            </element>
        </band>
    </summary>
</jasperReport>

ข้อกำหนดสถาปัตยกรรม:
splitType="Prevent": ป้องกันการฉีกขาดของแถวข้อมูลระหว่างรอยต่อหน้ากระดาษ
whenNoDataType="AllSectionsNoDetail": ประคองโครงสร้างเอกสารให้ออกมาแม้ไร้ข้อมูลจาก Record

Hands-on Engineering Lab 1.2.1: The Zero-Break & Crash Defense Specification

🛠️ Lab 1.2.1: Crash Prevention & Split Control

เงื่อนไขทางเทคนิค (Full-Coverage 100%):
1. กำหนด Root <jasperReport> เป็น A4 (595x842pt, Margins 20pt) พร้อม whenNoDataType="AllSectionsNoDetail"
2. Detail Band ต้องมี splitType="Prevent" และความสูงต้อง < 802pt เพื่อป้องกัน Infinite Loop บน JVM
3. ใช้ Unified Element Model 7.0.x: <element kind="textField" ...> วาง $F{service_node_name}

Hands-on Engineering Lab 1.2.2: Full-Spectrum Bands Lifecycle & Swapping Architecture

🛠️ Lab 1.2.2: Band Lifecycle & Footer Swapping

เงื่อนไขทางเทคนิค (Full-Coverage 100%):
1. <background> ความสูงเต็ม Printable Area (802pt) วาง Watermark staticText "INTERNAL AUDIT ONLY"
2. <title> ความสูง 60pt พร้อมใส่ isTitleNewPage="false" (อยู่ร่วมหน้าแรก)
3. <pageFooter> ความสูง 20pt แสดงตัวแปร "Page " + $V{PAGE_NUMBER}
4. <lastPageFooter> ความสูง 20pt วางข้อความ "-- END OF AUDIT REPORT --" แทนที่ pageFooter ปกติในหน้าสุดท้าย
5. <summary> ความสูง 40pt พร้อมใส่ isSummaryNewPage="false" ล็อกยอดรวมให้เกาะต่อท้าย Detail

Step 3: Interactive Checkpoint Quiz (100% In-Content Guarantee)

แบบทดสอบ 15 ข้อเชิงลึก อ้างอิงจากหลักการ 11 Bands, Coordinate Calculation และจุดตายบน Production ที่สอนไว้ทั้งหมด:

⚡ Real-time Score Tracker (Level 1.2)
คะแนน: 0 / 15 (ตอบแล้ว: 0 / 15)