Wawi Druck aus DLL heraus

lireiner

Mitglied
Teammitglied
Hallo noch schnell in diesem Jahr an alle eine Frage.

Für zwischen die Tage hatte ich mir ein Projekt aufgehoben an welchem ich schon ne Weile sitze, leider nicht weiter komme.

Ich möchte aus einer Liste heraus einen Beleg erstellen und dann diesen Beleg drucken, allerdings nicht anzeigen sondern nur als PDF exportieren.

Dazu habe ich diesen Code in VB.Net implementiert (in einer Funktion DruckBeleg)
*****
Dim session As Sagede.OfficeLine.Engine.Session
session = Nothing
Try
'session = Sagede.OfficeLine.Engine.ApplicationEngine.CreateSession(datenbankName, Sagede.OfficeLine.Shared.ApplicationToken.System, Nothing, New NamePasswordCredential(userName, password))
session = Sagede.OfficeLine.Engine.ApplicationEngine.GetSession(Mandant.ParentSession.Id)
Catch ex As Exception
TraceLog.Logger.Error("*** Fehler: Session - " & CStr(ex.Message))
bOk = False
End Try

Dim sReportCaption As String = "Reportname_Test"
Dim _endpoint As Sagede.Shared.ApplicationServer.IEndpoint
Dim _endpointComplete As String = ""
Try
_endpoint = Sagede.OfficeLine.Shared.ServerConfiguration.ServerConfigurationProxy.GetSDataHttpsEndpoint(False, 0, 0)
_endpointComplete = String.Join("/", _endpoint.Address, "ol", "ControlCenterData", oMandant.DatasetName)
Catch ex As Exception
TraceLog.Logger.Error("*** Fehler: EndPoint - " & CStr(ex.Message))
bOk = False
End Try

Dim ViewModel As Sagede.Shared.ReportViewerControl.ReportViewerViewModel
Try
Call getDefaultNamedParameter()
Call getReportNamedParameter(CInt(sBelIDGut), "D", sReportCaption, 4000, "Gutschrift", False, False, False, 0, False)
ViewModel = New Sagede.Shared.ReportViewerControl.ReportViewerViewModel()
ViewModel.WaitForPrintCommand = False

TraceLog.Logger.Error("Kein Fehler: " & "vor ViewModel.Export")
'ViewModel.Export("C:\\tmp\\Gutschrift_Test.pdf", True)
ViewModel.ExportPdf("C:\\tmp\\Gutschrift_Test.pdf", False)
ViewModel.PrintReport(_endpointComplete, userName, PW, "Abf", "rptVKRechnung.Sage.Wawi", _namedParameters, "", False, True, "")

Catch ex As Exception
TraceLog.Logger.Error("*** Fehler: ViewModel - " & CStr(ex.Message))
bOk = False
End Try
*****

Dabei wird die Session, _endpoint und auch das ViewModel korrekt erzeugt meine ich. Allerdings wird die PDF nicht wie erwartet am definierten Ort abgelegt.
Ich denke da mache ich noch grundsätzlich etwas falsch. Hätte gern ein Beispiel, habe aber keines gefunden.

Wenn meinen Code jemand im Bereich ViewModel.Export / ViewModel.PrintReport korrigieren könnte wäre das echt hilfreich.

Im Voraus Danke und allen einen guten Rutsch in das neue Jahr.
Gruß Reiner
 
Ich hab C# bei mir WaitForPrintCommand = true und Namedparameter für "$StandardPrinter" auf "PDF-XChange"
dann PrintReport und separate Methode

void _viewModel_OnSendEmail(object sender, EventArgs e)
{
_viewModel.Export(_pdfPath);
}

und im Konstruktor _viewModel.OnSendEmail += _viewModel_OnSendEmail;
 
Hallo cs_skit und ein gesundes Neues,
vielen Dank für deine Nachricht.

Ja, WaitForPrintCommand habe ich zwar auf False, denn ich will ja nicht warten.
Den Standarddrucker habe ich auf PDF Creator, ein Drucker aus meinen Druckertreibern, denn den PDF-XChange braucht man doch nur für den direkten eMail Versand. Ich möchte ja nichts versenden, sondern nur als Datei im Dateisystem ablegen z.B. unter C:\tmp.

Aber das gelingt eben mit meinem Code nicht, dass dort eine PDF abgelegt wird. Auch wird der Druckertreiber nicht angesprochen, sonst würde bei mir der PDF Reader erscheinen, weil das im Creator so eingestellt ist.

Super wäre für mich ein Codesnipsel in VB.NET der einen funktionierenden Abschnitt für ViewModel hat, ich vermute in dem Bereich liegt mein Fehler.
Gruß Reiner
 
denn den PDF-XChange braucht man doch nur für den direkten eMail Versand
wobei der zentrale Part davon ja die PDF Generierung ist wofür der Drucker auch benutzt wird


In dem Entwicklerhandbuch ist im Kapitel "12.3.3 PDF Export von Belegen" auch dieser Weg beschrieben:

"Damit das Event „OnSendEmail“ auch tatsächlich ausgelöst wird, muss der Parameter
„$StandardPrinter“ zwingend auf "PDF-XChange" gesetzt werden.
Anschließend erfolgt der eigentliche Druckanstoß mit „PrintReport“.
Zuletzt wird das Event „OnSendEmail“ ausgelöst.
Hier findet mit der Methode Export die PDF-Erstellung statt.
"
Kann sein, dass die Export Methode also nur in Kombination mit PDF-XChange überhaupt funktioniert.

Die Methode ExportPDF ist da gar nicht wirklich dokumentiert und ob die überhaupt funktioniert und wozu die da ist weiss ich nicht. Aber wenn man auf PDF Creator druckt dann braucht man mMn doch vielleicht gar keine Export Methode weil der Ausgabepfad etc im PDF Creator eingestellt wird dann aber auch mit dediziertem Profil für Ausgabe in einen Pfad. Mir war das zu unsicher ich erzeuge nur die PDFs auf dem Weg der im Entwicklerhandbuch empfohlen wird und wenn ich die PDF habe drucke ich mit einem Chromium Print Framework von Google noch auf zusätzliche Drucker falls ich das will.
 
Kann sein, dass die Export Methode also nur in Kombination mit PDF-XChange überhaupt funktioniert.
Ich habe allerdings auch schon den PDF-XChange als Standardrucker hinterlegt und auch da passiert nichts.
Allerdings muss nach meinem Verständnis das Event „OnSendEmail“ im Code ausgelöst werden. Das habe ich bisher nicht implementiert, weil ich ja keine eMail versenden wollte.
Mein Ansatz war dann eigentlich auch den PDFCreator zu nutzen, weil der ja auch alleine die erzeugte PDF im gewünschten Ordner speichern kann. Aber der wird ja auch nicht angestubst?
Ich verstehe das bei dir so, das du es nach Entwicklerhandbuch in C# umgesetzt hast und es funktioniert dahingehend das eine PDF als Datei, oder in einer Vorschau erzeugt wird?
 
Vorschau hab ich nicht das ist bei mir eine externe Programmierung die einfach bestimmte Queues von Belegen als PDF exportiert. Geht aber auch über Mandant und Session also sollte auch von innerhalb gehen. Würde mir auch eine einfachere Implementierung wünschen und etwas mehr dokumentiert. Das mit den "Named Parameters" ist eine Totalkatastrophe und Async Druck hatte ich versucht klappt bei mir nicht also wenn man tausende drucken will dann muss man schon mal warten. Ansonsten läuft das aber zuverlässig hatte letztens mal 20k PDF gedruckt.
 
Ich danke dir bis hierhin, muss mich also weiter damit rumquälen. Na wird schon irgendwie gelingen.
Gruß Reiner
 
Ich hab C# bei mir WaitForPrintCommand = true und Namedparameter für "$StandardPrinter" auf "PDF-XChange"
dann PrintReport und separate Methode

void _viewModel_OnSendEmail(object sender, EventArgs e)
{
_viewModel.Export(_pdfPath);
}

und im Konstruktor _viewModel.OnSendEmail += _viewModel_OnSendEmail;
damit sollte es funktionieren
 
Hallo cs-skit, ich hätte auch gern den Blick in deinen Code, kannst du ihn mir auch senden? ;-)
 
Hallo Reiner,

ich drucke viel extern u. a. im Lager durch Api-Aufrufe von Tablets. Habe dafür einen Windowsdienst geschrieben, der die Druckaufträge quasi spoolt und ab arbeitet. Leider kommt es dabei immer mal wieder zu Aussetzern (leider nicht direkt reproduzierbar, alle 5-15 Tage hängt der Dienst sich mal auf).

Bei der ISV Konferenz ist Thomas Ostermann auf das Thema Druck aus externer Anwendung eingegangen.
Es war am 1. Tag in seinem Vortrag "Wie crasht man eine Sage 100".

Fazit war (aus dem Gedächtnis):
- einige Attribute bei Viewmodel sind unnötig bzw. funktionieren nicht.
- man muss aufpassen, wie schnell hintereinander man Druckaufträge absetzt, da es sonst zu Speicherproblemen führen kann.
- Wenn man nur das PDF benötigt, sollte man besser ohne ViewModel auskommen, dies ist per JSON / Api-Aufruf möglich und deutlich Ressourcen schonender und performanter.

Das neue SDK soll parallel zum Pilotbetrieb der 9.0.5 finalisiert werden und im Entwicklerhandbuch wird das Kapitel Druck aus externer Anwendung neu geschrieben.


Je nachdem wie dringend es ist, würde ich noch 4 Wochen warten, vielleicht gibt es in der neuen Dokumentation einen deutlich einfacheren Weg Deine Lösung umzusetzen.

Gruss Mark
 
Zuletzt bearbeitet:
Das liest sich aber gut mgosx, vielen Dank für die Info.
Ich konnte leider in diesem Jahr nicht an der ISV Konf teilnehmen, hatte schon ein Jahr zuvor Urlaub für diesen Zeitraum geplant.

Dann freue ich mich mal auf das neue SDK, ich bin ein Fan davon, eine gute Beschreibung zu lesen, mit der man eine Funktionalität auch wirklich einfach nachvollziehen kann. Kann man von der letzten Beschreibung leider nicht so recht behaupten.

Na dann warte ich noch ein paar Tage, darauf kommt es jetzt auch nicht mehr an.

Danke und Gruß Reiner
 
Ich habe mir das Code Beispiel nochmal angeschaut und es ist wirklich sehr gut überarbeitet und erklärt wie das bisher geht zusammen mit ein paar kleinen Erläuterungen im PDF.
Ich kann jetzt von der Herangehensweise keine große Änderungen erkennen das läuft alles wie bisher über das ViewModel und NamedParameters.

Der JSON Aufruf übergibt ja auch die NamedParams und würde mich wundern wenn er in der backend Implementierung dann nicht auch das ViewModel verwendet. Scheint aber für Einzeldrucke eine gute Lösung zu sein. Eine wirklich simplen Aufruf der nur eine BelID auf Default Report druckt ohne, dass man die ganzen Parameter angeben muss wie das der Sage100 Client schließlich auch macht weil er diese selbst zieht oder sogar den ganzen Druckprozess durchläuft muss man sich selbst implementieren.

Was mir im PDF etwas fehlt ist eine Empfehlung für welches Szenario welche Methoden verwendet werden sollten oder was vermieden werden sollte. Sowas wie "Best Practice" Anmerkungen dazu. Ich kann mir vorstellen, dass man sich auch mit dem Code aus dem Beispiel genauso seinen Appserver abschießen kann. KA welche MaxParralelRequests der so verträgt zB.

Ich werde wohl weiterhin wie vorher eine bewusst langsame/vorsichtige eigene Queue außerhalb der Produktivzeiten am Server machen bei Massendruck von hunderten++ Belegen. Wie schneller die Queue/Batch Implemetierung da bei welcher Parallelität oder Appserver Einstellungen ist und ab wann es Probleme gibt wäre schön zu wissen aber eventuell gibt es hier auch einfach keine allgemeingültigen Aussagen.
Der JSON Request klingt aber gut für einzelne zeitnahe Drucke oder wenn man generell nicht so viele Belege hat.
 
Wir nutzen seit letzter Woche den Externen Druck mittels JSON-Aufrufe.
Bisher hatte ich eine eigene Warteschlange mit ViewModel angesteuert, was jedoch ab und an zu Speicherproblemen führte.
Bisher klappt es mit den neuen Aufrufen gut.

Was mir jedoch aufgefallen ist...

1. Das Beispiel lief bei mir nicht einwandfrei
Es trat immer ein Interner Fehler auf.
Ich habe mir die Calls in Postman kopiert und die Parameter überprüft.
Hier konnte man dann schnell auch die Fehler (ich glaube es lag an den richtigen BelegHandle) anpassen bis alles läuft.

2. Dateien auf dem BlobStorage
Im BlobStorage verbleiben unter \BlobStorage\data\Containers\Data\{DB}\{Mandant}\ReportFiles die .rpt und .pdf Files, auch nach dem DeleteTracking Aufruf.
Bei einem Neustart des Blobstorage Servers werden diese dann gelöscht (vielleicht auch nach ein paar Tagen automatisch).

Ich will beobachten ob dies ein Fehler ist (ein Aufruf fehlt) oder ob dies einfach ein normales Verhalten des BlobStorage ist.

Gruss Mark
 
Zu 2) Das ist das normale Verhalten. "Delete Tracking" löscht nur den Eintrag in der Tracking-Datenbank, nicht die Datei im BlobStorage. Zu jeder Datei existiert auch eine Metadaten-Datei (Metadata-Ordner im BlobStorage), die ein Ablaufdatum enthält. Bei Erreichen dieses Datums, wird die Datei automatisch gelöscht, ggf. Nach einem Neustart des BS-Dienstes.
 
Zurück
Oben