Mencetak Struk di Windows Forms Format & Fungsi Penting

Mencetak Struk di Windows Forms Format & Fungsi Penting

cs.bimobo
0

Mencetak Struk di Windows Forms

Format & Fungsi Penting

Setelah UI kasir berhasil dirancang dan fungsionalitas tombol berjalan lancar, tahapan selanjutnya adalah memberikan output transaksi yang bisa dicetak — yaitu struk pembelian. Proses ini tidak sekadar formalitas, tapi bagian penting dari sistem penjualan yang membantu pembeli dan pelaku usaha merekam transaksi secara jelas.


Pada pembahasan kali ini, kita akan menggunakan komponen PrintDocument dan PrintPreviewDialog dari Windows Forms. Melalui event PrintPage, kita dapat menyusun layout cetak yang berisi daftar produk, jumlah, harga, total, dan bahkan salam penutup bagi pelanggan.


Artikel ini cocok bagi developer yang ingin melengkapi aplikasi kasir-nya agar tampil profesional. Format yang digunakan bisa disesuaikan: baik layout sederhana berbasis teks, maupun versi yang lebih kompleks dengan logo dan elemen branding.


Langkah 1: Menambahkan Komponen Cetak

Logika Tombol Tambah: Validasi, Hitung, dan Simpan ke ListView

Untuk memastikan input data produk akurat dan siap digunakan dalam proses transaksi dan pencetakan struk, tombol “Tambah Produk” dilengkapi dengan validasi dan struktur penambahan ke komponen ListView. Input harga dibersihkan dari tanda titik/koma agar tidak menimbulkan error saat parsing.


Berikut implementasi lengkap yang dapat langsung kamu salin ke dalam event btnTambah_Click pada form kasir digital berbasis Windows Forms:


