Laden...

mehrere Seiten drucken - wie?

Erstellt von medi vor 18 Jahren Letzter Beitrag vor 18 Jahren 17.421 Views
M
medi Themenstarter:in
126 Beiträge seit 2005
vor 18 Jahren
mehrere Seiten drucken - wie?

Hi,

Also das Drucken von einer Seite bekomme ich ja noch hin nur hapert es was mehrere Seiten nacheinander angeht. Das Problem, was ich habe ist, dass mein Programm einfach keine weitere Seite anlegt. Wie bekomm ich das hin?

Meine Seite wird so aufgebaut:
Schleife über alle Daten(Seiten)
Seitenkopf
dann ne Schleife mit Daten (im Prinzip n Zeilen)
Seitenfuß

Ich habe mir auch schon ein hier mal verlinktes Video angeschaut wo Drucken erklärt wird aber da wird nur auf das Benutzen von e.HasMorePages = (true/false) hingewiesen nur wie ich damit genau arbeiten muss wird nicht gesagt. Jedenfalls funktionierten meine Versuche damit bisher nicht...

Wie sag ich meinem Programm, dass es die Daten auf der nächsten Seite ausgeben soll? Geht das überhaupt?

3.825 Beiträge seit 2006
vor 18 Jahren

Das Ducken von mehrseitigen Dokumenten ist nicht so to toll gelöst in Dot.Net. Ich habe in Version 2.0 auf Besserung gehofft, aber war leider nix dabei.

😦

Beim Aufruf des Drucks wird ja deine PrintPage-Funktion aufgerufen.
Wenn noch eine Seite kommt dann setze am Ende e.HasMorePages = true.
In diesem Fall wird die PrintPage-Funktion ein weiteres Mal aufgerufen.
Die Seitenzahl hochzählen und die richtigen Elemente drucken musst Du selbst machen.
Wenn nichts mehr zu Drucken ist setzte e.HasMorePages auf false.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

C
193 Beiträge seit 2005
vor 18 Jahren

Musst dabei nur etwas aufpassen. Wenn du unten dann e.HasMorePages auf true gesetzt hast kannste dir dein ganzes PrintDoc vorstellen wie eine schleife. Also alle counter und so weiter die du in deinem printDoc oben setzt werden überschrieben. Achso, und du solltest dir sicher sein irgendwann wieder auf false gesetzt zu haben weil sonst kommten da paar seiten raus 😁

M
medi Themenstarter:in
126 Beiträge seit 2005
vor 18 Jahren

hi,

erstmal danke für die anteilnahme 😉

im prinzip hab ichs ja auch so gemacht wie ihr sagt. hab jetzt mal hasMorePages=true am ende des printdocs gesetzt und da spuckt er mir auch mehr als eine seite aus (halt ne ganze menge). setze ich es aber wieder auf false ist es wieder nur eine seite obwohl es zwei sein müssten.

