Limbajul de scripting hMET2

Limbajul de scripting hMET2 se folosește împreuna cu sistemul hMET în următoarele cazuri:
- Implementare de comenzi complexe în aplicații
Majoritatea aplicațiile HAMOR Soft suportă rularea unor comenzi complexe și generice definite la nivelul bazelor de date. Comenzile sunt menite să execute acțiuni complexe, compuse din mai multe operații și prezintă avantajul că pot fi definite la nivelul bazei de date. Comenzile generice asigură flexibilitatea aplicațiilor, permițând rezolvarea unor situații diverse, complexe și a cerințelor specifice la nivelul clienților, fără modificarea executabilului.
- Operații de întreținere a bazelor de date:
-modificare de structuri în baza de date,
-recalcul valori,
-prelucrarea mai multor baze de date,

Limbajul de scriping hMET2 are acces la resursele din biblioteca hLIB, recunoaște mediul hMET în care se rulează aplicația, astfel se pretează foarte bine la extinderea aplicațiilor sau la prelucrări de întreținere pentru bazele de date hMET. Cu toate aceste nu este un limbaj de programare, a fost proiectat pentru cazurile sus menționate, poate fi rulat în mediul hMET și nu se pretează pentru dezvoltarea unor aplicații sinestătătoare.

Rularea scripturilor hMET2 poate să se realizeze în mai multe feluri, în funcție de situația concretă.

Un exemplu simplu: programul Hello World

Instrucțiunile limbajului de scripting

Instrucțiunea #IF
Sintaxa:

#IF <Conditie>
        ...
        <Instructiuni>
        ...
