ListView drucken



  • Hier ist auch schon mein nächstes Problem 😞
    Ich möchte gerne meine ListView drucken können, wenn man "Drucken" im Mainmenu anklickt. Ich habe auch schon überall im I-Net gesucht, aber nichts gefunden, was mir wirklich geholfen hat. Das einzige was ich gefunden habe ist das hier:

    PrintDialog1->Execute();
    Form1->Print();
    

    Allerdings wird da das ganze Fenster gedruckt.

    PrintDialog1->Execute();
    ListView2->Print();
    

    funktioniert auch nicht, weil Print kein Teil von ListView2 ist...

    http://www.c-plusplus.net/forum/viewtopic-var-t-is-256984-and-highlight-is-listview+drucken.html
    Der Code funktioniert bei mir nicht. Was mache ich falsch?
    Ich hab ihn in der .cpp-datei eingefügt, aber es kommen Fehler. Fehlt was?
    Fehler: "vector" is not a member of "std",
    expression syntax,
    undefined symbol "vCols"

    soll ich nächstesmal gleich in dem älteren thread fragen oder ist es okay, wenn ich hier einen neuen eröffne?

    Mein anderes Problem ist, dass man, nachdem man die Einstellungen für den Druck bestätigt hat, den Ausgabenamen eingeben soll. (das konnte ich machen, als ich das ganze fenster drucken wollte) Ich denke mal dort soll ich reinschreiben wo die Datei zum Druck abgespeichert werden soll und wie sie heißt. Hab dann c:\programme\test.jpg+c:\programme\test.bmp und c:\programme\test.txt eingegeben. es öffnete sich ein fenster: "Der Druck ist im Gang."
    In dem Druckäufträge-Fenster war nur ein leerer Auftrag (keine beschriftung) und es wurde nichts gedruckt.
    Ich benutze den C++ Borland Builder 1...



  • Gibt es denn wenigstens die Möglichkeit eine ListView als Excel-Datei oder so in einer Tabelle abzuspeichern, damit ich die Datei dann mit Excel drucken kann?



  • schau dir mal TPrinter an

    und Excell kann CSV Dateien verarbeiten. Hier mal danach suchen

    grüssle 🙂



  • assassipretzel schrieb:

    http://www.c-plusplus.net/forum/viewtopic-var-t-is-256984-and-highlight-is-listview+drucken.html
    Der Code funktioniert bei mir nicht.
    [...]
    soll ich nächstesmal gleich in dem älteren thread fragen oder ist es okay, wenn ich hier einen neuen eröffne?

    Konkrete Nachfragen zu einem Beispielcode gehören auf jeden Fall in den Originalthread.



  • assassipretzel schrieb:

    http://www.c-plusplus.net/forum/viewtopic-var-t-is-256984-and-highlight-is-listview+drucken.html
    Der Code funktioniert bei mir nicht. Was mache ich falsch?
    Ich hab ihn in der .cpp-datei eingefügt, aber es kommen Fehler. Fehlt was?
    Fehler: "vector" is not a member of "std",
    expression syntax,
    undefined symbol "vCols"

    Um vector zu verwenden muss man den Header einbinden

    #include <vector>
    


  • Danke, das hat mir schonmal sehr geholfen!! 🙂
    Nun würde ich gerne wissen, wie ich das andere Problem löse.
    Es öffnet sich vor dem Druck immer ein Fenster, in dem ich die Ausgabedatei eingeben soll. Was soll ich da reinschreiben? Egal was ich reinschreibe, der drucker druckt nichts. Im Druckauftrag ist zwar einer angegeben, allerdings leer und beschädigt. Manchmal zeigt er 1,66 mb an und manchmal 4,55 mb;kommt drauf an in welchem format ich die datei abspeicher.



  • Also,

    wenn du ein TListView drucken willst, dann musst du das TCanvas von TPrinter verwenden und die Einträge des TListView einzeln auf den Canvas zeichnen.

    Ich habe jetzt kein Link parat, aber ungefähr so...

    Printer()->BeginDoc();  //----Drucker Dokument beginnen
    
    ///-------Einträge auf Canvas zeichnen
    Printer()->Canvas->TextOut(10,20,ListView->Items->Item[0]->Caption); 
    Printer()->Canvas->TextOut(10,50,ListView->Items->Item[1]->Caption);
    Printer()->Canvas->TextOut(10,80,ListView->Items->Item[2]->Caption);
    
    Printer()->EndDoc(); //------Dokument beenden und drucken
    

    Naja, so in der Art, kann sein, dass einige Fehler drin sind, aber suche nach TPrinter in der BCB Hilfe oder im Forum, da gibt es viele Beispiele...

    Ich hoffe das war eine kleine Hilfe für dich.

    Gruß
    Hawk



  • super, großartig 🙂
    zwar wird jetzt das gesamte programm (formular1) gedruckt, obwohl ich angegeben hatte, dass die listview2 in Formular2 gedruckt werden soll, aber meinem ziel bin ich einen großen schritt näher gekommen!
    vielen dank an alle die mir geholfen haben !!



  • // kopf
    #include <vector>
    #include <Printers.hpp>
    
    ...
    
    void PrintListview(TListView *lv, TPrintDialog *PrintDialog, String Titel);
    
    //---------------------------------------------------------------------------
    
    // button klick
    PrintListview(ListView1, PrintDialog1, "Titel"); 
    
    //---------------------------------------------------------------------------
    
    // funktion
    void PrintListview(TListView *lv, TPrintDialog *PrintDialog, String sTitel) {
    
        if (PrintDialog->Execute() ) {
    
            String sCurStr;
            TRect rCurRect;
    
            Printer()->Title = sTitel;
            Printer()->BeginDoc();
            float iPageHeight = Printer()->PageHeight;
            float iPageWidth = Printer()->PageWidth;
    
            float v = (iPageHeight + (2 * GetDeviceCaps(Printer()->Handle, PHYSICALOFFSETY))) / (29.7 * 0.95);
            //0.95 is a strange correction factor on the clients printer
            float h = (iPageWidth + (2 * GetDeviceCaps(Printer()->Handle, PHYSICALOFFSETX))) / 21;
    
            // calculate total width
            float iTotColsWidth = 0;
            for (int i = 0; i < lv->Columns->Count; i++) {
                iTotColsWidth = iTotColsWidth + lv->Column[i]->Width;
            }
    
            // calculate space between lMargin and rMargin
            float iInnerWidth = iPageWidth - 2*(1.5 * h); // space between margins ?
    
            std::vector<float> vCols;
    
            vCols.push_back(1.5 * h); //left margin
    
            //calculate start of each column
            for (int i = 0; i < lv->Columns->Count; i++) {
    
                vCols.push_back( vCols.back() + ((float)lv->Column[i]->Width / iTotColsWidth * iInnerWidth) );
            }
    
            vCols.push_back(iPageWidth - (1.5 * h)); //rigth margin
    
            int iTopMargin = 2.5 * v;
    
            TCanvas *zf = Printer()->Canvas;
    
            zf->Font->Size = 10;
            zf->Font->Style = TFontStyles();
            zf->Font->Name = "Arial";
            zf->Font->Color = clBlack;
            int iTextHeight = zf->TextHeight("WWW");
            int iLinesOnPage = (iPageHeight - (5 * v)) / iTextHeight;
            int iNumPages = 1;
    
            // get number of pages to print
            while ((iNumPages * iLinesOnPage) < lv->Items->Count) {
                iNumPages++;
            }
    
            // start
            int iCurLine = 0;
    
            for (int iCurItem = 0; iCurItem < lv->Items->Count; iCurItem++) {
    
                if (iCurLine > iLinesOnPage || iCurLine == 0) {
    
                    if (iCurLine > iLinesOnPage) Printer()->NewPage();
    
                    iCurLine = 1;
    
                    if (Printer()->PageNumber == iNumPages) {
    
                        zf->MoveTo(vCols[1], iTopMargin);
                        for (int i = 1; i < lv->Columns->Count; i++) {
    
                            zf->LineTo(vCols[i], iTopMargin + (iTextHeight * (lv->Items->Count - iCurItem + 2)));
                            zf->MoveTo(vCols[i + 1], iTopMargin);
                        }
                    }
                    else {
    
                        // draw vertical lines between data
                        for (int i = 1; i < lv->Columns->Count; i++ ) {
    
                            zf->MoveTo(vCols[i], iTopMargin);
                            zf->LineTo(vCols[i], iTopMargin + (iTextHeight * (iLinesOnPage + 1)));
                        }
                    }
    
                    zf->Font->Style = TFontStyles() << fsBold;
    
                    // print column headers
                    for (int i = 0; i < lv->Columns->Count; i++) {
    
                        zf->TextRect(Rect(vCols[i] + (0.1 * h), iTopMargin - (0.1 * v), vCols[i + 1] - (0.1 * h)
                            , iTopMargin + iTextHeight - (0.1 * v)), ((vCols[i + 1] - vCols[i]) / 2) +
                            vCols[i] - (zf->TextWidth(lv->Columns->Items[i]->Caption) / 2),
                            iTopMargin - (0.1 * v), lv->Columns->Items[i]->Caption);
                    }
    
                    // draw horizontal line beneath column headers
                    zf->MoveTo(vCols[0] - (0.1 * h), iTopMargin + iTextHeight - (0.05 * v));
                    zf->LineTo(vCols[lv->Columns->Count] + (0.1 * h), iTopMargin + iTextHeight - (0.05 * v));
    
                    // print date and page number
                    zf->Font->Size = 8;
                    zf->Font->Style = TFontStyles();
                    int iTmpPos = (zf->TextWidth(DateToStr(Now()) + " - " +
                        IntToStr(Printer()->PageNumber) + " / " + IntToStr(iNumPages))) / 2;
    
                    iTmpPos = iPageWidth - 1.5 * h - (iTmpPos * 2);
    
                    zf->Font->Size = 8;
                    zf->Font->Style = TFontStyles();
                    zf->TextOut(iTmpPos, (0.5 * v), DateToStr(Now()) + " - " + IntToStr(Printer()->PageNumber) + " / " + IntToStr(iNumPages));
    
                    // print report title
                    zf->Font->Size = 16;
                    if (iTmpPos < ((iPageWidth + zf->TextWidth(sTitel)) / 2 + (0.75 * h)) )
                        zf->TextOut((iPageWidth - zf->TextWidth(sTitel)) / 2, (1 * v), sTitel);
                    else
                        zf->TextOut(3 * h, 1 * v, sTitel);
    
                    zf->Font->Size = 10;
                    zf->Font->Style = TFontStyles();
                }
    
                rCurRect.Top = iTopMargin + (iCurLine * iTextHeight);
                rCurRect.Bottom = iTopMargin + ((iCurLine + 1) * iTextHeight);
    
                // print contents of Listview
                for (int iCurCol = -1; iCurCol < lv->Columns->Count - 1; iCurCol++) {
    
                    rCurRect.Left = vCols[iCurCol + 1] + (0.1 * h);
                    rCurRect.Right = vCols[iCurCol + 2] - (0.1 * h);
                    try {
                        if (iCurCol == -1)
                            sCurStr = lv->Items->Item[iCurItem]->Caption;
                        else
                            sCurStr = lv->Items->Item[iCurItem]->SubItems->Strings[iCurCol];
                    } catch (...) {
                        sCurStr = "";
                    }
    
                    // write string in TextRect
                    zf->TextRect(rCurRect, rCurRect.Left, rCurRect.Top, sCurStr);
                }
                iCurLine++;
            }
    
            Printer()->EndDoc();
        }
    }
    


  • Setzen 6



  • VergissEs schrieb:

    Setzen 6

    das bedeutet wohl ich bin zu blöd um das zu kapieren...



  • Naja mit aneinanderreihen von gefunden Code wird das nichts,
    man solle schon wissen was man tut.

    Also Grundlagen lernen.

    Und Print() druckt eben die Form aus, wenn du die Form nicht ausdrucken willst
    dann darfst du es auch nicht anwenden 🙂



  • VergissEs schrieb:

    Naja mit aneinanderreihen von gefunden Code wird das nichts,
    man solle schon wissen was man tut.

    Also Grundlagen lernen.

    Und Print() druckt eben die Form aus, wenn du die Form nicht ausdrucken willst
    dann darfst du es auch nicht anwenden 🙂



  • Gut dann hier die Lösung,

    void __fastcall TForm1::PrintBtnClick(TObject *Sender) 
    { 
        //ListView1 = das zu druckende ListView
        //PrintDialog1 = die PrintDialog 
        PrintListview(ListView1, PrintDialog1, "Druckauftrag Titel");
    } 
    //--------------------------------------------------------------------------- 
    void PrintListview(TListView *lv, TPrintDialog *PrintDialog, String sTitel) { 
    ...
    

    und schmeiß die ganzen

    ...
    Printer()->Canvas->TextOut(10,80,Form2->ListView2->Items->Item[4]->Caption);
    Printer()->Canvas->TextOut(10,80,Form2->ListView2->Items->Item[5]->Caption);
    ...
    

    aus der Funktion PrintListview wieder raus!



  • Also wie schon oben bereits gesagt, man sollte wissen, was der ganze Code bedeutet, aber versuch doch mal es ohne diesen Vector-Quatsch das zu machen.

    Denk doch mal ein bissl logisch: Also du versuchst alle Einträge einer Listview auszudrucken, aber nicht die ListView selbst.

    D.H. dein Programm muss erstmal den Druck vorbereiten...

    Printer()->Title="Mein ListView Ausdruck";
    Printer()->BeginDoc()
    

    Dann musst das Programm jeden Eintrag deines Listviews durchgehen - eleganterweise mit einer for-Schleife. In dieser Schleife liest du jeden Eintrag aus und zeichnest den Wert auf das Canvas des Printer().

    int Zeile=20; ///-----Startposition von oberen Rand
    for (int i=0;i<ListView1->Items->Count;i++)
    {
    Printer()->Canvas->TextOut(20,Zeile,ListView1->Items->Item[i]->Caption);
    Zeile+=Printer->Canvas->TextHeight(ListView1->Items->Item[i]->Caption)+10; ///Zeilenabstand berechnen
    //---Neue Seite nehmen, wenn z.B. Seite nach 30 Einträgen voll sein sollte
    if (i==30)
    {
    Printer()->NewPage();
    Zeile=10;
    }
    }
    

    Zum Schluss natürlich den Druck freigeben...

    Printer()->EndDoc();
    

    Fertig!

    Also, das war schon alles. Natürlich muss vieles modifiziert werden, wenn du auch die SubItems eines Eintrages haben willst, aber mehr brauchst du eigentlich nicht....

    PrintDialog->Execute() brauchst du nur wenn du vor dem Drucken unbedingt einen Drucker auswählen willst, aber ist nicht notwendig, denn ohne das wird der Standarddrucker genommen...

    Um alles natürlich besser zu machen, müsstest du Berechnungen über die max. Anzahl der Zeilen pro Seite machen, oder den Seitenrand noch berücksichtigen, aber dazu ein anderes mal.



  • VergissEs schrieb:

    Gut dann hier die Lösung,

    void __fastcall TForm1::PrintBtnClick(TObject *Sender) 
    { 
        //ListView1 = das zu druckende ListView
        //PrintDialog1 = die PrintDialog 
        PrintListview(ListView1, PrintDialog1, "Druckauftrag Titel");
    } 
    //--------------------------------------------------------------------------- 
    void PrintListview(TListView *lv, TPrintDialog *PrintDialog, String sTitel) { 
    ...
    

    und schmeiß die ganzen

    ...
    Printer()->Canvas->TextOut(10,80,Form2->ListView2->Items->Item[4]->Caption);
    Printer()->Canvas->TextOut(10,80,Form2->ListView2->Items->Item[5]->Caption);
    ...
    

    aus der Funktion PrintListview wieder raus!

    kann leider nicht compiliert werden= call to undefined function 'PrintListView'
    das kam immer wenn ich irgendwo listview angegeben hatte.
    trotzdem dankeschön ihr beiden!!!



  • @Hawkxxx
    schon mal geschaut was die Funktion PrintListview macht ?
    und vector als quatsch zu bezeichnen 😮 na dann bleib bei deinen "starren" Arrays und schau nicht über den Tellerrand, könnte ja was neues kommen 😉

    assassipretzel schrieb:

    kann leider nicht compiliert werden= call to undefined function 'PrintListView'
    das kam immer wenn ich irgendwo listview angegeben hatte.

    Du musst die Funktion natürlich noch im Header bekannt machen

    > C++ GRUNDLAGEN <<<<<<<<

    void PrintListview(TListView *lv, TPrintDialog *PrintDialog, String Titel);
    


  • @vergisses

    so meinte ich es nicht, aber man sollte es so einfach wie möglich für einen Anfänger machen, denn wenn man vector benutzt, dann muss man sich wieder damit noch auseinandersetzen - was meiner Meinung nach für sein Problemchen überflüssig ist.
    Ich wollte nur, dass er erstmal mit den einfachen Mitteln arbeitet und nicht sich mit neuen Headern und neuen Funktionen auseinandersetzt.

    Aber letztendlich ist er derjenige, der sich für eine einfache oder komplizierte Lösung entscheiden muss...



  • Hawkxxx schrieb:

    @vergisses

    so meinte ich es nicht, aber man sollte es so einfach wie möglich für einen Anfänger machen, denn wenn man vector benutzt, dann muss man sich wieder damit noch auseinandersetzen - was meiner Meinung nach für sein Problemchen überflüssig ist.
    Ich wollte nur, dass er erstmal mit den einfachen Mitteln arbeitet und nicht sich mit neuen Headern und neuen Funktionen auseinandersetzt.

    Aber letztendlich ist er derjenige, der sich für eine einfache oder komplizierte Lösung entscheiden muss...

    So habe ich früher auch gedacht, aber inzwischen bin ich anderer Meinung. Die Benutzung der STL ist mMn elementar und man sollte sich so früh wie möglich angewöhnen sie zu benutzen. Ansonsten eignet man sich Sachen an, die man schwer wieder los wird. Wenn die dynamischen C-Style arrays funktionieren warum sollte ich mich dann um Alternativen kümmern? malloc/realloc sind auch nur Einzeiler, warum sollte da ein std::vector::push_back() oder std::vector::resize() besser sein?
    Die STL gehört zu den Grundlagen, auch wenn man anfangs nicht viel versteht bzw. die Einarbeitungszeit etwas länger ist. Aber es zahlt sich langfristig aus, weil der höhere Zeitaufwand zum Lernen durch kürzerer Entwicklungszeiten kompensiert wird, und ab einem bestimmten Zeitpunkt überwiegt die Zeiteinsparung bei der Entwicklung.

    @assassipretzel:

    Du kannst natürlich so lange irgendwelche Codezeilen irgendwie hin- und herschieben, bis irgendwann irgendetwas herauskommt das irgendwie Ähnlichkeit mit dem Wunschergebnis hat. Das Ausdrucken einer ListView ist trivial, und wenn du dazu schon mehrmals fragen musst fehlen dir einfach die nötigen Grundlagen.
    Also: Basics lernen! Am besten suchst du dir ein gutes Buch (Vorschläge gibts hier im Forum) und arbeitest das durch.



  • VergissEs schrieb:

    Du musst die Funktion natürlich noch im Header bekannt machen

    > C++ GRUNDLAGEN <<<<<<<<

    void PrintListview(TListView *lv, TPrintDialog *PrintDialog, String Titel);
    

    thx


Anmelden zum Antworten