hier mal der code:


		private void printDoc_PB_Kontrollmeldung(object sender, System.Drawing.Printing.PrintPageEventArgs e)
		{
			int Rand_oben, Rand_links, zeile_x,zeile_y,zeile_b,zeile_h,ID,max,rest,anzahl,aktDS;
			string sQuery,sTable,sStundenlohn;
			DataRow aktZeile,Kundenzeile;
			DBcon aktDB = new DBcon();
			DataTable Daten = new DataTable(); 

			// Querformat einstellen
			e.PageSettings.Landscape = true;
			// Blattbreite = 825 px
			// Seitenkopf drucken
			Font Schrift_groß = new Font("Time News Roman", 20, FontStyle.Bold);
			Font Schrift_mittel = new Font("Time News Roman", 12, FontStyle.Bold);
			Font Schrift_mittel_normal = new Font("Time News Roman", 12, FontStyle.Regular);
			Font Schrift_normal_Hauptdaten = new Font("Time News Roman", 14, FontStyle.Regular);
			Font Schrift_normal_Spaltentext = new Font("Time News Roman", 6, FontStyle.Regular);
			Font Schrift_normal_Tabellentext = new Font("Time News Roman", 8, FontStyle.Bold);
			Font Schrift_normal_Fussnote = new Font("Time News Roman", 8, FontStyle.Regular);
			Brush Farbe;
			
			Pen linie_oben = new Pen(Color.Black,3);
			Pen linie_unten = new Pen(Color.Black,1);
			Pen linie_unten_fett = new Pen(Color.Black,2);
			Pen linie_zeile_rahmen = new Pen(Color.Black,2);
			Pen linie_zeile_balken = new Pen(Color.Black,3);
			Pen linie_zeile_strich = new Pen(Color.Black,1);

			sTable = "Kunden";
			sQuery = "SELECT * FROM Kunden WHERE Kundennummer="+lbl_DISPO_KID.Text;
			Daten = aktDB.createDS(sQuery,sTable, strDB_Pfad.getDatenbankpfad(iPfadNr));
			Kundenzeile = Daten.Rows[0];

			// Zeile
			sTable = "MA_Buchungen";
			sQuery = "SELECT t2.*,t1.* FROM MA_Buchungen t1,Personaldaten t2 WHERE VA_ID="+Convert.ToInt32(lbl_DISPO_VAID.Text.ToString())+" AND t1.P_ID=t2.P_ID;";
			
			Daten = aktDB.createDS(sQuery,sTable, strDB_Pfad.getDatenbankpfad(iPfadNr));
			rest = Daten.Rows.Count;
			anzahl = 8;
			aktDS = 0;
			// Zeile
			for(int j=0;j<=Math.Ceiling(Daten.Rows.Count / anzahl);j++)
			{
			Rand_oben = 100;
			Rand_links = 30;
			Farbe = Brushes.Black;
			zeile_x = Rand_links;
			zeile_y = 200;
			zeile_b = 825 - 2 * Rand_links;
			zeile_h = 100;
				// Kopfdaten
				e.Graphics.DrawString(DateTime.Now.Date.ToString().Substring(0,10), Schrift_mittel, Farbe, Rand_links + 300, Rand_oben);
				e.Graphics.DrawString("...Überschrift... " + cmb_DISPO_VA_Kunde.Text.ToString(), Schrift_mittel_normal, Farbe, Rand_links, Rand_oben + 25);
			
				if(Daten.Rows.Count > anzahl)
				{
					if(rest > anzahl)
					{
						max = anzahl;
						rest -= max;
					}
					else max = rest;
				}
				else
					max = Daten.Rows.Count;
				for(int i=j;i<max;i++)
				{
					aktZeile = Daten.Rows[aktDS];
					
//.......
// verschiedene Berechnungen
//.......
					e.Graphics.DrawRectangle(linie_zeile_rahmen,zeile_x,zeile_y,zeile_b,zeile_h);
					// vertikal
					e.Graphics.DrawLine(linie_zeile_balken,zeile_x+200,zeile_y,zeile_x+200,zeile_y+zeile_h);
					e.Graphics.DrawLine(linie_zeile_balken,zeile_x+300,zeile_y,zeile_x+300,zeile_y+zeile_h);
					e.Graphics.DrawLine(linie_zeile_balken,zeile_x+450,zeile_y,zeile_x+450,zeile_y+zeile_h);
					e.Graphics.DrawLine(linie_zeile_balken,zeile_x+580,zeile_y,zeile_x+580,zeile_y+zeile_h);
					e.Graphics.DrawLine(linie_zeile_balken,zeile_x+670,zeile_y,zeile_x+670,zeile_y+zeile_h);
					// horizontal
					e.Graphics.DrawLine(linie_zeile_strich,zeile_x,zeile_y+20,zeile_x+zeile_b,zeile_y+20);
					e.Graphics.DrawLine(linie_zeile_strich,zeile_x,zeile_y+50,zeile_x+zeile_b,zeile_y+50);
					e.Graphics.DrawLine(linie_zeile_strich,zeile_x,zeile_y+70,zeile_x+zeile_b,zeile_y+70);
					
					// Daten 1. Zeile
//........
// viele Ausgaben sprich das Blatt wird bepinselt
//........
					
					// nächste Zeile
					zeile_y += zeile_h;
					aktDS++;
				}
				// Fußnote
				e.Graphics.DrawString("...Fußnote...", Schrift_normal_Fussnote, Farbe, Rand_links, 1100);
				e.HasMorePages = true;
			}
			e.HasMorePages = false;	
		}

