OFFICIUM INSERVIO
Your reliable partner for your business software...
9.0.4.x - Verkaufsbelegerfassung mit Vorbelegung Kunde und Belegart aus Makro öffnen / Open sales document editor from macro, pre-setting client and document type
9.0.4 - Build 6520 - 21.03.2023
Mittwoch, 10. Mai 2023
Lösungsoption 1 (nicht empfohlen)
Possible solution 1 (not recommended)
Possible solution 2 (recommended)
Deutsch
"Einfache" Anforderung?
Eine vermeintlich einfache Anforderung innerhalb des AppDesigners erweist sich bei näherer Betrachtung als "zeitraubendes Abenteuer"! 👎
Aus dem Adress-Stamm heraus soll durch Aufruf eines Menüpunkts direkt ein Verkaufsbeleg zur Erfassung vorbereitet werden, ähnlich wie Sage es im Kundenstamm mit einer dortigen Funktion löst.
Das erste gefundene Debitorenkonto der Adresse soll direkt mit einem Belegkennzeichen in der Belegerfassung vorbelegt werden, z.B. "VVA" für eine Auftragsbestätigung (das Belegkennzeichen kann in den Parametern eines zusatzprogrammierten AddOns von den Administratoren des AddOns bei Bedarf angepasst werden).
Lösungsansatz Sage?
Sage selber verwendet dazu im Kundenstamm ein dynamisches Kontextmenü, welches mittels .net-Code "DynamicMenuBelegAnlegen.CreateMacroBelegAnlegen" (Assembly "Sagede.OfficeLine.Wawi.RealTimeData") zur Laufzeit generiert wird.
Für unseren vorliegenden Anwendungsfall konnte jedoch kein dynamisches Kontextmenü verwendet werden, sondern es war ein "normales" Makro erforderlich, da unter anderem Rückfragen für den Anwender erscheinen sollen, bevor ein neuer Beleg in der Belegerfassung vorbelegt.
D.h. nach dem Aufruf des Kontextmenü-Eintrages im "Hamburger"-Menü des Adress-Stamms sind weitere Benutzerinteraktionen zwingend notwendig.
Beispielsweise, soll eine explizite Rückfrage erscheinen, wenn für die erste gefundene Debitorennummer eine Liefersperre vorliegt usw.
Interaktionen mit Bildschirm-Meldungen/Message-Boxen sind innerhalb von .net-Code, der innerhalb des Sage Applikationsservers läuft, bekanntermaßen so nicht möglich.
Eine Analyse des Sage Quellcodes des dynamischen Kontextmenüs ergibt, dass Sage selber dort zur Laufzeit im .net-Code entsprechende AppDesigner-Makro-Anweisungen zusammenbaut.
Vermeintlich sehr einfach wird dort z.B. folgendes Makro zusammengebaut:
Dim myMacros As Sagede.Shared.RealTimeData.Common.Macros = New Sagede.Shared.RealTimeData.Common.Macros()
Dim myMacro As Sagede.Shared.RealTimeData.Common.Macro = New Sagede.Shared.RealTimeData.Common.Macro()
myMacro.Command = Enumerations.MacroCommand.OpenDataEditPart
Dim indexedMacroValue1 As IndexedValue = New IndexedValue()
indexedMacroValue1.Index = 1
If erfassungsTyp = Tools.Erfassungstyp.Einkauf Then
indexedMacroValue1.Value = "ediEKBelegerfassung.Sage.Wawi"
Else
indexedMacroValue1.Value = "ediVKBelegerfassung.Sage.Wawi"
End If
myMacro.Parameters.Add(indexedMacroValue1)
Dim indexedMacroValue2 As IndexedValue = New IndexedValue()
indexedMacroValue2.Index = 2
indexedMacroValue2.Value = ""
myMacro.Parameters.Add(indexedMacroValue2)
Dim indexedMacroValue3 As IndexedValue = New IndexedValue()
indexedMacroValue3.Index = 3
indexedMacroValue3.Value = "Action:=""OpenNewBeleg"";PrimaryKeyValue1:=""" & kundennummer & """;PrimaryKeyValue2:=""" & erfassungsTyp & """;SubAction:=""" & kennzeichen & """"
myMacro.Parameters.Add(indexedMacroValue3)
So könnte man nun meinen, dass ein solcher direkter Aufruf in einem "normalen" Makro kein großes Problem sein sollte:
Jedoch: weit gefehlt! 👎😕
Da beginnen die Probleme erst richtig...
Es zeigt sich, wieder einmal, dass Sage bei diversen Aktionsarten (siehe 3. Parameter) noch "unter der Haube" der Anwendung hart codiert "Umleitungen" über MS-Access-Eval-Funktionen implementiert.
D.h. es geht von neuer Technik über COM-Interop durch die MS-Access und -VBA-Instanzen der Anwendung, dann zurück zu neuer Technik 😒.
Auf diesem Transportweg finden Parsing-Fehler statt, die zu nachfolgendem Fehler in der Belegerfassung (genauer in der "BelegEngine"-Klasse) führen.
Lösungsoption 1 (nicht empfohlen)
Der erste mögliche Lösungsansatz besteht darin, ebenfalls aus dem "normalen" Makro heraus direkt VBA-Funktionen zu verwenden, z.B. wie folgt:
Davon raten wir jedoch dringend ab!
Da der Adress-Stamm an einen Datensatz gebunden ist, würde o.g. VBA-Aufruf bedingen, dass jede Menge interne Felder als Dummy-Felder im Adress-Stamm-Datensatz im AppDesigner hinzugefügt werden müssten.
Ohne diese Dummy-Felder würde der Aufruf der Belegerfassung mit der Vorbelegung des Debitors und des Belegkennzeichens zwar funktionieren.
Allerdings würde der sicherlich allseits bekannte "nervige" Makro-Fehler ausgelöst:
Somit müsste man alle nachfolgenden internen Dummy-Felder als Erweiterung ("Anhängen an") des AppDesigner-Datensatzes für den Adress-Stamm anlegen.
Diese benötigt Sage bei der o.g. Abarbeitung des VBA-Befehls zwingend, damit bei dem Aufruf der Belegerfassung keine Makro-Fehler erscheinen.
Dies alles ist ein zusätzlicher "Overhead" und beinhaltet vermutlich mögliche Folgefehler in zukünftigen Sage Versionen.
Notwendige interne Dummy-Felder:
(alle diese internen Felder müssen hinzugefügt werden, um Makro Fehler zu vermeiden - ein ziemlicher "Overhead" !)
Lösungsoption 2 (empfohlen)
Deutlich sinnvoller ist der nachfolgende Lösungsansatz.
Man verwendet statt der "Action" mit der ID "OpenNewBeleg", die zur o.g. "Umleitung" in VBA-Code führt, die "Action" mit der ID "CreateBelegkopf".
Makro Befehl 1:
DatenEditDialogÖffnenParameter 1:
ediVKBelegerfassung.Sage.WawiParameter 2:
(leer)
Parameter 3:
Action:="CreateBelegkopf";Konto:="D100005";Adresse:=0;Erfassungsart:=4000;Belegkennzeichen:="VVA"English
"Simple" goal?
A supposedly simple goal within the AppDesigner turns out to be a "time-consuming adventure" on closer inspection! 👎
A sales document should be prepared directly in the sales document edit form, by calling a menu item directly from the address master data edit form, similar to the Sage function in the debtor master data edit form.
The first found debtor account number of the address should be preassigned for a new document within the sales document edit form, together with a preassigned document type, e.g. "VVA" for order confirmation (a parameter for the document type is stored in the parameters of an additional programmed AddOn and it can be adjusted by the administrators of the AddOn if the need arises).
Sage approach as a solution?
Sage itself uses a dynamic context menu in the debtor master data edit form, which is generated at runtime using the .net code "DynamicMenuBelegAnlegen.CreateMacroBelegAnlegen" (assembly "Sagede.OfficeLine.Wawi.RealTimeData").
For our goal, however, a dynamic context menu could not be used, but a "normal" macro was required because, among other things, on-screen messages and -questions should appear for the user before a new document is preassigned in the sales document edit form.
This means that after calling up the context menu entry in the "hamburger" menu of the address master data edit form, further user interactions are absolutely necessary.
For example, an explicit question should appear to the user if there is an active delivery block for the first found debtor account, etc.
As it should be known, any interactions with on-screen messages/message boxes are usually not possible within .net code running within the Sage application server.
An analysis of the Sage source code of the dynamic context menu shows that Sage itself assembles the corresponding AppDesigner macro instructions in the .net code at runtime.
The following macro, for example, is supposedly very easy:
Dim myMacros As Sagede.Shared.RealTimeData.Common.Macros = New Sagede.Shared.RealTimeData.Common.Macros()
Dim myMacro As Sagede.Shared.RealTimeData.Common.Macro = New Sagede.Shared.RealTimeData.Common.Macro()
myMacro.Command = Enumerations.MacroCommand.OpenDataEditPart
Dim indexedMacroValue1 As IndexedValue = New IndexedValue()
indexedMacroValue1.Index = 1
If erfassungsTyp = Tools.Erfassungstyp.Einkauf Then
indexedMacroValue1.Value = "ediEKBelegerfassung.Sage.Wawi"
Else
indexedMacroValue1.Value = "ediVKBelegerfassung.Sage.Wawi"
End If
myMacro.Parameters.Add(indexedMacroValue1)
Dim indexedMacroValue2 As IndexedValue = New IndexedValue()
indexedMacroValue2.Index = 2
indexedMacroValue2.Value = ""
myMacro.Parameters.Add(indexedMacroValue2)
Dim indexedMacroValue3 As IndexedValue = New IndexedValue()
indexedMacroValue3.Index = 3
indexedMacroValue3.Value = "Action:=""OpenNewBeleg"";PrimaryKeyValue1:=""" & kundennummer & """;PrimaryKeyValue2:=""" & erfassungsTyp & """;SubAction:=""" & kennzeichen & """"
myMacro.Parameters.Add(indexedMacroValue3)
So you might think that such a direct call in a "normal" macro shouldn't be a big problem:
However: far from it! 👎😕
That's when the problems really begin...
It turns out once again that Sage implements hard-coded "redirects" via MS Access Eval functions "under the hood" of the application for various types of actions (see 3rd parameter).
That means the application starts from new technology, then calls via COM interop the application's MS Access and VBA instances, and then back to new technology 😒.
Parsing errors occur on this transport path, which leads to the following error in the sales document edit form (more precisely in the "BelegEngine" class).
Possible solution 1 (not recommended)
The first possible solution is to use VBA functions directly from the "normal" macro, e.g. as follows:
However, we strongly advise against this!
Since the address master data edit form is linked to an AppDesigner data record, the above VBA call would mean that a large number of internal fields would have to be added as dummy fields in the address master data record in the AppDesigner.
Without these dummy fields, calling up the sales document edit form with the pre-assignment of the debtor account and the document type indicator would still work.
However, the following probably well-known "annoying" macro error would be triggered:
Thus, one must create all subsequent internal dummy fields as an extension ("Anhängen an") of the AppDesigner data record for the address master data section.
As mentioned above, Sage needs this to process the VBA command so that no macro errors appear when the sales document edit form is opened.
Hence, this approach requires additional "overhead" and possibly includes potential problems in future versions of Sage.
Necessary internal dummy fields:
(all those internal fields need to be added to avoid any macro errors - a lot of "overhead"!)
Possible solution 2 (recommended)
The following solution makes much more sense.
Instead of the "Action" with the ID "OpenNewBeleg", which leads to the above-mentioned "redirection" in VBA code, the "Action" with the ID "CreateBelegkopf" is used.
Macro instruction 1:
DatenEditDialogÖffnenParameter 1:
ediVKBelegerfassung.Sage.WawiParameter 2:
(empty)
Parameter 3:
Action:="CreateBelegkopf";Konto:="D100005";Adresse:=0;Erfassungsart:=4000;Belegkennzeichen:="VVA"







