5.6 KiB
Rapoarte VFP (.frx/.frt): citire, creare, verificare
Un .frx este un DBF cu 75 de campuri fixe (identice la toate rapoartele) + memo-ul .frt.
goExport.export2frx(cursor, "nume", ...) il lanseaza; getRepPath (oexport.prg) cauta
nume.frx in SET PATH (Rapoarte\) sau in USERREPORTS\<schema>\USR_nume.frx. Cursorul
selectat inainte de Report Form este sursa expresiilor din raport.
Campuri cheie
OBJTYPE: 1=raport (OBJCODE=53), 9=banda, 5=eticheta, 8=expresie/camp, 6=linie, 7=dreptunghi (OBJCODE=4), 18=variabila de raport, 25=dataenvironment.OBJCODEpeOBJTYPE=9: 0=Title, 1=Page Header, 2=Column Header, 3=Group Header, 4=Detail, 5=Group Footer, 6=Column Footer, 7=Page Footer, 8=Summary.EXPR: textul (intre ghilimele) la etichete, expresia la campuri, expresia de grupare la banda OBJCODE=3.PAGEBREAK=".T."pe OBJCODE=3 => pagina noua per grup.FONTFACE/FONTSIZE/FONTSTYLE(1=bold); obiectele auMODE=1.- Aliniere: la etichete (OBJTYPE=5)
PICTURE=""stanga,"@I"centrat,"@J"dreapta; la campuri (OBJTYPE=8)OFFSET= 0 stanga, 1 dreapta, 2 centrat. - Numere:
EXPR = transform(camp, get_mask(14, gnpa))(ca rapoartele existente)._PAGENO,goFirma.Antet,get_masksunt disponibile la randare.
Asocierea obiect -> banda (capcana centrala)
VFP NU asociaza obiectele dupa ordinea inregistrarilor si NU foloseste VPOS relativ la banda.
VPOS este absolut pe pagina, iar banda fiecarui obiect se determina cu intervalele
calculate de FFC\_FRXCursor.vcx: fiecarei benzi i se adauga un separator de 2083.333 FRU:
band_START = suma(inaltimilor benzilor precedente) + 2083.333 * (numarul de benzi precedente + 1)
band_STOP = band_START + HEIGHT
Obiectul apartine primei benzi cu band_START <= VPOS <= band_STOP si se deseneaza la VPOS
absolut. Deci, ca sa pui un obiect intr-o banda, calculeaza VPOS = band_START + offset (vezi
exemplu mai jos). Verificarea exacta: ruleaza _FRXCursor si citeste BANDS.START/STOP +
OBJECTS.BANDLABEL (vezi scriptul de mai jos).
Capcana: continutul benzii Group Header nu se randeaza (nici cu PAGEBREAK pe ea, nici fara;
obiectele sunt asociate corect dar nu apar). Solutia care merge: pune continutul per-grup
(antet, tabel document, texte, cap de tabel) in Page Header, cu VPOS in intervalul benzii
Page Header, si lasa banda Group Header goala (HEIGHT=0) doar cu PAGEBREAK=.T. ca sa
declanseze pagina noua per grup. Campurile de grup (nrdoc etc.) se evalueaza corect in Page
Header, pentru ca pagina noua incepe cu primul rand al grupului.
Crearea unui raport nou programatic (fara IDE)
COPY STRUCTURE NU e suficient: produce un .frx pe care motorul il raporteaza "is invalid"
(lipseste formatul de raport). Corect:
COPY FILE <model>.frx TO <nou>.frxsiCOPY FILE <model>.frt TO <nou>.frt(pastreaza antetul/memo-ul exact).USE <nou>.frx EXCLUSIVEapoiZAP.APPEND BLANK+REPLACEcampurile, per obiect (incepe cu unFUNCTION addreccu valorile implicite, suprascrie per tip).- Benzile:
HEIGHTsiOBJCODE; Title/PageFooter pot avea HEIGHT=0.
Exemplu de calcul VPOS pentru benzi Title(0), PageHeader(24000), GroupHeader(0), Detail(1800),
GroupFooter(15000), PageFooter(0): PH_START=2083.333, GH_START=28166.666,
DETAIL_START=30250, GF_START=34133.333. Obiectele din Page Header: VPOS=2083.333+offset.
Rulare headless (obligatoriu .FXP)
vfp9.exe -A "<script.prg>" deschide des editorul si nu scrie log (proces viu, log gol).
Corect: precompileaza intai (COMUN\utile\Teste\_precompile.ps1 -Prg <script.prg>), apoi
vfp9.exe -A "<script.FXP>" (fara -T). Prima linie: SET SAFETY OFF. Pune
ON ERROR DO ... WITH ERROR(), MESSAGE(), PROGRAM(), LINENO() care scrie in log si QUIT,
altfel orice eroare deschide un dialog nativ si blocheaza pana la timeout.
Verificarea ca raportul e valid si arata corect
- Validitate:
FoxBin2Prg.EXE "<raport>.frx" "" "" "" 1 0 1trebuie sa produca.fr2. - Continut:
SELECT <cursor>+REPORT FORM <raport> TO FILE <txt> ASCII NOCONSOLEsi cauta in<txt>antetul, coloanele, totalurile (TO FILEfaraASCIIscrie binar). - Aspect:
REPORT FORM <raport> PREVIEW NOWAIT, apoi muta fereastra copil "Print Preview" (MoveWindow) ca sa nu acopere pagina si fa screenshot pe fereastra copil cu titlul raportului (PrintWindow). Fara mutarea barei, jumatatea de sus a paginii e mascata de umbra ei.
Capcane
COPY STRUCTUREda un.frxinvalid; folosesteCOPY FILE+ZAP(punctul de mai sus).- Continutul benzii Group Header nu se randeaza; muta-l in Page Header (punctul de mai sus).
LOCAL laFields+AFIELDS(laFields, ...)da eroarea 232 "not an array"; declaraLOCAL ARRAY laFields[1,1].- Fara
ON ERROR ... QUIT, o eroare intr-un script headless deschide un dialog nativ si pare "agatat" (proces viu, CPU ~0, log gol). vfp9.exe -A "<script>"pe.prg(nu.FXP) deschide editorul; ruleaza.FXP.- Diacriticele se scriu ca octeti cp1250 (in
.prgle construiesti cuCHR()), nu cu Edit/Write. Setul de caractere se declara pe fiecare obiect text/camp prinDOUBLE=.T.+RESOID=238(Central European); pentru rapoarte fara diacritice,RESOID=0si texte ASCII. - Fundal pe un cap de tabel:
FILLRED/GREEN/BLUE+FILLPAT=1siMODE=0- laMODE=1(transparent) fundalul nu se deseneaza. - Cursorul referit de raport trebuie sa fie cel selectat la
Report Form; altfel expresiile dau "Variable not found". VFP 9nu face word-wrap la etichete: liniile lungi se taie la latime; puneCHR(13)explicit in textul etichetei (intre ghilimele) pentru linii multiple.