ne Idee wo der Denkfehler ist?

abgesehn davon, dass e.PageSettings.Landscape = true; bei mir auch nicht funktioniert - die ausgabe ist immer hochformat 🙁

F
10.010 Beiträge seit 2004
vor 18 Jahren

Es sind einige designfehler und denkfehler in deinem Code.

  1. Der Code in PrintDoc sollte nur drucken, keine DB-Abfragen oder ähnliches,
    denn wenn Du z.B. mit printpreview arbeiten willst, geht das bestimmt in die hose.

  2. Deine Routine wird komplett durchlaufen, verlassen, und dann schaut
    der umgebende Teil ob hasmorepages gesetzt ist und ruft deine Routine neu auf.
    Wenn Du also am ende hasmorepages auf false setzt wird natürlich nicht mehr gedruckt.

  3. Alle Objekte die Du anlegst, wie Fonts und Brushes solltest Du vor dem PrintDok anlegen,
    und danach mit Dispose Freigeben, sonst kann es zu ResourceProblemen mit den Handles kommen.

  4. Das was Du da machen willst ist mit einem ReportTool warscheinlich ein 3 Zeiler.

Also zusammengefasst:
Datenbankabfragen Vorher machen.
Resourcen Vorher anlegen, hinterher freigeben.
Mal nachschauen ob ein Reportingtool nicht einfacher ist.

3.825 Beiträge seit 2006
vor 18 Jahren

Am Ende muss z.B. stehen :

seite++;
e.HasMorePages = (seite<seitenzahl);

seitenzahl muss vorher berechnet werden.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

M
medi Themenstarter:in
126 Beiträge seit 2005
vor 18 Jahren

Original von FZelle
Es sind einige designfehler und denkfehler in deinem Code.

  1. Der Code in PrintDoc sollte nur drucken, keine DB-Abfragen oder ähnliches,
    denn wenn Du z.B. mit printpreview arbeiten willst, geht das bestimmt in die hose.
  1. Deine Routine wird komplett durchlaufen, verlassen, und dann schaut
    der umgebende Teil ob hasmorepages gesetzt ist und ruft deine Routine neu auf.
    Wenn Du also am ende hasmorepages auf false setzt wird natürlich nicht mehr gedruckt.
  1. Alle Objekte die Du anlegst, wie Fonts und Brushes solltest Du vor dem PrintDok anlegen,
    und danach mit Dispose Freigeben, sonst kann es zu ResourceProblemen mit den Handles kommen.
  1. Das was Du da machen willst ist mit einem ReportTool warscheinlich ein 3 Zeiler.

Also zusammengefasst:
Datenbankabfragen Vorher machen.
Resourcen Vorher anlegen, hinterher freigeben.
Mal nachschauen ob ein Reportingtool nicht einfacher ist.

Original von BerndFfm
Am Ende muss z.B. stehen :

seite++;  
e.HasMorePages = (seite<seitenzahl);  
  

seitenzahl muss vorher berechnet werden.

Grüße Bernd

danke werd ich machen 🙂

F
10.010 Beiträge seit 2004
vor 18 Jahren

Das Drucken in .NET ist deutlich anders als Du es Dir vorstellst.

Grobe Herangehensweise:

Du erzeugst dein PrintDokument, und weist es dem PrintPreview zu.

Dann sagst Du print.
Jetzt wird Solange dein PrintDoc_PB.. aufgerufen wie Du seiten hast
( also hasMorePages == true ) und angezeigt.

Wenn Du jetzt Druckst, wird der ganze Sermon wieder gemacht.

Also solltest Du die Datenbank abfragen vorher machen, denn es kann sich
ja schon einiges getan haben.

