Pemisah Kontrol dan Total

Deteksi perubahan grup, pencetakan header pemisah, subtotal per grup, dan total akhir.

Daftar isi

Laporan batch pada umumnya mengelompokkan baris menurut kunci tertentu, misalnya kelas, wilayah, atau jenis layanan. Topik ini membahas teknik pemisah kontrol (control break) untuk menyusun laporan semacam itu, yaitu deteksi perubahan kunci grup, pencetakan header grup, perhitungan subtotal, dan perhitungan total akhir. Setelah membacanya, laporan bertingkat dari berkas terurut dapat dihasilkan dalam satu kali pembacaan berkas, lengkap dengan subtotal per grup dan total keseluruhan.

Konsep pemisah kontrol#

Pemisah kontrol (control break) adalah peristiwa berubahnya nilai kunci grup pada berkas yang terurut menurut kunci tersebut. Berkas transaksi memuat baris-baris detail yang sudah diurutkan menurut kunci grup, misalnya kode kelas. Program menyimpan kunci grup yang sedang diproses pada sebuah variabel penahan, kemudian membandingkan kunci setiap rekaman baru dengan variabel itu. Ketika keduanya berbeda, satu pemisah terjadi, yaitu saat subtotal grup lama dicetak, header grup baru dibentuk, dan akumulator subtotal dikembalikan ke nol.

Alur kerjanya sama untuk berkas sekuensial apa pun.

  1. Baca rekaman perdana sebelum perulangan, salin kuncinya ke variabel penahan, dan cetak header grup pertama.
  2. Selama rekaman berikutnya berkunci sama, cetak baris detailnya dan tambahkan nilai yang dihitung ke subtotal grup.
  3. Ketika kunci berubah, cetak subtotal grup lama, salin kunci baru ke variabel penahan, cetak header grup baru, dan nolkan subtotal.
  4. Setelah berkas habis dibaca, cetak subtotal grup terakhir, kemudian cetak total keseluruhan.

Tiga variabel kerja menopang alur tersebut, yaitu variabel penahan kunci, akumulator subtotal, dan akumulator total. Akumulator total ditambah pada setiap baris detail, sedangkan akumulator subtotal hanya berlaku selama satu grup. Kedua akumulator dideklarasikan dengan PIC 9(3), sehingga nilai terbesar yang dapat ditampung adalah 999 dan ukurannya perlu diperbesar bila datanya lebih besar dari itu.

Syarat keterurutan berkas bukan formalitas. Deteksi pemisah hanya membandingkan kunci berurutan, sehingga kelompok dengan kunci sama yang terpecah pada dua bagian berkas dianggap dua kelompok berbeda. Aturan sederhana ini membuat program tidak perlu menampung seluruh berkas di memori, dan itulah sebabnya teknik ini layak dipakai untuk berkas berukuran besar.

Perulangan bersarang pada PROCEDURE DIVISION#

Struktur PERFORM yang sesuai untuk pola ini adalah dua perulangan bersarang. Perulangan luar berjalan sampai akhir berkas, sedangkan perulangan dalam berjalan selama kunci rekaman masih sama dengan variabel penahan. Akhir berkas ditandai level 88 bernama SELESAI, sehingga kondisi perulangan cukup ditulis UNTIL SELESAI.

Pembacaan rekaman di dalam perulangan hanya terjadi pada satu tempat, yaitu di ujung perulangan dalam, sedangkan rekaman perdana dibaca sebelum perulangan dimulai. Pola ini menjamin setiap rekaman diproses tepat satu kali, baik oleh percabangan deteksi pemisah maupun oleh pencetakan baris detail. Tanpa pola seragam seperti ini, rekaman pertama tiap grup mudah tercetak dua kali atau justru terlewat.

Angka pada keluaran diformat melalui variabel teredit (edited field), yaitu variabel yang picture-nya memuat huruf Z. Huruf Z menekan nol di depan dengan menggantinya menjadi spasi, sehingga nilai 9 tampil sebagai 9 dan bukan 009. Penampilan semacam ini penting pada laporan karena deretan nol di depan mempersulit pembacaan, sementara perhitungan tetap berlangsung pada variabel numerik biasa sebelum dipindahkan ke variabel teredit.

Data dan program#

Data contoh berisi catatan jam piket siswa dari tiga kelas. Setiap baris berukuran 12 karakter, terdiri atas kode kelas tiga karakter, satu spasi, nama lima karakter, satu spasi, dan jam piket dua digit. Berkas sudah terurut menurut kelas, sesuai syarat pemisah kontrol. Struktur FD memecah setiap baris menjadi lima field sesuai posisi kolomnya, dan dua field FILLER menampung spasi pemisah yang tidak diproses. Field yang tidak diproses tetap wajib dideklarasikan agar posisi field berikutnya tidak bergeser.

text piket.dat
10A ALI   03
10A BUDI  02
10A CITRA 04
10B DEWI  05
10B EKA   01
10C FAJAR 02
10C GITA  03

Program berikut membaca berkas tersebut dan mencetak laporan lengkap dengan subtotal per kelas.

cobol laporan.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. LAPORAN-PIKET.
      *> Rekap jam piket dengan pemisah kontrol per kelas.
       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT DATA-PIKET ASSIGN TO "piket.dat"
               ORGANIZATION IS LINE SEQUENTIAL.
       DATA DIVISION.
       FILE SECTION.
       FD  DATA-PIKET.
       01  REK-PIKET.
           05  RP-KELAS         PIC X(3).
           05  FILLER           PIC X.
           05  RP-NAMA          PIC X(5).
           05  FILLER           PIC X.
           05  RP-JAM           PIC 9(2).
       WORKING-STORAGE SECTION.
       01  WS-EOL               PIC X     VALUE "N".
           88  SELESAI                    VALUE "Y".
       01  WS-KUNCI             PIC X(3).
       01  WS-SUBTOTAL          PIC 9(3)  VALUE 0.
       01  WS-TOTAL             PIC 9(3)  VALUE 0.
       01  WS-JAM-ED            PIC Z9.
       01  WS-SUB-ED            PIC ZZ9.
       01  WS-TOT-ED            PIC ZZ9.
       PROCEDURE DIVISION.
       UTAMA.
           OPEN INPUT DATA-PIKET
           DISPLAY "REKAP JAM PIKET SISWA"
           DISPLAY "====================="
           READ DATA-PIKET
               AT END MOVE "Y" TO WS-EOL
           END-READ
           PERFORM UNTIL SELESAI
               MOVE RP-KELAS TO WS-KUNCI
               DISPLAY " "
               DISPLAY "Kelas " WS-KUNCI
               PERFORM UNTIL SELESAI
                              OR RP-KELAS NOT = WS-KUNCI
                   PERFORM CETAK-BARIS
                   ADD RP-JAM TO WS-SUBTOTAL WS-TOTAL
                   READ DATA-PIKET
                       AT END MOVE "Y" TO WS-EOL
                   END-READ
               END-PERFORM
               PERFORM CETAK-SUBTOTAL
           END-PERFORM
           MOVE WS-TOTAL TO WS-TOT-ED
           DISPLAY " "
           DISPLAY "Total keseluruhan : " WS-TOT-ED
           CLOSE DATA-PIKET
           STOP RUN.
       CETAK-BARIS.
           MOVE RP-JAM TO WS-JAM-ED
           DISPLAY "  " RP-NAMA "   " WS-JAM-ED.
       CETAK-SUBTOTAL.
           MOVE WS-SUBTOTAL TO WS-SUB-ED
           DISPLAY "  Subtotal " WS-KUNCI " : " WS-SUB-ED
           MOVE 0 TO WS-SUBTOTAL.
text Keluaran
REKAP JAM PIKET SISWA
=====================
 
Kelas 10A
  ALI      3
  BUDI     2
  CITRA    4
  Subtotal 10A :   9
 
Kelas 10B
  DEWI     5
  EKA      1
  Subtotal 10B :   6
 
Kelas 10C
  FAJAR    2
  GITA     3
  Subtotal 10C :   5
 
Total keseluruhan :  20

Kompilasi program dengan perintah berikut, kemudian jalankan ./laporan.

bash
# kompilasi program laporan pemisah kontrol
cobc -x laporan.cbl

Keluaran memperlihatkan tiga grup, yaitu kelas 10A, 10B, dan 10C. Baris Subtotal tercetak setiap kali perulangan dalam berakhir, baik karena nilai RP-KELAS berbeda dari WS-KUNCI maupun karena berkas habis. Baris Total keseluruhan hanya tercetak satu kali pada akhir laporan. Angka 9, 6, dan 5 merupakan penjumlahan jam tiap kelas, sedangkan 20 adalah jumlah seluruhnya. Perbandingan RP-KELAS NOT = WS-KUNCI pada perulangan dalam menjadi titik terjadinya pemisah, sedangkan perulangan luar berhenti ketika SELESAI bernilai benar.

Kesalahan umum#

  • Berkas tidak terurut menurut kunci. Kelompok yang sama terpecah menjadi beberapa header dengan subtotal yang keliru. Urutkan berkas terlebih dahulu, misalnya dengan verb SORT atau utilitas sort, sebelum laporan dijalankan.
  • Subtotal grup terakhir terlupa. Percabangan pemisah hanya berjalan saat kunci berubah, sehingga grup terakhir tidak pernah ditutup. Cetak subtotalnya di luar perulangan, tepat sebelum total dicetak.
  • Kunci baru tidak disalin ke variabel penahan. Perbandingan terus mendeteksi perubahan pada setiap rekaman, sehingga header dan subtotal tercetak berulang. Salin kunci baru ke variabel penahan segera setelah pemisah ditangani.

Ringkasan#

  • Pemisah kontrol mendeteksi perubahan kunci grup pada berkas terurut dan menutup tiap grup dengan subtotal.
  • Variabel penahan kunci, akumulator subtotal, dan akumulator total adalah tiga variabel kerja utamanya.
  • Perulangan luar menjangkau seluruh berkas, sedangkan perulangan dalam menjangkau satu grup berkunci sama.
  • Subtotal grup terakhir dicetak setelah perulangan berakhir, karena tidak ada perubahan kunci yang memicunya.

Referensi#