private void btnTambah_Click(object sender, EventArgs e)
{
    string nama = txtNamaProduk.Text.Trim();
    string hargaStr = txtHarga.Text.Trim().Replace(".", "").Replace(",", ""); // Hilangkan separator jika user pakai titik/koma
    int jumlah = (int)numJumlah.Value;

    // Validasi input
    if (string.IsNullOrEmpty(nama))
    {
        MessageBox.Show("Nama produk harus diisi.", "Peringatan", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        txtNamaProduk.Focus();
        return;
    }
    if (string.IsNullOrEmpty(hargaStr))
    {
        MessageBox.Show("Harga harus diisi.", "Peringatan", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        txtHarga.Focus();
        return;
    }
    if (!double.TryParse(hargaStr, out double harga) || harga <= 0)
    {
        MessageBox.Show("Harga tidak valid. Pastikan berupa angka positif.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        txtHarga.Focus();
        return;
    }
    if (jumlah <= 0)
    {
        MessageBox.Show("Jumlah harus lebih dari 0.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        numJumlah.Focus();
        return;
    }

    // Hitung subtotal
    double subtotal = harga * jumlah;

    // Tambahkan ke ListView
    var item = new ListViewItem(nama)
    {
        SubItems =
        {
            jumlah.ToString(),
            harga.ToString("N0"),
            subtotal.ToString("N0")
        }
    };

    lstStruk.Items.Add(item);

    // Update total
    total += subtotal;
    lblTotal.Text = $"Total: Rp {total:N0}";

    // Reset input
    txtNamaProduk.Clear();
    txtHarga.Clear();
    numJumlah.Value = 1;
    txtNamaProduk.Focus();
}

Kode ini sudah mendukung format harga berantakan yang diketik pengguna, validasi lengkap untuk mencegah input kosong atau negatif, serta integrasi otomatis ke lstStruk untuk kebutuhan pencetakan dan penyimpanan data. Tampilan angka juga diformat ribuan agar struk terlihat profesional.


Untuk memulai proses pencetakan struk, tambahkan dua komponen utama ke dalam form Windows Forms: PrintDocument dan PrintPreviewDialog. Keduanya tersedia di Toolbox Visual Studio dan dapat langsung disisipkan ke form.


Setelah komponen ditambahkan, pastikan properti Document dari PrintPreviewDialog mengarah ke PrintDocument yang akan digunakan. Ini memungkinkan preview menampilkan output sesuai logika yang kita susun.


Mengatur Ukuran Kertas Thermal untuk Cetak Struk

Agar hasil cetakan struk tampil sempurna sesuai lebar kertas thermal (misalnya 72mm atau 80mm), kita dapat mengatur ukuran kertas secara manual melalui event BeginPrint milik PrintDocument. Pengaturan ini memastikan isi struk tidak terpotong dan tetap proporsional di semua printer thermal.


Ukuran satuan yang digunakan oleh komponen PaperSize adalah 1/100 inch. Jadi, untuk lebar 72mm (≈2.83 inch), kita gunakan nilai 283. Tinggi kertas bisa disesuaikan dengan jumlah data transaksi—umumnya 500–1000 satuan untuk hasil optimal.


private void printDocument1_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
    // Lebar 72mm = 2.83 inch × 100 = 283
    // Tinggi 200mm = 7.87 inch × 100 = 787 (ubah sesuai kebutuhan, bisa 500, 700, 1000, dst)
    PaperSize customSize = new PaperSize("Nota Thermal", 283, 700); // 72mm × 7 inch (contoh)

    // Hilangkan margin
    printDocument1.DefaultPageSettings.PaperSize = customSize;
    printDocument1.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);
}

Pastikan kamu menghubungkan event ini melalui inisialisasi di Form_Load atau constructor, seperti berikut:

printDocument1.BeginPrint += new PrintEventHandler(printDocument1_BeginPrint);

Dengan konfigurasi ini, ukuran kertas cetak akan menyesuaikan kebutuhan sistem kasir digital yang kamu bangun, menjadikannya kompatibel dengan printer thermal dan tidak perlu bergantung pada ukuran default sistem.


Pastikan kamu sudah menghubungkan event ini pada form load atau saat inisialisasi:

printDocument1.BeginPrint += new PrintEventHandler(printDocument1_BeginPrint);

Dengan pengaturan ini, hasil cetakan akan menyesuaikan lebar kertas nota dan tidak terpotong, cocok digunakan untuk printer thermal mini maupun printer biasa.


Langkah 2: Menyusun Format Struk pada Event PrintPage

Mencetak Struk dengan Layout Rapi dan Dinamis

Untuk menghasilkan struk yang tampil profesional dan mudah dibaca, layout cetak harus disusun secara proporsional—dengan penataan label produk di sebelah kiri dan nominal Rupiah rata kanan. Pendekatan ini menggunakan ukuran kertas thermal standar 72mm dan font monospace agar alignment tetap konsisten.


Berikut implementasi lengkap dari event PrintPage, yang mendukung layout dinamis, pemangkasan label panjang, serta cetak teks rata tengah untuk header dan footer:


private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
    // Setting ukuran dan font
    int paperWidth = 283; // 72mm thermal paper
    int xLeft = 10;
    int xRight = paperWidth - 10; // ujung kanan, minus margin kecil
    int y = 20;
    Font fontRegular = new Font("Consolas", 10, FontStyle.Regular);
    Font fontBold = new Font("Consolas", 10, FontStyle.Bold);

    // Fungsi cetak teks rata tengah
    void DrawCentered(string text, Font font, int yPos)
    {
        SizeF size = e.Graphics.MeasureString(text, font);
        float x = (paperWidth - size.Width) / 2;
        e.Graphics.DrawString(text, font, Brushes.Black, x, yPos);
    }

    // --- Header toko rata tengah ---
    DrawCentered("TOKO SEDERHANA", fontBold, y); y += 20;
    DrawCentered("WONODADI", fontBold, y); y += 30;

    // Tanggal dan judul
    e.Graphics.DrawString($"Tanggal: {DateTime.Now:dd/MM/yyyy HH:mm}", fontRegular, Brushes.Black, xLeft, y); y += 20;
    e.Graphics.DrawString("Produk:", fontRegular, Brushes.Black, xLeft, y); y += 20;

    // Hitung label terpanjang agar tidak nabrak harga
    int spaceBetween = 10;
    decimal totalHarga = 0;
    int maxLabelWidth = 0;

    foreach (ListViewItem item in lstStruk.Items)
    {
        string nama = item.SubItems[0].Text;
        string qtyStr = item.SubItems[1].Text;
        string labelProduk = $"- {nama} x{qtyStr}";
        SizeF sizeLabel = e.Graphics.MeasureString(labelProduk, fontRegular);
        if (sizeLabel.Width > maxLabelWidth)
            maxLabelWidth = (int)sizeLabel.Width;
    }

    int maxNamaRight = xRight - 80;
    if (xLeft + maxLabelWidth > maxNamaRight)
        maxLabelWidth = maxNamaRight - xLeft;

    // Cetak daftar produk
    foreach (ListViewItem item in lstStruk.Items)
    {
        string nama = item.SubItems[0].Text;
        string qtyStr = item.SubItems[1].Text;
        string hargaStr = item.SubItems[2].Text.Replace(",", "").Replace(".", "");

        int qty = int.Parse(qtyStr);
        decimal harga = decimal.Parse(hargaStr);
        decimal totalPerItem = qty * harga;
        totalHarga += totalPerItem;

        string labelProduk = $"- {nama} x{qtyStr}";
        string nilaiRp = $"Rp {totalPerItem:N0}";

        SizeF sizeRp = e.Graphics.MeasureString(nilaiRp, fontRegular);
        float posRp = xRight - sizeRp.Width;

        // Potong nama jika kepanjangan
        SizeF ukuranLabel = e.Graphics.MeasureString(labelProduk, fontRegular);
        string namaTampil = labelProduk;
        while (ukuranLabel.Width > (posRp - xLeft - spaceBetween) && namaTampil.Length > 3)
        {
            namaTampil = namaTampil.Substring(0, namaTampil.Length - 4) + "...";
            ukuranLabel = e.Graphics.MeasureString(namaTampil, fontRegular);
        }

        // Cetak label & harga
        e.Graphics.DrawString(namaTampil, fontRegular, Brushes.Black, xLeft, y);
        e.Graphics.DrawString(nilaiRp, fontRegular, Brushes.Black, posRp, y);
        y += 20;
    }

    // Garis pemisah
    y += 10;
    e.Graphics.DrawLine(Pens.Black, xLeft, y, xRight, y); y += 10;

    // Total akhir
    string totalStr = $"Total: Rp {totalHarga:N0}";
    SizeF sizeTotal = e.Graphics.MeasureString(totalStr, fontBold);
    float posTotal = xRight - sizeTotal.Width;
    e.Graphics.DrawString(totalStr, fontBold, Brushes.Black, posTotal, y); y += 40;

    // Footer: ucapan terima kasih
    DrawCentered("Terima kasih", fontRegular, y); y += 20;
    DrawCentered("Sudah berbelanja", fontRegular, y);
}

Struktur ini fleksibel terhadap panjang nama produk, menjaga jarak antar kolom tetap proporsional, dan memastikan keseluruhan isi struk tampil rapi serta dapat dipahami pembeli. Format ini cocok digunakan baik untuk printer thermal kecil maupun printer biasa.


Langkah 3: Menjalankan Cetak dan Preview

Tambahkan tombol “Cetak Struk” pada form, lalu hubungkan event click-nya ke kode berikut. Kamu bisa menampilkan preview terlebih dahulu, atau langsung mencetak tanpa tampilan pendahuluan.


private void btnCetakStruk_Click(object sender, EventArgs e)
{
    printPreviewDialog1.ShowDialog(); // Tampilkan preview cetak
    // printDocument1.Print();        // Langsung cetak ke printer
}

🧾 Penting: Pastikan printer terhubung dan driver telah terinstal dengan baik. Jika hanya ingin melakukan simulasi, kamu dapat menggunakan printer virtual atau PDF output sebagai alternatif.

Setelah langkah-langkah ini diterapkan, sistem kasir kamu sudah mampu menghasilkan cetakan struk yang informatif dan rapi. Format dapat disesuaikan sesuai kebutuhan bisnis, mulai dari penempatan logo, penambahan informasi promo, hingga pesan penutup untuk pelanggan.


Form Kasir

Gambar 1: Tampilan aplikasi kasir

Form Kasir

Gambar 2: Hasil Cetak Nota


Terima kasih sudah mengikuti tutorial ini hingga akhir 🙌 Semoga artikel ini membantu kamu menciptakan sistem kasir sederhana yang tidak hanya fungsional tetapi juga tampil profesional. Proses mencetak struk yang rapi, validasi input yang kuat, dan layout UI yang konsisten adalah fondasi penting dari aplikasi transaksi yang dapat diandalkan.


Jangan ragu untuk mengembangkan fitur lebih lanjut seperti penyimpanan database, pencetakan diskon, atau integrasi struk digital berbasis QR Code. Semuanya bisa dibangun bertahap dari pondasi yang sudah kamu rapikan.

Posting Komentar

0 Komentar

Posting Komentar (0)
3/related/default