Da das was Du machen willst, nicht unüblich ist, gibt es schon zig verschiedene
Biblioteken, die mit Vorlagen ausgestattet irgendwelche Datenbankabfragen
ausdrucken könne. die nennen sich dann Reporttools, wie z.B.
Crystal Reports, EasiReports, Report Services....

M
medi Themenstarter:in
126 Beiträge seit 2005
vor 18 Jahren
ich mal wieder :D

hi,

hab jetzt "hoffentlich" alles so gemacht wie vorgeschlagen. also erst die DB Abfragen in ner Klasse zwischengespeichert und dann im PrintDoc eingebunden.

private void btn_drucken_Kontrollmeldung_Click(object sender, System.EventArgs e)
{
			Kontrollzeugs.Kontrollmeldung_vorbereiten(Convert.ToInt32(lbl_DISPO_VAID.Text.ToString()), strDB_Pfad.getDatenbankpfad(iPfadNr), lbl_DISPO_KID.Text.ToString());

			GLOB_maxSeiten = Convert.ToInt32(Math.Floor(Kontrollzeugs.get_AnzahlDS() / 10));
                        GLOB_aktSeite = 0;

			Kontrollzeugs.set_aktDS(0);
			printPreviewDialog1.Document = PD_Kontrollmeldung;
			printPreviewDialog1.ShowDialog();	
		}



		private void printDoc_PB_Kontrollmeldung(object sender, System.Drawing.Printing.PrintPageEventArgs e)
...Variablendeklarationen...
...PD Parameter festlegen...

anzahl = 10;
rest = Kontrollzeugs.get_rest();
if(rest > anzahl) rest = anzahl;

...Blattüberschrift ausgeben...

for(int i=0;i<rest;i++)
{
...Zeile mit Daten ausgeben

// nächste Zeile
zeile_y += zeile_h;
Kontrollzeugs.set_incDS();
}
GLOB_aktSeite++;
...Blattfußnote ausgeben

e.HasMorePages = (GLOB_aktSeite <= GLOB_maxSeiten);
if(e.HasMorePages == true)
	PD_Kontrollmeldung.PrintPage += new PrintPageEventHandler(this.printDoc_PB_Kontrollmeldung);

Funktioniert auch so alles in der PrintPreview. Wenn ich dann aber ein PDF erzeugen will (also erst PrintPeview und dann auf Drucken) dann spuckt er mir nur die Überschrift und die Fußnote aus. Kann es sein, dass das an der Var rest liegt?

379 Beiträge seit 2004
vor 18 Jahren

Hallo medi,

ich sehe zwar jetzt nicht wie du deinen Rest ermittelst (was Kontrollzeugs.get_rest() macht), aber du musst nach einem Druck natürlich deine Variablen wieder rücksetzen...

M
medi Themenstarter:in
126 Beiträge seit 2005
vor 18 Jahren

hi,

ja das hab ich gestern auch bemerkt...dummerweise weiss ich nicht wo. mache ich das so


e.HasMorePages = (GLOB_aktSeite <= GLOB_maxSeiten);
			if(e.HasMorePages == false)
			{
				if(Kontrollzeugs.get_aktDS() == Kontrollzeugs.get_AnzahlDS()) 
				{
					Kontrollzeugs.set_aktDS(0);
					Kontrollzeugs.set_rest(Kontrollzeugs.get_AnzahlDS());
					GLOB_aktSeite = 0;
				}
			}				
			else
			{
				PD_Kontrollmeldung.PrintPage += new PrintPageEventHandler(this.printDoc_PB_Kontrollmeldung);
			}

dann rennt ruft der nochmal die printDoc_PB_Kontrollmeldung Funktion auf und spuckt mir nur Mist aus. Es ist zum Heulen 🙁

F
10.010 Beiträge seit 2004
vor 18 Jahren

Nimms nicht zu persönlich, aber vielleicht solltest Du anfangen zu verstehen was
Du tust, sonst wird es echt schwer Fehler zu finden.

