Export ohne Benutzeraktionen

Hallo ich bin neu bei der Combit-Community gelandet. Ich bin mittlerweile ein pensionierter Mathematik- und Physiklehrer, der aber immer noch Programme für die alte Schule erstellt bzw. etwas pflegt. Ich bin aber sicher kein Profi.

Ich würde gern (wie in der Programmierreferenz im Punkt 7.1.5 beschrieben) ohne Benutzeraktion
das Listenobjekt xxx.lst als PDF-Dokument xxx.pdf exportieren und in einem Verzeichnis speichern.

Ich programmiere mit dem Embarcadero C+±Builder. Als Compiler verwende ich den klassischen Borlandcompiler und erzeuge 32-bit-Anwendungen.

Das vom Punkt 7.1.5 abgekupferte, leicht geänderte Codefragment lautet:

void __fastcall TForm1::PrintButtonClick(TObject *Sender)
{
int Fehlercode;
HWND__ *hWnd=Form1->Handle;
HLLJOB  hJob;
hJob = LlJobOpen(0);

	LlXSetParameter(hJob, LL_LLX_EXTENSIONTYPE_EXPORT, L"PDF",L"Export.File", L"xxx.pdf");
	LlXSetParameter(hJob, LL_LLX_EXTENSIONTYPE_EXPORT, L"PDF",L"Export.Path", L"C:\\Users\\Helmut\\Documents\\ListUndLabelTestReports\\");
	LlXSetParameter(hJob, LL_LLX_EXTENSIONTYPE_EXPORT, L"PDF",L"Export.Quiet", L"1");
		LlPrintWithBoxStart(hJob, LL_PROJECT_LIST, L"xxx.lst",LL_PRINT_EXPORT, LL_BOXTYPE_BRIDGEMETER, hWnd,L"PDF");
		LlPrintSetOptionString(hJob, LL_PRNOPTSTR_EXPORT, L"PDF");
		Fehlercode = LlPrint(hJob);
		//Ll28Test->Print();
		LlPrintEnd(hJob,1);

LlJobClose(hJob);
Label1->Caption=Fehlercode;
}

Ein Click auf den PrintButton bewirkt aber nicht das gewünschte Ergebnis, es wird kein PDF-Datei erzeugt und abgespeichert.
Der Fehlercode lautet -4!
Die Anwendung besitzt die Instanz Ll28Test der TListLabel28-Komponente. Muss eventuell diese mehr eingebunden werden?
Aber Ll28Test->Print() hat mir auch nicht weitergeholfen.

Wer kann weiterhelfen?

H. Schüßler

Ps.: Wo finde ich die Liste der ENUM-Werte wie Export.File, Export.Path … für pszKey.

Und nochwas: Ich finde den Abmelden-Button vom Forum nicht.

Der Code sieht so aus, als ob keine der Komponenten (BDE oder FireDAC) zum Einsatz kommt, sondern man die manuelle Druckschleife mit eigener Datenversorgung vorgezogen hat - quasi Programmierung per API

Der Fehlercode -4 sagt ja, dass eine Druckfunktion aufgerufen wurde, obwohl gar keiner gestartet wurde… denke, dass hier schlicht die Reihenfolge nicht stimmt… LlXSetParameter-Aufrufe sollte erst NACH LlPrintWithBoxStart aufgerufen werden.

Wenn man aber das Databindung (Datenkommen aus einem DataSet oder sowas) von BDE oder FireDAC verwenden möchte, dann muss man keine eigene Druckschleife verwenden. Dann müsste man das Event SetPrintOptions in der Komponenten (siehe auch Export ohne Benutzerinteraktion mit OCX / VCL und .NET) verwenden und dort LlXSetParameter aufrufen - das zeigt sogar eines der mitgelieferten Delphi-Beispiel - “Export Example” oder so heißt es.

1 Like

Der ist hier versteckt :slight_smile::

image

Jetzt habe ich das “Versteck” gefunden. Dankeschön!

1 Like

Hallo Herr Hambrecht, dank ihrer Hilfe klappt es nun mit dem “PDF-Export”!

Das folgende zeigt den Testcode für den C+±Builder unter Verwendung der VCL.
Vielleicht hilft das Codefragment auch anderen Nichtexperten. Nach einem Klick auf den “PrintButton” wird gedruckt
und dann noch ein PDF-Export durchgeführt.

Ll28Test ist eine Instanz der TListLabel28-Komponete.
Man beachte:
LlXSetParameter(…) ist kein Element von Ll28Test sondern von Ll28Test->Core.
Die Klasse ExportConfiguration existiert in der VCL nicht, jedenfalls habe ich sie nicht gefunden.

TForm1 *Form1;
//
//---------------------------------------------------------------------------------------------------
//
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
FilePraefixName="Export";                                             //"variabler" Präfix der Exportdatei
FilePfad="C:\\Users\\Helmut\\Documents\\ListUndLabelTestReports\\";   //"variabler" Dateipfad
}
//
//---------------------------------------------------------------------------------------------------
//
void __fastcall TForm1::DesignButtonClick(TObject *Sender)
{
Ll28Test->Design();
}
//
//---------------------------------------------------------------------------------------------------
//
void __fastcall TForm1::PrintButtonClick(TObject *Sender)
{
	for(int ii=0;ii<2;ii++)
	{
		if(ii==0)
		{
			Ll28Test->Print();
        }
		if(ii==1)
		{
			Ll28Test->OnDefinePrintOptions=DefinePrintOptionsFuerPdfExport; //Zuweisung der Eventroutine
			Ll28Test->Print();
		}
	}
}
//
//---------------------------------------------------------------------------------------------------
//
void __fastcall TForm1::DefinePrintOptionsFuerPdfExport(TObject *Sender)
{
	UnicodeString FileName=FilePraefixName+".pdf";
	Ll28Test->Core->LlXSetParameter(LL_LLX_EXTENSIONTYPE_EXPORT, "PDF", "Export.File", FileName);
	Ll28Test->Core->LlXSetParameter(LL_LLX_EXTENSIONTYPE_EXPORT, "PDF", "Export.Path", FilePfad);
	Ll28Test->Core->LlXSetParameter(LL_LLX_EXTENSIONTYPE_EXPORT, "PDF", "Export.Quiet", L"1");
	Ll28Test->Core->LlPrintSetOptionString(LL_PRNOPTSTR_EXPORT, "PDF");
}
1 Like

Hi Helmut, nur so als Nachtrag, die TListLabel hat eine DoExport Prozedur, vielleicht macht die manches einfacher :wink: aber so passt es natürlich auch

  Procedure DoExport(              Wnd        : HWND;
                                   const ProjectFile: String;
                                   const OriginalProjectFile: String;
                                   MaxPages   : Integer;
                                   const ExportFormat: String); overload;
  Procedure DoExport(              Wnd        : HWND;
                                   const ProjectFile: String;
                                   const OriginalProjectFile: String;
                                   MaxPages   : Integer;
                                   const ExportFormat, ExportPath, ExportFile: String;
                                   const ExportQuiet, ExportShow: Boolean); overload;
1 Like

Hallo Herr Erdal Alacali,

vielen Dank für ihren Hinweis, wie sich mit Hilfe der VCL des C++Builders Print-Optionen setzen lassen und habe dies gleich mal getestet:

Ll28Test->DoExport(
this->Handle,
“C:\Users\Helmut\Documents\ListUndLabelTestReports\xxx.lst”,
“C:\Users\Helmut\Documents\ListUndLabelTestReports\xxx.lst”,
0,
“PDF”,
“C:\Users\Helmut\Documents\ListUndLabelTestReports\”,
“Export.pdf”,
true,
false);

Das hat gut geklappt. Die notwendigen Parameter habe ich allerdings einwenig nach “Bauchgefühl” verwendet, da ich in der Dokumentation keine Beschreibung der Funktion gefunden habe.

Wissen Sie, wo dazu etwas zu finden ist?

                                                       ***

In meiner Anwendung würde ich gerne die (mit wenig Benutzereingaben) erstellten Dokumente, bevor sie gedruckt werden, zunächst im Previewer anzeigen lassen. Die Befehlsfolge

Ll28Test->AutoDestination=pmPreview;
Ll28Test->Print();

liefert diese Vorschau. Der Previewer lässt aber sehr viele Einstellmöglichkeiten zu, die ich aber stark einschränken,
d.h. die Möglichkeiten der Tool-Menü-Leiste weitestgehend unterdrücken, möchte. Im Grunde soll in dieser Vorschau nur noch das bearbeiten von Formularelementen möglich sein und der Previewer (ggf. nach Speicherung) natürlich wieder geschlossen werden können.

Dazu bin ich auf den Artikel

gestoßen, in dem dieses “Problem” angesprochen wurde und Sie Ratschläge gegeben haben. Insbesondere haben Sie dort angedeutet, dass Sie diese Anforderung an die Entwicklungsabteilung weiterzugeben.

Natürlich habe ich versucht ihren Code mit Hilfe des C+±Builders und der TListLabel28-Komponete der VCL nachzuvollziehen, habe aber bemerkt, dass z.B. der Typ-Name “ProjectParameter” nicht vorhanden ist, was mit “LL.ProjectParameters[LlProjectParameter.SaveAsFilename]” erreicht wird; mich irritieren hier besonders die eckigen Klammern
[ … ]. Außerdem finde ich keine Entsprechung der Komponente “ExportConfiguration”. Damit kam ich mit meinem Versuch nicht weit.

Können Sie mir bei der Problematik weiterhelfen?

Mit freundlichen Grüßen

Helmut Schüßler

Hallo Herr Alacali,

Sorry: Teil 2 meiner Fragen von gestern hat sich erledigt. Ich habe die Komponente TLlPreviewControl28 entdeckt und werde jetzt mit ihr mal experimentieren. Manchmal ist man einfach blind!!

Ein schönes Wochenende!

Helmut Schüßler

1 Like

Hallo Helmut, sorry im Moment viel zu tun, ich werde dir gerne Heute Abend mal antworten, was genau ist den noch offen an den Fragen :slight_smile: LG

Hallo Erdal, im Moment komme ich soweit schon zurecht und habe im Moment nur eine Frage:
Setzt man in der TListLabel28-Komponente die Eigenschaft

AutoShowPrintOptions=true;

und startet den Druck mit der Print() Methode, so erscheint zunächst
ein Fenster für Ausgabe-Einstellungen. Hier lässt sich u.a. der Druckvorgang
durch Klick auf den Abbrechen-Button vorzeitig beenden und das Fenster wird
wieder geschlossen.

Kennst du oder kennt jemand im Forum den Rückgabewert bei diesem Vorgang und
wie er programmtechnisch abgefragt werden kann?

Danke für dein Hilfsangebot, ich komme sicher noch darauf zurück.

Helmut

P.S.: Ich programmiere mit dem C++ Builder und damit mit der VCL.

Hallo Helmut,

ich denke, dass im Falle des Abbruchs eine Exception ausgelöst wird, da Print/DoExport ja void-Funktionen (also ohne Rückgabewert) sind. In Delphi würde das Konstrukt ungefähr so aussehen:

...
try
  // so something with List & Label ;-)
  ListLabel.Print;
except
  on E: Exception do
  begin
     MessageBox(self.Handle, PWideChar(E.Message), 'List & Label', MB_OK);
  end
end;
...

Für C++ Builder lehne ich mich nun mal aus dem Fenster - sowas in der Art hier:

...
try
{
    // so something with List & Label ;-)
	ListLabel->Print();
}
catch (Exception &E)
{
    MessageBox(self->Handle, E->Message, "List & Label", MB_OK);
}
...

Kommst du damit schon weiter?

Hi Helmut entweder das probieren was Oli schreibt, oder du setzt einen eigenen Druckdialog davor, den kannst ja wie du willst steuern, die Devmode welche du zurück kriegst kannst ja dann per LlSetPrinterInPrinterFile an LL übergeben usw.

Hallo Oliver,

danke für dein Feedback. Ich habe deinen Vorschlag ausprobiert.
Da (mir) nicht bekannt ist, welche Exception ausgelöst wird, kann im Catch-Block
die Sonderform catch(…) verwendet werden. Die Behandlungsroutine wird dann für
alle möglichen Exceptions aufgerufen.

LL28_Bestellung->AutoDestination=pmExport;
LL28_Bestellung->AutoShowPrintOptions=true;
//
// -- Den Klick "Druck abbrechen" abfangen und behandeln
//
try
{
	LL28_Bestellung->Print();
}
catch(...)
{
	// -- Behandlungsroutine
	VorgangAbschliessenButton->Enabled=false;
	...
}

Der obige Code löst das “Problem”. Vielen Dank!

Helmut

1 Like

Hallo Erdal,

danke für dein Feedback. Ich habe Olivers Vorschlag ausprobiert.
Da (mir) nicht bekannt ist, welche Exception ausgelöst wird, kann im Catch-Block
die Sonderform catch(…) verwendet werden. Die Behandlungsroutine wird dann für
alle Exceptions aufgerufen.

LL28_Bestellung->AutoDestination=pmExport;
LL28_Bestellung->AutoShowPrintOptions=true;
//
// -- Den Klick "Druck abbrechen" abfangen und behandeln
//
try
{
	LL28_Bestellung->Print();
}
catch(...)
{
	// -- Behandlungsroutine
	VorgangAbschliessenButton->Enabled=false;
	...
}

Dein Lösungsvorschlag müsste aber auch klappen. Vielen Dank!

Helmut