198 lines
14 KiB
Markdown
198 lines
14 KiB
Markdown
---
|
|
name: roa-vfp-frx-report
|
|
description: Creeaza, editeaza si verifica rapoarte VFP 9 (.frx/.frt) fara IDE - layout, benzi, grupare, totaluri, chenare, aliniere, orientare, preview PNG. Foloseste-l OBLIGATORIU cand utilizatorul cere un raport nou sau modificarea unuia existent ("fa un proces-verbal / o situatie / o lista tiparita", "modifica raportul X", "schimba layout-ul raportului", "adauga o coloana in raport", "pune total pe document", "trece-l pe portret", "raportul se rupe / nu se randeaza / iese invalid"), cand verifica un .frx nou, cand vrea preview sau PNG al unui raport, sau cand lucreaza cu .frx/.fr2 (creare, conversie, structura DBF, band-uri). Nu improviza structura: VPOS e absolut, banda unui obiect se calculeaza cu separatorul de 2083.333, la REPORTBEHAVIOR 90 obiectele din Group Header se randeaza doar cu SUPRPCOL=3 + SUPGROUP=nr.grup+5, iar totalurile pe grup se fac cu variabile de raport - procedura e mai jos.
|
|
---
|
|
|
|
# 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)
|
|
|
|
0. Alege un model `.frx` valid care se randeaza deja (ex. `Rapoarte\listmfcota.frx`); pleci de la
|
|
antetul/memo-ul lui, nu de la zero.
|
|
1. Creeaza fisierul: `COPY FILE <model>.frx TO <nou>.frx` si la fel `.frt`, apoi
|
|
`USE <nou>.frx EXCLUSIVE` + `ZAP`. `COPY STRUCTURE` NU merge (vezi Capcane).
|
|
2. Scrie benzile, in ordinea de sus in jos, cu un `addrec` implicit + suprascriere per tip:
|
|
`OBJTYPE=9` + `OBJCODE` (0 Title, 1 Page Header, 3 Group Header, 4 Detail, 5 Group Footer,
|
|
7 Page Footer) + `HEIGHT`. Retine `band_start` pentru fiecare banda (formula mai jos).
|
|
3. Scrie obiectele, fiecare in banda ei: `VPOS = band_start + offset`. Tipuri: `OBJTYPE=5` eticheta,
|
|
`8` camp/expresie, `6` linie, `7` dreptunghi (`OBJCODE=4`).
|
|
4. Verifica structura: `scripts/structura_frx.prg` (ruleaza `FFC\_FRXCursor.vcx`) si confirma ca
|
|
fiecare obiect are `BANDLABEL`-ul dorit si ca benzile au `START/STOP` asteptate.
|
|
5. Verifica validitatea: `scripts/frx_convert.ps1 -Path <nou>.frx` trebuie sa produca `.fr2`.
|
|
6. Randare + numaratoare (REPORTBEHAVIOR **80**): script headless cu cursor de test,
|
|
`REPORT FORM <raport> TO FILE <txt> ASCII NOCONSOLE`; verifica totalurile numeric.
|
|
7. 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)**: `VPOS` e absolut pe pagina, NU relativ la banda.
|
|
`band_START = suma(HEIGHT benzi anterioare) + 2083.333 * numar benzi anterioare` (verificat pe
|
|
`pvcasare_mf`: Detail = 0 + 8646 + 12729 + 3 * 2083.333 = 27625); fiecare
|
|
banda adauga un separator de 2083.333 FRU. Obiectul apartine primei benzi cu
|
|
`START <= VPOS <= STOP`. Pune `VPOS = band_START + offset` si 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 are `SUPRPCOL=3` + `SUPGROUP=6` (grupul 1; = nr. grup + 5), cum le
|
|
scrie Designer-ul. Cu `0/0` (obiecte generate programatic sau mutate din Page Header) nu apar
|
|
(pe `pvcasare_mf` lipseau pe primul PV). Alternativ: continut in Page Header, GH cu `HEIGHT=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 prin `HEIGHT`-ul Page Header si offseti.
|
|
- **Total / nr. crt. pe grup**: variabile de raport `OBJTYPE=18` (`EXPR` camp numeric, `TOTALTYPE=2`
|
|
Sum / `1` Count, `RESETTOTAL=6`, `TAG=0`), afisate in GF cu `transform(var, get_mask(14,gnpa))` si
|
|
`TOTALTYPE=0`. NU precalcul in cursor, NU `recno()` 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=1` **si `MODE=0`**
|
|
(la `MODE=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_mask` real da separator
|
|
SPATIU (`transform(3000,"99 999 999 999 999.99")` => `"3 000.00"`); `SET SEPARATOR` nu-l schimba.
|
|
`get_mask`, `_PAGENO`, `gnpa` sunt 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 portret `Rapoarte\listmf_inv.fr2`. Reaseaza HPOS/WIDTH pe latimea noua si verifica
|
|
`max(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)` (si `gofirma.cod_fiscal` etc.).
|
|
- **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 cu `VPOS` diferit (cap de coloana care nu incape in W).
|
|
- **Editarea unui raport existent**: generator `.prg` reutilizabil (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 avea `HEIGHT=0`).
|
|
- **Continutul benzii Group Header nu se randeaza** (la 90; tipic doar pe primul grup) -> obiectele
|
|
au `SUPRPCOL=0/SUPGROUP=0` -> pune `SUPRPCOL=3`, `SUPGROUP=6` pe 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 `VPOS` absolut, iar la 90 zona separatorului e taiata -> `VPOS = band_START + offset`
|
|
(Retete); verifica `BANDS.START/STOP` cu `structura_frx.prg`.
|
|
- **Totalul iese `****`** -> `TOTALTYPE=2` pe `transform(...)` (string) -> suma pe variabila de raport numerica,
|
|
`transform` doar in campul de afisare cu `TOTALTYPE=0` (`references/totaluri.md`).
|
|
- **Fatal error C0000005 la `REPORT FORM`** -> variabile de raport `OBJTYPE=18` construite 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 FILE` scrie binar** -> lipseste `ASCII` sau rulezi la 90 (listener) -> `ASCII NOCONSOLE` la
|
|
80 (`references/reportbehavior-80-90.md`).
|
|
- **Rulare headless agatata, log gol** -> `vfp9 -A <script.prg>` (deschide editorul), lipsa
|
|
`ON ERROR ... QUIT`, `OBJECT TYPE 1` (se blocheaza) sau un vfp9 strain inca viu -> ruleaza
|
|
intotdeauna prin `watchdog_vfp.ps1`; citeste intai PNG + dump text din `-OutDir`.
|
|
- **`Variable 'lcX' is not found` intr-o PROCEDURE** -> variabila declarata `LOCAL` in programul
|
|
apelant -> declara `PRIVATE` ce folosesc procedurile auxiliare (ex. `errhand`, log).
|
|
- **Eroarea 232 `'laFields' is not an array`** -> `LOCAL laFields` fara dimensiune ->
|
|
`LOCAL ARRAY laFields[1,1]`.
|
|
- **`Alias 'GOFIRMA' is not found` / pagina alba in preview** -> raportul foloseste `goFirma`/`gnpa`/
|
|
`get_mask` -> defineste-le in scriptul de test (`PUBLIC goFirma` + `Antet`, `gnpa`,
|
|
`FUNCTION get_mask` cu masca reala).
|
|
- **`File 'zoom 100.prg' does not exist`** -> `_REPORTPREVIEW = "ZOOM 100"` nu e zoom -> scoate linia
|
|
(`references/preview-png.md`).
|
|
- **Diacritice corupte** -> `.prg` cu diacritice scris cu Edit/Write -> construieste textele cu
|
|
`CHR()` in `.prg` ASCII, sau declara `RESOID=238` pe obiect.
|
|
- **Linia dintre randuri ramane sus cand Denumirea trece pe 2+ randuri** -> linia orizontala din
|
|
Detail nu e `FLOAT` (sau a mostenit `STRETCH=.T.` copiata dintr-o verticala) -> `FLOAT=.T.`,
|
|
`STRETCH=.F.`, `TOP=.F.`; campul de text lung cu `STRETCH=.T.`.
|
|
- **Linie groasa/dubla sub ultimul rand** -> linie de detaliu + linie la inceputul GF -> sterge-o pe
|
|
cea din GF.
|
|
- **`r.fr2.bak` langa raport** -> il lasa FoxBin2Prg cand `.fr2` exista 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.**
|
|
|
|
1. **Valid**: `frx_convert.ps1 -Path <raport>.frx` produce `.fr2` fara eroare.
|
|
2. **Structura**: `structura_frx.prg` arata fiecare obiect in banda dorita (`BANDLABEL`) si benzile
|
|
cu `START/STOP/HEIGHT` asteptate.
|
|
3. **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).
|
|
4. **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.
|
|
5. **Curatenie**: niciun `vfp9` pornit de tine ramas viu.
|
|
|
|
## Scripturi
|
|
|
|
- `scripts/frx_convert.ps1` - `.frx` <-> `.fr2` cu FoxBin2Prg (`-Path <fisier>`; directia din
|
|
extensie).
|
|
- `scripts/structura_frx.prg` - dump benzi + obiecte (VPOS -> banda) prin `FFC\_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 face `SET 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 `.prg` vs 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 vezi `references/`).
|