14 KiB
Rapoarte VFP (.frx/.frt): creare, editare, verificare fara IDE
Un .frx e un DBF cu 75 de campuri fixe + memo-ul .frt. Se lanseaza cu
goExport.export2frx(cursor, "nume"); getRepPath (oexport.prg) cauta nume.frx in SET PATH
(Rapoarte\) sau in USERREPORTS\<schema>\USR_nume.frx. Cursorul selectat inainte de
REPORT FORM e sursa expresiilor.
Aplicatia randeaza cu REPORTBEHAVIOR 90 (COMUN\programe\oexport.prg:1733-1738); verificarea
finala se face la 90, nu la 80. La 90 obiectele din Group Header cu SUPRPCOL=0/SUPGROUP=0 nu se randeaza (pe primul grup) si
obiectele din zona separatorului sunt taiate; la 80 se randeaza. Detalii:
references/reportbehavior-80-90.md.
Cand se foloseste
- "fa un proces-verbal / o situatie / o lista tiparita", raport nou de la zero sau pornit din model.
- "modifica raportul X" (layout, coloane, totaluri, antet, subsol), "schimba alinierea", "trece-l pe portret".
- "raportul iese invalid", "nu se randeaza", "continutul nu apare", "se rupe pe pagini", "campul iese trunchiat".
- verificare: "e valid raportul?", preview/PNG, numaratoare de pagini, totaluri.
- orice atingere de
.frx/.frt/.fr2(conversie, structura, editare fara IDE).
Nu pentru rapoarte generate de alt motor (.lbx etichete, Excel) si nu pentru goExport in sine.
Pasi (secventa cea mai scurta care a mers)
- Alege un model
.frxvalid care se randeaza deja (ex.Rapoarte\listmfcota.frx); pleci de la antetul/memo-ul lui, nu de la zero. - Creeaza fisierul:
COPY FILE <model>.frx TO <nou>.frxsi la fel.frt, apoiUSE <nou>.frx EXCLUSIVE+ZAP.COPY STRUCTURENU merge (vezi Capcane). - Scrie benzile, in ordinea de sus in jos, cu un
addrecimplicit + suprascriere per tip:OBJTYPE=9+OBJCODE(0 Title, 1 Page Header, 3 Group Header, 4 Detail, 5 Group Footer, 7 Page Footer) +HEIGHT. Retineband_startpentru fiecare banda (formula mai jos). - Scrie obiectele, fiecare in banda ei:
VPOS = band_start + offset. Tipuri:OBJTYPE=5eticheta,8camp/expresie,6linie,7dreptunghi (OBJCODE=4). - Verifica structura:
scripts/structura_frx.prg(ruleazaFFC\_FRXCursor.vcx) si confirma ca fiecare obiect areBANDLABEL-ul dorit si ca benzile auSTART/STOPasteptate. - Verifica validitatea:
scripts/frx_convert.ps1 -Path <nou>.frxtrebuie sa produca.fr2. - Randare + numaratoare (REPORTBEHAVIOR 80): script headless cu cursor de test,
REPORT FORM <raport> TO FILE <txt> ASCII NOCONSOLE; verifica totalurile numeric. - Aspect + verificare finala (REPORTBEHAVIOR 90):
scripts/randare_preview.ps1(PNG) si citeste PNG-ul inainte de "gata" (references/preview-png.md).
Retete
- Stilul casei (OBLIGATORIU la orice raport nou/modificat): fonturi, grupare, ordonare, linii
intre randuri cu
FLOAT, cap de tabel pe un rand, total, comisie ->references/stil-rapoarte.md. - Banda unui obiect (regula centrala):
VPOSe absolut pe pagina, NU relativ la banda.band_START = suma(HEIGHT benzi anterioare) + 2083.333 * numar benzi anterioare(verificat pepvcasare_mf: Detail = 0 + 8646 + 12729 + 3 * 2083.333 = 27625); fiecare banda adauga un separator de 2083.333 FRU. Obiectul apartine primei benzi cuSTART <= VPOS <= STOP. PuneVPOS = band_START + offsetsi obiectul cade in banda corecta. - Grupare cu pagina noua per grup: banda
OBJCODE=3,EXPR= expresia de grupare,HEIGHT=0,PAGEBREAK=.T.. Continutul per grup (antet, cap de tabel, texte) poate sta in Group Header daca FIECARE obiect din GH areSUPRPCOL=3+SUPGROUP=6(grupul 1; = nr. grup + 5), cum le scrie Designer-ul. Cu0/0(obiecte generate programatic sau mutate din Page Header) nu apar (pepvcasare_mflipseau pe primul PV). Alternativ: continut in Page Header, GH cuHEIGHT=0. - Plafon cap de tabel -> detaliu: cu continut in Page Header si o banda Group Header goala
intre, spatiul minim dintre capul de tabel si primul rand de detaliu este
2 * 2083.333 = 4166.667 FRU. Nu se elimina complet fara scoaterea benzii GH (necesara pentru grupare + page break per document); minimizeaza-l prinHEIGHT-ul Page Header si offseti. - Total / nr. crt. pe grup: variabile de raport
OBJTYPE=18(EXPRcamp numeric,TOTALTYPE=2Sum /1Count,RESETTOTAL=6,TAG=0), afisate in GF cutransform(var, get_mask(14,gnpa))siTOTALTYPE=0. NU precalcul in cursor, NUrecno()pentru nr. crt., NU nume de variabila egal cu un camp din cursor. Programatic doar copiind o variabila facuta in IDE (SCATTER/GATHER MEMO). Detalii:references/totaluri.md. - Fundal gri pe cap de tabel:
FILLRED/GREEN/BLUE=200+FILLPAT=1siMODE=0(laMODE=1, transparent, fundalul nu se deseneaza).RECT-ul gri se opreste la marginea tabelului, nu dincolo de linia verticala. Linie sub cap:OBJTYPE=6,PENPAT=8. - Linii/chenare:
OBJTYPE=6(PENPAT=8,PENSIZE=1); chenar =OBJTYPE=7,OBJCODE=4. - Aliniere: la etichete (
OBJTYPE=5)PICTURE=""stanga,"@I"centrat,"@J"dreapta; la campuri (OBJTYPE=8)OFFSET= 0 stanga, 1 dreapta, 2 centrat. Text la stanga, numere la dreapta. - Masca numerica:
EXPR = transform(camp, get_mask(14, gnpa)).get_maskreal da separator SPATIU (transform(3000,"99 999 999 999 999.99")=>"3 000.00");SET SEPARATORnu-l schimba.get_mask,_PAGENO,gnpasunt disponibile la randare; in harness trebuie definite cu masca reala (stub cu virgula => preview mincinos). - Orientare portret/landscape: in memo-ul inregistrarii REPORT,
ORIENTATION(0=portret, 1=landscape),PAPERSIZE=9,COLOR=2. Latime utila ~74000 FRU portret, ~80000 landscape; referinta portretRapoarte\listmf_inv.fr2. Reaseaza HPOS/WIDTH pe latimea noua si verificamax(HPOS+WIDTH) <= latimea paginii. Trunchierea de camp tine de W vs FONT, nu de valoare. Detalii:references/orientare-si-latimi.md. - Antet firma:
EXPR = alltrim(goFirma.Antet)(sigofirma.cod_fiscaletc.). - Standard de layout cerut: texte fixe fara diacritice (ASCII simplu) si sentence case
(doar prima litera mare); datele din baza raman cum vin. Daca totusi trebuie diacritice:
RESOID=238+DOUBLE=.T.(Central European) pe fiecare obiect text/camp. - Text pe mai multe linii: VFP 9 nu face word-wrap la etichete; pune
CHR(13)explicit in text sau rupe pe mai multe obiecte cuVPOSdiferit (cap de coloana care nu incape in W). - Editarea unui raport existent: generator
.prgreutilizabil (reasezare) SAU editare.fr2+frx_convert(modificari mici) - o singura sursa de adevar, nu ambele. Detalii:references/editare-iterativa.md.
Capcane (simptom -> cauza -> remediu)
- "Report file ... is invalid" dupa creare ->
COPY STRUCTURE(lipseste formatul de raport) ->COPY FILE <model>.frx+ZAP(punctul 1); modelul trebuie sa aiba toate benzile. - "Report file ... is invalid" la un raport altfel corect -> lipseste banda Page Footer
(
OBJCODE=7) -> adaug-o (poate aveaHEIGHT=0). - Continutul benzii Group Header nu se randeaza (la 90; tipic doar pe primul grup) -> obiectele
au
SUPRPCOL=0/SUPGROUP=0-> puneSUPRPCOL=3,SUPGROUP=6pe fiecare obiect din GH (sau in IDE: Print When, ca obiectele care se vad). - Obiectul apare in alta banda / dispare la 90 / page break in loc gresit -> obiectele se
asociaza dupa
VPOSabsolut, iar la 90 zona separatorului e taiata ->VPOS = band_START + offset(Retete); verificaBANDS.START/STOPcustructura_frx.prg. - Totalul iese
****->TOTALTYPE=2petransform(...)(string) -> suma pe variabila de raport numerica,transformdoar in campul de afisare cuTOTALTYPE=0(references/totaluri.md). - Fatal error C0000005 la
REPORT FORM-> variabile de raportOBJTYPE=18construite de mana (APPEND BLANK+REPLACE) -> copiaza o variabila facuta in IDE (SCATTER/GATHER MEMO). Nu repeta instructiunea: izoleaz-o intr-un script minim si schimba abordarea. - Camp trunchiat cu "..." -> W prea mic pentru fontul campului (nu pentru valoare) -> mareste
coloana / aliniaza W-ul la detaliu (
references/orientare-si-latimi.md). - Cap de coloana care iese peste linia verticala / "fundal gri dincolo de linie" -> labelul nu incape in W-ul coloanei si nu se taie la margine -> rupe-l pe 2-3 randuri care incap.
- Fundalul nu se vede ->
MODE=1(transparent) ->MODE=0. TO FILEscrie binar -> lipsesteASCIIsau rulezi la 90 (listener) ->ASCII NOCONSOLEla 80 (references/reportbehavior-80-90.md).- Rulare headless agatata, log gol ->
vfp9 -A <script.prg>(deschide editorul), lipsaON ERROR ... QUIT,OBJECT TYPE 1(se blocheaza) sau un vfp9 strain inca viu -> ruleaza intotdeauna prinwatchdog_vfp.ps1; citeste intai PNG + dump text din-OutDir. Variable 'lcX' is not foundintr-o PROCEDURE -> variabila declarataLOCALin programul apelant -> declaraPRIVATEce folosesc procedurile auxiliare (ex.errhand, log).- Eroarea 232
'laFields' is not an array->LOCAL laFieldsfara dimensiune ->LOCAL ARRAY laFields[1,1]. Alias 'GOFIRMA' is not found/ pagina alba in preview -> raportul folosestegoFirma/gnpa/get_mask-> defineste-le in scriptul de test (PUBLIC goFirma+Antet,gnpa,FUNCTION get_maskcu masca reala).File 'zoom 100.prg' does not exist->_REPORTPREVIEW = "ZOOM 100"nu e zoom -> scoate linia (references/preview-png.md).- Diacritice corupte ->
.prgcu diacritice scris cu Edit/Write -> construieste textele cuCHR()in.prgASCII, sau declaraRESOID=238pe obiect. - Linia dintre randuri ramane sus cand Denumirea trece pe 2+ randuri -> linia orizontala din
Detail nu e
FLOAT(sau a mostenitSTRETCH=.T.copiata dintr-o verticala) ->FLOAT=.T.,STRETCH=.F.,TOP=.F.; campul de text lung cuSTRETCH=.T.. - Linie groasa/dubla sub ultimul rand -> linie de detaliu + linie la inceputul GF -> sterge-o pe cea din GF.
r.fr2.baklanga raport -> il lasa FoxBin2Prg cand.fr2exista deja -> sterge-l (nu e livrabil).
Criterii de acceptare si dovada (GATA)
Fara dovezile de mai jos, raportul NU se raporteaza ca terminat. Build fara eroare NU e GATA.
- Valid:
frx_convert.ps1 -Path <raport>.frxproduce.fr2fara eroare. - Structura:
structura_frx.prgarata fiecare obiect in banda dorita (BANDLABEL) si benzile cuSTART/STOP/HEIGHTasteptate. - Randare + numaratoare (REPORTBEHAVIOR 80): script headless cu cursor de test (2 documente x
2 randuri),
REPORT FORM <raport> TO FILE <txt> ASCII NOCONSOLE; in<txt>: numarul de pagini (o aparitie a titlului per document), randurile si totalurile numerice egale cu suma manuala (ex. doc 1001 -> 4200/3400, doc 2002 -> 5800/4600). - Aspect (REPORTBEHAVIOR 90):
randare_preview.ps1-> PNG cu pagina intreaga; pentru FIECARE cerinta de layout, dovada vizuala pe PNG. Verifica explicit:- trunchiere de camp ("..." / "***") si capete de coloana care ies din tabel;
- fundalul gri peste marginea tabelului / dincolo de linia verticala;
- totalurile numerice (masca, coloane, sume) si alinierea (text stanga / numere dreapta);
max(HPOS+WIDTH) <= latimea paginii(portret ~74000, landscape ~80000). Nu confunda clipul grilei ASCII (80 car./linie) sau un cap de coloana iesit din coloana cu depasirea paginii.
- Curatenie: niciun
vfp9pornit de tine ramas viu.
Scripturi
scripts/frx_convert.ps1-.frx<->.fr2cu FoxBin2Prg (-Path <fisier>; directia din extensie).scripts/structura_frx.prg- dump benzi + obiecte (VPOS -> banda) prinFFC\_FRXCursor.vcx; headless:vfp9 -A "<...>\structura_frx.FXP" "<raport>.frx" ["<iesire>.txt"](se termina cu QUIT).scripts/randare_preview.ps1- PNG cu pagina din PREVIEW (-Fxp <script.FXP> -Png <png> [-TitleMatch <nume>]); captureaza fereastra "Report Preview", nu "Report Designer"/Command Window; scriptul VFP dat faceSET REPORTBEHAVIOR 90+REPORT FORM ... PREVIEW NOWAIT+INKEY.- Existent:
COMUN\utile\Teste\_precompile.ps1(precompilare izolata),COMUN\utile\Teste\watchdog_vfp.ps1(rulare cu watchdog),D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE. - Scriptul de test/preview se scrie dupa modelul:
SET SAFETY OFF/ cursor de test /gnpa,goFirma,get_mask(masca reala, cu spatiu) /REPORT FORM/QUIT.
Buget de context
Lucreaza raportul in story-uri mici (o cerinta de layout per rulare), nu intr-o singura sesiune lunga; la finalul fiecarui bloc scrie handoff-ul pe disc cu o sectiune "Pentru skill" (simptom -> cauza -> remediu, doar ce s-a verificat). Rapoartele reale se itereaza pe mai multe runde; fara handoff, runda urmatoare reia investigatia.
Referinta (doar la nevoie)
references/reportbehavior-80-90.md- diferentele 80 vs 90, ce dovada la ce behavior.references/totaluri.md- totaluri pe grup cu variabile de raport (reteta + capcane),get_mask.references/orientare-si-latimi.md- portret/landscape, latimi, trunchiere de font, cap de coloana, subsol.references/preview-png.md- captura ferestrei "Report Preview", runner, watchdog, zoom.references/editare-iterativa.md- generator.prgvs editare.fr2, sursa unica de adevar.references/stil-rapoarte.md- stilul aprobat (fonturi, grupare, ordonare, linii, total, comisie).COMUN\docs\creare-editare-rapoarte-frx.md- tabelul complet de campuri DBF si structura_FRXCursor(istoric; pentru comportamentul 90 vezireferences/).