[#ELSEIF] <Conditie>
        ...
        <Instructiuni>
        ...
[#ELSE]
        ...
        <Instructiuni>
        ...
[#ENDIF]

Pot exista un număr oarecare de clauze #ELSEIF.
Instrucțiunile pot fi imbricate. Nivelul de adâncime al imbricărilor nu este limitat.
Cuvintele cheie #IF, #ELSE, #ELSEIF, #ENDIF intotdeauna trebuie să fie scrise cu majuscule !

Instrucțiunea #WHILE
Sintaxa:

#WHILE <Conditie>
        ...
        <Instructiuni>
        ...
        [#LOOP]
        ...
        <Instructiuni>
        ...
        [#EXIT]
        ...
        <Instructiuni>
        ...
#ENDDO


Execută comenzile din ciclu până când <Conditie> returnează true.

#LOOP - întrerupe necondiționat executarea ciclului și face saltul la început, evaluează <Conditie> și dacă acesta returnează true, reia executarea ciclului, altfel continuă cu instrucțiunea imediat următoare ciclului.

#EXIT - întrerupe necondiționat executarea ciclului și face saltul la comanda imediat următoare ciclului.
Cuvintele cheie #WHILE, #LOOP, #EXIT, #ENDDO intotdeauna trebuie să fie scrise cu majuscule !
 

#DO <Fisier_program_sursa>
Valabil numai în scripturile scrise pentru utilitarul hMET2UP.
Întrerupe executarea programului și continuă cu instrucțiunile din fișierul <Fisier_program_sursa>.
La întâlnirea comenzii #RETURN sau a sfârșitului fisierului, revine în programul apelant și continuă executarea programului cu instrucțiunea imediat următoare de după #DO.

În cadrul unui subprogram apelat prin instructiunea #DO în continuare pot fi apelate si alte subprograme prin #DO.
Nu există limitări privind adâncimea apelurilor.

Variabilele folosite în programul principal rămân vizibile și în programele apelate prin #DO.
Având în vedere că nu există un mecanism special privind transmiterea parametrilor de la programul principal la programul apelat, transmiterea datelor se realizează prin variabile.
Important: Variabilele declarate în cadrul subprogramului nu se distrug la revenire ! Rămân vizibile în continuare.

<Fisier_program_sursa> este un fișier text obișnuit.
Trebuie sa conțină instrucțiuni HMET2UP, nu există nici o altă convenție privind structura fișierului.
Nu există nici o regulă în ceea ce privește numele fisierului.
În mod implicit extensia fișierului este "TXT", dar poate avea orice altă extensie.
În cadrul instrucțiunii #DO extensia fișierului nu trebuie specificată doar dacă este diferită de valoarea implicită "TXT".

Alte instrucțiuni utilizabile
Executarea instrucțiunilor din scripturile comenzilor generale se realizează în mod interpretativ. Instrucțiunile recunoscute sunt instrucțiuni CLIPPER V5, dar sintaxa acestora nu este cea cunoscută din acest limbaj.
În CLIPPER comenzile din fișierele sursă sunt preprocesate și traduse în apeluri de funcții. Aceste apeluri de funcții pot fi executate direct de limbajul de scripting.

De exemplu am dori să executăm comanda:
REPLACE FOR nomm->GRUPA="AMB" nomm->PVIN WITH 0

Comanda nu va fi "înțeleasă" în această formă.
Pentru ca această comandă să poată fi rulată, în locul instrucțiunii de mai sus se va trece:
DBEval( {|| nomm->PVIN := 0}, {|| nomm->GRUPA="AMB"},,,, .F. )

Aceste apeluri de funcții pot fi generate prin limbajul CLIPPER.
În acest scop se creează un fișier program CLIPPER (de exemplu TEST.PRG), în care se trece instrucțiunea dorită cu sintaxa folosită în CLIPPER. Se lansează compilatorul CLIPPER cu opțiunile P și S:

    CLIPPER TEST.PRG /P /S

Va rezulta un fișier cu extensia "PPO" (TEST.PPO în cazul nostru), care va conține instrucțiunea din TEST.PRG în forma preprocesată.

Limbajul de scripting suportă blocurile de cod cunoscute din limbajul CLIPPER.

O instrucțiune poate să se continue în linia urmatoare dacă se introduce ; în ultima poziție din linie.

În cadrul programelor liniile care încep cu caracterele // sunt considerate linii de comentarii.

Din programul scripting sunt accesibile fișierele din baza de date pentru care a fost lansat programul, direct prin funcțiile hLIB.

Astfel, de exemplu dacă se execută script-ul pentru o baza de date HSALAR, vom putea apela direct:
h_UseAlias("P_",x_open).

Variabile sistem
Scripturile hMET întodeauna sunt rulate în contextul hMET.
Acest lucru înseamnă că în momentul rulării sunt accesibile variabilele sistem existente în mediul HAMOR și cele specifice ale aplicației care rulează scriptul.

Pentru studierea variabilelor sistem existente in aplicațiile scrise în hMET, consultați documentația hLIB.
Variabilele accesibile în momentul rulării scripturilor pot fi specifice și aplicațiilor care rulează scriptul:
- aplicațiile scrise în hMET2 sunt caracterizate de un set suplimentar de variabile sistem,
- aplicația hMARFA nefiind un program scris în hMET2, este caracterizată de un set proprii de variabile sistem, inaccesibile din aplicații hMET2.

Variabile sistem:

h_ApplCode codul aplicației pentru care a fost lansat scriptul, hMET
Perioada perioada curentă hMET2
NumePerioada numele perioadei curente hMET2
fil_xxx indicele fișierului. Ex. fil_p_; fil_s_;
Corespunde cu numărul zonei de lucru în care va fi deschisă.
hMET
h_FilePath[] vector sistem. Conține calea de acces către fișiere.
Ex.Calea de acces către fișierul p_: h_FilePathes[fil_p_]
hMET
X_1,...,X_2 Variabile predefinite cu caracter general.
Pot primi orice valoare. Sunt variabile globale, astfel valorile atribuite vor exista pe durata unei sesiuni de lucru, pot transmite date de la o operație la alta, dar atenție valoarea unei astfel de variabile poate fi modificată între timp de o instrucțiune sau de un script !
hMET2

Funcții utile

Limbajul scripting hMET2UP acceptă apelarea funcțiilor definite în limbajul CLIPPER precum și a funcțiilor cele definite în mediul HAMOR. În acest sens parcurgeți documentațiile Clipper, bibliotec hLIB precum și funcțiile specifice ale aplicațiilor care rulează scripturile.

Funcții speciale

Sunt funcții special dezvoltate pentru scriptul hMET2UP.

NewMsg()
Creează o fereastră de monitorizare.
În continuare pe parcursul executării programului se pot afișa mesaje, care de obicei reprezintă etapele parcurse de program.

PutMsg(smsg)
Afișează mesajul smsg în fereastra de monitorizare.
Fereastra de mesaje trebuie să fie deja creată.

EndMsg()
Distruge fereastra de monitorizare creată.

De exemplu considerăm următorul script:
  NewMsg()
  PutMsg("Faza 1")
  h_Inkey(0)
  PutMsg("Faza 2")
  h_Inkey(0)
  PutMsg("Faza 3")
  h_Inkey(0)
  EndMsg()
După afișarea mesajului "Faza 3" vom avea următoarea fereastră:



h_GetParam(xParam,[sTitle],[sPrompt],[eHlp],[eVal],[sPict])
Afișează o fereastră de editare și așteaptă completarea unui câmp de către utilizator.
xParam - parametru de intrare/ieșire. La intrare: conținutul cîmpului ce urmează să fie completat de utilizator. La ieșire: valoarea introdusă de utilizator.
Parametrul xParam poate fi un șir de caractere, o dată calandaristică, sau o valoare logică
Înainte de apel parametrul poate fi inițializat. Dacă nu este inițializat, adică este fără valoare (NIL), primește valoarea implicită de SPACE(20).
Pentru ca valoarea introdusă de utilizator să fie returnată de funcție, parametrul se transmite cu operatorul @ în față.
sTitle - titlul ferestrei de editare ce se afișează.
sPrompt - șir de caractere ce se afișează înainte de câmpul de editare ce urmează să fie completat de utilizator.
eHlp - expresie de ajutor. Se execută când utilizatorul tastează F1.
Trebuie transmis sub formă de șir de caractere (încadrat între " sau ') !
eVal - formula de validare. Se execută automat la părăsirea câmpului. Dacă returnează true, câmpul este acceptat; dacă returnează false, câmpul nu este acceptat.
În cadrul expresiei de validare prin variabila sistem xParam avem acces la conținutul câmpului conpletat de utilizator.
Parametrul eVal trebuie transmis sub formă de șir de caractere (încadrat între " sau ') !
Exemplu:

    dData := DATE()
    #IF ! h_GetParam(@dData,;
            "Data de referinta",;
            "Data [zz/ll/aa]",;
            "h_Calendar()",;
            "h_ValDate(xParam)",;
            "99/99/99")
        Abandon("C")
    #ENDIF



Abandon([smode],[sretcode],[lEndMsg])
Termină necondiționat rularea programului și revine în meniul principal din HMET2UP.
Termină cu EndMsg() fereastra de mesaje deschisă cu NewMsg(), dacă lEndMsg nu este .F.

Dacă se transmite parametrul smode="C", închide toate fișierele de date deschise.

Al doila parametru sretcod, reprezintă codul de revenire din script. Există următoarele coduri:
-R - terminarea normală a scriptului și este valoarea implicită a parametrului.
Se consideră, că procedura implementată de script s-a terminat cu succes.
-A - abandonarea scriptului.
Procedura nu s-a putut executa corect.
De exemplu nu s-a reușit deschiderea unei fișier și nu se poate continua algoritmul.
-C - abandonat prin Cancel (intrerupt de utilizator).
Se afișează automat un mesajul: "Executie intrerupta"

Codul de revenire, are importanță la scripturile hMARFI.
În funcție de codul returnat de script, se reface automat jurnalul început.
Refacera jurnalului are loc pentru codurile "A" și "C".

lEndMsg- Abandon fara acest parametru pus pe .F. face EndMsg
                      NIL - executa EndMsg, inchide fereastra doar daca exista          
                      .T. - executa EndMsg, inchide fereastra doar daca exista          
                      .F. - nu executa EndMsg
         Exemplu: Aceasta este un apel tipic
         NewMsg()
         #IF h_FileEx
             Abandon()  - executa si EndMsg
         #ENDIF       
         In cazul Q_ANAF si Q_ANAFC, se executa Abandon, dar nu trebuie inchisa fereastar Msg
         se va apela in acestea Abandon(,,.F.)
         Functional de la hMARFA V8.E0.4, hMARFT V4.E0.4

Secvențe de program utile

Prezentăm câteva secvențe de program utile, frecvent utilizate în scripturile din comenzile generale.

Deschiderea fișierelor de date din aplicație
Pentru deschiderea a două fișiere de date din aplicație (ex. fișierele "p_" și "s_") se va folosi următoarea secvență:

   
x_open := {}
...
#IF ! h_UseAlias({"p_","s_"},x_open)
    // daca deschiderea fisierului "s_" esueaza, atunci inchide "p_"
    h_CloseAlias(,x_open) 
    // alte operatii necesare pt. terminarea scriptului
    ...
    Abandon("C") 
#ENDIF
// operatii de prelucrare
...
// inchide ambele fisiere deschise
h_CloseAlias(,x_open)
 
-  Pentru deschiderea fișierelor numai în regim de scriere, se va folosi h_UseAlias({"p_","s_"},x_open,"R")

Deschiderea unui fișier de date extern (nedefinit în baza de date a aplicației)
Fișierele din bazele de date de tip HAMOR sunt descrise în catalogul fișierelor (FILES.DBF).
Fișierele de date nedescrise în catalogul fișierelor sunt considerate externe. În unele cazuri este necesar accesul la un asemenea fișier extern. Pentru deschiderea fișierelor externe se folosește funcția:

h_NetUse(sFile,sUse,NIL,sName,sAlias)

-sFile - numele fișierului extern
-
sUse - dacă este necompletat, fișierul este deschis în regim de consultare în mod partajat,
- E - fișier deschis exclusiv,
- R - fișier deschis numai în regim de consultare
-NIL - nu se completează - se va utiliza valoarea prestabilită
-sName - numele utilizator al fișierului extern
-sAlias - aliasul fișierului

   
h_NewSelect()
// selecteaza o zona de lucru libera.
fil_man := SELECT()
// nr.zona de lucru nou selectat memorat in fil_man

#IF ! h_NetUse (FDName,,,"Fisier extern", "man")
// eroare deschidere fisier extern
// ... operatii necesare pentru inchidere, revenire
    Abandon("C")
#ENDIF

... prelucrari

// inchidere fișier extern
DBSELECTAREA(fil_man)
#IF USED()
    DBCLOSEAREA()
#ENDIF

Alias și zone de lucru
Fiecare fișier de date deschis ocupă o zonă de lucru. Zonele de lucru sunt numerotate în ordine: 1, 2, 3, ... etc.
Funcția SELECT() - returnează numărul de ordine a zonei de lucru curente. Fișierul și zona de lucru poate fi adresată prin "alias" ce se transmite la deschiderea fișierului.
În scripturi în mod obligatoriu se folosește un alias la deschiderea fișierelor.
ALIAS() - returnează alias-ul pentru zona de lucru curentă.
Zonele de lucru pentru fișierele de date din aplicație se alocă la lansarea programului.
Pentru fișierele din aplicație la lansarea programului se încarcă și un pointer. Pointerul conține numărul de ordine al zonei de lucru.
Pointerul fișierului de date are sintaxa fil_alias.
Adică cuvântul cheie fil_ urmat de aliasul fișierului. Exemplu fil_nomm.

Selectarea unei zone de lucru:
-DBSELECTAREA(alias) - zonă de lucru referit prin alias,
-DBSELECTAREA(nalias) - zonă de lucru referit prin număr de ordine,
Exemple: DBSELECTAREA("nomm")
         DBSELECTAREA(fil_nomm)
Pentru fișierele externe programatorul va trebui să rezerve zone de lucru libere.
Funcția h_NewSelect() selectează o zonă de lucru neocupată și nerezervată pentru un alt fișier de date.
Deci înainte de deschiderea unui fișier extern, se selectează o zonă de lucru liberă prin h_NewSelect()

Adresarea unui câmp dintr-un fișier de date
Pentru adresarea unui câmp din fișierul de date există două modalități:

1.direct: alias->Nume_camp
          field->Nume_camp
Permite citirea valorii unui câmp și atribuirea unei valori noi la câmp.
Accesul direct permite citirea-scrierea câmpului chiar dacă în zona de lucru curentă este deschis un alt fișier.
2.prin funcții
-pentru citirea valorii: FIELDGET(FIELDPOS(NumeCâmp))
-pentru atribuirea unei valori noi: FIELDPUT(FIELDPOS(NumeCâmp),Valoare)
În zona de lucru curentă trebuie să fie deschis fișierul care se prelucrează. Pentru selectarea și revenirea la zona de lucru inițială se folosește adresarea on-line:
   alias->(FIELDGET(FIELDPOS(NumeCâmp)))
   alias->(FIELDPUT(FIELDPOS(NumeCâmp),Valoare))

Ordinea de parcurgere a fișierului de date
Este determinată de fișierul index primar. Pentu fișierele de date din aplicație, prin h_UseAlias() automat se deschid și fișierele index asociate. Primul index devine automat indexul primar astfel ordinea de parcurgere este determinată de acesta. Fișierele index secundare nu determină ordinea de afișare, dar sunt actualizate dacă se modifică câmpurile fișierului de date.
Alegerea unui alt fișier index primar se face prin DBSETORDER(n) unde "n" este numărul fișierului index, care urmează să devină primar.

Salt la începutul fișierului
DBGOTOP() - face saltul la primul articol conform indexului primar din fișierul de date.
Indicatorul BOF() devine .T.

Salt la sfârșitul fișierului
DBGOBOTTOM() - face saltul la ultimul articol conform indexului primar din fișierul de date.

Selectarea articolului următor
DBSKIP() - selectează articolul următor conform indexului primar din fișierul de date.
Dacă articolul curent este ultimul din fișier, prin DBSKIP() se depășește și acesta, iar indicatorul EOF() devine .T.

Numărul articolului curent
Numărul articolului curent este returnat de RECNO()

Adăugarea unui articol nou
DBAPPEND() - adaugă un articol nou la fișierul curent.
În rețea articolul nou adăugat rămâne blocat. Va trebui eliberat cu DBUNLOCK()
În mediile HAMOR este accesibilă și h_AddRec() cu funcții similare. Descrierea completa pentru h_AddRec() se regăsește în biblioteca hLIB.

Percurgerea unui fișier de date
1.Algoritmul implementat prin instrucțiuni:
   DBGOTOP()
   #WHILE ! EOF()
   //    ... operatii de prelucrare
       DBSKIP()
   #ENDDO
2.Rapid prin DBEVAL(): DBEVAL(bBlock, bForCondition, bWileCondition)

Parcurge un fișier de date și execută acțiunea bBlock pentru fiecare articol care satisface condiția bForCondition și până când condiția bWhileCondition este îndeplinită.

Exemplu: Numărarea articolelor din grupa "MR". Presupunem că fișierul conține un câmp GR de tip caracter cu lungimea de 5 caractere, în care au fost înscrise grupele pentru articole. Aliasul pentru fișier este lotm.
   ii := 1
   DBEVAL({|| ii:=ii+1}, {|| lotm->GR = "MR    "})

DBEVAL() este mult mai eficient în cea ce privește timpul de răspuns. Acest lucru se explică prin faptul că interpretarea se face doar o dată la început, față de algoritmul implementat prin instrucțiuni, unde înainte de executarea fiecărei instrucții este necesară interpretarea acestuie.
Chiar și instrucțiunile Clipper de prelucrarea fișierelor sunt implementate prin DBEVAL().
DBEVAL() permite prelucrarea globală a fișierelor: actualizarea globală și condiționată ale câmpurilor, ștergerea din articolele fișierelor.

Regăsirea unui articol din fișier
Căutare secvențială
__dbLocate( bCond,bWhile,,, .F. )

Unde: bCond - condiția,
      bWhile - condiția WHILE
Exemplu:
__dbLocate( {|| nomm->GR = "MR "},,,, .F. )
Caută primul articol în care câmpul nomm->GR este "MR ".

După o căutare cu succes indicatorul FOUND() returnează .T. și pointerul se poziționează pe articolul găsit
După o căutare nereușită indicatorul FOUND() returnează .F. și pointerul se poziționează la sfârșit
__DBCONTINUE() - caută articolul următor care satisface condiția din ultimul apel la __DBLOCATE().
Exemplu:
   __dbLocate( {|| nomm->GR = "MR    "},,,, .F. )
   #WHILE FOUND()
   //    ... operatii de prelucrare
       __DBCONTINUE()
   #ENDDO

Căutare după index DBSEEK(sValoare,lSoftSeek) - salt la primul articol conform primului index.
Prin DBSEEK() se încearcă regăsirea primului articol care pentru cheia index generează valoarea transmisă prin sVal.
În mod normal, dacă cheia nu este regăsită, articolul curent se poziționează pe ultimul articol și indicatorul FOUND() returnează .F.
Dacă lSoftSeek a fost transmis, în situația în care cheia căutată nu este regăsită, articolul curent se poziționează la prima cheie care este mai mare de cea căutată.

Funcția h_vfcode(sKey,bVerif,nindex)
Implementează ambele moduri de căutare: căutarea secvențială și căutarea după index.
Parametrii:
-sKey   - cheia căutată - se transmite doar dacă se implementează o căutare după index.
La căutarea secvențială acest parametru nu se transmite.
-bVerif - bloc de cod.
La căutarea secvențială implementează condiția de căutare.
La căutarea după index, validează dacă articolul găsit întradevă satisface condiția de căutare.
-nindex - Numarul de ordine al indexului după care se face căutarea.
Daca =0, implementează căutarea secvențială.

Înainte de apelul funcției este necesară selectarea zonei de lucru în care este deschis fișierul de date în care va avea loc căutarea.
Dacă are loc o căutare după index, prin bVerif se poate implementa o verificare, prin care se validează articolul regăsit. Prin această verificare se asigură corectitudinea fișierului index. Dacă fișierul index este distrus, prin blocul de verificare acest lucru poate fi depistat și semnalat și nu au loc calcule/actualizări eronate

Exemple:
Se caută articolul cu codul "M-MARFA " din fișierul nomm confom indexului nr.1:
  DBSELECTAREA("nomm")
  sKey := "M-MARFA "
  h_vfcode(sKey,{|| nomm->COD = sKey},1)

Sa caută secvențial articolul cu codul "M-MARFA " din fișierul nomm:
  DBSELECTAREA("nomm")
  sKey := "M-MARFA "
  h_vfcode(,{|| nomm->COD = sKey},0)

Crearea unui fișier de date extern
Un fișier de date nou se creează cu ajutorul funcției CLIPPER DBCREATE().
Exemplu:

   
DBCREATE(FDName,{{"NUME",    "C", 20, 0}, ;
                 {"PRENUME", "C", 20, 0}, ;
                 {"DNAST",   "D",  8, 0}, ;
                 {"VBRUT",   "N", 12, 0}})

FDName - conține numele fișierului nou creat.
Al doilea parametru este un vector care conține structura fișierului ce urmează să fie creat, în forma:
{{<NUME_CIMP_1>, <TIP_1>, <LUNGIME_1>, <ZECIMALE_1>},
 {<NUME_CIMP_2>, <TIP_2>, <LUNGIME_2>, <ZECIMALE_2>},
 ...}
 
Citirea liniilor unui fișier de text
Citirea liniilor din fișierul de text MAN.TXT situat în catalogul temporar al mediului HAMOR:
 
   
FName := h_FilePathes[fil_tmp]+"MAN.TXT"
// numele fisierului de text
sline := ""   
// buffer pt. liniile citite

#IF ! h_OpenInp(FName)
// eroare deschidere fisier text
// ... operatii necesare pentru inchidere, revenire
   Abandon("C")
#ENDIF

#WHILE h_GetLine(@sline)
// ... prelucrare linie citita
#ENDDO
// inchidere fisier text
h_CloseInp()

Crearea unui fișier de text
Crearea fișierului de text nou MAN.TXT în catalogul temporar al mediului HAMOR

   
// numele fisierului de text
FName := h_FilePathes[fil_tmp]+"MAN.TXT"

#IF ! h_OpenOut(FName)
// eroare creare
// ... operatii necesare pentru revenire
   Abandon("C")
#ENDIF

h_PutLine("Linia 1")
h_PutLine("Linia 2")
h_PutLine("Linia 3")

h_CloseOut()

Vizualizarea unui fișier de text
Vizualizarea unui fișier de text cu posibilitate de tipărire
 
    h_ViewFile(FName,sTitle,pgwidth,pglen,mode)


-FName - numele fișierului de vizualizat
-sTitle - titlul ferestrei de vizualizare
-pgwidth - lățimea paginii
-pglen - lungimea paginii
-mode - P - permite lansarea tipăririi din fereastra de vizualizare prin tasta <F10>

Executarea unei operații hMET2
Pentru executarea operațiilor "01" pentru fișierul "E6" și "02" pentru fișierul "E7", se va utiliza secvența de instrucțiuni:
 
   
i := sal_findex("E6")
#IF i>0
    x_setfis(i)
    op_sal("O","01",.T.)
#ENDIF

i := sal_findex("E7")
#IF i>0
    x_setfis(i)
    op_sal("O","02",.T.)
#ENDIF
...

Bineînțeles secvența poate fi transcrisă pentru oricare alt fișier de tip hMET2 pentru o operație existentă.
În funcția op_sal(), pentru primul și ultimul parametru se introduc valorile "O" și respectiv ".T.".

Crearea unei ferestre de mesaje
Exemplu pentru crearea și afișarea unei ferestre de mesaje.
   
aMes := {}
AADD (aMes, "")
AADD (aMes, "Recalcularea datelor a fost executata cu succes.")
AADD (aMes, "Pentru siguranta va rugam reindexati baza de date")
AADD (aMes, "cu ajutorul utilitarului hUTIL")
AADD (aMes, "")

aMesHlp :=  h_NewMessage("",,,,,"Sfirsit prelucrare","HELP", aMes)

h_PopUpWindow (aMesHlp)

Prin rularea exemplului de mai sus, se va afișa fereastra:

Tipul ferestrei va fi determinat de primul parametrul, iar paleta de culori cu care se va afișa fereastra de parametrul 7.
Astfel se folosesc următoarele combinații: ajutor: "H", "HELP", avertizare: "W", "WARNING", eroare: "E", "ERROR", informații: "", NIL (necompletat).

Crearea unei ferestre de decizie
Mai jos prezentăm modul în care se creează o fereastră de decizie pentru alegerea uneia dintre operațiile Op1, Op2 sau abandonarea prelucrării.
 

   
aMes := ARRAY(2)

aMes[ 1] := "" aMes[ 2] := " Alegeti una dintre operatiile de mai jos"
wMes := h_NewOptions("O", ;                      ,,,, ;                      NIL,"*", {aMes,{" Op1 ", " Op2 ", " Abandon "}} ,{1})
#IF !h_PopUpWindow (wMes) .OR. wMes[13,1] = 3 // operatie abandonata #ELSEIF wMes[13,1] = 1 // ramuara "Op1" #ELSEIF wMes[13,1] =2 // ramura "Op2" #ENDIF
Prin rularea secvenței de mai sus se va afișa fereastra: