15. Apr. 2011

for english readers

Unterformulare drucken in der V12

Die Druck-Architektur der V12 soll endlich Schluß machen mit dem Print form-Gedöns und der Beschränkung auf horizontale Schnitte, mehr drucken wie das Verteilen von Lego-Steinen auf einer Platte. Mit Print object können die zu druckenden Objekte überall auf der Seite platziert werden. Und wurde das Objekt bereits an der richtigen Stelle im Formular angelegt, kann ich es mir sparen Koordinaten an den Befehl Print object weiterzureichen. Klasse! Endlich, Supercallifragalisticespiyaladocious, da hat sich doch die Entwickler-Konferenz wieder gelohnt.

formularSubForms

Das ist meine Ausgangslage:

Ein Hauptformular und darin zwei Unterformulare. Das obere der Briefkopf und das untere die Fußzeile.

Das Drucken erledigt diese Methode:

methodStruct

Gedruckt wird nur das blaue Main Form, denn nur diese beiden Zeilen funktionieren:
OPEN PRINTING FORM("Main_Form")
$erfolg_b:=Print object(*;"@")

Subforms werden nicht gedruckt! Im Handbuch steht zwar, nur Hierarchische Listen und WebAreas können nicht Print object gedruckt werden. Doch das Handbuch wird jetzt ergänzt um und keine Subforms.

Kaum zu glauben! Nee, wirklich nicht. So ein schönes Feature, so eine große Hilfe, gibt sogar zwei Technotes 10-14_4Dv12_Print_Objects und Dynamic_Object_Printing, die mir sofort einfallen*, und niemand bemerkte, daß die wichtigste Funktionalität nämlich Subforms zu drucken nicht implementiert ist.

notwhatIexpected

#@&%§@# … -::- … uno momento prego.

Mit OPEN PRINTING FORM("FormName") wird der On Load-Event getriggered. Klar, so geht das! Ein
$erfolg_b:=Print object(*;"@")
in der Subform-Methode und alle Subform-Objekte werden gedruckt.

Gedruckt werden sie schon, nur an falscher Stelle. 4D verwendet die Koordinaten im Unterformular und nicht die unter Berücksichtigung der Lage des Unterformulares im Hauptformular.

Och nee, nicht noch so'n Klopper.

Ich stelle es mir einfach vor, das zu lösen. Alle Koordinaten über eine Matrix berechnen und voila, werden die Objekte dort gedruckt wo sie durch die Subform platziert wurden. Das ist doch nicht so schwer, nur tägliche Praxis.

Stimmt, eigentlich einfach. Wenn's einfach ist, kann ich es auch mit 4D-Mitteln lösen und brauche auf niemanden zu warten, schon gar nicht bis der Groschen fällt.

So geht das jetzt:
// das Masterformular aktivieren
OPEN PRINTING FORM("Zeugnis_Master")
// die Koordinaten der Subform in upperLeft_L und upperTop_L merken
OBJECT GET COORDINATES(*;$printSF_Footer;upperLeft_L;upperTop_L;$r_L;$b_L)
// das Subformular aktivieren
OPEN PRINTING FORM("Zeugnis_Footer")

hodn

und in der Formmethode des Subformulars die Transformation vornehmen:

:($what="Service_PrintAll")
ARRAY TEXT($t_Objects;0)
ARRAY POINTER($t_P_vars;0)
FORM GET OBJECTS($t_Objects;$t_P_vars)
$N:=Size of array($t_Objects)
For ($i;1;$N)
// für alle Objekte die neuen Koordinaten errechnen
  OBJECT GET COORDINATES(*; $t_Objects{$i}; $l_L; $t_L; $r_L; $b_L)
  OBJECT MOVE(*;$t_Objects{$i}; upperLeft_L+$l_L; upperTop_L+$t_L; upperLeft_L+$r_L; upperTop_L+$b_L;*)
// und dann dort drucken
$erfolg_b:=Print object(*;$t_Objects{$i})
oder die Koordinaten direkt an den Print object-Befehl durchreichen, dann brauche ich links und oben und die Breite und die Höhe.

