03 - Open SourceHarbour

Harbour – Primi passi nello sviluppo

Last Updated on 13 Giugno 2021 by Roberto De Pedrini

Vediamo oggi in questo articolo alcune nozioni base per cominciare a scrivere codice con harbour e comprendere meglio le funzioni messe a disposizione.

Tipo di dati semplici disponibili

blocco di codice (disponibile solo come variabile interna in Harbour)

Il tipo blocco di codice può essere immaginato come una scatola che come una funzione ha ingresso e uscita, però quest’ultimo non viene eseguito direttamente ma si comporta come un valore (Per trattare questo oggetto si fa uso delle macro EVAL(),AEVAL(),DBEVAL()), la sua esecuzione avviene durante la fase di compilazione del programma. Evitando quindi la valutazione di una macro-istruzione, la lentezza di chiamare una procedura e l’errore di funzioni non associate al programma eseguibile.

ESEMPI di blocco di codice:

  • blocco di codice con costante in memoria:
{||"Buongiorno"} nessun argomento, restituisce la stringa buongiorno il valore rimane come costante 
  • blocco di codice con costante che viene stampata a video:
?EVAL({||"buongiorno"} //stampa a video buongiorno
  • blocco di codice memorizzato in una variabile che contiene uno o più argomenti:
LOCAL quadrato := {|x|x^2}
?(EVAL(quadrato,2) + EVAL(quadrato,3) // stampa a video 13.00
  • blocco di codice che permette di esportare variabili:
PROCEDURE main()
     LOCAL raggio := 5 , altezza := 10
     ?altezza*EVAL(sup(),5) //restituisce un blocco di codice contenente una variabile locale a sup(), 
                            //la variabile pi che è perfettamente visibile all'interno del  resto del programma
RETURN
FUNCTION sup()
    LOCAL pi := 3.14159
RETURN({|x|pi*x*x})

Tipo char (C) (presente sia come variabile interna in Harbour che come tipo campo in una tabella dbf)

Come tutti i linguaggi esistenti anche harbour usa i tipi di dato stringa o carattere in particolare segue lo standard del linguaggio C. Per rappresentare il valore come carattere abbiamo (come su RPG,Python ecc…) l’uso del singolo apice. Mentre per Rappresentare la stringa usiamo il doppio apice (in alternativa al doppio apice possiamo usare le parentesi quadre).

ESEMPIO di caratteri:

stringa1 = "Ciao" //La notazione piu comune
stringa2 = 'Hello' // la notazione per definire il dato in formato carattere come in RPG
stringa3 = [Hola] //metodo alternativo per definire una stringa
//-----------------------------------------------------------------
grazie all'uso delle parentesi quadre possiamo delimitare le stringhe come:
stringa1 = [Egli domandò:"A che ora arriva?" ]
// oppure in alternativa
stringa2 = "Il riferimento "bibliografico [1]"

Tipo date (D) (presente sia come variabile interna in Harbour che come tipo campo in una tabella dbf)

Il tipo date che troviamo su Harbour ci permette di gestire in maniera semplice qualsiasi tipo di data, svolgendo qualsiasi tipo di operazione aritmetica. Sfruttando poi il comando SET DATE possiamo rappresentarla in qualsiasi standard richiesto.

ESEMPIO tipo date :

FUNC domani()
RETURN date()+1

Tipo booleano (presente sia come variabile interna in Harbour che come tipo campo in una tabella dbf)

Altro dato standard disponibile anche in Harbour è il tipo logico. Per rappresentarli in clipper si usano .T. per valore True e .F. per valore False.

Esempio valore bool:

 LOCAL y := .F.
 IF  y = .T. 
      ? "Working"
 ELSE
      ? "Borken"
 ENDIF 

Tipo dati MEMO (M) (disponibile solo come tipo all’interno delle tabelle dbf)

Il tipo dati MEMO eredita le caratteristiche del campo di tipo carattere ma la differenza è che la sua lunghezza è variabile, questo tipo di dato lo si può trovare solo all’interno di una tabella DBF e non direttamente come variabile interna di Harbour, può essere accomunato al campo di tipo varchar dei database SQL .

Tipo dati numerico (N) (presente sia come variabile interna in Harbour che come tipo campo in una tabella dbf)

A differenza di altri linguaggi, Harbour usa un solo tipo numerico (il numero a virgola mobile a doppia precisione). Con una serie di funzioni riesce a capire il tipo usato e viene automaticamente nel suo formato interno. è possibile definire valori compresi tra 1.7*10^-308 e 1.7*10^308.

Comandi SET

Dopo aver visto i tipi di dato esistenti in Harbour, ci tenevo prima di parlare della gestione dei file DBF a spiegare i comandi SET. Quest’ultimi sono dei comandi globali con cui possiamo in maniera flessibile abilitare e disabilitare funzioni o proprietà. Ad esempio possiamo creare gli indici sui nostri file DBF con il comando SET INDEX o impostare lo standard della data con il comando SET DATE. Di seguito viene riportato un elenco dei comandi esistenti con una descrizione della funzione che svolge (ogni comando fa riferimento (CA-Clipper 5.3 . Guide To CA-Clipper – Short Entry (itlnet.net)) anche questo sito come la documentazione clipper è valido e rispetto alla documentazione offre i comandi separati per categoria :

 SET ALTERNATE   Echo console output to a text file
 SET BELL        Toggle sounding of the bell during full-screen operations
 SET CENTURY     Modify the date format to include or omit century digits
 SET COLOR*      Define screen colors
 SET CONFIRM     Toggle required exit key to terminate GETs
 SET CONSOLE     Toggle console display to the screen
 SET CURSOR      Toggle the screen cursor on or off
 SET DATE        Set the date format for input and display
 SET DECIMALS    Set the number of decimal places to be displayed
 SET DEFAULT     Set the CA-Clipper default drive and directory
 SET DELETED     Toggle filtering of deleted records
 SET DELIMITERS  Toggle or define GET delimiters
 SET DESCENDING  Change the descending flag of the controlling order
 SET DEVICE      Direct @...SAYs to the screen or printer
 SET EPOCH       Control the interpretation of dates with no century digits
 SET ESCAPE      Toggle Esc as a READ exit key
 SET EVENTMASK   Specify events to be returned by the INKEY() function
 SET EXACT*      Toggle exact matches for character strings
 SET EXCLUSIVE*  Establish shared or exclusive USE of database files
 SET FILTER      Hide records not meeting a condition
 SET FIXED       Toggle fixing of the number of decimal digits displayed
 SET FORMAT*     Activate a format when READ is executed
 SET FUNCTION    Assign a character string to a function key
 SET INDEX       Open one or more order bags in the current work area
 SET INTENSITY   Toggle enhanced display of GETs and PROMPTs
 SET KEY         Assign a procedure invocation to a key
 SET MARGIN      Set the page offset for all printed output
 SET MEMOBLOCK   Change the block size for memo files
 SET MESSAGE     Set the @...PROMPT message line row
 SET OPTIMIZE    Change the setting that optimizes using open orders
 SET ORDER       Select the controlling order
 SET PATH        Specify the CA-Clipper search path for opening files
 SET PRINTER     Toggle echo of output to printer or set the print destination
 SET PROCEDURE*  Compile procedures and functions into the current object file
 SET RELATION    Relate two work areas by a key value or record number
 SET SCOPE       Change the boundaries for scoping keys in controlling order
 SET SCOPEBOTTOM Change bottom boundary for scoping keys in controlling order
 SET SCOPETOP    Change top boundary for scoping keys in controlling order
 SET SCOREBOARD  Toggle the message display from READ or MEMOEDIT()
 SET SOFTSEEK    Toggle relative seeking
 SET TYPEAHEAD   Set the size of the keyboard buffer
 SET UNIQUE*     Toggle inclusion of non-unique keys into an index
 SET VIDEOMODE   Change the current video mode of the current application
 SET WRAP*       Toggle wrapping of the highlight in menus

Che cos’è un DBF?

La prima domanda che viene spontanea a chi conosce per la prima volta Harbour o il clipper o chi vagamente lo ricorda è il file con estensione .DBF. Creato inizialmente da Dbase nel 1983 è diventato uno dei file standard che ancora oggi viene ampiamente usato. Questa estensione si comporta come un file PF su ibm i e rispetto ad altri linguaggi che hanno bisogno di driver esterni per manipolare i dati al suo interno, harbour come RPG riesce ad aprire questi file in maniera nativa. Vediamo in questo articolo i comandi principalmente usati.

Creazione di un file DBF (batch)

Per creare un file DBF all’interno di Harbour, rechiamoci all’interno della cartella dove vogliamo far risiedere il nostro DBF e apriamo nel terminale l’interprete HBRUN a questo punto usiamo il comando CREATE o la funzione dbcreate() per creare il nostro primo file DBF. Questo è il comando che andremo a utilizzare:

    //comando per creare la struttura
    CREATE TempStru
    APPEND BLANK
    REPLACE Field_name WITH "Name",;
           Field_type WITH "C",;
           Field_len WITH 25,;
           Field_dec WITH 0
    CLOSE

    //comando per creare il file DBF
    CREATE NewFile FROM TempStru

Se osserviamo bene l’esempio possiamo notare che il comando CREATE ci permette di creare una struttura temporanea con le proprietà delle nostre colonne , con il comando APPEND BLANK aggiungiamo un nuovo spazio che il comando REPLACE per ogni colonna che dichiariamo verrà memorizzata all’interno della struttura. Successivamente con il comando CREATE dichiarando il nome del file e con il comando FROM indicando la struttura , abbiamo correttamente creato il nostro file DBF. Possiamo creare il file sia da interprete copiando ogni singolo comando oppure possiamo creare un file con estensione .prg copiare al suo interno i comandi e lanciare nel terminale (HBRUN script.prg) e a questo punto in batch verrà creato il nostro file pronto per essere usato.

Creazione di un file DBF (interattivo)

Se poi non abbiamo una struttura già pronta e vogliamo creare il .dbf in maniera interattiva, ci basterà lanciare nell’interprete HBRUN il comando CREATE con il nome che vogliamo dare al nostro DBF e subito dopo se notiamo, nella cartella dove il terminale era stato aperto viene creato il nostro file DBF , qui però dobbiamo fare attenzione perché attualmente il file è vuoto e non è stato inizializzato nemmeno con una colonna al suo interno. A questo punto se guardiamo sul terminale una volta dato il comando precedente la console sembra che non abbia fatto nulla, ma in realtà è in attesa di nostre istruzioni dato che il file è stato creato e impegnato da Harbour stesso. A questo punto ci viene spontaneo chiudere la finestra e credere di aver completato il lavoro. In realtà dobbiamo definire le colonne e per farlo è sufficiente scrivere nel terminale il comando BROWSE(), a questo punto ci comparirà una schermata su cui possiamo aggiungere colonne e definire le loro proprietà un po’ come il DBU su IBM i. A questo punto il file DBF conterrà come dati le proprietà delle colonne inserite preceentemente. Per finalizzare il nostro DBF dobbiamo lanciare il comando CREATE test FROM test, in questo modo Harbour leggerà le definizioni dei nostri campi e trasformerà il file pronto per ospitare i nostri dati.

1)apriamo il terminale e digitiamo hbrun
comando create per creare il dbf in questo caso il file si chiamerà test
file appena creato
Una volta creato il file lanciamo il comando Browse()
Definiamo i campi con le loro proprietà
a questo punto lancio il comando create per creare la tabella definitiva

Come aprire un DBF all’interno del nostro programma e esternamente

Una volta creato il DBF con le nostre colonne abbiamo il nostro file dbf che possiamo usare, la prima cosa che ci viene in mente è come possiamo visualizzare le righe del nostro file ?

Comando USE indispensabile

La prima cosa da fare sempre sia nel nostro sorgente e sia nell’HBRUN è aprire e allocare il file, per farlo come su SQL usiamo il comando USE, in questo modo Harbour come SQL e RPG con la specifica F sa che deve prendere il nostro file in considerazione .

//Esempio di utilizzo di USE
USE test //in questo modo stiamo impegnando il file se apriamo il file DBF in maniera condivisa come per i PF su RPG la tabella risulterà non accessibile ad altri utenti in scrittura e modifica ma devono attendere che la persona che impegna il file lo abbia liberato.
USE test alias t //assegno un alias al nome file da qui in poi per usare le colonne devo prendere in considerazione l'alias
USE test NEW // in questo modo impegno il file e lo posiziono in memoria , da usare quando devo impegnare più di un file DBF, posso impegnare fino a 10 DBF in contemporanea.

USE test SHARED NEW //in questo modo impegno il file DBF in maniera condivisa posso far inserire righe a più utenti in rete.

USE test VIA "DBFCDX" // in questo modo dichiariamo quale driver di database deve essere preso in considerazione, ne parleremo più avanti
//Notare bene:
//nel caso in cui il file dbf non si trovi nella stessa cartella va specificato l'intero percorso del file , per passare valori ai comandi (le istruzioni senza le parentesi) attraverso costanti o variabili , vanno racchiusi tra parentesi tonde ecco un esempio con il comando USE in questo caso

LOCAL percorsoDBF := 'C:\hb32\test.dbf' // per inizializzare una variabile si usa sempre := per cambiare il valore solo =
USE (percorsoDBF)

Inserire e modificare le righe nel DBF

Se ci troviamo ora su HBRUN o abbiamo creato un nostro programma dagli esempi della cartella tests e abbiamo immesso USE ci viene da chiederci quale comando dobbiamo usare per visualizzare i nostri dati? Per farlo è molto semplice, se vogliamo visualizzarlo in schermata console e non ne dobbiamo creare una personalizzata, possiamo avvalerci della tabella standard. Sia nel nostro programma che nell’HBRUN possiamo usare il comando BROWSE(). In questa schermata possiamo aggiungere rimuovere o editare righe.

Comando browse() per modificare,eliminare o inserire righe
schermata browse() di default

Se vogliamo invece integrare questa visualizzazione base della nostra nuova tabella possiamo usare il comando browse() all’interno della nostra applicazione console e la possiamo personalizzare a nostro piacimento.

//ESEMPIO BASE DI VISUALIZZAZIONE DATI FORNITO DIRETTAMENTE DA HARBOUR DISPONIBILE NELLA CARTELLA tests
// Testing Browse()

#include "inkey.ch"

PROCEDURE Main()

   LOCAL cColor := SetColor( "W+/B" )



   CLS

   USE test
   Browse()

   SetColor( cColor )
   CLS

RETURN

Per vedere in azione questo esempio basterà recarci nella cartella tests con il terminale e se voglaimo eseguirlo in maniera interpetata lanciamo il comando hbrun browse.prg oppure se vogliamo generare un eseguibile e avere il programma compilato usiamo il comando hbmk2 browse.prg

Esempio browse.prg eseguito in maniera compilata
Output eseguibile

Se vogliamo invece inserire una riga direttamente sul DBF senza visualizzare la griglia dovremo usare la combinazione di comandi APPEND BLANK e REPLACE nome_colonna WITH nostro valore. In questo modo di default alla fine delle righe esistenti Harbour andrà a creare una nuova riga vuota e con il comando REPLACE andremo a sostituire per i ogni singola colonna i nostri valori.

//esempio di inserimento nuovo valore
PROCEDURE main()
   USE test VIA "DBFCDX"
   APPEND BLANK
   REPLACE name WITH "Mario"
RETURN

Se vogliamo sostituire i valori di una riga già esistente dobbiamo usare direttamente il comando REPLACE, quest’ultimo si comporta come il comando UPDATE di SQL. Questo comando può essere usato per condizionare la modifica. Vediamo ora un esempio dettagliato:

// comando UPDATE del linguaggio SQL
UPDATE tabella SET colonna = valore where id = valore

// comando REPLACE di Harbour
local nome1
nome1 := 'mario'
USE clienti 
REPLACE nome with nome1 FOR id = 1 //sostituisco il valore della colonna nome in tutte le righe con la colonna ID = 1
// oltre il FOR posso usare il WHILE REPLACE nome with 'mario' WHILE id = 1
//se specifico solo il REPLACE senza le condizioni la modifica verrà effettuata nella riga dove Harbour è attualmente posizionato  
COMMIT //comando facoltativo che permette la forzatura della modifica della  riga in caso di problemi

Indici e interrogazioni sui file DBF

Un punto di forza che Harbour ha a disposizione è la possibilità di creare indici sui file DBF utili nel nostro programma per cercare dati in maniera veloce. Per creare un indice ci basterà usare il comando INDEX ON colonna TO nome_indice. In questo modo Harbour andrà a creare un file con il nostro indice e quando lo vogliamo usare all’interno del nostro programma ci basterà usare il comando SET INDEX TO nome_indice, questo comando viene principalmente usato in caso in cui abbiamo più di un DBF aperto e indici creati , in questo modo diciamo ad Harbour di prendere in considerazione il nostro indice in una particolare situazione. I file indici possono essere accomunati ai file logici dell’IBM I utili da usare ad esempio in una ricerca per indice.

// esempio di ricerca sfruttando il comando seek la controparte della chain su harbour ( argomento affrontato nell'articolo introduttivo)
RPG--------------------------------------------------------------------
 Chain klst1 FILE01;
 If %found(FILE01);

     Dsply 'Record found';
 
 Endif;
-----------------------------------------------------------------------

HARBOUR----------------------------------------------------------------
 USE Customer NEW
 INDEX ON Customer->ID TO ID
 SEEK "Doe"
 IF FOUND()
 
      ? “Record found”
 
 ENDIF
-----------------------------------------------------------------------

Come vediamo in questo esempio ci avvaliamo del SEEK, questo comando permette di cercare in maniera casuale un valore che gli abbiamo dato in input all’interno della colonna. Questo comando è molto veloce l’unico inconveniente è l’obbligo di ricercare su un campo indicizzato facendo inizare da dove sono posizionato con il cursore, a differenza del CHAIN, in combinazione con il comando SKIP il SEEK permette di cercare più di una corrispondenza all’interno di una tabella .

//esempio con seek per trovare un valore su più righe - esempio ripreso dalla documentazione clipper 
//si possono trovare riferimenti in dettaglio sul seek nel seguente link:
https://www.itlnet.net/programming/program/Reference/c53g01c/ng49aff.html
PROCEDURE main()
        USE Customer INDEX Customer NEW //possiamo indicizzare direttamente nella USE
        SEEK "Smith"
        DO WHILE FOUND()
           ? customer->name //con il simbolo -> seleziono la colonna dalla tabella l'equivalente SQL di tabella.colonna
           SKIP //passo al record successivo fino a quando trovo corrispondenza

        ENDDO
RETURN

Se volgiamo evitare di usare cicli per cercare valori nella tabella e vogliamo usare un approccio simile ad SQL , possiamo affidarci ai comandi LIST e DISPLAY. Quest’ultimi si comportano come una SELECT, come requisito importante in entrambi è di dichiarare sempre il nome delle colonne che vogliamo visualizzare altrimenti ci vengono restituite righe vuote (non è presente il carattere * per visualizzare tutte le colonne se devo visualizzare tutto come spiegato prima uso il comando BROWSE()). Anche questi comandi includono la possibilità di filtrare dati attraverso l’uso delle condizioni. Questi comandi ci consentono di decidere dove stampare il nostro output se specifichiamo il comando TO FILE seguito da un nome di un file, Harbour scriverà l’output direttamente al suo interno. Se specifichiamo TO PRINTER l’output verrà direttamente stampato dalla stampante. Una delle caratteristiche che contraddistingue DISPLAY da LIST è la possibilità di specificare il numero di righe che ci vengono restituite in output. Ma vediamo un piccolo esempio dei due comandi che possiamo usare sia nei nostri programmi e anche in maniera interattiva:

//esempi comando display - per maggiori dettagli fare riferimento alla documentazione 
   USE Sales NEW //impegno il file  
   DISPLAY DATE(), TIME(), Branch //mostro a video solo la riga in cui è attualmente posizionato il cursore con le colonne che ho dichiarato 
   DISPLAY NEXT 20 DATE(), TIME(), Branch //mostro a video 20 righe a partire dal cursore con le colonne che ho specificato
   DISPLAY Branch, Salesman FOR Amount > 500 //Vengono mostrati a video i record che soddisfano la condizione specificata
   DISPLAY Branch, Salesman FOR Amount > 500 TO PRINTER //display con condizioni usando un ciclo FOR 
                                           //e invio i risultati che ho richiesto direttamente alla stampante con il comando TO PRINTER
   DISPLAY Branch, Salesman while Amount = 500 TO FILE prova //display con condizioni usando un ciclo while
                                                   //e invio i risultati che ho richiesto ad un file ad esempio di testo con il comando 
                                                   //TO FILE nome_FILE
   DISPLAY ALL Branch, Salesman // mostra tutti i record 

//esempio comando list - per maggiori dettagli fare riferimento alla documentazione  

   USE Sales
   LIST Date(), Time(), Branch // mostro tutte le righe a video con queste colonne specificate
   In questo esempio, il programma mi restituisce in ouput tutte le righe con amount > 500, e l'output viene 
   inviato ad un file in questo caso il file si chiama test
   LIST Branch, Salesman FOR Amount > 500 TO file test
   In questo esempio, il programma mi restituisce in ouput tutte le righe con amount > 500, e l'output viene inviato ad una stampante
   LIST Branch, Salesman FOR Amount > 500 TO PRINTER 
   

   esempio di LIST usando la condizione WHILE la query in questo specifico esempio prosegue all'infinito 
   fino a quando l'utente ha premuto il tasto Esc:

   #define K_ESC     27
   USE Sales INDEX Salesman NEW
   LIST Branch, Salesman, Amount WHILE Inkey() != K_ESC

Il Setll di Harbour

Prima di andare avanti è doveroso spiegare un comano importante, il GO. Quest’ultimo si comporta come su RPG , ovvero ci permette di spostare il cursore all’interno della tabella in maniera desiderata utile in tutti comandi come il SEEK per decidere dove far iniziare una ricerca all’interno della tabella.Vediamo subito come si usa:

Documentazione su comando go disponibile qui: https://www.itlnet.net/programming/program/Reference/c53g01c/ngcc35b.html
//comando per tornare all'inizio della tabella 
RPG------------------
setll *loval;
---------------------
Harbour -------------
go top
---------------------
//comando per posizionare il cursore alla fine della tabella
RPG ------------
setll *hival;
----------------
Harbour --------
go bottom
----------------

//posizionamento su un record specifico

go 10 // il cursore si posiziona alla riga 10

// esempio riportato dalla documentazione
// in questo esempio viene usata una ricerca e viene usato il go per tornare sulla riga precedente
FUNCTION KeyExists( xKeyExpr )

        LOCAL nSavRecord := RECNO()      // Save the current record
                                         // pointer position
        LOCAL lFound

        SEEK xKeyExpr
        IF ( lFound := FOUND() )
            ? "record found"
        ENDIF

        GO nSavRecord      // Restore the record pointer position

RETURN ( lFound )

Eliminare una riga nel file DBF

Dopo aver inserito, modificato e visualizzato il nostro record. Viene da chiederci come posso cancellare un record all’interno del nostro file. Qui bisogna avere una piccola attenzione, quando Harbour va a cancellare il record nel nostro file la effettua in maniera logica. Per preparare la riga alla cancellazione uso il comando DELETE anche quest’ultimo può essere condizionato con il WHILE e FOR e posso marcare più di una riga che rispetta le condizioni che gli ho indicato. Una volta che ho segnato i record per confermare la cancellazione si usa il comando PACK. Se vogliamo poi recuperare un record o più di uno, dobbiamo usare il comando RECALL prima di PACK. Se vogliamo invece cancellare la nostra tabella da tutte le righe usiamo il comando ZAP.

//Per una documentazione su tutti i comandi citati si può fare riferimento qui https://vivaclipper.wordpress.com/tag/delete/
//esempio cancellazione record
 USE Sales INDEX Salesman NEW
 DELETE ALL FOR Inactive //vengono eliminati tutti i record con valore booleano nella colonna Inactive = true
 PACK // confermo l'eliminazione del file

//esempio cancellazione record e recall

  USE Sales NEW
       
  DELETE RECORD 4
  ? DELETED()               // Result: .T. // segno il record alla riga n 4 e con deleted() controllo se è stato marcato
 
  RECALL
  ? DELETED()               // Result: .F.

 //per annullare uso recall e se reinterrogo la funzione  deleted() questa volta' mi restituira .F. false
  
//cancello l'intera tabella
 ZAP

Per una panoramica su altri comandi o funzioni si può fare riferimento alla documentazione ufficiale: https://harbour.github.io/doc dove prende riferimento questo articolo.

Costruzione di interfacce console – esempio di una mini applicazione funzionante

Per chi ricorda il buon vecchio clipper, quest’ultimo era famoso per la progettazione semplificata di interfacce console. Sappiamo bene anche se obsolete, le nostre care schermate 5250 o console, restano ancora oggi molto produttive. Grazie alla sua sintassi semplificata come visto nell’articolo introduttivo con poche righe di codice possiamo creare un menù selettivo o una schermata di inserimento dati (simile alla creazione dei display file su IBM i).Ma vediamo in dettaglio un piccolo esempio:

//piccolo esempio maschera di input con creazione e inserimento valori all'interno del DBF anagrafica
PROCEDURE Main ()
    //comando per creare la struttura della tabella 
    CREATE TempStru
    APPEND BLANK //aggiungo nella tabella temporanea  è necessario append blank per la creazione delle definizioni dei nuovi campi
    REPLACE Field_name WITH "NOME",;
           Field_type WITH "C",;
           Field_len WITH 25,;
           Field_dec WITH 0
    APPEND BLANK
    REPLACE Field_name WITH "COGNOME",;
           Field_type WITH "C",;
           Field_len WITH 25,;
           Field_dec WITH 0
    APPEND BLANK
    REPLACE Field_name WITH "ETA",;
           Field_type WITH "N",;
           Field_len WITH 3,;
           Field_dec WITH 0
    CLOSE

    //comando per creare il file DBF
    CREATE anagrafica FROM TempStru
   CLS
   cCognome = SPACE(20)
   cNome = SPACE(20)
   nEta = 0
   @ 07,18 TO 13,63 DOUBLE COLOR "g+/n"
   @ 08,20 SAY "Inserire il cognome  " COLOR "w+/n" get cCognome COLOR "rg+/r"
   @ 10,20 SAY "Inserire il nome     " COLOR "w+/n" get cNome COLOR "rg+/r"
   @ 12,20 SAY "Inserire l'eta       " COLOR "rg+/n" get nEta COLOR "w+/b"
   READ
   USE anagrafica ALIAS anag
   APPEND BLANK
   REPLACE anag->COGNOME WITH cCognome
   REPLACE anag->NOME WITH cNome
   REPLACE anag->ETA  WITH nEta
   
   
RETURN

Per compilare il nostro esempio ci basterà all'interno della cartella dove abbiamo creato il nostro sorgente il comando:
hbmk2 nomesorgente.prg 
se vogliamo lanciarlo senza compilazione all'interno dell'interprete di harbour usiamo il comando 
hbrun nomesorgente.prg 
se poi abbiamo inserito una riga lanciando il programma e vediamo all'interno della nostra tabella che i campi sono stati aggiunti all'interno del nostro file DBF.

Output:

Come possiamo vedere in due righe abbiamo creato una schermata di inserimento pronta all’uso. Analizziamo ora la sintassi in dettaglio:

CLS – equivalente del comando DOS per pulire le schermate del terminale

cCognome = SPACE(20) inizializzo una variabile per catturare il valore in input immesso dall’utente

@ – il simbolo @ mi consente di specificare la posizione del campo che vado ad inserire.

SAY – il comano SAY corrisponde ad un campo di tipo etichetta da usare come costante o come campo di output

COLOR – seguendo una tabella prensente nella documentazione possiamo dichiarare il colore di ogni singolo elemento.

GET – Il comando GET corrisponde al campo di input ( restando in tema ibm i equivale al campo FLD000x) che usiamo per ottenere valore da parte dell’utente.

READ – Comando che legge i valori di input

@ 07,18 TO 13,63 DOUBLE COLOR “g+/n” – Questo comando composto permette di creare una cornice con doppio riquadro.

Questa sintassi è universale e con l’evoluzione di Harbour non siamo costretti a studiare librerie grafiche particolari (salvo se non vogliamo usare una libreria specifica come QT). Una volta appreso il funzionamento di questi comandi possiamo usarli con le rispettive librerie nella creazione di schermate desktop o web , nel prossimo capitolo vedremo come fare per creare una form desktop classica sfruttando la libreria grafica HMG. Nel frattempo per chi vuole curiosare sui comandi per l’interfaccia può far riferimento sempre alla documentazione ufficiale.

LINK ESTERNI PRESI DI RIFERIMENTO PER QUESTO ARTICOLO:

https://vivaclipper.wordpress.com/

CA-Clipper 5.3 . Guide To CA-Clipper – Short Entry (itlnet.net)

Harbour Language Wiki Home

ElektroSoft – Informatica ed Elettronica in Sicilia – Caltanissetta

Harbour Reference Guide · Index

About | Fivetech Software

Il linguaggio Harbour – il vecchio Clipper ha nuova vita | Elettronica Open Source (emcelettronica.com)

Related Posts
DB2 for i SQL – Stringhe – POSSTR-LOCATE-LOCATE_IN_STRING (IT)

Introduzione Spesso, nelle nostre applicazioni, abbiamo la necessità di lavorare con le stringhe di testo e l'SQL del DB2 può Read more

DB2 for i & SQL – FAQ & Howto (Part. 1) (IT)

Database DB2 e SQL ... forse lo strumento più potente e completo che abbiamo sulla piattaforma IBM i: ecco una Read more

Annuncio IBM i 7.4

Arriva direttamente con l'uovo di Pasqua questo annuncio IBM per le novità della versione IBM i 7.4, versione iNext secondo Read more

Generated Always Columns – Approfondimenti (IT)

Introduzione "Generated Always Column": sono colonne, campi, di una tabella il cui contenuto è controllato direttamente dal sistema ... e Read more

About author

Giorgio Caponera, appassionato sviluppatore del mondo IBM i, Fresh Face IBM nel 2019.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *