WinForms 12 – Tlačenie – Praktické použitie

V dnešnom diely si trochu oddýchneme od ukážok rôznych ovládacích prvkov a ukážeme si ako vytvoriť dvojstranový dokument pre tlačenie. V príklade si ukážeme A4 faktúru.

UPOZORNENIE : Dnešný diel bude pojatý viac ako bežný tutoriál. Pokúsim sa v ňom vysvetliť reálne použitie funkcií tlačenia C#.

Príprava

Pred tým ako začnete pracovať na samotnom spracovaní údajov, je nutné pripraviť GUI pre používateľa. V našom prípade budeme tvoriť program, ktorý vytlačí jednoduchú faktúru na A4 papier a tak budete musieť pridať nasledujúce prvky :

  1. 1 krát TextBox – na zadanie mena produktu ktorý budete predávať.
  2. 4 krát NumericUpDown – na zadanie množstvaceny, výšky DPHčísla objednávky.
  3. 1 krát CheckBox – na výber či sa má použiť výpočet DPH.
  4. 1 krát ListView – na zobrazenie zoznamu kupujúceho.
  5. 5 krát Button – na ovládanie programu.
  6. (Nepovinné) 5 krát Label – na popis prvkov.
  7. 1 krát PrintDialog
  8. 1 krát PrintDocument
  9. 1 krát PrintPreviewDialog

Do riešenia odporúčam pridať aj obrázok a nastaviť aby bol vždy v zložke (alebo jednej z podzložiek) vášho programu.

Nastavenia prvkov

NumericUpDowns

  1. Prvý NumericUpDown pre množstvo tovaru odporúčam nastaviť na základnú a minimálnu hodnotu 1 a maximálnu hodnotu 1000.
  2. Druhý NumericUpDown určujúci cenu tovaru nastavte opäť odporúčam nastaviť na minimum 0.10 a maximum 10000 a zároveň nastaviť počet desatinných miest na 2.
  3. Tretí NumericUpDown označujúci DPH nastavte na 21 a maximánu hodnotu na 100. Opäť môžete nastaviť 2 desatinné miesta.
  4. Posledný a teda štvrtý NumericUpDown, ktorý je určený pre číslo objednávky odporúčam nastaviť tak, aby maximálna hodnota bola veľmi vysoká.

ListView je nutné prepnúť do Detials módu a pridať do neho tri stĺpce (Columns), prvý bude označovať množstvo, druhý produkt a tretí cenu bez DPH.

CheckBox pre DPH nastavte tak, že bude v základe zaškrtnutý a základné nastavenie máte dokončené.

U mňa po nastavení vyzerá Form nasledovne.

Window
Kliknite pre zväčšenie

Priradenie kódu eventom.

Ako prvý si ukážeme CheckBox a jeho CheckedChanged event.

DPHnumber.Enabled = checkBox1.Checked; //DPHnumber je NumericUpDown pre hodnotu DPH

Tento kód je pomerne jednoduchý a len zabezpečí, aby sa NumericUpDown deaktivoval ak vypnete DPH.

Ďalej sa pozrieme na tlačidlá a ich Click eventy. Ako prvé je tlačidlo STORNO.

NameOf.Text = ""; //NameOf - TextBox
CountOf.Value = 1; //CountOf - NumericUpDown označujúci množstvo tovaru
PrizePerItem.Value = 0; //PrizePerItem - NumericUpDown označujúci cenu tovaru

Tento jednoducho obnoví hodnoty textboxu a numericupdownov na pôvodné hodnoty.

Na rade je tlačidlo ACCEPT

ListViewItem item = new ListViewItem(CountOf.Value.ToString());
ListViewItem.ListViewSubItem name = new ListViewItem.ListViewSubItem();
name.Text = NameOf.Text;
ListViewItem.ListViewSubItem prize = new ListViewItem.ListViewSubItem();
prize.Text = (PrizePerItem.Value * CountOf.Value).ToString("F2") + " €";
item.SubItems.Add(name);
item.SubItems.Add(prize);
            
listView1.Items.Add(item);

storno.PerformClick();