Nun reicht es diese drei Befehl abzusetzen und in der Formularmethode des Unterformulars Zeugnis_Printer ("Service_PrintAll")
aufzurufen. Dann sind die Objekte dort wo sie durch die Lage der Subform im Hauptformular liegen sollen.

Jetzt sitzt der Kopf oben, der Fuß unten und ich gestalte komplexe Druck-Formulare im Formular-Editor und genieße den Komfort der Subforms.

Warum nicht gleich so?

* keine Ahnung warum in zwei TechNotes das gleiche erzählt wird

lieber auf deutsch

Printing Subforms in V12

The new printing-features of V12 should finally make the Print form-annoyances obsolete, not cutting horizontally only any more, printing like placing Lego-bricks on platforms. Using Print object, objects to be printed can be placed anywhere on the form. Is the object already perfectly positioned, then the coordinates can be omitted from Print object. Super! Finally, Supercallifragalisticespiyaladocious, a reason to attend developers conference.

formularSubForms

That's my situation:

A main form and two subforms. The top one for the letterhead and a footer of course in the lowest part. Printing is done by these lines:

methodStruct

But there is something wrong. Only the blue text Main Form is printed, only these two lines actually work:
OPEN PRINTING FORM("Main_Form")
$erfolg_b:=Print object(*;"@")

Subforms can't be printed! The manual says, only Hierarchical Lists and WebAreas can't be printed by Print object. The manual will get enhanced with and no Subforms.

Hard to believe? Such a nice feature, such a splendid help, there are even two Technotes 10-14_4Dv12_Print_Objects and Dynamic_Object_Printing, I've seen*, and nobody realized, that an important, most important functionality of printing subforms, isn't implemented.

notwhatIexpected

#@&%§@# … -::- … uno momento prego.

Executing OPEN PRINTING FORM ("FormName") triggers an On Load-event in the subform. Sure, that's it! That subform-method line
$erfolg_b:=Print object(*;"@")
prints all subform-objects.

Sure, they get printed, but on the wrong spot. 4D uses the coordinates inside the subform without taking into account the subform-position on the main form.

Ohh no, not again!

That ought to be solvable. Calculating with matrices should make things working anywhere. It's not that difficult, or is it?

If it's not difficult, I can solve it myself with the tools of 4D. No need to wait for anybody or till the penny has dropped.

This is how it works:
// activate the mainform
OPEN PRINTING FORM("Zeugnis_Master")
// get the subform-coordinates and store upperLeft_L and upperTop_L
OBJECT GET COORDINATES(*; $printSF_Footer; upperLeft_L; upperTop_L; $r_L; $b_L)
// activate the subform
OPEN PRINTING FORM("Zeugnis_Footer")

hodn

then calculate the transformation as part of the subform On Load-event:

:($what="Service_PrintAll")
ARRAY TEXT($t_Objects;0)
ARRAY POINTER($t_P_vars;0)
FORM GET OBJECTS($t_Objects;$t_P_vars)
$N:=Size of array($t_Objects)
For ($i;1;$N)
// calculate the new coordinates for all objects
  OBJECT GET COORDINATES(*; $t_Objects{$i}; $l_L; $t_L; $r_L; $b_L)
  OBJECT MOVE(*;$t_Objects{$i}; upperLeft_L+$l_L; upperTop_L+$t_L; upperLeft_L+$r_L; upperTop_L+$b_L;*)
// and now print at the new spot
$erfolg_b:=Print object(*;$t_Objects{$i})
I could even calculate width and height and use
$erfolg_b:=Print object(*;$t_Objects{$i}; upperLeft_L; upperTop_L; width; height)

Things getting easy with these three lines and the subform formmethod will call Zeugnis_Printer ("Service_PrintAll"). Now all objects will be printed where I thought they would be printed while still misinterpreting the DevCon-talkings.

Now header is on top, footer at the end of the page and myself is drawing complex printing-forms the easy way.

* no idea why there are two TechNotes telling the same thing twice