Den Code für Max Und AktSeite solltest Du in BeginPrint schreiben, denn das
wird bei jedem Start des Druckens ausgeführt.

Sonst ist nach dem PrintPreview ja deine AktSeite schon grösser Max und
er druckt nichts.

Vielleicht solltest Du ersteinmal alle Texte der Hilfe zu PrintDocument durchlesen und verstehen.

Es nutzt nie, einfach "drauflos zu coden", das rächt sich früher oder später.

M
medi Themenstarter:in
126 Beiträge seit 2005
vor 18 Jahren

nö nehm ich nicht persönlich...ich wills ja verstehen nur waren bisher alle texte, die ich zu diesem thema gefunden habe nur wenig hilfreich. dann werde ich mal deinen vorschlag durchprobieren - danke schonmal 🙂

M
medi Themenstarter:in
126 Beiträge seit 2005
vor 18 Jahren

so das mit dem BeginPrint funzt tadellos...danke nochmal 🙂

Jetzt hab ich aber noch das Problem, das ich ein PDF "drucken" lassen will aber das funktioniert nicht mehrseitig. In der PrintPreview werden mir zb. 2 Seiten angelegt....wenn ich dann aber das PDF erstellen lasse, druckt der 2x auf die selbe Seite und speichert mir also nur eine Seite. Woran kann das liegen? Gehe ich den Sourcecode step-by-step durch, reagiert das Programm nicht anders als wenn es das PrintPreview erzeugt...wo ist also der Unterschied?

379 Beiträge seit 2004
vor 18 Jahren

Wie "druckst" du denn das PDF? Mit einem speziellen Druckertreiber? Also PdfCreator oder ähnliches?

Also bei mir funktioniert es ganz normal

F
234 Beiträge seit 2006
vor 18 Jahren

Bei PDF musst Du ihm glaub ich extra sagen, daß das jetzt Seite 2 , 3, ... usw ist.
Dem "richtigen" Drucker ist das ja egal, wenn die Seite draussen ist, nimmt er die nächste, klar. Aber wie gesagt, wenn hasmorepages == true ist und der schmodder nochmal aufgerufen wird, sind ALLE Angaben zurückgesetzt, also auch die Seitennummer. Scheinbar kann das Printpreview das automatisch handeln, dein PDF-Drucker wohl nicht.

M
medi Themenstarter:in
126 Beiträge seit 2005
vor 18 Jahren

jap ich nutze eDocPrint als druckertreiber. wie sag ich dem pdf creator denn, auf welcher seite ich mich denn befinde?

ach und apropo hasmorepages...bei mir tritt das phänomen auf, dass er noch 2x den "schmodder" aufruft, nachdem ich hasmorepages auf false gesetzt habe. sollte er nicht dann sofort abbrechen? (er druckt zwar nix weil ich das abfange aber ruft das printdoc halt nochmal auf)

F
234 Beiträge seit 2006
vor 18 Jahren

Zu dem zweiten : Also das kann ich mir nur so erklären, daß bei Deiner Berechnung des Wertes für hasmorepages was schief geht. Passiert das nur bei PDF oder bei allen ?

Das erste war jetzt nur so ne Vermutung. Hab da nix in den Dokus gefunden und eDocPrint kenn ich nicht. Aber theoretisch müsste der automatisch eine weitere Seite in dem Job anlegen, statt die erste Seite zu überschreiben ... hmmm


else
            {
                PD_Kontrollmeldung.PrintPage += new PrintPageEventHandler(this.printDoc_PB_Kontrollmeldung);
            }

Kanns vielleicht daran liegen ?
Wenn der EventHandler einmal gesetzt ist, brauchst ihn dort nicht nochmal setzen. Könnte mir vorstellen, daß der PDF-Treiber das dann als neuen Job ansieht und den alten wegschmeisst. Folge: Du kriegst immer nur die letzte Seite.

M
medi Themenstarter:in
126 Beiträge seit 2005
vor 18 Jahren

hmm muss ich mal rumprobieren....

ich meld mich morgen wieder 😁