V tomto prípade sme najprv vytvorili ListViewItem, ktorý má ako text množstvo tovaru (CountOf.Value.ToString()).

Ďalej vytvoríme dva ListViewSubItemi, ktoré budú mať ako text meno produktu a jeho cenu (vrátane znaku €) a oba priradíme ListViewItemu.

Na koniec toto celé pridáme do ListViewu a simulujeme stlačenie tlačidla Storno, čo vyčistí textbox a numericupdowny a pripraví nás na ďalší tovar.

Tlačídlo REMOVE, ktoré slúži na odstránenie tovaru zo zoznamu má jednoduchý kód :

if (listView1.SelectedItems.Count > 0)
    listView1.SelectedItems[0].Remove();

Najprv skontrolujeme, či je v zozname viac ako 1 item a ak áno, tak prvý vybraný odstránime.

Ako ďalšie máme v poradí tlačidlo PREVIEW, ktoré zobrazí ukážku pred tlačov

printPreviewDialog1.Document = printDocument1;
printPreviewDialog1.ShowDialog();

Toto priradí dokument dialógu a následne ho zobrazí. Nič viac, nič menej.

Tlačidlo PRINT je klasickým zobrazením dialógu a kontrolou používateľovej odpovede.

printDialog1.Document = printDocument1;
if (printDialog1.ShowDialog() == DialogResult.OK)
    printDocument1.Print();

Najprv opäť dialógu priradíme dokument a následne v podmienke zobrazíme dialóg a skontrolujeme jeho výsledok.

Ak používateľ klikol na tlačidlo OK, dokument vytlačíme.

Form by mal po tomto nastavení vyzerať takto :

Okno

Generovanie strán

Príprava statickej grafiky

Aby ste mohli tlačiť, je nutné priradiť Dokumentu, ktorý mate v designéri PrintPage event.

Pred tým ako začnete v tomto evente niečo robiť ešte si do classu vložte globálnu premennú typu INT s hodnotou 0 (ja som ju pomenoval polozka).

Najprv si vo metóde eventu vytvorte objekty Fontov, ktoré budete používať ako písmo. Ja som použil Times New Roman, veľkosti 15, pričom jeden font má Bold variantu.

Font F15 = new Font(new FontFamily("Times New Roman"), 15);
Font F15Bold = new Font(F15, FontStyle.Bold);

Ďalej budete potrebovať vykresliť hlavičku stránky. V nej vykreslujem logo predajcu, číslo faktúry a rovnú čiaru. V prípade reálnej faktúry by ste museli vykresliť aj údaje predajcu, ako je adresa, meno firmy atď.

e.Graphics.DrawImage(Image.FromFile("Images\\header_new2.png"), new Point(35, 35));
e.Graphics.DrawString("Faktúra za objednávku číslo #" + numericUpDown1.Value.ToString(), F15, Brushes.Black, new Point(35, 150));
e.Graphics.DrawLine(Pens.Black, new Point(35, 250), new Point(800, 250));

Na vykresľovanie sa používa člen Graphics argumentov eventu. Obrázok vykreslíte metódou DrawImage, ktorej parametre sú obrázok (Image, načítavame zo súboru) a pozícia (Point).
Na vykreslenie textu použijeme metódu DrawString, ktorej zadáme text, font, farbu (Brush) a pozíciu na ktorej sa má vykresliť.
Na vykreslenie čiary pre zmenu použijeme metódu DrawLine, ktorá namiesto brushu používa Pen a dva body, medzi ktorými sa čiara nakreslí.

Ďalej vykreslíme základnú mriežku, v ktorej sa budú zobrazovať údaje.

e.Graphics.DrawLine(Pens.Gray, new Point(390, 260), new Point(390, 1090));
e.Graphics.DrawLine(Pens.Gray, new Point(540, 260), new Point(540, 1090));
e.Graphics.DrawLine(Pens.Gray, new Point(680, 260), new Point(680, 1090));
//Tri vertikálne čiary oddeľujúce stĺpce

e.Graphics.DrawLine(Pens.Black, new Point(35, 290), new Point(800, 290));
e.Graphics.DrawLine(Pens.Black, new Point(35, 330), new Point(800, 330));
//Dve horizontálne čiary vymedzujúce miesto pre celkový súhrn objednávky.

e.Graphics.DrawLine(Pens.Black, new Point(35, 1100), new Point(800, 1100));
//Horizontálna čiara na spodku mriežky

Pred čímkoľvek ďalším túto mriežku ešte musíme zaplniť statickými údajmi – čiže popismi stĺpcov. Všetky sú písane klasickým fontom čiernej farby.

e.Graphics.DrawString("Položka", F15, Brushes.Black, new Point(35, 260));
e.Graphics.DrawString("Cena", F15, Brushes.Black, new Point(400, 260));
e.Graphics.DrawString("DPH bez DPH", F15, Brushes.Black, new Point(550, 260));
e.Graphics.DrawString("Cena z DPH", F15, Brushes.Black, new Point(690, 260));

Dynamicky meniaca sa grafika

Teraz sa ideme sústrediť na vykreslenie grafiky, ktorá bude dynamicky generovaná podľa toho, čo používateľ zadá.

Najprv si musíme vypočítať celkovú cenu všetkého tovaru BEZ DPH.

float spolu = 0.00f;

foreach (ListViewItem item in listView1.Items)
{
    spolu += float.Parse(item.SubItems[2].Text.Substring(0, item.SubItems[2].Text.Length - 2));
}

Na to slúži tento jednoduchý kód, ktorý si údaje berie z ListViewu (konkrétne z jeho 3. stĺpca – 2. subitem), ktorého Textu skrátime o 2 znaky, čiže odstránime symbol € a medzeru, a toto celé skonvertujeme na float a pripočítame k celku.

Keď poznáme sumu, ktorú chceme naúčtovať, môžeme zaplniť prvý vyhradený riadok údajmi.

e.Graphics.DrawString("SPOLU", F15Bold, Brushes.Black, new Point(35, 300));

e.Graphics.DrawString(spolu.ToString("F2") + " €", F15Bold, Brushes.Black, new Point(400, 300));

if (checkBox1.Checked)
{
    e.Graphics.DrawString("(" + DPHnumber.Value + "%) " + (spolu / 100 * (float)DPHnumber.Value).ToString("F2") + " €", F15Bold, Brushes.Black, new Point(550, 300));
    e.Graphics.DrawString((spolu / 100 * (100 + (float)DPHnumber.Value)).ToString("F2") + " €", F15Bold, Brushes.Black, new Point(700, 300));
}
else
{
    e.Graphics.DrawLine(Pens.Black, new Point(550, 310), new Point(670, 310));
    e.Graphics.DrawString(spolu.ToString("F2") + " €", F15Bold, Brushes.Black, new Point(700, 300));
}

Do prvého stĺpca vypíšeme tučným fontom slovo SPOLU a do druhého stĺpca sumu (z dvomi desatinnými miestami) a symbolom €.

Následne s program odvíja podľa toho, či máme alebo nemáme počítať DPH. Ak máme, tak sa vypíše percentuálne DPH v zátvorke a suma koľko € to je, a následne do ďalšieho stĺpca vypíšeme celkovú sumu aj z DPH.

Ak však nechceme počítať DPH, tak sa nám prvý stĺpec vyplní rovnou čiarou a do druhého sa len opäť vypíše cena bez DPH.

Ďalší postup je o niečo náročnejší, tak si ho rozdelíme na dva kroky.

Ako prvé musíme zabezpečiť, aby sa v prípade, že v zozname máme viac položiek, ako sa zmestí na jednu stranu tlačilo aj na stranu ďalšiu.

int i = 330;
while ((polozka < listView1.Items.Count) && (i < 1090))
{
    //Vykreslenie
}

if (polozka < listView1.Items.Count) e.HasMorePages = true;
else { e.HasMorePages = false; polozka = 0; }

Tento systém počíta z globálnou premennou polozka, ktorú sme definovali na začiatku a vytvára nezávislí cyklus.

Najprv sme si deklarovali premennú i, ktorá označuje vzdialenosť od vrchu stránky, kde začneme vykreslovať (v tomto prípade 330).

Následne vytvoríme cyklus, ktorý bežať, dokým je i menšie ako 1090 a teda nevykereslujeme mimo stranu a zároveň, dokým sme nedosiahly koniec zoznamu.

Po opustení cyklu overíme, či ešte zostávajú nejaké položky na vykreslenie. Ak áno, nastavíme že sa má tlačiť aj ďalšia strana. Ak nie, nastavíme naopak, že sa tlačiť nemá a vynulujeme premennú označujúcu aktuálnu položku.

Toto spôsobí, že ak sme dosiahli koniec strany, ale stále sme nevykreslili celý zoznam (polozka < listView1.Items.Count), tak sa vykreslí ďalšia stránka. Pri tom je celý PrintPage zavolaný odznova a preto potrebujeme globálnu premennú, ktorá označuje aktuálnu položku.

Vykreslovanie položiek prebieha vnútri cyklu a jeho kód je

int count = int.Parse(listView1.Items[polozka].SubItems[0].Text);
string name = listView1.Items[polozka].SubItems[1].Text;
float prize = float.Parse(listView1.Items[polozka].SubItems[2].Text.Substring(0, listView1.Items[polozka].SubItems[2].Text.Length - 2));
e.Graphics.DrawString(count + "x " + name, F15, Brushes.Black, new Point(35, i + 10));
e.Graphics.DrawString(prize.ToString("F2") + " €", F15, Brushes.Black, new Point(400, i + 10));
if (checkBox1.Checked)
{
    e.Graphics.DrawString("(" + DPHnumber.Value + "%) " + (prize / 100 * (float)DPHnumber.Value).ToString("F2") + " €", F15, Brushes.Black, new Point(550, i + 10));
    e.Graphics.DrawString((prize / 100 * (100 + (float)DPHnumber.Value)).ToString("F2") + " €", F15, Brushes.Black, new Point(700, i + 10));
}
else
{
    e.Graphics.DrawLine(Pens.Black, new Point(550, i + 20), new Point(670, i + 20));
    e.Graphics.DrawString(prize.ToString("F2") + " €", F15Bold, Brushes.Black, new Point(700, i + 10));
}

i += 40;
polozka++;

e.Graphics.DrawLine(Pens.Gray, new Point(35, i), new Point(800, i));

Prvé tri riadky by vám mali byť jasné. Z aktuálnej položky (opäť globálna premenná) získame početmenocenu bez DPH.

V Ďalších dvoch riadkoch vykreslíme práve tieto veci. Ďalej opäť nasleduje podmienka použitia DPH pričom sa DPH a Cena s DPH vykreslí rovnako ako pri príklade celej sumy.

Po vykreslení textu položiek ešte musíme zvýšiť hodnotu o 40 (výška riadku) a posunúť sa na ďalší riadok. Prišlo mi dobré vykresliť ešte jednu horizontálnu šedú čiaru práve na tejto pozícií.
Na konci strany ešte môžete ako ja zobraziť malý informačný text.

e.Graphics.DrawString("Tutoriál pre web https://www.akoprogramovat.sk/", F15, Brushes.Black, new Point(35, 1120));

Kompletný kód eventu PrintPage teda vyzerá takto :

Font F15 = new Font(new FontFamily("Times New Roman"), 15);
Font F15Bold = new Font(F15, FontStyle.Bold);

e.Graphics.DrawImage(Image.FromFile("Images\\header_new2.png"), new Point(35, 35));
e.Graphics.DrawString("Faktúra za objednávku číslo #" + numericUpDown1.Value.ToString(), F15, Brushes.Black, new Point(35, 150));
e.Graphics.DrawLine(Pens.Black, new Point(35, 250), new Point(800, 250));

e.Graphics.DrawLine(Pens.Gray, new Point(390, 260), new Point(390, 1090));
e.Graphics.DrawLine(Pens.Gray, new Point(540, 260), new Point(540, 1090));
e.Graphics.DrawLine(Pens.Gray, new Point(680, 260), new Point(680, 1090));

e.Graphics.DrawLine(Pens.Black, new Point(35, 290), new Point(800, 290));
e.Graphics.DrawLine(Pens.Black, new Point(35, 330), new Point(800, 330));

e.Graphics.DrawLine(Pens.Black, new Point(35, 1100), new Point(800, 1100));

e.Graphics.DrawString("Položka", F15, Brushes.Black, new Point(35, 260));
e.Graphics.DrawString("Cena", F15, Brushes.Black, new Point(400, 260));
e.Graphics.DrawString("DPH bez DPH", F15, Brushes.Black, new Point(550, 260));
e.Graphics.DrawString("Cena z DPH", F15, Brushes.Black, new Point(690, 260));


float spolu = 0.00f;

foreach (ListViewItem item in listView1.Items)
{
    spolu += float.Parse(item.SubItems[2].Text.Substring(0, item.SubItems[2].Text.Length - 2));
}


e.Graphics.DrawString("SPOLU", F15Bold, Brushes.Black, new Point(35, 300));

e.Graphics.DrawString(spolu.ToString("F2") + " €", F15Bold, Brushes.Black, new Point(400, 300));

if (checkBox1.Checked)
{
    e.Graphics.DrawString("(" + DPHnumber.Value + "%) " + (spolu / 100 * (float)DPHnumber.Value).ToString("F2") + " €", F15Bold, Brushes.Black, new Point(550, 300));
    e.Graphics.DrawString((spolu / 100 * (100 + (float)DPHnumber.Value)).ToString("F2") + " €", F15Bold, Brushes.Black, new Point(700, 300));
}
else
{
    e.Graphics.DrawLine(Pens.Black, new Point(550, 310), new Point(670, 310));
    e.Graphics.DrawString(spolu.ToString("F2") + " €", F15Bold, Brushes.Black, new Point(700, 300));
}


int i = 330;
while ((polozka < listView1.Items.Count) && (i < 1090))
{
    int count = int.Parse(listView1.Items[polozka].SubItems[0].Text);
    string name = listView1.Items[polozka].SubItems[1].Text;
    float prize = float.Parse(listView1.Items[polozka].SubItems[2].Text.Substring(0, listView1.Items[polozka].SubItems[2].Text.Length - 2));

    e.Graphics.DrawString(count + "x " + name, F15, Brushes.Black, new Point(35, i + 10));
    e.Graphics.DrawString(prize.ToString("F2") + " €", F15, Brushes.Black, new Point(400, i + 10));
    if (checkBox1.Checked)
    {
        e.Graphics.DrawString("(" + DPHnumber.Value + "%) " + (prize / 100 * (float)DPHnumber.Value).ToString("F2") + " €", F15, Brushes.Black, new Point(550, i + 10));
        e.Graphics.DrawString((prize / 100 * (100 + (float)DPHnumber.Value)).ToString("F2") + " €", F15, Brushes.Black, new Point(700, i + 10));
    }
    else
    {
        e.Graphics.DrawLine(Pens.Black, new Point(550, i + 20), new Point(670, i + 20));
        e.Graphics.DrawString(prize.ToString("F2") + " €", F15Bold, Brushes.Black, new Point(700, i + 10));
    }

    i += 40;
    polozka++;

    e.Graphics.DrawLine(Pens.Gray, new Point(35, i), new Point(800, i));
}


if (polozka < listView1.Items.Count) e.HasMorePages = true;
else { e.HasMorePages = false; polozka = 0; }

e.Graphics.DrawString("Tutoriál pre web https://www.akoprogramovat.sk/", F15, Brushes.Black, new Point(35, 1120));

Na záver tu tento krát pre vás mám nielen projekt na stiahnutie, ale aj ukážku faktúry ktorú môžete takto vytlačiť vo formáte PDF.

download
Faktúra
download
Program

Dúfam že sa vám tento článok páčil a nabudúce sa pozrieme na pravdepodobne krátky članok o Reportoch a  WPF elementoch, čo bude predposledný článok venujúci sa záložkám ToolBoxu.

Pridajte Komentár

Vaša e-mailová adresa nebude zverejnená.

Scroll to Top