Hallo,
ich habe bei einem Report (Rechnung) das Problem gehabt, dass ich diesen auf Geschäftspapier drucken muss und habe hier mal eine kleine Anleitung angehängt, wie das realisierbar ist. Als Hintergrund noch: In einem Projekt habe ich verschiedene Reports (Listen, Rechnung). Der Kunde hat ein Drucker mit zwei Papierfächern, im einen blanko Papier, im anderen Geschäftspapier. Die Listen sollen auf blanko Papier gedruckt werden, die Rechnung auf Geschäftspapier. Vorübergehend habe ich auf dem Rechner den Drucker ein zweites mal installiert und habe dort in den Druckereinstellungen das andere Fach als Standard eingestellt. Die Drucker konnte ich schon vorher im Programm extra für jeden Report einstellen, nur das Papierfach nicht. Das habe ich aber jetzt auch umgesetzt.
Noch was als Grundlage: Man kann nicht einfach dem Drucker sagen: Papierfach := 1 oder Papierfach := 2. Jeder Druckertreiber handhabt dies etwas anders und den Papierfächer sind Namen zugeordnet, entsprechend den Einstellungen im Druckertreiber.
Damit das ganze funktioniert, habe ich mir eine Formular angelegt, in dem ich die Einstellungen mache und dann in eine INI-Datei speichere. Andere Dinge sind natürlich auch möglich. Auf dem Form gibt es dann für die verschiedenen Reports jeweils zwei Comboboxen. Eine für den Drucker und die zweite für das Papierfach.
Delphi-Quellcode:
uses
..., frxPrinters, IniFiles, ...;
procedure Form1.FormCreate(Sender: TObject)
var
Ini: TIniFile;
begin
// Alle Im System installierte Drucker in ComboBox
cb_Rechnung.Items := frxPrinters.Printers;
Ini := TIniFile.Create('INI.INI');
try
// Zuvor gespeicherten Drucker wieder selektieren
cb_Rechnung.ItemIndex := cb_Rechnung.Items.IndexOf(Ini.ReadString('PRINTERS', 'RECHNUNG', ''));
// Drucker in frxPrinters selektieren, damit ich die Papierfächer auslesen kann
frxPrinters.PrinterIndex := frxPrinters.IndexOf(cb_Rechnung.Text);
cb_RechnungFach.Items := frxPrinters.Printer.Bins; // Papierfächer in Combobox
// Zuvor gespeichertes Fach wieder selektieren
cb_PrinterBelegFach.ItemIndex := Ini.ReadInteger('PRINTERS', 'RECHNUNGFACH', 0);
// Beim Papierfach habe ich den Index gespeichert und nicht den Namen des Faches, da bei den
// Papierfächern auch am Anfang Leerzeichen vorkommen können und diese bei Ini.ReadString
// abgeschnitten werden (ist jedenfalls bei mir so)
finally
Ini.Free;
end;
end;
procedure Form1.cb_RechnungChange(Sender: TObject);
begin
frxPrinters.PrinterIndex := frxPrinters.IndexOf(cb_Rechnung.Text);
cb_RechnungFach.Items := frxPrinters.Printer.Bins;
end;
procedure Form1.SpeichernButtonClick(Sender: TObject);
var
Ini: TIniFile;
begin
Ini := TIniFile.Create('INI.INI');
try
Ini.WriteString('PRINTERS', 'RECHNUNG', cb_Rechnung.Text);
Ini.WriteInteger('PRINTERS', 'RECHNUNG', cb_RechnungFach.ItemIndex);
finally
Ini.Free;
end;
end;
So, Drucker ist eingestellt, mit Papierfach, jetzt muss ich es noch dem Fastreport vor dem Drucken mitteilen.
Delphi-Quellcode:
uses
..., frxPrinters, IniFiles, ...;
procedure PrintRechnungForm.PrintButtonClick(Sender: TObject;
var
Ini: TIniFile;
ReportPage: TFrxReportPage;
begin
Ini := TIniFile.Create('INI.INI');
try
// Eingestellten Report wieder aus INI-Datei lesen und zuweisen
frxReport_Rechnung.PrintOptions.Printer := Ini.ReadString('PRINTERS', 'RECHNUNG', '');
// In 'ReportPage' wird die Einstellung für das Papierfach gemacht
// Man kann leider nicht direkt darauf zugreifen
// frxReport_Rechnung ist meine TfrxReport, das auf dem Fromular liegt
// 'PageRechnung' ist der Name meiner Seite, wie ich sie im Fastreport-Designer benannt habe
ReportPage := TFrxReportPage(frxReport_Rechnung.FindObject('PageRechnung'));
// Den Drucker wieder setzen, damit ich die Papierfächer zurück bekomme
frxPrinters.PrinterIndex := frxPrinters.IndexOf(frxReport_Rechnung.PrintOptions.Printer);
// Das Papierfach für die erste Seite wird in .Bin angegeben
// Der Name des Papierfachs muss in irgendeine interne Nummer umgewandelt werden
// Standardeinstellungen sind über die Konstanten DMBIN_XXX (Windows.pas) definiert, passen aber nicht für die meisten Drucker
ReportPage.Bin := frxPrinters.Printer.BinNameToNumber(frxPrinters.Printer.Bins[Ini.ReadInteger('PRINTERS', 'RECHNUNGFACH', 0)]);
// Alle anderen Seiten auch über das selbe Fach
ReportPage.BinOtherPages := ReportPage.Bin;
finally
Ini.Free;
end;
if frxReport_Rechnung.PrepareReport then begin
frxReport_Rechnung.Print;
end;
end;
Ein paar zusätzliche Abfragen und Prüfungen habe ich mir hier gespart, damit der Code nicht zu lange wird, kann ja jeder nach Bedarf noch anpassen. Mir ging es hier um die grundsätzliche Funktionsweise.
Jetzt hoffe ich auch, dass es so funktioniert, denn ich habe im Büro nur ein Papierfach. Ich habe jedenfalls keine Fehlermeldung bekommen und der Drucker hat eine Seite ausgespuckt. Morgen werde ich es beim Kunden testen und gebe dann noch mal eine Info durch.
Habs gerade beim Kunden getestet und es funktioniert wunderbar.
Grüße
Sven