L’AZIENDA

 

 

SYSTEM LOGISTICS

 

 

L’innovazione come filosofia aziendale System SPA opera nel settore dell’automazione industriale da oltre 25 anni. Il suo core business è nella industria ceramica dove opera con il marchio System Ceramics, leader mondiale per la decorazione e smaltatura, linee di scelta, pallettizzatori, movimentazione e stoccaggio per l` industria ceramica. Complessivamente System esporta circa 80% della produzione, ed il suo fatturato nel 1997 è stato 125 miliardi di cui ben 40 nella divisione Logistics.

Le conoscenze di know how acquisito, hanno permesso di diversificare l’attività: dal 1986 System Logistics opera nel settore del material handling. Il nuovo logo “SYSTEM LOGISTICS” che ha sostituito CMA, è stato scelto per sottolineare il supporto completo offerto al Cliente nella gestione d’impresa.L’attività di System Logistics è infatti basata sulla produzione di sistemi automatici di immagazzinaggio e movimentazione per diversi settori industriali: quali ad esempio magazzini verticali automatici, robots di pallettizzazione, impianti trasloelevatori, navette a guida laser per la movimentazione, trasporti interni.

Le prime esperienze di System Logistics sono avvenute con soluzioni “su misura” a clienti istituzionali. L’esperienza acquisita e la conoscenza del mercato hanno poi permesso di standardizzare i prodotti in una vasta gamma, che trova riscontro nelle oltre 650 installazioni effettuate fino ad oggi.

La propensione al servizio e al supporto consulenziale e tecnico di System SpA emerge anche dalla sua organizzazione. I dipendenti di System sono circa 300, di questi, 90 sono impiegati nella divisione Logistics.

 

 

La missione

 

 

System Logistics è oggi “partner di impresa“ per il cliente. Grazie all’ampia gamma di prodotti e al patrimonio d` esperienza acquisito con le oltre 650 installazioni sul mercato mondiale, System è in grado di predisporre l` offerta più idonea all` esigenza del cliente.

L’obbiettivo primario è quello di convertire la fornitura di “prodotti tecnologici” in fornitura di “prodotti di servizio”, ponendosi come costante supporto del cliente nell’ambito del material handling, sia per i semilavorati e componenti per la produzione, sia per i prodotti finiti destinati alla distribuzione.

Avvalendosi di qualificati servizi interni in grado di studiare attentamente i flussi delle merci per ridurne i cicli di movimentazione, System Logistics offre “soluzioni complete” nei sistemi avanzati ed automatici di magazzinaggio: impianti e software gestionale.

I programmi di gestione degli impianti forniti, sono sviluppati su piattaforma WINDOWS NT : fino ad oggi questi “pacchetti” software supervisione sono stati applicati per la gestione di oltre 350000 UDC (unità di carico).

Questa modalità di intervento è in grado di promuovere una gestione avanzata della logistica di fabbrica controllando i flussi delle merci da e per il magazzino.

Il risultato finale delle soluzioni presentate da System Logistics, assicura una migliore gestione dell’approvvigionamento e della consegna dei materiali, permettendo il recupero di produttività; la gestione dei materiali cessa così di essere una problematica per l’impresa, e diviene un fattore determinante per il miglioramento della competitività.

 

 

 

 

 

 

L’innovazione come filosofia aziendale

 

 

System SPA opera nel settore dell’automazione industriale da oltre 25 anni. Il suo core business è nella industria ceramica dove opera con il marchio System Ceramics, leader mondiale per la decorazione e smaltatura, linee di scelta, pallettizzatori, movimentazione e stoccaggio per l` industria ceramica.

Complessivamente System esporta circa 80% della produzione, ed il suo fatturato nel 1997 è stato 125 miliardi di cui ben 40 nella divisione Logistics. Le conoscenze di know how acquisito, hanno permesso di diversificare l’attività: dal 1986 System Logistics opera nel settore del material handling. Il nuovo logo “SYSTEM LOGISTICS” che ha sostituito. CMA, è stato scelto per sottolineare il supporto completo offerto al Cliente nella gestione d’impresa.

L’attività di System Logistics è infatti basata sulla produzione di sistemi automatici di immagazzinaggio e movimentazione per diversi settori industriali: quali ad esempio magazzini verticali automatici, robots di pallettizzazione, impianti trasloelevatori, navette a guida laser per la movimentazione, trasporti interni.

Le prime esperienze di System Logistics sono avvenute con soluzioni “su misura” a clienti istituzionali. L’esperienza acquisita e la conoscenza del mercato hanno poi permesso di standardizzare i prodotti in una vasta gamma, che trova riscontro nelle oltre 650 installazioni effettuate fino ad oggi.

La propensione al servizio e al supporto consulenziale e tecnico di System SpA emerge anche dalla sua organizzazione. I dipendenti di System sono circa 300, di questi, 90 sono impiegati nella divisione Logistics.

 

 

 

Come opera System Logistics

 

 

Le più recenti tendenze della cultura manageriale pongono il concetto di logistica, inteso come organizzazione e movimentazione delle risorse in azienda, al centro delle scelte strategiche aziendali. In corrispondenza delle nuove tecniche di “lean production” e delle richieste di estrema flessibilità e dinamismo, la logistica è divenuta disciplina vitale nell’attività d’impresa.

Il punto di forza di System Logistics è proprio la sua capacità di gestire interamente progetti complessi: basti pensare che in Texas è stata in grado di realizzare una commessa pluriennale per impianti di movimentazione e magazzinaggio per un valore oltre i 60 milioni di dollari.

System  Logistics offre infatti, ai diversi settori industriali e aziendali, “soluzioni complete” per fare fronte alla competizione, che oggi si gioca specialmente a livello di servizio, oltre che di prezzo e di tecnologia.

Per questo la sua attività non è limitata alla fornitura di macchinari, ma ha il suo fulcro nell’offerta di vere e proprie “soluzioni complete” per la gestione integrata dei magazzini automatici, affiancata dall’analisi svolta da personale specializzato con il supporto di sistemi di simulazione.

 

 

Una rete mondiale al servizio del cliente

 

 

Una qualificata e continua assistenza post vendita è garantita da una struttura interna dedicata che opera in tutto il mondo, anche in teleassistenza, in collaborazione con le società estere appartenenti a System SPA : System Espana, System France, System Southeast, System Bohemia e System Brasil in grado di garantire un servizio tempestivo e qualificato, attraverso personale specializzato che interviene direttamente in caso di guasto o di problemi nell’utilizzo dei macchinari.

 

 

Le soluzioni System Logistics

 

 

I problemi che caratterizzano la gestione delle merci, dal momento dell’approvvigionamento alla loro distribuzione finale, sono molteplici e di diverse proporzioni a seconda di numerose variabili. Tra i fattori da valutare per la scelta di un sistema di immagazzinaggio ottimale, vanno presi in considerazione innanzitutto il tipo di merci, l’attività svolta dal cliente e la struttura a disposizione dell’impresa stessa.

Proprio per questo System Logistics ha studiato un’ampia gamma di prodotti che, adottati singolarmente o affiancati fra loro in “sistemi integrati”, sono in grado di fornire la risposta più mirata all’esigenza del cliente.

I due grandi ambiti in cui System Logistics si trova ad operare sono:

 

1.     Impianti di immagazzinaggio:

        -    magazzini verticali automatici Modula

-        trasloelevatori Miniload

-        trasloelevatori Robostore e/o sterzanti

       2.   Impianti handling

-        sistemi di convogliamento e trasporto

-        palletizzatori robottizzanti

-        veicoli laser guidati LGV

 

Impianti e movimentazione interna

 

 

La linea Handling & Storage è stata creata da System Logistics per assicurare l’ottimizzazione della gestione delle merci in tutte le aziende, con proposte pensate appositamente per ogni settore produttivo.Con la sua vasta gamma di prodotti, la linea Handling & Storage  offre soluzioni applicabili alle più svariate esigenze lavorative ed alle diverse configurazioni strutturali degli ambienti, in modo da pianificare e realizzare un magazzino automatico su misura per ogni azienda.

La linea integrata di trasloelevatori Robostore e di sistemi di convogliamento realizzati con componenti modulari, consente di realizzare flussi delle merci in termini di tempo, qualità e costi predeterminanti.

La qualità principale della proposta Robostore di  System Logistics è infatti quella di favorire uno sfruttamento totale dell’area di magazzino, garantendo precisione nell’esecuzione dei prelievi e dei carichi, evitando danni alle merci o errori di stoccaggio anche quando è richiesta elevata velocità nelle operazioni.

La linea Handling & Storage comprende anche robots di pallettizzazione progettati per la preparazione di pallet aventi carichi con forme, dimensioni e pesi tra i più svariati, e si completa con robots manipolatori, fino ad arrivare ai moderni LGV(veicoli laser guidati per la movimentazione merci in ambienti industriali).

Una qualificata analisi preprogetto, il servizio post vendita e le applicazioni Software per la gestione e il controllo di sistemi di magazzini automatici, qualificano System Logisticss come Patners d’impresa per il cliente, nell’ottica di offrire soluzioni sempre adeguate alle esigenze e servizi totali di assistenza e consulenza.

 

 

 

 

 


INQUADRAMENTO DELLA TESI

 

 

 

Obiettivo specifico della tesi

 

 

Il mio progetto è inserito all’interno di un progetto generale col quale System intende eseguire un controllo sulle reali dimensione delle posizioni e profondità  delle celle di un proprio magazzino.

Questo progetto che System intende portare avanti consiste nel rilevare le misure reali delle posizioni e profondità delle celle dello scaffale attraverso una macchina MICRO-IMAGECHECKER M100 che montata su un carrello gli permetterà di scorrere tutto il magazzino rilevando le distanze in base alle varie situazioni di luce. MICRO-IMAGECHECKER M100 è una macchina dalle dimensioni ridotte sulla quale è possibile montare una o più telecamere attraverso le quali essa sarà in grado di rilevare il chiaro del vuoto o lo scuro di un oggetto.

Una volta rilevate le misure reali MICRO-IMAGECHECKER M100 le invierà al Personal Computer attraverso una porta seriale che le inserirà in una tabella di un DataBase. A questo punto entrerà in gioco il mio progetto, attraverso il quale un operatore potrà inserire in un’altra tabella le misure previste per quel magazzino.

Una volta che abbiamo le misure reali e le misure previste del magazzino avverrà un  confronto, e se risultassero delle discordanze rilevanti, quindi che superino un limite stabilito, verranno segnalate; in base a questa segnalazione l’operatore controllerà personalmente le celle del magazzino e se necessario provvederà a correggere questa irregolarità.

La mia tesi in sostanza si occupa della quotazione del magazzino, quindi dell’inserimento in una tabella di un Database delle coordinate X, Y e Z delle posizioni e profondità delle celle di una parte, di più parti o dell’intero magazzino per una o più macchine; dovrà poi permettere all’operatore di modificare queste coordinate sommandogli un numero costante o variabile, quindi oltre all’eliminazione di uno o più record dalla tabella dovrà consentire anche di creare in tabella una copia di una definizione macchina evitando così l’inserimento manuale di tutti i dati.

Interessante sottolineare che il progetto generale pensato da System Logistics è totalmente innovativo, infatti mai in precedenza è stato provata un operazione del genere usando un Personal Computer, questi rilievi sono sempre stati fatti attraverso l'uso di PLC.

 

 

Fasi del lavoro

 

 

Il mio progetto si può sostanzialmente dividere in cinque fasi:

 

1.     Definizione dello scaffale per una determinata macchina

2.     Calcolo quote di una o più parti dello scaffale

3.     Modifica quote di una o più parti dello scaffale

4.     Creazione di uno scaffale per una macchina copiandone uno già esistente in tabella.

5.     Eliminazione di uno scaffale, di uno o di tutti i record presenti in tabella.

 

Nella prima fase viene definito lo scaffale per una determinata macchina e quindi le celle in cui quella macchina può andare a depositare un’unità di carico; verrà inoltre definita la tipologia della cella, quindi il numero posizioni ed il numero profondità che essa può assumere. La definizione da noi creata per una data macchina sarà inserita in una tabella all’interno della quale il numero macchina sarà univoco, infatti non potranno esistere in tabella due definizioni scaffale per la stessa macchina.

Nella seconda fase il progetto permette ad un operatore di calcolare ed inserire in tabella le quote di una parte, di più parti o dell’intero scaffale ora presente in tabella dopo averlo inserito nella prima fase. Le quote saranno calcolate partendo dalle coordinate di una cella iniziale in base a passo piani e passo colonne dati inseriti sempre in questa fase.

Nella terza fase il progetto si occupa della modifica delle quote celle. Per modifica delle quote si intende poter sommare a queste una costante o una variabile incrementale. La modifica si riferisce alle coordinate X, Y in prima e seconda profondità; il tutto sempre riferito ad una parte o all’intero scaffale definito in prima fase.

La quarta fase si occupa della creazione di uno scaffale per una determinata macchina  copiandone uno già esistente in tabella. È possibile inoltre creare per la stessa macchina lo scaffale di sinistra copiandone quello di destra già esistente in tabella e viceversa. Questa fase mi permette di creare uno scaffale saltando la fase uno e la fase due quindi l’inserimento manuale di tutti i dati.

La quinta fase permette l’eliminazione di un record,  di tutti i record riferiti alla macchina o di tutti i record presenti in tabella.

 

 

Macchine e  magazzini a cui è riferito il mio progetto

 

 

Traslo_elevatori

 

 

Il modello RoboStore RS 50 è utilizzato nella movimentazione di scatole o cassette del peso massimo di 50 kg. La struttura è monocolonna in alluminio con doppio gruppo di traslazione, inferiore e superiore; il quadro elettrico è posizionato a terra. Il dispositivo di prelievo può essere previsto con catena, pinze laterali, piattaforma telescopica o gruppo speciale per prelievo / deposito contemporaneo.Le motorizzazioni con servomotori ed il sistema di controllo garantiscono i massimi livelli di prestazione.

I modelli RoboStore RS 100, RS 200 e RS 300 sono utilizzati nella movimentazione di scatole o cassette per la con peso massimo di 300 kg. Sono la versione monocolonna in acciaio e bicolonna in acciaio per carichi multipli. Il dispositivo di prelievo può essere previsto con catena, pinze laterali, piattaforma telescopica o gruppo speciale per prelievo/deposito contemporaneo. Il sistema a due ruote motrici, le motorizzazioni con servomotori ed  il sistema di controllo garantiscono i massimi livelli di prestazione.

I modelli RoboStore RS 350, RS 500 e RS 650 sono utilizzati nelle movimentazioni di carichi pallettizzanti fino 650 kg o di contenitori. La struttura è monocolonna in acciaio con sollevamento a catena.Il dispositivo di prelievo è normalmente realizzato con forche telescopiche a singola e multipla profondità o con gruppi di estrazione a strisciamento. Le motorizzazioni con servomotori ed il sistema di controllo garantiscono i massimi livelli di prestazione. Tutti i modelli sono forniti anche in allestimento “sterzante” per operare su un singolo trasloelevatore su più corsie.

I modelli RoboStore RS 750, RS 1000 e RS 1250 sono i più frequentemente utilizzati nella movimentazione di carichi pallettizzanti con peso massimo di 1250 kg. La struttura è monocolonna in acciaio con sollevamento a catena. Il dispositivo di prelievo è normalmente realizzato con forche telescopiche con singola e multipla profondità. Le motorizzazioni con servomotori ed il sistema di controllo garantiscono i massimi livelli di prestazione. Tutti i modelli sono forniti anche in allestimento “sterzante” per operare su un singolo trasloelevatore su più corsie di magazzino fino ad una altezza di 22 m.

I modelli RoboStore RS 1500 e RS 2000 sono utilizzati nella movimentazione di pallet o contenitori metallici con peso massimo di 2000 kg. La struttura è monocolonna in acciaio con sollevamento a catena. Il dispositivo di prelievo è normalmente realizzato con forche telescopiche con singola e multipla profondità. Le motorizzazioni con servomotori ed il sistema di controllo garantiscono i massimi livelli di prestazione. I modelli sono forniti anche in allestimento “sterzante” per operare su un singolo trasloelevatore su più corsie di magazzino fino ad una altezza di 22 m.

I modelli RoboStore RS 1500, RS 2000,RS 2500 e RS 3000 twin mast, sono utilizzati nella movimentazione di carichi ingombranti con peso massimo di 3200 kg. La struttura è bicolonna in acciaio con sollevamento a catena. Il dispositivo di prelievo è normalmente realizzato con forche telescopiche con singola e multipla profondità. IL sistema a due ruote motrici, le motorizzazioni con servomotori ed il sistema di controllo garantiscono i massimi livelli di prestazione.

 

 

Magazzini e Scaffali

 

 

I trasloelevatori vanno a lavorare su magazzini che appaiono come scaffali costituiti da piani e colonne che vanno a definire un certo numero di celle. Questi scaffali possono raggiungere una altezza di 30 m ed una lunghezza di 185, fino ad avere un numero di 5000 celle. All’interno di ogni cella si possono avere fino a tre posizioni e due profondità e quindi spazio per 6 UDC unità di carico. 

Le macchine sono in grado, scorrendoci in mezzo, di lavorare contemporaneamente su due scaffali uno di destra e uno di sinistra.

Quindi un utilizzatore di questo magazzino può arrivare a gestire un numero che si aggira sulle 30000 UDC esclusivamente attraverso l’uso di macchine.

 

 

 

 

 

 


CAPITOLO 1

 

 

 

 

IL PROBLEMA

 

 

 

Questo capitolo è dedicato alla presentazione del problema trattato all’interno della tesi; questo è stato suddiviso in quattro parti che rispecchiano inoltre le fasi principali del progetto.

Per facilitarne la comprensione il problema è stato presentato attraverso le immagini di tutti i controlli usati all’interno del progetto e alla spiegazione della loro utilità e del loro funzionamento.

Questo capitolo è molto utile per poter fare il primo vero passo all’interno del progetto e capire il modo in cui questo va a risolvere le varie funzioni che permetteranno all’operatore di definire, quotare e modificare le coordinate del magazzino.

 

 

 

 

 


1.1      DEFINIZIONE DELLO SCAFFALE

 

 

Per definizione dello scaffale si intende fornire i dati che mi permetteranno di calcolare il numero di celle, di posizioni e profondità che lo determineranno; questa definizione sarà sempre riferita ad una macchina e ad uno scaffale anch’essi specificati dall’utente.

Si parla di scaffale per riferirsi ad un enorme contenitore di celle dove una o più macchine depositeranno una o più unità di carico U.D.C, questo sarà definito da un numero colonne ed un numero piani, in più per ogni colonna noi possiamo avere più di una cella, quindi in totale avremo un numero celle uguale ai piani per le colonne per il numero celle per colonna; ogni cella avrà anche la possibilità di contenere fino a sei UDC avendo a disposizione tre posti in prima e volendo anche in seconda profondità.

 

 

 


 

 


La definizione avviene nella prima pagina della form contenuta all’interno di un pageframe, che contiene altre quattro pagine per ulteriori funzioni, cliccando sul comando Calcola unico comando attivo, come si vede sotto in figura, che lancerà la procedura Calcolacelle contenuta nelle procedure della Form.

 


 

 

 


Come si vede tutte le Caselle di testo sono inizializzate a 1 per indicare il valore minimo accettato, se infatti venisse inserito uno zero non sarebbe accettato attraverso un apposito controllo che mi vigilerà anche sul valore massimo inserito, che si differenzierà per ogni Casella di testo a seconda della propria funzione.

In questa videata non è visibile la Casella di testo per la prima cella di sinistra perché non è stata selezionato il lato sinistro nella apposita Casella di riepilogo. Una volta selezionato il lato S la Casella di testo per la prima cella di sinistra mi apparirà nello spazio “Selezione lato” a fianco della Casella di riepilogo, quindi potrò inserire il numero del codice cella dal quale inizierà lo scaffale di sinistra.

 Il primo dato che viene inserito nella prima pagina è il numero macchina.

 

 


 

 


Il numero macchina mi permette di specificare per quale trasloelevatore  è riferita la definizione che io sto calcolando, le macchine da noi considerate possono arrivare fino 99 quindi per questa Casella di testo saranno accettati valori che vanno da 1 a 99.

Se si è inserito un numero macchina già presente in tabella al momento del calcolo nella procedura Calcolacelle l’operatore verrà posto davanti a due strade :

1.Rinunciare alla definizione

2.Sostituire la nuova definizione a quella vecchia

In caso si rinunci alla definizione l’operatore verrà riportato a pagina uno per permettergli una nuova definizione, mentre se decidesse di proseguire la procedura eliminerà tutti i record riferiti alla macchina in questione presenti in tabella e quindi inserirà i nuovi. Tutto questo viene fatto perché il numero macchina deve rimanere sempre univoco all’interno della tabella

Una volta inserito il numero macchina bisogna specificare a che scaffale è associata. La macchina può lavorare su un magazzino a due scaffali, quindi può essere associata a due scaffali uno di destra e uno di sinistra.

Per la selezione dello scaffale in prima pagina è stato pensato un apposito spazio “Selezione lato” all’interno del quale io posso appunto selezionare lo scaffale attraverso una Casella di riepilogo che mi permette di scegliere tra due voci “D” o “S” che definiscono rispettivamente lo scaffale di destra e lo scaffale di sinistra.

All’avvio della Form questa casella di riepilogo sarà inizializzata a D; per il motivo che se il primo lato è considerato quello di destra, infatti la sua prima cella sarà sempre la numero uno, a differenza dello scaffale di sinistra dove la prima cella sarà decisa dall’operatore.

Lo scaffale di sinistra è praticamente il continuo dello scaffale di destra, infatti se ad esempio l’ultima cella dello scaffale di destra è la numero 999 la prima di sinistra sarà la numero 1000.

 


 

 

 


L’inserimento della prima cella dello scaffale di sinistra sarà possibile solo se viene selezionato “S” nell’apposita Caselle di riepilogo, infatti quando la selezione avviene sulla casella “D” una disabilitazione del comando Visible non permetterà di vedere la Casella di testo riservata alla prima cella dello scaffale di sinistra, mentre verrà abilitata quando nella Casella di riepilogo verrà selezionato “S”, come si vede dalla figura sotto. Alla selezione di “S” tramite la procedura InteractiveChance della casella di riepilogo verrà reso attiva la Casella di testo per la prima cella dello scaffale di sinistra.

Il valore della Casella di testo della prima cella di sinistra sarà sempre inizializzata, attraverso un controllo, alla prima cella dello scaffale di sinistra della macchina attualmente esistente in pagina uno, trovata in tabella, altrimenti se non venisse trovata sarà inizializzata a zero. In figura 1261 sarà il codice cella della prima cella di sinistra trovata in tabella riferita alla macchina attualmente presente in pagina uno.


 


All’interno della prima pagina compare un secondo spazio “Dati per la definizione” dove inserire i dati per la definizione e quindi il calcolo dei codici, posizioni e profondità delle celle componenti lo scaffale.

 


 

 

 


I primi valori ad essere inseriti in questo spazio sono il numero colonne, il numero piani e il numero celle per colonna. I dati di sinistra mi permetteranno di capire le dimensioni del mio magazzino per questi valori è previsto un numero che va da 1 a n, quindi questi valori vengono inizializzati a 1 e su questi il programma non prevede particolari controlli

 

 


 

 


Se l’operatore provasse ad inserire il numero zero non gli verrebbe permesso da un controllo inserito nella procedura InteractiveChance delle Caselle di testo.

Ogni cella di uno scaffale può avere 1, 2 o 3 posizioni ed 1 o 2 profondità, avendo quindi la possibilità di contenere fino a 6 U.D.C.

Particolare da non dimenticare e’ che le tre posizioni in seconda profondità, quindi dietro a quelle in prima profondità, potrebbero essere sfasate in altezza, mantenendo sempre la stessa X, ma variando di conseguenza la Y altezza e la Z profondità.

Per numero posizioni di una cella si intende un numero posti dove poter depositare unità di carico. Se il numero posizioni è uguale a uno significa che all` interno di quella cella  è prevista la presenza di un'unica unità di carico al centro, mentre per numero posizioni uguale a due le unità di carico previste saranno due, una di sinistra e una di destra, ed infine per numero posizioni uguale a tre le unità di carico possibili all’interno della cella saranno tre, in ordine secondo l` indice usato nel progetto, una di centro, una di sinistra e una di destra.

Il numero profondità uguale a uno indicherà che per quelle celle sono previste solo le posizioni anteriori, mentre per numero profondità uguale a due significherebbe che è possibile inserire due unità di carico nella stessa posizione all` interno della stessa cella una davanti e una dietro.

Se il numero profondità ha valore uguale a due il programma andrà ad abilitare, come si vede sotto, le coordinate in seconda profondità che si trovano in pagina due inizialmente disabilitate essendo tutti i valori in prima pagina inizializzati a uno.

 

 


 


 

 

 

 


Quindi con Numero profondità uguale a due significa che il magazzino è previsto per ospitare U.D.C. anche in seconda profondità; queste coordinate prevedono solo Y e Z infatti la X sarà la stessa dell’unità di carico in prima profondità.

 

 


 


 

 

 

 


La procedura Calcolacelle con la quale si fa il calcolo e l’inserimento in tabella dei codici, posizione e profondità delle celle verrà lanciata tramite un bottone di comando posto all’interno di un contenitore di pulsanti rappresentato da una calcolatrice, abilitato appositamente in questa pagina per questa funzione.

 


 

 

 

 

 


1.2    QUOTAZIONE SCAFFALE

 

 

La quotazione di una parte, di più parti o dell’intero scaffale è possibile attuarla in pagina due. Nella seconda pagina è possibile inserire i dati attraverso i quali  la procedura Coordinate mi calcolerà tutte le quote X, Y e Z delle posizioni e profondità delle celle appartenenti alla parte di scaffale definita sempre in seconda pagina.

Importante sapere è che la parte di scaffale considerata farà riferimento alla definizione avvenuta in pagina uno e quindi alla macchina al momento presente in prima pagina.

L’accesso a questa pagina sarà quindi permesso solo se viene riscontrata in tabella una situazione macchina uguale a quella in prima pagina.

Questo controllo verrà fatto prima sul numero celle poi sulla situazione posizioni e profondità ed alla prima discordanza verrà vietato l’accesso per evitare di lavorare sulla macchina errata.

 

 


 

 

 


La quotazione avviene nella seconda pagina della form contenuta all’interno di un pageframe, che contiene altre quattro pagine per ulteriori funzioni, cliccando sul comando Calcola unico comando attivo, come si vede in figura, che lancerà la procedura Coordinate contenuta nelle procedure della Form.

 


 

 

 


La seconda pagina è suddivisa in tre spazi all’interno dei quali inserire i dati per le diverse funzioni.

Nel primo spazio verranno inseriti i dati per la definizione della parte di scaffale per la quale si vuole inserire in tabella le quote delle posizioni e profondità delle celle ed i dati che mi permetteranno di avere il passo col quale calcolarle, in sostanza qui l’utente selezionerà la parte di tabella su cui fare la quotazione.

Colonna inizio mi indicherà la colonna dello scaffale da dove iniziare la quotazione della definizione al momento presente in prima pagina e Numero colonne mi dirà per quante colonne questa quotazione deve proseguire; il passo colonne invece mi indicherà il passo della colonna e quindi, a seconda del numero celle per colonna in prima pagina, mi darà il riferimento per il calcolo delle coordinate X.

Su questi valori andranno fatti vari controlli al fine di evitare che l’operatore possa cadere il diversi malfunzionamenti. Il primo controllo verrà fatto sulla colonna inizio infatti questa non dovrà mai essere maggiore del Numero colonne dello scaffale come non dovrà mai superare questo valore anche il Numero colonne sommato alla Colonna inizio, altrimenti la quotazione inizierà o continuerà per colonne che in realtà non esistono. Per il passo colonne non ci sono particolari limitazioni.

La parte di destra di questo spazio è riservata al piano da dove iniziare la mia quotazione ed il numero piani per i quali questa deve proseguire ed un passo piani che mi indica appunto l’altezza di un piano e quindi mi permettere di calcolare le coordinate Y Per questi valori vale naturalmente il discorso fatto in precedenza per le colonne e quindi i loro valori non dovranno superare il reale valore del numero piani dello scaffale definito in pagina uno.

Un secondo spazio è dedicato alle coordinate della prima cella da cui inizierà il calcolo delle quote eseguito grazie al passo colonne ed al passo piani

 


 

 

 


La prima cella da cui partire con la quotazione è già stata trovata prima grazie ai dati inseriti nel primo spazio, ora grazie a queste coordinate la procedura Coordinate saprà da che valori iniziare il calcolo delle quote e quindi sarà in grado una volta determinati i giusti valori di inserire in tabella le coordinate X, Y e Z fino a questo momento uguali a zero..

Le coordinate della prima cella si riferiranno precisamente alla prima posizione all’interno della prima cella che sarà uguale a quella centrale se il numero posizioni fosse uguale a 1 o a 3; se invece il numero posizioni fosse uguale a 2 la prima sarebbe quella di sinistra

Il terzo spazio è riservato alle coordinate in seconda profondità come già trattato nel paragrafo precedente saranno utilizzabili dall’utente solo se in prime pagina è stato inserito un numero profondità uguale a 2 in caso contrario queste rimarranno allo stato iniziale vale a dire disabilitate.

Queste coordinate saranno riferite alla prima posizione della prima cella in seconda profondità quindi manterranno sempre la stessa X della posizione più avanzata, ma potranno essere sfasate in altezza e in profondità

La procedura Coordinate con la quale si fa il calcolo e l’inserimento in tabella delle quote, verrà lanciata tramite un bottone di comando posto all’interno di un contenitore di pulsanti rappresentato da una calcolatrice, abilitato appositamente in questa pagina per questa funzione.

 


 

 

 

 

 


1.3    MODIFICA QUOTE

 

 

La modifica di una parte, di più parti o dell’intero scaffale è possibile attuarla in pagina tre.

Per modifica si intende poter andar a sommare alle coordinate X e Y in precedenza inserite in tabella una costante o una variabile incrementale, inserita in una apposita Casella di testo dall’utente che sempre in terza pagina avrà inserito anche i dati necessari per la selezione delle celle su cui andare a fare l’operazione.

Nella terza pagina è quindi possibile inserire i dati attraverso i quali  la procedura Modificacelle mi calcolerà tutte le nuove quote delle posizioni e profondità delle celle appartenenti alla parte di scaffale definita all’interno della stessa pagina.

Importante è il fatto che la parte di scaffale considerata sarà riferita alla definizione avvenuta in pagina uno e quindi alla macchina al momento presente in prima pagina. L’accesso a questa pagina sarà quindi permesso solo se viene riscontrata in tabella una situazione macchina uguale a quella in prima pagina.

Questo controllo verrà fatto prima sul numero celle poi sulla situazione posizioni e profondità ed alla prima discordanza verrà vietato l’accesso per evitare di andare a lavorare sulla macchina errata.

 

 

 

 


 

 


La modifica avviene come detto nella terza pagina della Form contenuta all’interno di un pageframe, che contiene altre quattro pagine per ulteriori funzioni, cliccando sul comando Modifica unico comando attivo, come si vede in figura, che lancerà la procedura Modificaquote contenuta nelle procedure della Form.

 


 

 

 


La pagina è divisa in tre spazi “Dati per la modifica delle celle” , “Somma costante” e “Somma incrementale” ognuno caratterizzato da specifiche funzioni.

Il primo spazio sarà riservato ai dati per la definizione della parte di scaffale per la quale si vuole andare a modificare le quote delle posizioni e profondità delle celle, qui noi in sostanza andiamo a selezionare la parte di tabella su cui fare la modifica.

Colonna inizio mi indicherà la colonna dello scaffale da dove iniziare la modifica della definizione al momento presente in prima pagina, mentre il Numero colonne mi dirà per quante colonne questa modifica deve proseguire. Su questi valori andranno fatti vari controlli al fine di evitare che l’operatore possa cadere il diversi malfunzionamenti. Il primo controllo verrà fatto sulla colonna inizio infatti questa non dovrà mai essere maggiore del Numero colonne dello scaffale come non dovrà mai superare questo valore anche il Numero colonne sommato alla Colonna inizio altrimenti la modifica inizierà o continuerà per colonne che in realtà non esistono.

La parte di destra di questo spazio è riservata al piano da dove iniziare la mia modifica ed il numero piani per i quali questa deve proseguire. Per questi valori vale naturalmente il discorso fatto in precedenza per le colonne e quindi i loro valori non dovranno superare il reale valore del numero piani dello scaffale definito in pagina uno.

Un secondo spazio è dedicato alle “Somma costante” con la quale ci si propone di sommare a tutte le coordinate delle posizioni e profondità delle celle selezionate prima una costante; questa somma è possibile farla contemporaneamente sulla variabile X e Y come si vede dalla figura dove nel caso specifico verrà sommato 100 contemporaneamente alle X e alle Y.

 

 

 

 


 

 

 

 


Un terzo spazio è dedicato alla “Somma incrementale” con la quale è possibile sommare a tutte le coordinate delle posizioni e profondità delle celle selezionate prima, una variabile che verrà moltiplicata da un numero che incrementerà di uno di cella in cella, questo numero si rinizializzerà tutte le volte che si passerà ad una cella del piano superiore; come prima anche questa somma è possibile farla contemporaneamente sulla variabile X e Y; cosa che non è possibile è di fare il calcolo di questa somma contemporaneamente alla somma costante della stessa variabile, infatti, come si vede dalla figura, se una Casella di testo di una variabile per la somma costante risulta essere diversa da zero un controllo disabiliterà immediatamente la Casella di testo della stessa variabile per la somma incrementale, e viceversa, impedendo quindi che tutte e due siano diverse da zero per evitare malfunzionamenti del programma; regola che vale anche per la somma costante infatti anche questa non potrà mai essere fatta contemporaneamente ad una somma incrementale della stessa variabile.

 


 

 

 


La procedura Modificaquote con la quale si fa il calcolo delle nuove quote, verrà lanciata tramite un bottone di comando posto all’interno di un contenitore di pulsanti rappresentato da una matita e un righello, abilitato appositamente in questa pagina per questa funzione.

 


 

 


1.4    COPIA DI UNA DEFINIZIONE

 

 

Per copia di una definizione intendiamo la creazione di una definizione di uno scaffale per una macchina copiandone una già esistente in tabella; questa operazione, eseguibile in quinta pagina, risulterà molto utile perché permetterà di evitare l’inserimento dato per dato e quindi la fase uno e la fase due. Nella quinta pagina è possibile inserire i dati attraverso i quali il programma contenuto all’interno della sua procedura Click mi creerà ed inserirà in tabella la nuova definizione.

Per creare la copia della definizione la procedura avrà bisogno di sapere il numero macchina da cui copiarla e il numero macchina per quale crearla e i rispettivi scaffali e se necessario la prima cella degli scaffali di sinistra

 

 

 

 


 

 

 


La copia avviene nella quinta pagina della form contenuta all’interno di un pageframe, che contiene altre quattro pagine per ulteriori funzioni, cliccando sul comando Copia unico comando attivo, come si vede in figura, che eseguirà il programma contenuto all’interno della sua procedura Click.

 


 

 

 


Questa pagina è divisa in due spazi “Crea una definizione scaffale per una macchina copiandone una già esistente” e “Elimina solo una parte della tabella”. Nel primo è possibile creare una definizione scaffale per una macchina nuova semplicemente copiandone una già presente in tabella. Questa operazione sarà possibile inserendo nella Casella “Sorgente” il numero macchina da cui si vuole copiare la definizione ed nella Casella “Lato sorgente” il suo scaffale; poi andando ad inserire sotto gli stessi dati per la nuova macchina.

 


 

 

 


Il lato è stato inizializzato a “D”, ma se venisse selezionato il lato sorgente “S”, come in figura, verrebbe resa visibile la Casella di testo “Prima cella sinistra sorgente” fino a quel momento non visibile e quindi reso possibile l’inserimento del giusto valore senza li quale il programma non sarebbe in grado di trovare la prima cella dello scaffale di sinistra in tabella riferita a quella macchina; questo valore andrà inserito anche quando il lato sorgente è ”D”, perché il programma dovrà essere sempre in grado di sapere dove termina questo lato per non fare la copia di celle che appartengono al lato sinistro. Nell’esempio in figura sopra il programma andrà a fare la copia dello scaffale di sinistra della macchina uno per lo scaffale di destra della macchina due; andrà quindi in tabella e partendo dalla cella numero 1261 della definizione scelta farà la copia


 

 

 


E’ possibile anche creare, come in figura sopra, una definizione dello scaffale di sinistra per una macchina copiandone la sua definizione dello scaffale di destra già esistente in tabella; in questo esempio non è stato inserito il valore della prima cella sinistra sorgente perché in tabella il programma troverà solo celle del lato destro.

Un errore che può essere fatto è voler fare una copia del lato di destra quando in tabella sono presenti entrambi i lati e non inserire il valore della prima cella del lato di sinistra, infatti a questo punto il programma quando va a fare la copia non si limiterà al lato destro, ma non potendo distinguerli continuerà facendo la copia di entrambi.


 

 


Nel secondo spazio l’operatore sarà in grado di poter eliminare dalla tabella tutte i record riferiti ad una macchina da lui voluta. Per usufruire di questa possibiltà bisognerà selezionare la Casella di controllo “Elimina solo una macchina” così che venga abilitato, come si vede in figura, il comando Cancella fino a quel momento disabilitato. Questo comando mi permetterà l’eliminazione dei record della macchina inserita nella Casella di testo “Macchina” grazie ad un programma nella sua procedura Click.


CAPITOLO 2

 

 

 

 

 

 

 

LA SOLUZIONE

 

 

 

 

 

 

Questo capitolo si occupa, a differenza del primo dove si è cercato di rappresentare il problema nel modo più semplice possibile, della soluzione e quindi entrerà più nello specifico della programmazione degli oggetti e dei controlli usati all’interno del progetto. Il capitolo è diviso in tre parti che rappresentano i principali oggetti utilizzati dal progetto.

Verrà spiegato passo per passo la progettazione del Form, del Pageframe e dei Comandi e quindi di tutti gli oggetti in essi contenuti, descrivendone le proprietà e la procedure più significative.

 

 

 

 

 


2.1    FORM

 

 

La Form del mio progetto è composto essenzialmente da due oggetti: un Pageframe ed un contenitore di comandi. Questo oggetto mi permette di avere sempre ben in vista la situazione comandi e una semplice e veloce consultazione delle varie situazioni grazie alle cinque pagine componenti il Pageframe. È stato usato un form di tipo Formmodal per adeguarsi alle esigenze del programma WINSTORE 3.00 utilizzato per la progettazione e descritto dettagliatamente nel capitolo seguente.


La proprietà principale utilizzata dalla Form è stata DataSession impostata a due che indica una sessione dati privata. Ho utilizzato la procedura Init per innanzitutto rendere attiva all’inizializzazione della Form la pagina 4 e quindi dare una idea generale della situazione attuale all’operatore attraverso la consultazione della tabella, poi per inizializzare la Casella di testo della prima cella dello scaffale di sinistra mettendola uguale al giusto valore trovato in tabella per la macchina attualmente in prima pagina o a zero se in tabella risultasse non presente uno scaffale di sinistra per quella macchina. Poi ho creato altre tre procedure per la Form che mi permetteranno di eseguire le principali funzioni del progetto. La prima procedura creata si chiama Calcolacelle, questa procedura calcola le posizioni e profondità delle celle di uno scaffale e le inserisce in tabella con coordinate tutte a zero. Coordinate è la seconda procedura creata e mi permette di fare il calcolo delle quote della parte dello scaffale da me desiderata. L’ultima procedura inserita è Modificacelle, questa mi permette di sommare alle celle in tabella un numero che può essere costante o incrementale.

2.1.1    La procedura Calcolacelle

 

 

La procedura si occupa della creazione delle posizioni e profondità delle celle di uno scaffale e le mette in tabella tutte a coordinate azzerate. Questa procedura svolge la funzione più importante per il mio progetto, infatti prima di questa nessuna delle altre due procedure Coordinate e Modificaquote potrà essere eseguita.

Come prima cosa la procedura va a selezionare la tabella all’interno del database sulla quale lavorare, attraverso il comando Select, poi fà il calcolo del numero celle grazie ai dati inseriti nel secondo spazio “Dati per la definizione” di pagina uno.

Ora Calcolacelle tenta il blocco della tabella per impedire che venga usata da più utenti. Secondo controllo che viene fatto è se il numero celle calcolato per lo scaffale di destra comprende celle di sinistra, in questo caso l’utente verrà informato tramite un messaggio mostrato dalla figura sotto e gli verrà permesso di rinunciare o continuare l’operazione attraverso il clic su “ANNULLA” o su “OK”.

 

 

 


 


Terzo ed ultimo controllo viene fatto sul numero macchina; infatti la procedura vede se esiste già in tabella la macchina che è stata scelta, se la macchina è presente l’utente verrà posto davanti a due strade, rinunciare o continuare; nel caso l’utente voglia continuare sarà messo al corrente che la definizione attuale andrebbe a sostituire quella già presente in tabella.


 

 


Questa sostituzione avviene prima eliminando tutti i record in tabella riferiti alla macchina, poi inserendo i nuovi. L’eliminazione dei record non avviene in senso fisico, ma mettendo il numero macchina a zero e selezionando il record con Delete; in questo modo i record selezionati verranno messi all’inizio della tabella da un apposito indice e potranno poi essere recuperati al momento opportuno, grazie alla selezione non saranno visibili in tabella.

Quindi ora la procedura inizia l’inserimento dei valori nei campi dei record usando il comando Replace.

Il primo valore inserito è il numero macchina, poi la procedura per inserire il codice cella deve controllare se lo scaffale è di destra o di sinistra, quindi se la prima cella è uno o uguale alla Casella di riepilogo numero prima cella di sinistra.

A questo punto vengono definiti i valori dei campi posizione e profondità grazie alle apposite Caselle di testo in pagina uno. Sono state previste tre posizioni: centrale, sinistra e destra per queste posizioni in tabella verranno inseriti rispettivamente “00””01”e”02”, mentre per le due profondità anteriore e posteriore “00” e “01”. Gli ultimi valori inseriti sono le coordinate che questa procedura metterà tutte a zero.

Infine Calcolacelle sblocca la tabella e fa un Refresh sulla tabella aggiornandola e attiva pagina due per permettermi l’inserimento delle quote. Il lancio della procedura sarà possibile al clic del comando Calcola, infatti all’interno della procedura Click di questo comando vi è un richiamo alla procedura Calcolacelle.

A questo punto dopo avere fatto il clic del comando Calcola avremo in tabella tutta la definizione riguardante la macchina e solo ora potrò inserire o modificare le quote.

 

2.1.2    La procedura Coordinate

 

 

Coordinate permette di calcolare ed inserire in tabella le quote delle celle di una parte, di più parti  o dell’intero scaffale.

Importante sapere di questa procedura è che il calcolo si basa sui dati di pagina due, ma considerando le celle riferite alla definizione scaffale per la macchina inserita in pagina uno, anche per questo a scanso di errori sono stati pensati diversi controlli tutte le volte che viene richiesto l’accesso alla pagina due, quindi l’uso della pagina sarà concesso solo se esiste una definizione in tabella corrispondente ai dati di pagina uno; questo controllo verrà fatto prima sul numero celle, poi sullo stato delle posizione e delle profondità. Nel caso venga impedito l’accesso vorrebbe significare che l’operatore inavvertitamente ha cambiato il valore numero macchina, e quindi la definizione non risulta più essere quella per la macchina inserita in tabella, o chiede di entrare in pagina due senza avere prima lanciato Calcolacelle e quindi inserito i dati in tabella; a questo punto verrà attivata pagina uno per permettergli di inserire un numero macchina corretto o di cliccare su Cmd1 ed inserire la definizione in tabella. Questo controllo evita di quotare o modificare celle differenti alle quali l’operatore sia realmente interessato.

Il calcolo delle quote verrà fatto, partendo da una coordinata iniziale ed in base al passo colonne digitati in pagina due e al numero colonne e numero celle per colonna di pagina uno per le X, mentre per le Y in base al passo piani e al numero piani.

Se in pagina1 sono state inserite due profondità, Coordinate è in grado di calcolare anche le quote in seconda profondità, quindi all’attivazione della seconda pagina un controllo abiliterà Y2 e Z2 per permetterne l’uso. Per queste celle risulterà una variazione di Y e Z, mentre X rimarrà invariata, quindi le celle in seconda profondità saranno sfasate anche in altezza.

Questa procedura sarà lanciata grazie al clic di Cmd1 il comando Calcola, rappresentato da una calcolatrice, che verrà abilitato all’attivazione di pagina due per il suo lancio.

Come prima cosa, dopo avere selezionato attraverso Select la tabella all’interno del database su cui lavorare e inizializzato tutte le variabili utili alla procedura Coordinate, calcolerà il passocelle; questo valore risulterà molto importante infatti è il valore che mi permette di sapere il passo effettivo di una cella avendo prima solo il passo delle colonne, quindi se il passo colonne sarà dieci e le celle per colonna due il passocella sarà uguale al primo diviso il secondo quindi cinque.

Ora la procedura trova la posizione della prima cella della parte scaffale in base ai dati inseriti in pagina due e da questa partirà con la quotazione, se lo scaffale considerato è quello di sinistra allora si sommerà a questo numero il numero della prima cella di sinistra.

Dopo avere imposto di considerare solo i record non selezionati da Deleted con un Set deleted on e ordinato la tabella secondo un indice creato in precedenza, tenta di bloccarla per evitare che più utenti lavorino contemporaneamente su di essa. Se il blocco tabella non ha avuto successo l’operatore ne verrà messo al corrente attraverso un messaggio, mentre in caso contrario la procedura continuerà con il calcolo vero e proprio e l’inserimento dei dati nei record in tabella.

Attraverso cinque cicli For con una Seek la procedura Coordinate seleziona la giusta posizione e profondità della cella considerata e inserisce nel record selezionato le quote X, Y e Z calcolate in base al valore delle Caselle di testo delle coordinate della prima cella e del passocella che viene calcolato alla fine del ciclo delle posizioni cella. Dopo avere inserito i dati ci sarà un aggiornamento della posizione della cella da selezionare.

Alla fine del ciclo delle profondità con una Skip si selezionerà il record successivo, mentre alla fine del ciclo delle colonne la procedura farà il calcolo della X e della Y da inserire nella prossima cella al piano superiore.

 

 

 

 

 

 

2.1.3    La procedura Modificaquote

 

 

Modificaquote fa la somma di una costante o una variabile incrementale alle quote delle celle della parte di scaffale determinata da colonna e piano iniziale, numero colonne e numero piani inseriti in pagina tre. Questo calcolo lo fa sempre riferendosi alle celle della macchina in prima pagina, quindi come in Coordinate verrà concesso l’accesso in pagina tre solo se in tabella è rilevata una situazione macchina uguale a quella risultante in pagina uno; questo controllo verrà fatto prima sul numero celle, poi sullo stato delle posizione e delle profondità, in caso contrario all’operatore sarà impedito l’accesso. In questi casi vorrebbe dire che l’operatore inavvertitamente ha cambiato il valore numero macchina, e quindi la definizione non risulta più essere quella per la macchina inserita in tabella o chiede di entrare in pagina tre senza avere prima lanciato Calcolacelle e quindi inserito i dati in tabella; a questo punto la procedura attiverà pagina uno per permettergli di inserire il numero macchina esatto o di cliccare  su Cmd1 ed inserire la definizione in tabella. Questo controllo evita di quotare o modificare celle differenti alle quali l’operatore sia realmente interessato. La somma alle quote può essere costante o incrementale e può essere effettuata alle X o alle Y.

Per somma costante si intende semplicemente prendere le quote delle celle in una determinata posizione e profondità e sommargli una costante, mentre la una somma incrementale consiste nel sommare una variabile che verrà moltiplicata per un numero che incrementerà di uno di cella in cella fino a tornare al numero iniziale passando ad un piano superiore.

La somma costante escluderà la somma incrementale per la stessa coordinata, infatti un controllo all’uso di una disabiliterà l’altra. L’utilizzazione di questa procedura è permessa dal clic su cmd2 il comando Modifica, rappresentato da una matita e un righello, che verrà abilitato all’attivazione di pagina tre.

Come prima cosa Modificaquote selezionerà con Select la tabella all’interno del database su cui lavorare e dopo avere inizializzato tutte le variabili utili alla procedura calcolerà la posizione della prima cella della parte scaffale in base ai dati inseriti dall’operatore nel primo spazio di pagina tre e da questa partirà con la somma, se lo scaffale considerato è quello di sinistra allora si sommerà al codice cella trovato il numero della prima cella di sinistra.

Dopo avere imposto di considerare solo i record non selezionati da Delete con un Set deleted on e ordinato la tabella secondo un indice creato in precedenza tenta di bloccarla per evitare che più utenti lavorino contemporaneamente su di essa. Se il blocco tabella non ha avuto successo l’operatore ne verrà messo al corrente attraverso un messaggio, mentre in caso contrario la procedura continuerà con il calcolo vero e proprio e l’inserimento dei dati nei record in tabella.

Attraverso cinque cicli For  con una Seek la procedura Modificaquote selezionerà la giusta posizione e profondità della cella considerata e inserirà nel record selezionato le somme di X e Y calcolate in base al valore delle apposite Caselle di testo in pagina tre

Dopo avere inserito i dati ci sarà un aggiornamento della posizione della cella da selezionare.

Alla fine del ciclo delle profondità con una Skip si selezionerà il record successivo, mentre alla fine del ciclo delle colonne la procedura calcolerà il contatorey, col quale eseguirà il calcolo della somma incrementale alle Y, mi azzererà il contatorex per la somma incrementale delle X.

Infine viene sbloccata la tabella e chiusa la transizione.

 

 

 

 

 

 

 

 

 

2.2   IL PAGEFRAME

 

 

Questo oggetto mi permette di raccogliere in modo ordinato e quindi mi permette una semplice consultazione di tutte le informazioni contenute all’interno del progetto suddividendole in cinque pagine caratterizzate ognuna da una specifica funzione.

Non sono state usate procedure di questo oggetto ed in particolare è stata usata una proprietà, che determina il suo numero di pagine, Page Count impostata naturalmente a cinque.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2.2.1    Prima Pagina

 

 

La prima pagina è sicuramente la più importante nell’esecuzione del progetto, qui infatti vengono inseriti i dati grazie ai quali la procedura Calcolacelle creerà ed inserirà i record in tabella.

Di questa oggetto è stata usata solo la sua procedura Refresh() per rinfrescare il valore della Casella di testo della prima cella di sinistra in modo d’avere sempre all’accesso in pagina il valore riferito alla macchina giusta.

 


 

 

 


Attraverso la proprietà Caption è stato possibile intestare la pagina con “Definizione Scaffale”

Oggetti contenuti in pagina uno e loro proprietà e procedure più significative:

 

 

Cmalabel1: Etichetta Nmac “Macchina”

 

Nmac: Casella di testo attraverso la quale viene definito il numero macchina

Procedure utilizzate: Lostfocus

Proprietà  utilizzate: Name, Tablndex, Value

 

Shape1: Spazio riservato ai dati per il lato 

Proprietà utilizzati: SpecialEffect

 

Cmalabel2: Etichetta Shape1 “Selezione lato :”

 

Cmalabel3: Etichetta Combo1 “Lato :”

 

Cmalabel4: Etichetta Npce “Numero prima cella lato SX :”

Proprietà utilizzate: Visible

 

Npce: Casella di testo che definisce il numero prima cella di sinistra

Proprietà  utilizzate : Name, Tablndex, Value, Visible

 

Combo1: Casella di riepilogo che definisce il lato scaffale

Procedure utilizzate: Init, Interactivechace, Lostfocus

Proprietà utilizzate: Name, Rowsource, RowsourceType, Tablndex

 

Shape2: Spazio riservato ai dati per la definizione

 

Cmalabel5: Etichetta Shape2 “Dati per la definizione:”

 

Cmalabel6: Etichetta Ncol “Numero colonne:”

 

Cmalabel7: Etichetta Npia “Numero piani:”

 

Cmalabel8: Etichetta Ncco “Numero celle per colonna”:

 

Cmalabel9: Etichetta Npos “Numero posizioni”

 

Cmalabel10: Etichetta Npro “Numero profondità”

 

Ncol: Casella di testo che mi definisce il numero di colonne

 

Npia: Casella di testo che mi definisce il numero di piani

 

Ncco: Casella di testo che mi definisce il numero di celle per colonna

 

Npos: Casella di testo che mi definisce il numero di posizioni

Procedure utilizzate: LostFocus

 

Npro: Casella di testo che mi definisce il numero di profondità

Procedure utilizzate: LostFocus

 

 

Funzionamento delle principali procedure e proprietà utilizzate dai vari oggetti contenuti in pagina uno.

 

 

Ho inserito nel metodo Active di pagina1 un Refresh della form che  permetta l’attivazione dei comandi utili alla pagina. La proprietà Caption mi permette di rappresentare la pagina con “ Definizione scaffale”. Per le etichette Cmalabel è stata usata un’unica proprietà significativa Caption con la quale si definito il suo testo. Nella prima pagina ho inserito un insieme di CmaText che permetteranno all`operatore di inserire con Nmac il numero di macchina, Ncol il numero colonne, Npia il numero piani, Ncco il numero celle per colonne ed inoltre con Npos ed Npro il numero posizioni e numero profondità  previste all’interno di una singola cella; una semplice Combo invece mi guiderà alla selezione  del lato dello scaffale destro o sinistro. Ogni dato inserito avrà delle limitazioni e controlli che eviteranno errori all’interno del progetto. Per il numero macchina è stato previsto un numero che va da 1 a 99; questo all’interno della tabella deve essere univoco, quindi se viene inserita una definizione scaffale con un numero macchina già presente nella tabella il programma permetterà due strade:

1.     Annullare la definizione

2.     Proseguire la definizione andando a sostituire quella già esistente.

La scelta del lato dello scaffale è stata facilitata da Combo1 nella quale andare a selezionare il lato “D “ o il lato “S “, nella sua procedura Interactivechace ho inserito un controllo che renderà visibile Cmalabel4 e Ncpe se e solo se il lato risulterà essere quello di sinistra, se venisse inserito un valore diverso dai due detti in precedenza un controllo all’interno della procedura Lostfocus me lo farà notare e metterà il valore uguale a ”D “, infatti ogni altro valore non sarà permesso perché potrebbe portare a diversi errori. Nella procedura Init inizializzo la Combo1 mettendo il suo valore uguale a “D “. Le proprietà Rowsource e RowsourceType mi definiscono i valori delle caselle della Combo.

In Npce verrà riportato il numero della prima cella del lato sinistro dello scaffale , questo dovrà essere inserito sempre anche se la definizione non interessa apparentemente  questo lato, perché la procedura Calcolacelle ne avrà bisogno, infatti sarà fondamentale sapere dove inizia e dove termina il lato destro.

Inizialmente Npce non sarà visibile grazie all` impostazione a false della sua proprietà Visible, sarà possibile vederlo solo se sarà selezionato il lato sinistro. Il suo valore sarà uguale a quello della prima cella di sinistra, relativa al numero macchina corrente, presente in tabella; se non venisse trovato nessun valore Npce risulterà uguale a zero. Per il numero colonne non ci sono ne’ limitazioni ne’ controlli come per il numero di piani ed il numero celle per colonna.

Il numero posizioni all’interno della cella dovrà essere 1 2 o 3, mentre il numero profondità potrà  essere 1 o 2. In base a questo valore verranno abilitate le coordinate in seconda profondità situate in seconda pagina, mettendo le loro proprietà Enabled, proprietà che determina se un controllo è attivo o meno, uguale a true. I controlli di Npos e Npro verranno fatti usando Lostfocus, così rilasciando la Casella  di testo il programma attraverso un messaggio informerà dell’errore l’operatore e lo correggerà automaticamente forzando il valore a uno.

Una volta inseriti tutti questi dati l’operatore e’ in grado di poter calcolare e quindi definire il numero di celle dello scaffale, con coordinate tutte a 0, attraverso l` apposito pulsante Cmd1 rappresentato da una calcolatrice. Se tutto va bene verranno così inserite tutte le celle con relativa macchina, posizione, profondità e coordinate tutte a zero in una tabella QUOTE e tramite Activepage, attivazione di una macchina, si salta a pagina due, ma se il programma tramite un controllo Refresh, rinfresco comandi, di pagina due non trovasse in tabella una definizione rappresentante la situazione in pagina uno bloccherà il passaggio e  la pagina attivata rimarrà la numero uno.

 

 

 

2.2.2    Seconda Pagina

 

 

La seconda pagina è la parte del progetto che mi permette di quotare una parte della tabella, qui infatti vengono inseriti i dati grazie ai quali la procedura Coordinate calcolerà ed inserirà in tabella le coordinate fino a quel momento uguali a zero.

Di questa pagina è stata usata solo la sua procedura Refresh per controllare che in tabella esista una definizione che rispecchi la situazione in pagina uno e per abilitare o meno le coordinate in seconda profondità a seconda del numero profondità inserito in pagina uno; in più è stata usata la procedura Active che all’attivazione della pagina abilita i comandi.

 


 

 

 

 


Oggetti contenuti in pagina due e loro proprietà e procedure più significative:

 

 

 

Shape1: Spazio riservato ai dati per la quotazione scaffale

Proprietà  utilizzate: SpecialEffect

 

Cmalabel1: Etichetta Shape1 “Selezione lato”

 

Cmalabel2: Etichetta Colini “Colonna Inizio”

 

Cmalabel3: Etichetta Ncol “Numero colonne :”

 

Cmalabel4: Etichetta PasCol “Passo colonne“

 

Cmalabel5: Etichetta PiaIni “Piano inizio”

 

Cmalabel6: Etichetta Npia “Numero piani“

 

Cmalabel7: Etichetta PasPia “Passo piani”

 

Colini: Casella di testo che definisce la colonna di inizio

Procedure utilizzate: LostFocus

 

 

Ncol: Casella di testo che definisce il numero colonne

Procedure utilizzate: LostFocus

 

PasCol: Casella di testo che definisce il passo colonna

 

PiaIni: Casella di testo che definisce il piano di inizio

Procedure utilizzate: LostFocus

 

Npia: Casella di testo che definisce il numero piani

Procedure utilizzate: LostFocus

 

Paspia: Casella di testo che definisce il passo piani

 

Shape2: Spazio riservato alle coordinate della prima cella in prima profondità

Proprietà  utilizzate: SpecialEffect

 

Cmalabel8: Etichetta Shape2 “Coordinate prima cella”

 

Cmalabel9: Etichetta X “X”

 

Cmalabel10: Etichetta Y “Y”

 

Cmalabel11: Etichetta Z “Z”

 

X: Casella di testo che definisce la coordinata x prima cella

 

Y: Casella di testo che definisce la coordinata y prima cella

 

Z: Casella di testo che definisce la coordinata z prima cella

 

Shape3: Spazio riservato alle coordinate della prima cella in seconda profondità

Proprietà  utilizzate: SpecialEffect

 

Cmalabel12: Etichetta Shape3 “Coordinate prima cella in seconda profondità :”

Proprietà utilizzate: Enabled

 

Cmalabel13: Etichetta Y “Y”

Proprietà utilizzate: Enabled

 

Cmalabel14: Etichetta Z “Z”

Proprietà utilizzate: Enabled

 

Y2: Casella di testo che definisce la coordinata y in seconda profondità

Proprietà utilizzate: Enabled

 

Z2: Casella di testo che definisce la coordinata z in seconda profondità

Proprietà utilizzate: Enabled

 

 

 

Funzionamento delle principali procedure e proprietà utilizzate dai vari oggetti contenuti in pagina due

 

 

Con un RefreshForm inserito in Active di pagina due rinfresco la situazione pulsanti andando ad abilitare solo quelli utili alla pagina. 

Nella procedura Refresh della pagina ho inserito un controllo che mi permette di lavorare sulla pagina solo se è stata rilevata in tabella una situazione macchina uguale a quella riscontrata in Page1, questo per evitare che l’operatore vada a quotare una scaffale per una macchina diversa da quella realmente voluta. Il programma andrà prima a fare un controllo sul numero celle poi sulle posizioni e profondità; trovata una discordanza l’operatore verrà informato tramite un messaggio e verrà impedito l’accesso alla pagina venendo riportati a pagina uno.

Sempre nel Refresh sono state inserite delle istruzioni che mi permetteranno di andare ad abilitare le coordinate in seconda profondità, in partenza disabilitate, se in pagina uno il numero  profondità inserito è uguale a due.

Per gli spazi Shape è stata usata la proprietà SpecialEffect con la quale si ottiene un effetto tridimensionale dei bordi che delimitano lo spazio all’interno del quale andare ad inserire i dati.

Per le etichette Cmalabel è stata usata un’unica proprietà significativa Caption con la quale si è definito il suo testo; in alcune attraverso la proprietà Enable è stata prevista l’abilitazione solo in particolari situazioni.

Nella seconda pagina l’operatore inserirà il numero della prima colonna e del primo piano dello scaffale da cui si vuole partire con la quotazione ed il numero delle colonne e dei piani per i quali questa deve proseguire.

Verranno poi inseriti il passo delle colonne ed il passo dei piani, infine verranno inserite le coordinate delle prima cella in prima, ed  eventualmente in seconda profondità. Come nella pagina precedente con l` apposito comando verrà quotata la parte di scaffale in base alle coordinate iniziali e al passo colonne e passo piani.

Nel metodo LostFocus del numero prima colonna Colini e primo piano PiaIni sarà’ inserito un controllo che impedirà l’inserimento di un numero uguale a 0 o maggiore di quello inserito in pagina1, mentre nel numero colonne Ncol e numero piani Npia questo controllo si assicurerà che la somma del numero di inizio e del numero di scansione non superi il numero totale di piani o colonne in pagina uno.

Per il CmaText  passo colonne e passo piani non sono state previste limitazioni, così come per le coordinate in prima e seconda profondità’.

Per tutti i CmaText è stata usata la proprietà Value per inizializzarne il valore: per le coordinate uguale a zero e per gli altri uguale a uno.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2.2.3    Terza Pagina

 

 

La terza pagina è la parte del progetto che mi consente di modificare le quote di una parte della tabella, qui infatti vengono inseriti i dati grazie ai quali la procedura Modificaquote calcolerà ed inserirà in tabella le nuove coordinate.

In questa pagina è stata usata la procedura Refresh, come nella pagina precedente, per controllare che in tabella esista una definizione che rispecchi la situazione in pagina uno, in più è stata usata la procedura Active per permettere l’abilitazione dei pulsanti.

 


 

 

 

 


Oggetti contenuti in pagina tre e loro proprietà e procedure più significative:

 

 

 

Shape1: Spazio riservato ai dati per la modifica delle celle  

Proprietà utilizzate: SpecialEffect

 

Cmalabel1: Etichetta Shape1 “Dati per la modifica delle celle :”

 

Cmalabel2: Etichetta Colini “Colonna Inizio :”

 

Cmalabel3: Etichetta  Ncol “Numero colonne :”

 

Cmalabel4: Etichetta PiaIni “Piano inizio”

 

Cmalabel5: Etichetta Npia “Numero piani “

 

Colini: Casella di testo che definisce la colonna inizio

Procedure utilizzate: LostFocus

 

Ncol: Casella di testo che definisce il numero colonne

Procedure utilizzate: LostFocus

 

PiaIni: Casella di testo che definisce il numero piani

Procedure utilizzate: LostFocus

Npia: Casella di testo che definisce il numero piani

Procedure utilizzate: LostFocus

 

Shape2: Spazio riservato alle costanti da  sommare alle quote delle celle selezionate

Proprietà utilizzate: SpecialEffect

 

Cmalabel6: Etichetta Shape2 “Somma costante”

 

Cmalabel7: Etichetta X cost “X”

 

Cmalabel8: Etichetta Y cost “Y”

 

Xcost: Casella di testo che definisce la somma costante x

Procedure utilizzate: InteractiveChange

Proprietà utilizzate : Enabled

 

Ycost: Casella di testo che definisce la somma costante y

Procedure utilizzate: InteractiveChange

Proprietà utilizzate : Enabled

 

Shape3: Spazio riservato alle variabili da sommare alle quote delle celle selezionate

Proprietà utilizzate: SpecialEffect

 

Cmalabel9: Etichetta Shape3 “Somma incrementale”

 

Cmalabel10: Etichetta X inc “X”

 

Cmalabel11: Etichetta Y inc “Y”

 

Xinc: Casella di testo che definisce la somma incrementale x

Procedure utilizzate: InteractiveChange

Proprietà utilizzate : Visible

 

Yinc: Casella di testo che definisce la somma incrementale y

Procedure utilizzate: InteractiveChange

Proprietà utilizzate : Visible

 

 

Funzionamento delle principali procedure e proprietà utilizzate dai vari oggetti contenuti in pagina tre

 

 

Con un RefreshForm inserito in Active di pagina due rinfresco la situazione pulsanti abilitando solo quelli utili alla pagina.

Nella procedura Refresh della pagina ho inserito un controllo che mi permette di entrare solo se è stata rilevata in tabella una situazione macchina uguale a quella riscontrata in pagina uno, questo per evitare che l’operatore vada a quotare una scaffale per una macchina diversa da quella realmente voluta. Il programma andrà prima a fare un controllo sul numero celle poi sulle posizioni e profondità; trovata una discordanza l’operatore verrà informato tramite un messaggio e verrà impedito l’accesso alla pagina venendo riportati a pagina uno.

Per gli spazi Shape è stata usata la proprietà SpecialEffect con la quale si ottiene un effetto tridimensionale dei bordi che delimitano lo spazio all’interno del quale inserire i dati. Per le etichette Cmalabel è stata usata un’unica proprietà significativa Caption con la quale si è definito il suo testo.

La terza pagina permette all’operatore di sommare una costante o una variabile incrementale alle coordinate X, X1,Y1 e Y2 delle celle di una parte dello scaffale. Questa pagina prevederà l’inserimento del numero  della prima colonna e primo piano, del numero  colonne e numero piani, per stabilire la parte di scaffale, poi naturalmente la variabile per la somma costante o incrementale di X o Y. La somma costante ad una coordinata escluderà la  somma incrementale grazie ad un controllo inserito nel InteractiveChance di Xcos, Ycos e Xinc, Yinc attraverso il quale si varia la proprietà Enabled che abilita o meno la Casella di testo.

Nel metodo LostFocus del numero prima colonna Colini e primo piano PiaIni sarà’ inserito un controllo che impedirà l’inserimento di un numero uguale a 0 o maggiore di quello inserito in pagina uno, mentre nel numero colonne Ncol e numero piani Npia questo controllo si assicurerà che la somma del numero di inizio e del numero di scansione non superi il numero totale di piani o colonne in pagina uno.

 

 

 

 

 

 

 

 

 

 

 

 

2.2.4    Quarta Pagina

 

 

La quarta pagina è la parte del progetto che mi permette di consultare la situazione celle attraverso una griglia che mi rappresenta la tabella sulla quale il progetto va a lavorare. La Griglia descriverà la situazione celle grazie a numero macchina, codice cella, posizione, profondità, quota x, quota y e quota z divisi da sette colonne.

Di questa pagina è stata usata solo la procedura Active che consente l’abilitazione dei pulsanti utili alla pagina..

 

 


 

 

 

 


Oggetti contenuti in pagina tre e loro proprietà e procedure più significative:

 

 

 

Grid1: Griglia che rappresenta la tabella

Procedure utilizzate: Refresh

Proprietà utilizzate: ColumnCount, RecordSource

 

 

Funzionamento delle principali procedure e proprietà utilizzate dai vari oggetti contenuti in pagina tre

 

 

Nella quarta pagina sarà possibile controllare la situazione aggiornata dello scaffale attraverso una tabella che mi fotograferà la situazione attuale di ogni cella.

La tabella e’ rappresentata attraverso un controllo Grid; con la proprietà Column si definisce il numero colonne di questo controllo uguale a sette rappresentanti: numero macchina, codice cella, posizione, profondità, coordinata x, coordinata y e coordinata z. La proprietà RecordSource indicherà dove prelevare i dati da inserire all’interno della griglia

A questa tabella e’ associato un indice che attraverso la procedura Refresh la ordina  per numero macchina, codice cella, posizione e  profondità .

 

 

 

 

 

 

2.2.5    Quinta Pagina

 

 

Attraverso la quinta pagina l’operatore è in grado di creare una copia di una definizione già presente in tabella per una macchina da lui inserita in più selezionando la Casella di controllo potrà anche eliminare tutti i record presenti in tabella riferiti ad una macchina .

In questa pagina è stata usata la procedura Active per permettere l’abilitazione delle Caselle delle prime celle di sinistra, della macchina da eliminare e dei comandi utili alla pagina.

 


 

 

 

 


Oggetti contenuti in pagina cinque e loro proprietà e procedure più significative:

 

 

 

 

Shape1: Spazio riservato ai dati per la copia di una macchina  

Proprietà utilizzate: SpecialEffect

 

Cmalabel1: Etichetta Shape1 “Crea definizione scaffale per una macchina copiandone una esistente”

 

Cmalabel2: Etichetta Nmaces “Sorgente:”

 

Cmalabel3: Etichetta Nmacin “Destinazione :”

 

Cmalabel4: Etichetta Combo1 “Lato macchina esistente”

 

Cmalabel5: Etichetta Combo2 “Lato macchina da inserire“

 

Cmalabel9: Etichetta Npces “Prima cella sinistra sorgente”

Cmalabel10: Etichetta Npced “Prima cella sinistra destinazione”

 

Npces: Casella di testo che definisce il numero cella di sinistra sorgente

 

Npced: Casella di testo che definisce il numero cella di sinistra destinazione

 

Nmaces: Casella di testo che definisce la macchina sorgente

Procedure utilizzate: LostFocus

 

Nmacis: Casella di testo che definisce la macchina destinazione

Procedure utilizzate: LostFocus

 

Combo1: Casella di riepilogo che definisce il lato sorgente

Procedure utilizzate: Init, InteractivreChange, LostFocus

Proprietà utilizzate: RowSource, RowSource Type

 

Combo2: Casella di riepilogo che definisce il lato destinazione

Procedure utilizzate: Init, InteractivreChange, LostFocus

Proprietà utilizzate: RowSource, RowSource Type

 

Shape2: Spazio riservato alle macchina da eliminare

Proprietà utilizzate: SpecialEffect

 

Cmalabel6: Etichetta Shape2 “Elimina solo una parte della tabella”

 

Cmalabel7: Etichetta Nmaccan “Numero macchina:”

 

Cmacheck1: Casella di controllo che abilita Nmaccan e Cmd5

Procedure utilizzate: InteractiveChange

 

 

Nmaccan: Casella di testo che definisce i record macchina da eliminare

Proprietà utilizzate: Enabled

 

 

Funzionamento delle principali procedure e proprietà utilizzate dai vari oggetti contenuti in pagina cinque

 

 

Per gli spazi Shape è stata usata la proprietà SpecialEffect con la quale si ottiene un effetto tridimensionale dei bordi che delimitano lo spazio all’interno del quale inserire i dati.

Per le etichette Cmalabel è stata usata un’unica proprietà significativa Caption con la quale si è definito il suo testo.

Attraverso la procedura LostFocus di Nmacin e Nmaces vengono controllati che i dati inseriti siano corretti, quindi compresi tra 1 e 99.

Per Combo1 e Combo2 sono state utilizzate le procedure Init, InteractiveChange e LostFocus; con la prima si è andato ad inizializzare la Combo con “D”, con la seconda, se necessario, si rendono visibili le Caselle di testo per la prima cella di sinistra e con la terza si controlla che i caratteri inseriti siano corretti, mentre con le proprietà RowSource e RowSource Type si definiscono i valori delle Caselle di testo delle Combo.

Poi per la Casella di controllo Cmacheck1 è stata usata la procedura InteractiveChange con la quale si abilita il comando per la cancellazione dei record di una macchina.

 

 

 

 

 

 

 

2.3    COMANDI

 

 

I pulsanti hanno la funzione di eseguire tutte le procedure fondamentali del progetto; quindi l’utente grazie a questi sarà in grado in ogni momento di eseguire le varie funzioni aiutato anche da immagini e indicazioni che caratterizzeranno ogni pulsante in base alla propria funzionalità.

Attraverso il semplice clic su un pulsante è possibile lanciare ad esempio le procedure Calcolacelle, Coordinate e Modificaquote contenute nelle procedure della Form oppure cancellare record dalla tabella o copiare definizioni di scaffale.

Ogni pulsante sarà abilitato solo in precise pagine, questo per evitare che si vadano ad eseguire funzioni in pagine non previste per esse.

Ogni pulsante può anche essere in grado di eseguire più di una funzione a seconda della pagina in quel momento attiva; il pulsante calcola se attiva la pagina uno lancia Calcolacelle se attiva pagina due lancia Coordinate se al contrario è attiva qualsiasi altra pagina il pulsante risulterà disabilitato.

 

 

 


 

 

 

 

 

 


2.3.1    Comando Cmd1 Calcola

 


 

 

 


Questo comando può avere due funzioni a seconda della pagina attiva in quel momento infatti con pagina uno Calcola lancia Calcolacelle e quindi comporta la definizione dello scaffale mentre con attiva pagina due lancia Coordinate e quindi calcola le quote.

È stata usata la proprietà Picture con la quale è stato possibile rappresentarlo con una piccola calcolatrice e due procedure Refresh e Click; con la prima è possibile rinfrescare le abilitazioni e i testi per ogni pagina mentre con la seconda stabilire le funzioni che ha a seconda della pagina.

 


 

 


2.3.2    Comando Cmd2 Modifica

 

 


 

 

 

 


Attraverso il clic di questo comando si va a lanciare la procedura Modificaquote con la quale il programma va a modificare le quote in tabella.

L’uso di questo comando è possibile solo se ci si trova in pagina tre per tutte le altre pagine sarà disabilitato.

È stata usata la proprietà Picture con la quale è stato possibile rappresentarlo attraverso un righello e una matita e due procedure Refresh e Click; con la prima è possibile rinfrescare le abilitazioni e i testi per ogni pagina, mentre con la seconda lanciare la procedura Modificaquote inserita tra le procedure della Form.

 

 


 

 

 

 


2.3.3   Comando Cmd3 Cancella Tabella

 

 

 

 


 

 


A differenza dei comandi precedenti Cancella Tabella ha un programmino all’interno della sua procedura Click col quale al clic del comando l’operatore eliminerà tutti i record in tabella prima dell’eliminazione sarà però messo al corrente dell’operazione con un messaggio che gli permetterà di continuare o rinunciare.

L’eliminazione dei record non avviene fisicamente, ma selezionandoli con l’istruzione Delete e mettendo il numero macchina uguale a zero così da essere posti ad inizio tabella dall’indice e pronti per essere recuperati dall’istruzione Recall; prima di fare qualsiasi operazione la tabella sarà stata prontamente bloccata.

L’uso di questo comando è possibile solo se ci si trova in pagina quattro, la pagina dove è consultabile la tabella, per tutte le altre pagine sarà disabilitato.

È stata usata la proprietà Picture con la quale è stato possibile rappresentarlo attraverso una tabellina affiancata da una X e due procedure Refresh e Click; con la prima è possibile rinfrescare l’ abilitazione per la pagina tre e la disabilitazione per le altre pagine, mentre con la seconda lanciare il programma contenuto al suo interno al clic del comando.

 

 

 

 

 

2.3.4    Comando Cmd4 Copia

 

 

 


 

 

 

 


Come il comando precedente Copia ha un programma all’interno della sua procedura Click con il quale al clic del comando l’operatore copierà una definizione scaffale già presente in tabella per una macchina scelta dall’operatore che non sia stata ancora inserita in tabella; questo comando risulterà molto utile per un utente che non voglia inserire dato per dato una definizione copiandone semplicemente una già in tabella.

È possibile anche fare la copia dello scaffale di destra  sullo scaffale di sinistra di una stessa macchina e viceversa.

Se viene preso in considerazione lo scaffale di sinistra la procedura per proseguire avrà bisogno di sapere sempre la prima cella dello scaffale di sinistra altrimenti non sarà possibile proseguire; la procedura verrà interrotta anche se la macchina da copiare non è stata trovata, mentre se la macchina da inserire è già presente l’operatore potrà o rinunciare all’operazione o sostituire tutti i record riferiti alla macchina in tabella coi nuovi creati dalla procedura.

Passati tutti i controlli iniziali vengono selezionati i record da copiare e viene calcolato i codici cella dei nuovi basandosi sullo scaffale e sulla prima cella di sinistra. Il codice cella è l’unico campo che cambia infatti posizione, profondità e coordinate rimarranno uguali al record presente in tabella. Se lo scaffale da copiare è quello di destra  un controllo alla fine della procedura mi impedirà di continuare il ciclo nel caso venisse trovata la prima cella dello scaffale di sinistra, consentendomi di fare la copia solo ed esclusivamente delle celle di destra.

L’uso di questo comando è possibile solo se ci si trova in pagina cinque, per tutte le altre pagine sarà disabilitato.

È stata usata la proprietà Picture con la quale è stato possibile rappresentarlo attraverso una pagina vuota e due procedure Refresh e Click; con la prima è possibile rinfrescare l’abilitazione per la pagina quattro e la disabilitazione per le altre pagine, mentre con la seconda eseguire il programma contenuto al suo interno al clic sul comando.

 

 

 

2.3.5    Comando Cmd5 Cancella Record

 

 


 

 

 


Questo comando può avere due funzioni a seconda della pagina attiva in quel momento infatti con pagina quattro Cancella Record mi eliminerà il record al momento selezionato in tabella oppure con attiva pagina cinque mi elimina tutti i record in tabella della macchina scelta dall’operatore all’interno della pagina.

Il comando Cancella Record ha una serie di istruzioni all’interno della sua procedura Click con le quali al clic del comando l’operatore eliminerà il record selezionato in tabella; mentre l’eliminazione dei record macchina sarà possibile solo se è attiva pagina cinque e se è stata selezionata la Casella di controllo che mi abilita il comando per la pagina cinque, prima di ogni eliminazione sarà però messo al corrente dell’operazione con un messaggio che gli permetterà di continuare o rinunciare, se i record sono riferiti ad una macchina non esistente la procedura verrà terminata ed il controllo ritornerà.al programma chiamante.

L’eliminazione dei record non avviene fisicamente, ma selezionandoli con l’istruzione Delete e mettendo il numero macchina uguale a zero così da essere posti ad inizio tabella dall’indice e pronti per essere recuperati dall’istruzione Recall; prima di fare qualsiasi operazione la tabella è stata prontamente bloccata.

È stata usata la proprietà Picture con la quale è stato possibile rappresentarlo attraverso una X e due procedure Refresh e Click; con la prima è possibile rinfrescare l’abilitazione per la pagina quattro e cinque e la disabilitazione per le altre pagine, mentre con la seconda eseguire il programma contenuto al suo interno al clic sul comando.

 

 

 

 

 

 

 

 

 

 

 


CAPITOLO 3

 

 

 

 

 

DOCUMENTAZIONE

 

 

 

 

La prima parte di questo capitolo ha l’obbiettivo di fornire dettagli sull’uso delle classi e sulla strutturazione dei progetti per il programma di gestione dei magazzini WINSTORE creato ed utilizzato da System Logistics in un ambiente di sviluppo rappresentato da VISUAL FOX.

La seconda parte è dedicata alla documentazione del codice più significativo sviluppato all’interno del mio progetto.

 

 

 

 

 

 

 


3.1        PROGRAMMA WINSTORE

 

 

 

 

 

 

 

3.1.1    Preparazione dell’ambiente

 

 

Dopo aver installato il VISUAL FOX PRO ed essere entrati nell’ambiente di sviluppo, alla voce “OPZIONI” del menu “TOOLS” occorre effettuare le seguenti impostazioni:

 

 


 

 

 


 

 

 


La seguente finestra di configurazione contiene tutti i percorsi significativi del sistema FOX.

Si lasceranno tutti invariati, ad eccezione di PATH (come si vede, i files verranno cercati dapprima nelle directories del sottoprogetto della commessa, poi, in assenza di essi, nelle directories comuni.

Il flag di “DEFAULT DIRECTORY” sara’ deselezionato, in modo da assumere, per ogni sottoprogetto, l’opportuna “ROOT DIRECTORY”; questo sara’ ottenuto realizzando, in WINDOWS, dei Links all’eseguibile VFP.EXE (eseguibile di FOX), con ambiente di lavoro uguale alla directory del sottoprogetto.

 

 


 

 

 


nel caso lo sviluppatore sia client di un SERVER VISUAL SOURCE SAFE, e’ possibile integrare l’ambiente FOX con il SOURCE SAFE stesso con la seguente impostazione:

 

 


 

 

 

 


I settaggi relativi alla valuta, alla data e ora etc. potranno essere presi da quelli impostati in ambiente WINDOWS (Pannello di Controllo) con il seguente settaggio:

 

 

 


 

 

 


Tutti i valori non menzionati nelle surriportate finestre potranno essere lasciati ai valori di default.

 

 

3.1.2    Struttura del progetto

 

 

Per ogni commessa, il nome consigliato per la directory ROOT del progetto e’:

-        WINSTORE_<nomeCommessa>.

 

Le sottodirectory fisse (contenenti form, classi e reports comuni ai vari sottoprogetti che formeranno la commessa) sono:

-        code (contenente i forms di uso piu’ comune);

-        lib (contenente le classi di uso piu’ comune);

-        lib\bmp (contenente le immagini e le icone di uso piu’ comune);

-        report (contenente i reports di stampa di uso piu’ comune).

 

Saranno poi create tante directories quanti sono i sottoprogetti che costituiscono la commessa. Ognuna di esse potra’ avere il proprio “code”, “lib”, “lib\bmp”, “report”, in cui saranno collocati i files specifici del sottoprogetto (peraltro “prioritari”, a parita’ di nome, rispetto a quelli comuni, in virtu’ della sopracitata configurazione del PATH di RICERCA).

 

Nella ROOT del sottoprogetto sara’ creato il file di progetto (.pjx, abbinato al suo indice.pjt), che rappresenta il collettore dei files che costituiscono il sottoprogetto.

 

Nota per utilizzatori del SOURCE SAFE:

In ambiente integrato con VISUAL SOURCE SAFE, esiste (oltre ai files.pjx e.pjt) anche un terzo file (prodotto automaticamente dal SOURCE SAFE all’atto dell’inserimento del progetto stesso nel SOURCE SAFE), con estensione.pjm.

Si tratta di un file di testo, contenente tutti i nomi dei files (coi loro percorsi relativi rispetto alla posizione del progetto) contenuti nel progetto. Esso e’ l’unico file (tra i tre suddetti) che viene realmente posto sotto SOURCE SAFE. Quando un operatore deve aggiornare la struttura di un progetto, deve effettuare l’operazione di “Join Source Control Project” (menu’ File), specificando il progetto corretto; questo garantisce l’aggiornamento dei due files locali.pjx e.pjt.

A questo punto, l’operatore puo’ aggiornare la struttura ed effettuare la “Update Project List” (menu’ “Project \ Source Control”), riportando, cosi’, le modifiche locali al.pjm, di cui, per terminare,.dovra’ essere fatto il Check In direttamente dall’ambiente Source Safe, per renderlo disponibile anche ad altri utenti.

 

 

3.1.3    Classi

 

 

Le classi gia’ realizzate contengono la maggior parte delle proprieta’ e dei metodi che possono occorrere al programmatore per realizzare progetti WINSTORE (ed anche non correlati a WINSTORE).

Preme ricordare che tutte le istanze delle classi, i forms ed eventuali nuove classi (ereditate o meno da quelle gia’ esistenti) vanno legate all’opportuno file di costanti (normalmente WS_BASE.H), agiendo sul menu’: FORM / Include File.. o: CLASS / Include File…

 

Esistono alcuni files di classi di utilita’ generale che conviene sempre linkare al progetto:

-        CMAGEN.VCX: contiene la maggior parte delle classi visuali e di utilita’ generale utilizzate per la realizzazione dei progetti. Eventuali personalizzazioni non dovranno essere effettuate su queste classi, ma su classi ereditate da queste, normalmente poste nel file USER.VCX, posto nella directory.

Le classi principali contenute in CMAGEN.VCX sono:

·     Classe Application: viene utilizzata come classe da cui ereditare la classe USER (contenuta nel file USER.VCX) e contiene tutte le proprieta’ di uso generale per tutti i progetti, non le relative inizializzaioni (il metodo ReadIni, invocato dall’evento Init, provvede a leggere dal file init.ini, nella stessa directory dell’eseguibile, e dai files indSock.ini e inicom.ini, nella stessa directory del DataBase principale, i parametri di configurazione, da riportare su altrettante proprieta’).

Nella classe USER (specifica del progetto), potranno essere create ed inizializzate altre proprieta’ (oltre che implementati altri metodi).

 

Il file main.prg (contenente il codice con cui il programma parte) provvede a inizializzare una variabile globale (unica di tutto il progetto), detta “oApp”, ponendovi il puntatore ad una istanza della classe USER.

Viene di seguito riportato un tipico main.prg:

 

* Inclusione file di costanti (esso include, a sua volta, il link ai files di costanti generali)

#INCLUDE WS_BASE.H

 

 

* Apertura files di classi utilizzate nel programma:

SET CLASSLIB TO CMAGEN, USER, UT_LOG, UT_MENU………..

 

* Eventuali settaggi relativi allo SCREEN (icona, titolo, etc.)

_SCREEN.icon           = "cma2.ico"

_SCREEN.caption      = "Titolo Applicativo"

…..

 

* Eliminazione menu principale (verra’ ricostruito in base all’utente loggato)

SET SYSMENU OFF

 

* Crea applicazione;

* Testa che sia andata a buon fine la creazione;

* Chiama il metodo di creazione delle istanze delle classi di utilita’ linkate ad oApp (iniUti);

* Abilita la costruzione dei menu’ personalizzati per gli utenti;

* Invoca il metodo principale (DO), in cui viene richiesto il Login, costruito il menu’ personalizzato per l’utente loggato (se necessario). In programmi Mono-Form (un unico form modale, in cui si svolge tutta la gestione) il form stesso viene lanciato direttamente dal metodo DO, senza costruzione del menu’.

 

PUBLIC oApp

oApp = CREATEOBJECT("User")

 

if TYPE('oApp') = "O"

  if oApp.iniuti() =.T.

    oApp.NoAddToMenu =.F.                          && -- &&

    oApp.Do()                                                    && -- &&

  endif 

endif 

 

* Liberazione memoria e conclusione programma

CLOSE DATA ALL                                           && -- &&

CLEAR ALL                                                      && -- &&

RELEASE ALL EXTENDED                             && -- &&

 

 

N.B. E’ possibile, semplicemente eliminando, dal main.prg, le righe di codice denotate con “&& -- &&”, ottenere un semplice programma (normalmente chiamato oApp.prg), linkato al progetto ma marcabile come “ESCLUSO” (perche’ non sara’ impiegato nell’eseguibile finale, ma solo in fase di DEBUG). Lanciando preventivamente tale.prg, sara’ possibile lanciare e provare i singoli forms, che si troveranno tutte le proprieta’ generali gia’ inizializzate.

 

Naturalmente, occorrera’, al termine del DEBUG, deallocare la memoria e chiudere tutti i databases e le tabelle.

Questo e’ possibile semplicemente costruendo un.prg (normalmente chiamato release.prg), linkato al progetto ma escluso da esso, contenente le seguenti righe di codice:

 

CLOSE DATA ALL

CLEAR ALL

RELEASE ALL EXTENDED

 

 

Durante il corso del programma, potra’ essere referenziata una qualunque proprieta’ generale di USER (o APPLICATION) tramite la notazione:

oApp.proprieta’.

 

ESEMPI SIGNIFICATIVI:

 

oApp.fileIni                = file.ini locale per parametri di configurazione;

oApp.fileIniCom         = file.ini comune per parametri configurazione generali;

oApp.pathFiles         = Path in cui e’ contenuto il dataBase principale e le relative tabelle;

oApp.pathWork        = Path in cui sono contenute eventuali tabelle di appoggio per l’applicativo (di default, coincide con la directory dell’eseguibile);

oApp.lingua                = Codice della lingua (IT, SP, FR, IN,..);

oApp.help                   = File di help (Path completo);

oApp.terminale           = Numero terminale (01 – 99);

oApp.tipoApp             = Tipo applicazione (AN per Anagrafiche, LS per liste, CO per configuratore, etc.);

oApp.chiaviTab(n,3)= Array di tre colonne, inizializzato nell’evento init di USER, in cui:

oApp.chiaviTab(n, 1) = “Nome tabella”;

oApp.chiaviTab(n, 2) = “Campi da visualizzare nel log delle modifiche (USER_LOG), per identificare univocamente il record modificato”;

oApp.chiaviTab(n, 3) = “Campo indice qualunque che verra’ utilizzato dal metodo di rinfresco degli indici prima di una ricerca in una tabella (uti.seek)”;

 

 

·       Classe FormModal: rappresenta la classe immediatamente ereditata dalla classe FORM, corredata di diverse funzionalita’:

Ø     Scrittura su file init.ini della posizione della finestra sulla chiusura (metodo WriteWindowPos) con recupero posizione sull’apertura (metodo RestoreWindowPos);

Ø     Traduzione automatica dei testi sull’apertura della finestra (se richiesta) (metodo formTrad).

Ø     Possibilita’ di implementare la barra di scorrimento nei LOOPs:

thisform.barra(BAR_CREA, TitoloBarra, Val.minimo, Val. massimo, Val. di incremento, Possibilita’ di uscita con CTRL + F12 (.t. o.f.))            à crea barra;

thisform.barra(BAR_INCREM)         à incrementa contatore;

thisform.barra(BAR_DELETE)         à distrugge barra.

 

La classe si linka, sull’inizializzazione, le istanze delle due classi UT_FORM (nome istanza: UTI) e USER_LOG (nome istanza: LOG), particolarmente utili, in quanto contenenti metodi fondamentali per la gestione (vedi di seguito).

A tali metodi potro’ riferirmi, in qualunque momento, con:

thisform.uti.<nomeMetodo>(elenco parametri)

     o con:

thisform.log.<nomeMetodo>(elenco parametri)

 

N.B. Per creare un form derivandolo non dalla classe base FORM, ma da una classe ereditata da FORM (come la FormModal), occorre, nel menu’ Tools / Opzions, effettuare la seguente configurazione:

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 


N.B. Una volta creato un form (derivato da una qualunque classe ereditata dalla classe FORM) sara’ possibile creare proprieta’ e metodi personalizzati semplicemente usando le voci di menu’:

form / New Property;

form / New Method.

 

 

·       Classe FormBase: ereditata da FormModal e corredata della seguente funzionalita’ aggiuntiva:

Ø     Aggiunta e rimozione al/dal menu (menu’ Finestre) del titolo del form (metodi AddToMenu e RemoveFromMenu, invocati rispettivamente all’inizializzazione ed alla distruzione del form);

·       Classe FormTabella: ereditata da FormBase, e’ dotata delle funzionalita’ di base per gestire una tabella (barra degli strumenti, istanza della classe DBButtonArray). L’ambiente dati e’ PRIVATO (proprieta’ DataSession = 2), il che evita interferenze con dati di altri form concorrenti.

E’ necessario, per gestire una tabella anagraficamente, legare la tabella all’ambiente dati del form (DataEnvironment), settare la proprieta’ del DataEnvironment InitialSelectedAlias = Alias della Tabella e creare, sul form, la griglia (meglio se istanziata dalla classe GRIDFILT, in quanto gia’ corredata di diverse funzionalita’, che verranno di seguito descritte), che sara’ legata all’Alias della Tabella (campo RecordSource) e le cui colonne saranno legate ai campi opportuni (campo ControlSource delle colonne).

 

N.B. Allo scopo di consentire, RUNTIME, una collocazione del / dei Databases diversa da quella dell’ambiente di sviluppo, e’ assolutamente necessario collocare, nell’evento BeforeOpenTables del DataEnvironment, per ogni Alias (Cursor) presente, la seguente riga di codice:

this.cursorN.DataBase = <DataBase con Path completo>

(Esempio: this.cursor1.DataBase = oApp.pathFiles + “WSTOREDB.DBC”).

 

Questo provvede, prima dell’apertura del DataBase e delle Tabelle, a settarne opportunamente il DataBase.

 

Inoltre, e’ necessario ricordare, per gestire correttamente le tabelle in modo “Ottimistico per Record”, di settare, per ogni Alias, le seguente proprieta’:

BufferModeOverride = 3.

 

E’, per finire, corretto (anche se non indispensabile, in quanto puo’ essere fatto anche da codice, non appena occorre) inizializzare il campo Order (Indice) dell’Alias.

 

N.B. E’ estremamente utile, ai fini di evitare interferenze tra i dati presentati sul form (per esempio sulla griglia) ed i dati trattati nel codice, utilizzare, nel DataEnvironment, Alias diversi per la stessa tabella (uno di essi verra’ agganciato agli strumenti di visualizzazione, l’altro, o gli altri, utilizzato/i per gestire controlli o modifiche sulla tabella).

Non attenersi a questo approccio rende la programmazione piu’ complessa e porta quasi certamente ad errori (sfasamenti di indici, spuntamento del record, etc.)

 

 

Nella DbButton appaiono i pulsanti di spostamento e di modifica (gia’ funzionanti), un testo per digitare il campo da cercare secondo l’indice corrente (o i campi dell’indice composto, separati da “;”), una combo per la selezione degli indici possibili ed una combo per impostare Nuovi filtri o filtri gia’ preimpostati.

Il caricamento della combo degli indici, si effettua inserendo, per ogni indice da presentare, nella init della dbButton, la seguente riga di codice (dopo l’invocazione del codice base della classe, con DODEFAULT()):

this.addIndice(“Descrizione indice”, “nome indice”, "Tipo indice»(“C” o “N”))

 

La possibilita’ di utilizzare la combo per il caricamento di filtri si ottiene nel modo seguente:

v    Inizializzare la proprieta’ “Filtro_TipoTabw” con il tipo di dati di TABWORK (3 caratteri alfanumerici, costituenti un tipo non gia’ utilizzato (vedi elenco voci TabWork nel documento allegato)) che il programma impieghera’ per bufferizzare i futuri filtri impostati;

v    Inizializzare la proprieta’ Filtro_Tabelle, che comprende l’elenco, separato da “,”, delle tabelle su cui potranno essere impostati filtri (i cui campi, con le descrizioni in chiaro, potranno essere caricati nella tabella FILTRI con l’opportuno FORM di utilita’);

v    Inizializzare la proprieta’ Filtro_Alias, che comprende l’elenco, separato da “,”, degli alias delle tabelle di cui al punto precedente (stesso ordine);

v    Inizializzare la proprieta’ Filtro_Desc, che rappresenta l’elenco, separato da “,”, delle descrizioni in chiaro delle suddette tabelle (stesso ordine).

 

 

E’ possibile personalizzare i metodi di modifica/cancellazione/inserimento (abilitrazione/disabilitazione oggetti, controlli aggiuntivi, etc.) inserendo il codice personalizzato nei metodi:

v    SAVE, invocato dal pulsante:

 


 


v   

RESTORE, invocato dal pulsante:

 

 


v    OKDELETE, invocato dal pulsante (che chiama il metodo DELETE e, dopo conferma da parte dell’utente, il metodo OKDELETE):


 

 


v    AZZCAMPIINDICE, in cui il flusso di codice passa, dopo aver bloccato il record da cancellare, subito prima della cancellazione: qui il programmatore puo’ inserire le REPLACE necessarie per portare il record al TOP della tabella, secondo l’indice che sara’ usato per il recupero (vedi metodo RECURECORD della classe UT_FORM);

 

v    ADDNEW, invocato dal pulsante:


 

 


(Si tenga presente che il metodo ADDNEW crea/recupera il record e lo lascia bloccato, in attesa che vengano operate le modifiche da parte dell’utente e chiamato il metodo SAVE, che effettua lo sblocco e la registrazione sullo USER_LOG della transazione).

 

 

La classe FORMTABELLA e’ anche dotata di una istanza della classe PRINTEXPIMP:


 

 


Questa classe mette a disposizione 3 funzionalita’:

v    Stampa: la pressione del primo tasto produce l’apertura di un form, derivato dalla classe FRMREPORTS, che consente di selezionare il form di stampa e se effettuare un PREVIEW, una stampa su stampante o su file.

I forms di stampa devono, naturalmente, essere preparati a priori; possono essere linkati al progetto (essere inglobati nell’eseguibile) o essere esterni all’eseguibile.

Occorre creare, in TABWORK, un tipo dati (che poi sara’ indicato nella proprieta’ Stampe_Tipo di PRINTEXPIMP), in cui, per ogni Codice, oltre che la descrizione del report di stampa, dovranno essere riportati, nel campo Valore, il nome del report ed il titolo di default (modificabile RUNTIME dal form di stampa), nel formato:

|Nome report|Titolo di default|

v    Import: la pressione del secondo tasto produce la chiamata del metodo IMPORT, che va, naturalmente, personalizzato.

v    Export: la pressione del terzo tasto produce la chiamata del metodo EXPORT, che va, naturalmente, personalizzato.

 

·       Classe FormPageTabella: ereditata da FormTabella. Un’istanza di questa classe, al cui DataEnvironment sia stato legato (con gli accorgimenti suddetti) l’Alias di una Tabella e la cui GRIDFILT sia stata agganciata all’Alias, e’ un form di gestione di una Tabella gia’ funzionante e completo.

Per la gestione filtri ed indici sulla DBButton, vale quanto detto al punto precedente.

La seconda pagina della finestra e’ riservata ai campi della tabella che possono essere modificati (basta porre nella seconda pagina dei text, agganciati, tramite la proprieta’ ControlSource, ai campi opportuni dell’Alias).

·       Classe GRIDFILT: rappresenta una classe ereditata dalla classe base GRID, dotata,  in particolare,  delle seguenti caratteristiche:

v    Se la caption dell’Header di una colonna non viene modificata (rimane settata al valore “Header”),  la colonna non verra’ resa visibile.

v    Se la proprieta’ Tag del TEXT di una colonna viene posto = al campo della tabella agganciato alla colonna (ALIAS.nomeCampo) à l’Header della colonna,  RUNTIME,  verra’ sottolineato e l’utente,  con un doppio click sopra di esso,  potra’ ottenere un filtro immediato (anche composto con altre colonne) sulla condizione: ALIAS.nomeCampo = <valore del campo del record attualmente selezionato>

·       Classe ARRCOMBO: ereditata dalla classe COMBOBOX, e’ corredata di una proprieta’ – array, denominata ArrDati(), che puo’ essere ridimensionata (istruzione DIMENSION) mano a mano che la combo viene caricata (con this.addItem(..)), ponendo in ogni elemento dell’array una o piu’ caratteristiche corrispondenti ad ogni voce caricata.

·       Classe COMBOTAB: ereditata dalla classe COMBOBOX, viene impiegata per contenere le descrizioni (selezionabili a tendina) ed i codici corrispondenti di un certo tipo, tratte dalla tabella TABWORK (vedi tabulato allegato al documento, contenente le informazioni depositate in tale tabella). Una volta incollata al form una istanza di tale classe, basta settare le seguenti proprieta’:

v                                    Alias        : alias usato, nel form, per TABWORK (normalmente, TABWORK);

v                                    TipoDati  : 3 caratteri alfanumerici, che rappresentano il tipo dati di TabWork;

v                                    AliasDest : Eventuale alias per uno dei cui campi viene usata la COMBOTAB; settando questa proprieta’, se per tale alias eof() risulta vera, la COMBOTAB viene automaticamente disabilitata.

·       Classe UT_FORM: si tratta di una classe non visuale, ereditata dalla classe CUSTOM (normalmente, la sua istanza viene chiamata “UTI” e si trova sicuramente su tutte le forms derivati dalla classe FORMMODAL o dalle classi da essa ereditate). Contiene la maggior parte dei metodi di utilita’ normalmente utilizzati, sia nella gestione dei DataBases e delle tabelle, sia per altre funzionalita’.

Alcuni di essi sono:

v                                                                                           CloseOpen(Exclusive)      : Chiude l’alias corrente e lo riapre (se passato.t. come parametro, in esclusiva). Se l’alias e’ l’unico aperto per la tabella, questa operazione puo’ essere impiegata per forzare il sistema operativo a liberare memoria.

v                                                                                           GetCampiStr(stringa, separatore, @array)                                                    : pone nell’array (opportunamente ridimensionato) tutti i campi estrapolati dalla stringa e separati da “separatore”. La stringa puo’ iniziare e/o terminare con “separatore”, oppore no. Restituisce il numero di campi trovati (0 se stringa vuota).

v                                                                                           InsLogErr(Codice, Metodo, Descrizione) : Inserisce nella tabella LOGERR la registrazione dell’errore, avente quella descrizione (max. 100 caratteri), il riferimento al metodo in cui si e’ verificato ed il codice.

I possibili codici sono i seguenti (estratto del file: CMA.H):

 

Ø                                                                                                         #DEFINE SEEK_ERR "AA"   &&     Seek fallita

Ø                                                                                                         #DEFINE LOCK_ERR "AB"   &&     Blocco del Record fallito

Ø                                                                                                         #DEFINE FBLK_ERR "AC"   &&     Blocco del File fallito

Ø                                                                                                         #DEFINE ABBINA_ERR     "AD"   &&     Abbinamento tra Udc e Cella non trovato

Ø                                                                                                         #DEFINE TIPO_ERR   "AE"   &&     Tipologia missione non Prevista

Ø                                                                                                         #DEFINE HEAD_ERR "AF"    &&     Intestazione Msg ricevuto da Liv1 sconosciuto

Ø                                                                                                         #DEFINE ERROPENTAB     "AG"   &&     Errore durante l'apertura di una tabella

Ø                                                                                                         #DEFINE BUFFERERR     "AH"   &&     Errore rilevato durante la save dei dati dal buffering

Ø                                                                                                         #DEFINE NOTHANDERROR "AI"     &&      Errori non gestiti

Ø                                                                                                         #DEFINE LISTINCOMERR    "AJ"     &&      Lista incompleta

Ø                                                                                                         #DEFINE IMMEINCOMERR     "AK"   &&     Immediato incompleto

Ø                                                                                                         #DEFINE NUMRIMPMAXERR     "AL"    &&     Numero rimpiazzi eccessivo

Ø                                                                                                         #DEFINE ABORT_ERR     "AM"  &&     Abortita

Ø                                                                                                         #DEFINE ANNULLATA_ERR     "AN"   &&     Annullata

Ø                                                                                                         #DEFINE PESO_SAG_ERR     "AO"   &&     Errore di peso o di sagoma

Ø                                                                                                         #DEFINE TIMEOUT_ERR     "AP"    &&     Errore di timeout

Ø                                                                                                         #DEFINE MISSDUPL_ERR     "AQ"   &&     Missione duplicata

Ø                                                                                                         #DEFINE RIMP_IMP_ERR     "AR"   &&     Rimpiazzo impossibile

Ø                                                                              #DEFINE VUOTO_VUOTO_ERR           "AS"     &&      Errore di vuoto su vuoto

Ø                                                                              #DEFINE PIENO_PIENO_ERR   "AT"   &&     Errore di pieno su pieno

Ø                                                                                                         #DEFINE SORG_INES_ERR     "AU"   &&     Errore di sorgente inesistente

Ø                                                                                                         #DEFINE DEST_INES_ERR     "AV"   &&     Errore di destinazione inesistente

Ø                                                                                                         #DEFINE SORG_INIB_ERR     "AW"  &&     Errore di sorgente inibita

Ø                                                                                                         #DEFINE DEST_INIB_ERR     "AY"   &&     Errore di destinazione inibita

Ø                                                                                                         #DEFINE NUMMACERR_ERR     "AZ"    &&     Numero macchina errato

Ø                                                                                                         #DEFINE TIPMISSERR_ERR     "BA"   &&     Tipologia missione errata

Ø                                                                                                         #DEFINE DIMUDCERR_ERR     "BB"   &&     Dimensioni Udc errate

Ø                                                                                                         #DEFINE BUFL1PIENO_ERR     "BC"   &&     Buffer Livello1 pieno

Ø                                                                              #DEFINE MISSSCONOSC_ERR "BD"   &&     Missione Sconosciuta

Ø                                                                                                         #DEFINE STAMIS_ERR     "BE"    &&      Stato missione incongruente

Ø                                                                              #DEFINE MISINCOURSE_ERR  "BF"    &&     Missione in Corso

 

v                                                                                           SaveAlias(@OldAlias, @OldOrder, @OldRecord)                             : Pone nelle tre variabili passate per indirizzo l’Alias corrente, il tag indice corrente ed il puntatore al record corrente. Questo consente, alla fine delle operazioni, chiamando il metodo RestAlias, di ripristinare la situazione dati originaria.

v                                                                                           RestAlias(OldAlias, OldOrder, OldRecord)                                                    : Seleziona l’alias corrente, settandone il tag indice passato ed andando al numero di record indicato.

v                                                                                                                                              Trad(testo)      : Rende la traduzione del testo passato (max. 100 caratteri), in base alla lingua codificata in oApp.lingua, legata all’operatore corrente o letta dal file init.ini (sezione [CONFIG], parametro DEFLINGUA=).

OApp.lingua puo’ valere:

Ø                                          IT                                                   : Italiano (testo viene reso identico);

Ø                                          FR                                                  : francese;

Ø                                          SP                                                  : spagnolo;

Ø                                          IN                                                  : inglese;

Ø                                          …….

 

La ricerca della traduzione viene fatta nella tabella LINGUA. Se il testo italiano non viene trovato (nel gruppo delle traduzioni di quella specifica lingua), il metodo provvede ad aggiungere un record, con il campo della traduzione vuoto, e rende il testo da tradurre preceduto da “_”.

v                                                                                                                                              Seek(Valore da Trovare)                                                                                   : Effettua la ricerca del valore da trovare nella tabella e secondo il tag indice correnti, dopo aver forzato il rinfresco degli indici della tabella da parte del sistema.

In ambienti multiutenza, questo metodo va sempre utilizzato, per evitare mancati ritrovamenti di records (inseriti da altri utenti o applicativi) legati al mancato rinfresco del contesto di memoria dell’applicativo.

v                                                                                                                                              Rec_Lock(numero, tipo)                                                                                   : Effettua il lock (blocco) del record corrente.

Ø                                                                                                                                     Tipo puo’ assumere i seguenti valori (estratto del file CMA.H):

Ø                                                                                                 #DEFINE LOC_NUMERO  "N"      && Tenta di bloccare il record per n Volte

Ø                                                                                                 #DEFINE LOC_SECONDI  "S"      && Tenta di bloccare il record per n Secondi

Ø                                                                                                 #DEFINE LOC_AUTO        "A"      && Aspetta fino a che non ha bloccato il record (indefinitivamente)

 

Quindi:

 

Ø                                                                                                 Tipo = LOC_NUMERO       : Numero rappresenta il numero di tentativi di lock (se falliscono tutti, il metodo rende.f., altrimenti.t.);

Ø                                                                                                 Tipo = LOC_SECONDI       : Numero rappresenta il tempo (in secondi) per cui e’ necessario tentare il lock (al termine, in caso negativo, il metodo rende.f., altrimenti rende.t. appene riesce nel blocco);

Ø                                                                                                 Tipo = LOC_AUTO : In questo caso, Numero deve essere posto a 0. Il metodo esce solo quando il record e’ stato bloccato (valore di ritorno =.f.).

 

N.B. Naturalmente, se mi trovo all’ eof(), il metodo restituisce, comunque,.f..

v                                                                                                                                              RecuRecord() : Effettua l’inserimento di un nuovo record nella tabella corrente, od il recupero di un record cancellato in precedenza (che viene sbiancato). All’uscita dal metodo, il record e’ bloccato.

E’ necessario, affinche’ il recupero venga fatto in modo corretto, selezionare, prima di invocare la funzione, il tag indice opportuno, che garantisca di trovare al TOP della tabella tutti i records deletati.

Cio’ si ottiene inserendo in un campo indice, all’atto della cancellazione del record, un valore sicuramente inferiore rispetto a quelli assunti di norma da quel campo.

Qualche esempio:

Ø                                                                                  Tabella UDC:        Sulla cancellazione, porre UDC_COD = -1 e, sul recupero, utilizzare l’indice XUDC_ID1 (su UDC_COD);

Ø                                                                                  Tabella SCOMPART:       Sulla cancellazione, porre SCO_ART = chr(13) e, sul recupero, utilizzare l’indice XSCO_ID14 (su SCO_ART);

Ø                                                                                  Tabella ARTICOLI:          Sulla cancellazione, porre ART_COD = chr(13) e, sul recupero, utilizzare l’indice XART_ID1 (su ART_COD);

Ø                                                                                  …..

 

-        UT_LOG.VCX: contiene, in particolare, una classe particolarmente utile:

·     USER_LOG: questa classe (la cui istanza viene normalmente denominata LOG ed e’ sempre presente sulle Forms derivati dalla classe FORMMODAL o dalle sue ereditate) contiene, in particolare, il seguente metodo:

Ø                                                                                                                   RegUnlock(nuovoRecord)   : effettua lo sblocco del record precedentemente bloccato, dopo aver fatto la registrazione della transazione sulla tabella USER_LOG.

 

Sono di seguito riportati i diversi casi di modifica o cancellazione o inserimento di records:

ü                                                                                                         Inserimento (recupero) (su USER_LOG vengono riportati tutti i nuovi valori dei campi):

SELECT <ALIAS>

SET ORDER TO <TAGINDICE per RECUPERO>

Thisform.uti.recuRecord()

REPLACE <CAMPO1> WITH <Valore1>,;

                    <CAMPO2> WITH <Valore2>,;

….

Thisform.log.regUnlock(.t.)

ü                                                                                                         Modifica (su USER_LOG vengono riportati tutti i valori vecchi e nuovi dei campi modificati):

SELECT <ALIAS>

SET ORDER TO <TAGINDICE per RICERCA>

Thisform.uti.Seek(<Valore da Ricercare>)

If found()

 If thisform.uti.rec_lock(2, LOC_NUMERO)

  REPLACE <CAMPO1> WITH <Valore1>,;

                    <CAMPO2> WITH <Valore2>,;

 ….

  Thisform.log.regUnlock(.f.)

 Else

  * Registrazione errore di lock

  thisform.uti.insLogErr(LOCK_ERR, “Metodo”, thisform.uti.trad(“No Blocco”))

 Endif

Else

 * Registrazione errore di seek

 thisform.uti.insLogErr(SEEK_ERR, “Metodo”, thisform.uti.trad(“No Trovato”))

Endif

ü                                                                                                         Cancellazione (su USER_LOG vengono riportati tutti i valori vecchi dei campi):

SELECT <ALIAS>

SET ORDER TO <TAGINDICE per RICERCA>

Thisform.uti.Seek(<Valore da Ricercare>)

If found()

 If thisform.uti.rec_lock(2, LOC_NUMERO)

  REPLACE <CAMPO per RECUPERO> WITH <Valore “Basso”>

  DELETE

  Thisform.log.regUnlock(.f.)

 Else

  * Registrazione errore di lock

  thisform.uti.insLogErr(LOCK_ERR, “Metodo”, thisform.uti.trad(“No Blocco”))

 Endif

Else

 * Registrazione errore di seek

 thisform.uti.insLogErr(SEEK_ERR, “Metodo”, thisform.uti.trad(“No Trovato”))

Endif

 

-        UT_MENU.VCX: contiene le classi necessarie per la crezione del menu’ e per la gestione delle funzioni dei diversi utenti.

E’ opportuno riassumere come e’ possibile personalizzare il menu’ di una applicazione e le diverse funzioni sui diversi forms.

Occorre agire su 2 tabelle:

v  CONFMENU: questa tabella contiene l’elenco delle voci di menu e sottomenu per ogni utente. Volendo aggiungere o togliere una voce di menu’ (o sottomenu), si agisca solo sull’utente WINSTORE (per gli altri utenti, provvedera’ la form OPERATORI a duplicare opportunamente le voci, abilitandole o disabilitandole).

Occorre notare che il campo MNU_OPE e’ costituito dal nome utente (15 caratteri) e da due caratteri alfanumerici che identificano il tipo dell’applicazione (proprieta’ oApp.tipoApp). In questo modo, e’ possibile avere menu’ diversi, per ogni utente, per ogni applicazione.

Esaminiamo gli altri campi:

MNU_POS                          : il primo carattere identifica il menu’ principale, il secondo i diversi sottomenu’;

MNU_MNU                        : nome menu’ principale (uguale per tutti i sottomenu’);

MNU_SUBM                      : nome sottomenu’;

MNU_SHRT                       : eventuale SHORTCUT (per esempio: ALT + F);

MNU_SYS                          : eventuale chiamata a funzioni del sistema operativo (per esempio, per il COPY di un testo selezionato, _MED_COPY);

MNU_FUNZ                       : condizione di disabilitazione;

MNU_DO                           : azione compiuta dal sottomenu’ (per esempio: DO FORM <nomeForm> LINKED per lanciare un form);

MNU_ABI                          : codice di abilitazione: settarlo a MA per i menu’ principali, a SA per i sottomenu’ (provvedera’ la form di gestione degli utenti a cambiare quei valori, per inibire, eventualmente, per un utente, quelle voci);

MNU_FORM                      : form cui e’ agganciato il sottomenu’ (blank per menu’ principali e per sottomenu’ non agganciati a form).

v  FUNZIONI: questa tabella contiene l’elenco delle funzioni previste per ogni form.

Elenco e decrizione campi:

FNZ_FORM                        : form cui e’ riferita la funzione;

FNZ_FNZ                           : elenco codici funzione (separati da, posto anche all’inizio ed alla fine dell’elenco); questi codici alfanumerici (arbitrari) sono, ognuno, agganciati ad una funzione specifica della form, cui l’operatore puo’ essere o non puo’ essere abilitato. In questo ruolo, FNZ_COD e’ blank e FNZ_NOME assume il nome della form.

FNZ_FNZ puo’ altresi’ essere impiegato per contenere la descrizione di dettaglio di un singolo codice (in tal caso, FNZ_COD contiene quel codice e FNZ_NOME e’ blank).

FNZ_ABI                            : va’ inizializzato a “A” (abilitato). Sara’, poi, la form di gestione operatori a disabilitare, per un particolare utente, quella funzione.

 

N.B. I codici delle funzionalita’ della form possono essere utilizzati liberamente, da codice, per testare se un utente puo’ o non puo’ effettuare quella particolare funzione. Questo si ottiene ponendo, sull’evento LOAD della form, la seguente riga di codice:

 

Thisform.StrAbiButton = oApp.access.GetstrAbiButton(Thisform.Name)

 

Nella proprieta’ (gia’ presente a livello di classe FORMMODAL) strAbiButton, in tal modo, mi trovero’ il valore estrapolato dal campo FNZ_FNZ (elenco funzioni, separate da “_”). Il test di abilitazione o meno alla funzione sara’, quindi:

If (“_” + <Codice funzione> + “_”) $ thisform.strAbiButton or ;

   empty(thisform.strAbiButton) or empty(<Codice funzione>) then

 * Utente abilitato

 …..

Else

* Utente disabilitato

 …..

Endif

 

 

(Si noti che strAbiButton vuota o <codice funzione> vuoto sono sinonimo di funzioni / funzione sempre abilitate / abilitata).

 

Molte funzioni utente, tuttavia, essendo gia’ gestite a livello di classe, non debbono essere gestite da codice, ma e’ sufficiente settare le opportune proprieta’. Per esempio, sulla barra degli strumenti della form, basta settare, sui pulsanti, la proprieta’ buttonCode (se vuota à funzione sempre abilitata) e, a livello di DBButton, le proprieta’: filtroCode (abilitazione all’uso dei filtri), indexCode (abilitazione all’uso degli indici) e cercaCode (abilitazione all’uso del cerca).

 

 

 

 

 

3.2        CODICE SVILUPPATO

 

 

3.2.1    Principali procedure

 

 

3.2.1.1    CALCOLACELLE

 

 

SELECT quote

N=((thisform.pageframe1.page1.ncco.value *thisform.pageframe1.page1.ncol.value)*thisform.pageframe1.page1.npia.value)

BEGIN transaction

*--------------------Tenta il blocco della tebella

IF !Flock()

  =MessageBox(ThisForm.Uti.trad("Tentativo di bloccare la tabella fallito"),;

    MB_ICONSTOP,ThisForm.Uti.trad("ERRORE"))

  RETURN .F.

ENDIF

pos=thisform.pageframe1.page1.npos.value

pro=thisform.pageframe1.page1.npro.value

nummacchina=thisform.pageframe1.page1.nmac.value

numprimacelscafsx=thisform.pageframe1.page1.npce.value

IF thisform.pageframe1.page1.combo1.value='D '

  IF n>=thisform.pageframe1.page1.npce.value

    msg=ThisForm.Uti.trad("Il numero calcolato di celle comprende celle del lato di sinistra !!!" )+CHR(13)

    msg=msg+thisform.Uti.trad("Vuoi continuare ?")

    IF messagebox(msg,65,ThisForm.Uti.trad("ATTENZIONE"))=2

      RETURN

      END transaction

      UNLOCK

    ENDIF

  ENDIF

ENDIF

SET deleted off

SET order to xquo_id1

SEEK str(nummacchina,2)

*--------------------Controlla che non vengano inserite due macchine uguali per lo stesso scaffale

*--------------------Se vuole inserire una macchina gia'presente provvede ad eliminare i suoi record

IF !eof()

  msg=ThisForm.Uti.trad("Questa macchina e'gia' presente nella tabella !!!" )+CHR(13)

  msg=msg+ThisForm.Uti.trad(' Vuoi sostituirla ?' )

  IF  messagebox(msg,65,ThisForm.Uti.trad("ATTENZIONE"))=1

    DO while !eof()

      REPLACE quo_mac with 0

      Delete

      SEEK str(nummacchina,2)

    ENDDO

  ELSE

    END transaction

    UNLOCK

    RETURN

  ENDIF

ENDIF

FOR i=1 to n

  FOR k=1 to pos

    FOR y=1 to pro

*-------------------Sfrutta se ci sono i record cancellati

      SEEK str(0,2)

      IF !eof()

        RECALL

      ELSE

        APPEND blank

      ENDIF

*-------------------Inizia inserimento dei dati

      REPLACE quo_mac with nummacchina

*-Inserisce codcella,scaffale e si assicura che la prima cella dello scaffale di destra sia 1 e quella di sinistra numprimacelscafsx

      IF (thisform.pageframe1.page1.combo1.value='D ') and (i<numprimacelscafsx)

        REPLACE quo_cel with  i

      ELSE

        IF thisform.pageframe1.page1.combo1.value='S '

          REPLACE quo_cel with (i+numprimacelscafsx-1)

        ELSE

          REPLACE quo_cel with i

        ENDIF

      ENDIF

*------------------Inserisce posizione,profondita'e coordinate

      DO case

      CASE (k=1) and (y=1) and (pos<>2)

        REPLACE quo_pos with cel_centro

        REPLACE quo_pro with cel_ant

      CASE (k=1) and (y=2) and (pos<>2)

        REPLACE quo_pos with cel_centro

        REPLACE quo_pro with cel_post

      CASE ((k=2) and (y=1) and (pos<>2)) or((k=1) and (y=1) and (pos=2))

        REPLACE quo_pos with cel_soccsx

        REPLACE quo_pro with cel_ant

      CASE ((k=2) and (y=2)and (pos<>2)) or ((k=1) and (y=2) and (pos=2))

        REPLACE quo_pos with cel_soccsx

        REPLACE quo_pro with cel_post

      CASE ((k=3) and (y=1) and (pos<>2))  or ((k=2) and (y=1) and (pos=2))

        REPLACE quo_pos with cel_soccdx

        REPLACE quo_pro with cel_ant

      CASE ((k=3) and (y=2) and (pos<>2)) or ((k=2) and (y=2) and (pos=2))

        REPLACE quo_pos with cel_soccdx

        REPLACE quo_pro with cel_post

      ENDCASE

      REPLACE quo_x   with 0

      REPLACE quo_y   with 0

      REPLACE quo_z   with 0

    NEXT

  NEXT

NEXT

SET deleted on

thisform.pageframe1.page4.grid1.refresh()

UNLOCK

END transaction

thisform.pageframe1.activepage=2

 

 

 

3.2.1.2    COORDINATE

 

 

 

 

SELECT quote

nx =thisform.pageframe1.page2.x.value

ny =thisform.pageframe1.page2.y.value

ny2=thisform.pageframe1.page2.y2.value

nz1 =thisform.pageframe1.page2.Z.value

xiniziale=thisform.pageframe1.page2.x.value

passocolonne=thisform.pageframe1.page2.PasCol.value

passopiani=thisform.pageframe1.page2.PasPia.value

numcolonne=(thisform.pageframe1.page2.Ncol.value)

numpiani=(thisform.pageframe1.page2.Npia.value)

numcellepercolonna=(thisform.pageframe1.page1.ncco.value)

nmac=thisform.pageframe1.page1.nmac.value

npos=thisform.pageframe1.page1.npos.value

npro=thisform.pageframe1.page1.npro.value

profonditacella=thisform.pageframe1.page2.z2.value

IF thisform.pageframe1.page1.ncco.value=1

  passocelle=(passocolonne)

ELSE

  passocelle=(passocolonne/thisform.pageframe1.page1.ncco.value)

ENDIF

*-------------------------Calcolo posizione prima cella

pos=(((thisform.pageframe1.page2.PiaIni.value-1)* thisform.pageframe1.page1.Ncol.value)*thisform.pageframe1.page1.ncco.value)+;

  (((thisform.pageframe1.page2.Colini.value-1)*thisform.pageframe1.page1.ncco.value)+1)

IF thisform.pageframe1.page1.combo1.value='S '

  pos=pos+thisform.pageframe1.page1.npce.value-1

ENDIF

BEGIN transaction

SET deleted on

SET order to xquo_id1

*---------------------Tenta il blocco della tabella

IF !Flock()

  =MessageBox(ThisForm.Uti.trad("Tentativo di bloccare la tabella fallito"),;

    MB_ICONSTOP,ThisForm.Uti.trad("ERRORE"))

  RETURN .F.

ENDIF

 

FOR p=1 to numpiani

  FOR i= 1 to numcolonne

    FOR k=1 to numcellepercolonna

*--------------------Si posiziona sulla cella corretta

      SEEK str(nmac,2)+bintoc(pos)

      FOR r=1 to npos

        FOR w=1 to npro

          IF w=1

*--------------------Inserisce coordinate in prima o seconda profondita'

            REPLACE quo_y with ny

            nz=nz1

          ELSE

            REPLACE quo_y with ny2

            nz=profonditacella

          ENDIF

          REPLACE quo_x with nx

          REPLACE quo_z with nz

*------------------Calcola la posizione della cella seguente

          IF r<npos or w<npro

          ELSE

            IF (numcolonne>i) or (numcellepercolonna>k)

              pos=pos+1

            ELSE

              pos=pos+((thisform.pageframe1.page1.Ncol.value-(thisform.pageframe1.page2.Colini.value+thisform.pageframe1.page2.Ncol.value-1))*numcellepercolonna)

              IF numpiani>p

                pos=pos+(((thisform.pageframe1.page2.Colini.value-1)*numcellepercolonna)+1)

              ENDIF

            ENDIF

          ENDIF

*-------------------Va al record successivo

          Skip

        ENDFOR

*-------------------Calcola coordinata x per il prossimo record

        DO case

        CASE npos =1

          nx=nx+passocelle

        CASE npos=2

          nx=nx+(passocelle/2)

        CASE r=1 and npos=3

          nx=nx-((passocelle/6)*2)

        CASE (r=2 or r=3) and npos=3

          nx=nx+((passocelle/6)*4)

        ENDCASE

        nz=0

      ENDFOR

    ENDFOR

  ENDFOR

*-------------------Calcola coordinate y,x per il prossimo record al piano superiore

  ny=(ny+passopiani)

  ny2=(ny2+passopiani)

  nx=xiniziale

ENDFOR

UNLOCK

thisform.pageframe1.page4.grid1.refresh()

END transaction

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3.2.1.3   MODIFICAQUOTE

 

 

 

 

SELECT quote

contatorex=0

contatorey=thisform.pageframe1.page3.Yinc.value

numcolonne=(thisform.pageframe1.page3.Ncol.value)

numpiani=(thisform.pageframe1.page3.Npia.value)

numcellepercolonna=thisform.pageframe1.page1.ncco.value

nmac=thisform.pageframe1.page1.nmac.value

npos=thisform.pageframe1.page1.npos.value

npro=thisform.pageframe1.page1.npro.value

costantex=thisform.pageframe1.page3.Xcost.value

costantey=thisform.pageframe1.page3.Ycost.value

incrementalex=thisform.pageframe1.page3.Xinc.value

incrementaley=thisform.pageframe1.page3.Yinc.value

nz=0

nx=0

*-------------------------Calcolo posizione prima cella

pos=(((thisform.pageframe1.page3.PiaIni.value-1)* thisform.pageframe1.page1.Ncol.value)*thisform.pageframe1.page1.ncco.value)+;

  (((thisform.pageframe1.page3.ColIni.value-1)*thisform.pageframe1.page1.ncco.value)+1)

IF thisform.pageframe1.page1.combo1.value='S '

  pos=pos+thisform.pageframe1.page1.npce.value-1

ENDIF

*-------------------------Tenta il blocco della tabella

IF !Flock()

  =MessageBox(ThisForm.Uti.trad("Tentativo di bloccare la tabella fallito"),;

    MB_ICONSTOP,ThisForm.Uti.trad("ERRORE"))

  RETURN .F.

ENDIF

BEGIN transaction

SET order to xquo_id1

SET deleted on

FOR p=1 to numpiani

  FOR i= 1 to numcolonne

    FOR k=1 to numcellepercolonna

*------------------Si posiziona sulla cella corretta

      SEEK str(nmac,2)+bintoc(pos)

      FOR r=1 to npos

        FOR w=1 to npro

*-------------------Calcola la somma coordinate x e y ,se incrementale,usando un contatore

          IF costantex>0

            nx =(quo_x+costantex)

          ELSE

            IF incrementalex>0

              IF (r=1) and (w=1)

                contatorex=contatorex + incrementalex

              ENDIF

              nx=quo_x

              nx =(nx+contatorex )

            ELSE

              nx=quo_x

            ENDIF

          ENDIF

          IF costantey>0

            ny=(quo_y+costantey)

          ELSE

            IF incrementaley>0

              ny=(quo_y+contatorey)

            ELSE

              ny=quo_y

            ENDIF

          ENDIF

          nz=quo_z

          REPLACE quo_x with nx

          REPLACE quo_y with ny

          REPLACE quo_z with nz

*-----------------Calcola la posizione della cella seguente

          IF (r<npos) or (w<npro)

          ELSE

            IF (numcolonne>i)  or (numcellepercolonna>k)

              pos=pos+1

            ELSE

              pos=pos+((thisform.pageframe1.page1.Ncol.value-(thisform.pageframe1.page3.ColIni.value+thisform.pageframe1.page3.Ncol.value-1))*numcellepercolonna)

              IF numpiani>p

                pos=pos+(((thisform.pageframe1.page3.ColIni.value-1)*numcellepercolonna)+1)

              ENDIF

            ENDIF

          ENDIF

*------------------Va al record seguente

          Skip

        ENDFOR

      ENDFOR

    ENDFOR

  ENDFOR

  contatorey=contatorey+incrementaley

  contatorex=0

  nx=quo_x

ENDFOR

UNLOCK

END transaction

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3.2.1.4    COPIA

 

 

 

 

SELECT quote

SET order to xquo_id1

scafs=thisform.pageframe1.page5.combo1.value

scafd=thisform.pageframe1.page5.combo4.value

nmac=thisform.pageframe1.page5.Nmaces.value

nmac2=thisform.pageframe1.page5.Nmacin.value

npsx1=thisform.pageframe1.page5.npces.value

npsx2=thisform.pageframe1.page5.npced.value

i=1

k=2

q=.f.

v=.f.

*--------------------Tenta il blocco della tebella

IF !Flock()

  =MessageBox(ThisForm.Uti.trad("Tentativo di bloccare la tabella fallito"),;

    MB_ICONSTOP,ThisForm.Uti.trad("ERRORE"))

  RETURN .F.

ENDIF

*-----------------Controlla se esiste la macchina da cui copiare

IF  npsx1=0 and scafs='S '

  msg=ThisForm.Uti.trad("La prima cella dello scaffale di sinistra della macchina sorgente non è stata inserita !!!" )+CHR(13)

  msg=msg+ThisForm.Uti.trad("Impossibile fare il calcolo " )

  messagebox(msg,49,ThisForm.Uti.trad("ATTENZIONE"))

    UNLOCK

    RETURN

  ENDIF

 IF  npsx2=0 and scafd='S '

  msg=ThisForm.Uti.trad("La prima cella dello scaffale di sinistra della macchina destinazione non è stata inserita !!!" )+CHR(13)

  msg=msg+ThisForm.Uti.trad("Impossibile fare il calcolo " )

  messagebox(msg,49,ThisForm.Uti.trad("ATTENZIONE"))

    UNLOCK

    RETURN

  ENDIF

 if scafs='D '

     SEEK str(nmac,2)+bintoc(1)

    else

     SEEK str(nmac,2)+bintoc(npsx1)

  endif

IF eof() or (scafs='D 'and quo_cel<>1) or (scafs='S ' and quo_cel<>npsx1)

  msg=ThisForm.Uti.trad("Macchina da copiare non esistente in tabella!!!" )+CHR(13)

  MESSAGEBOX(msg,48,ThisForm.Uti.trad("ATTENZIONE"))

  thisform.pageframe1.page5.Nmaces.value=1

  thisform.pageframe1.page5.combo1.value='D '

  unlock

  RETURN

ENDIF

*!*         *----------------Controlla se esiste già la macchina da inserire e permette la sua ridefinizione

 if scafd='D '

     SEEK str(nmac2,2)+bintoc(1)

    else

     SEEK str(nmac2,2)+bintoc(npsx2)

  endif

IF  (scafd='D ' and quo_cel=1) or (scafd='S ' and quo_cel=npsx2)

  msg=ThisForm.Uti.trad("Macchina e scaffale da inserire già esistente !!!" )+CHR(13)

  msg=msg+ThisForm.Uti.trad("Vuoi sostituirla ?" )

  IF messagebox(msg,49,ThisForm.Uti.trad("ATTENZIONE"))=2

    unlock

    RETURN

    else

    DO while quo_mac=nmac2 and !eof()

    REPLACE quo_mac with 0

    Delete

    SEEK str(nmac2,2)

    ENDDO

  ENDIF

ENDIF

 

*-------------------Esamina le varie combinazione di scaffali per inserire i codici cella corretti

 

 if scafs='D '

     SEEK str(nmac,2)+bintoc(1)

    else

     SEEK str(nmac,2)+bintoc(npsx1)

  endif

DO while (quo_mac=nmac) and (!eof()) and (!V)

*------------------Calcola il nuovo numero cella basandosi sul numero cella già esistente in tabella

    DO case

    CASE scafs='D 'and scafd='S '   

      cell=(quo_cel+npsx2-1)

    CASE scafs='S 'and scafd='D '

      cell=(quo_cel-npsx1+1)

    CASE scafs='D 'and scafd='D '

      cell=quo_cel

    CASE scafs='S 'and scafd='S '

      cell=quo_cel-npsx1+npsx2

    ENDCASE

  pos=quo_pos

  pro=quo_pro

  x=quo_x

  Y=quo_y

  z=quo_z

*-------------------Recupera i record eliminati,se possibile,ed inserisce i nuovi dati

  SEEK str(0,2)

  IF !eof()

    RECALL

  ELSE

    APPEND blank

  ENDIF

  REPLACE quo_mac with nmac2

  REPLACE quo_cel with cell

  REPLACE quo_pos with pos

  REPLACE quo_pro with pro

  REPLACE quo_x with x

  REPLACE quo_y with y

  REPLACE quo_z with z

 

  if scafs='D '

     SEEK str(nmac,2)+bintoc(1)

    else

     SEEK str(nmac,2)+bintoc(npsx1)

   endif

  Skip i

*-------------------Variabile che indica se si è arrivati alla prima cella dello scaffale di sinistra  

  if (scafs='D ' and quo_cel=npsx1) or (nmac=nmac2 and quo_cel=npsx2)

     v=.t.

  endif   

  i=i+1

ENDDO

Unlock

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3.2.2    Principali controlli

 

 

 

 

 

Controllo per l’accesso a pagina due e pagina tre inserito nelle procedure refresh delle pagine.

 

 

 

SELECT quote

SET order to xquo_id1

nummac=thisform.pageframe1.page1.nmac.value

npos=thisform.pageframe1.page1.npos.value

npro=thisform.pageframe1.page1.npro.value

SEEK str(nummac,2)

N=((((thisform.pageframe1.page1.ncco.value *thisform.pageframe1.page1.ncol.value)*;

  thisform.pageframe1.page1.npia.value)*npos)*npro)

*-----------------Controlla che la quotazione avvenga sullo scaffale corretto

num=0

DO while (quo_mac=nummac) and (!eof())

  Skip

  num=num+1

ENDDO

*------------------Controlla caso per caso la situazione posizione_profondità all'interno della cella

*------------------Se trova una discordanza mette c=0

SEEK str(nummac,2)

c=1

IF npos=1 and npro=1

  IF quo_pos='00' and  quo_pro='00'

  ELSE

    c=0

  ENDIF

ENDIF

IF npos=1 and npro=2

  IF quo_pos='00' and quo_pro='00'

    Skip

    IF quo_pos='00' and quo_pro='01'

    ELSE

      c=0

    ENDIF

  ELSE

    c=0

  ENDIF

ENDIF

IF npos=2 and npro=1

  IF quo_pos='01' and quo_pro='00'

    Skip

    IF quo_pos='02' and  quo_pro='00'

    ELSE

      c=0

    ENDIF

  ELSE

    c=0

  ENDIF

ENDIF

IF  npos=2 and npro=2

  IF quo_pos='01' and  quo_pro='00'

    Skip

    IF  quo_pos='01' and  quo_pro='01'

      Skip

      IF quo_pos='02' and  quo_pro='00'

        Skip

        IF quo_pos='02' and quo_pro='01'

        ELSE

          c=0

        ENDIF

      ELSE

        c=0

      ENDIF

    ELSE

      c=0

    ENDIF

  ELSE

    c=0

  ENDIF

ENDIF

IF npos=3 and npro=1

  IF quo_pos='00' and quo_pro='00'

    Skip

    IF quo_pos='01' and quo_pro='00'

      Skip

      IF quo_pos='02' and   quo_pro='00'

      ELSE

        c=0

      ENDIF

    ELSE

      c=0

    ENDIF

  ELSE

    c=0

  ENDIF

ENDIF

IF npos=3 and npro=2

  IF quo_pos='00' and   quo_pro='00'

    Skip

    IF quo_pos='00' and quo_pro='01'

      Skip

      IF quo_pos='01' and   quo_pro='00'

        Skip

        IF quo_pos='01' and  quo_pro='01'

          Skip

          IF quo_pos='02' and   quo_pro='00'

            Skip

            IF quo_pos='02' and  quo_pro='01'

            ELSE

              c=0

            ENDIF

          ELSE

            c=0

          ENDIF

        ELSE

          c=0

        ENDIF

      ELSE

        c=0

      ENDIF

    ELSE

      c=0

    ENDIF

  ELSE

    c=0

  ENDIF

ENDIF

IF num<>n or c=0

  msg=ThisForm.Uti.trad("La definizione dello scaffale in prima pagina non e' presente in tabella !!!" )+CHR(13)

  msg=msg+ThisForm.Uti.trad('Impossibile modificare quote.' )

  MESSAGEBOX(msg,64,ThisForm.Uti.trad("ERRORE"))

  thisform.pageframe1.activepage=1

ENDIF

 

 

 

 

 

Procedura inserita nel Refresh di pagina uno e nel LostFocus di Nmac che inizializza la prima cella di sinistra

 

 

 

*--------Inizializza numero prima cella sx con il corrispondente in tabella se c'e altrimenti con 0

SELECT celle

SET order to xcel_id1

nmac=thisform.pageframe1.page1.nmac.value

vera=.f.

SEEK str(nmac,2)

DO while !vera and !eof() and cel_mac=nmac

  IF cel_lato='S '

    primacella=cel_cod

    vera=.t.

  ENDIF

  Skip

ENDDO

IF vera

  thisform.pageframe1.page1.npce.value=primacella

ELSE

  thisform.pageframe1.page1.npce.value=0

ENDIF

 

 

 

 

 

 

 

 

 

Procedura inserita nel LostFocus di Npos che controlla il numero inserito

 

 

 

*----Controlla che il numero di posizoni all'interno della cella non sia maggiore di 3

IF this.value>3

  MESSAGEBOX(thisform.uti.trad("Il numero posizioni non puo'essere maggiore di 3 !"), 64, thisform.uti.trad("ERRORE"))

  this.value=1

ENDIF

IF this.value=0

  this.value=1

ENDIF

 

 

 

 

 

Procedura inserita nel LostFocus nelle combo che controlla i valori selezionati

 

 

 

if this.value<>'D 'and this.value<>'S '

   msg=ThisForm.Uti.trad("Il valore inserito non é corretto !!!" )+CHR(13)

   msg=msg+thisform.Uti.trad("Per selezionare il lato sinistro S per il lato destro D ?")

   messagebox(msg,65,ThisForm.Uti.trad("ATTENZIONE"))

   this.value='D '  

endif

 

 

 

 

 

Procedura inserita nel LostFocus di Colini e PiaIni che controlla valore inserito.

 

 

 

IF this.value>thisform.pageframe1.page1.ncol.value

  MESSAGEBOX(thisform.uti.trad("Il numero della colonna iniziale non puo'essere maggiore del numero max di colonne !"), 64, thisform.uti.trad("ERRORE"))

  this.value=1

ENDIF

IF ((this.value+thisform.pageframe1.page2.ncol.value)-1)>thisform.pageframe1.page1.ncol.value

  msg=thisform.uti.trad("La somma delle colonne  e' maggiore del numero max di colonne !")+CHR(13)

  msg=msg+thisform.uti.trad("Rinserire Colonna inizio e Numero colonne")

  MESSAGEBOX(msg, 64, thisform.uti.trad("ERRORE"))

  this.value=1

  thisform.pageframe1.page2.ncol.value=1

ENDIF

IF this.value=0

  this.value=1

ENDIF

 

 

 

 

 

Procedura inserita nel LostFocus di Ncol e Npia che controlla il valore inserito.

 

 

 

IF ((this.value+thisform.pageframe1.page2.Colini.value)-1)>thisform.pageframe1.page1.ncol.value

  msg=thisform.uti.trad("La somma delle colonne  e' maggiore del numero max di colonne !")+CHR(13)

  msg=msg+thisform.uti.trad("Rinserire Colonna inizio e Numero colonne")

  MESSAGEBOX(msg, 64, thisform.uti.trad("ERRORE"))

  this.value=1

  thisform.pageframe1.page2.ncol.value=1

ENDIF

IF this.value=0

  this.value=1

ENDIF

 

 

 

 

 

Case che inserito nella procedura clic dei comandi lancia Calcolacelle, Coordinate o Modificaquote.

 

 

 

DO case

CASE ThisForm.Pageframe1.ActivePage = 1

  thisform.calcolacelle

 

CASE ThisForm.Pageframe1.ActivePage = 2

  thisform.Coordinate

 

ENDCASE

 

 

 

 

 

Case che inserito nella procedura Refresh dei comandi rinfresca l’abilitazione

 

 

 

DO case

CASE ThisForm.Pageframe1.ActivePage = 1

  this.enabled = .t.

  this.ToolTipText = "Avvia la procedura di calcolocelle "

 

CASE ThisForm.Pageframe1.ActivePage = 2

  this.enabled = .t.

  this.ToolTipText = "Avvia la procedura di quotazione celle"

 

CASE ThisForm.Pageframe1.ActivePage = 3

  this.enabled = .f.

  this.ToolTipText = ""

 

CASE ThisForm.Pageframe1.ActivePage = 4

  this.enabled = .f.

  this.ToolTipText = ""

CASE ThisForm.Pageframe1.ActivePage = 5

  this.enabled = .f.

  this.ToolTipText = ""

 

ENDCASE

 

 

 

 

 

Procedura inserita nel Click di Cmd5 che elimina o il record selezionato o i record macchina

 

 

 

SELECT quote

SET order to xquo_id1

IF !Flock()

  =MessageBox(ThisForm.Uti.trad("Tentativo di bloccare la tabella fallito"),;

    MB_ICONSTOP,ThisForm.Uti.trad("ERRORE"))

  RETURN .F.

ENDIF

*-------------------Cancella tutti i record della macchina

IF thisform.pageframe1.page5.cmacheck1.value=.t. and thisform.pageframe1.activepage=5

  msg=ThisForm.Uti.trad("Questa operazione eliminera' tutti i record relativi alla macchina !!!" )+CHR(13)

  msg=msg+thisForm.Uti.trad("Sei sicuro !")

  IF  messagebox(msg,68,ThisForm.Uti.trad("ATTENZIONE"))=6

    macc=thisform.pageframe1.page5.Nmaccan.value

    SEEK str(macc,2)

    IF eof()

      msg=ThisForm.Uti.trad("Macchina non esistente !!!" )+CHR(13)

      MESSAGEBOX(msg,49,ThisForm.Uti.trad("ATTENZIONE"))

      RETURN

      UNLOCK

    ENDIF

    DO while quo_mac=macc and !eof()

      REPLACE quo_mac with 0

      Delete

      SEEK str(macc,2)

    ENDDO

  ENDIF

ELSE

*-------------------Elimina il record selezionato

  IF thisform.pageframe1.activepage=4

    REPLACE quo_mac with 0

    Delete

    GO recno()

  ENDIF

  thisform.pageframe1.page4.grid1.refresh()

ENDIF

UNLOCK

 


CAPITOLO 4

 

 

 

 

UN ESEMPIO APPLICATIVO

 

 

 

In questo capitolo viene descritto un esempio applicativo col quale ci si propone di mostrare il vero funzionamento delle fasi del progetto rendendone il più semplice possibile la comprensione da parte del lettore.

In questo esempio supponiamo che l’operatore voglia definire lo scaffale di destra di un magazzino per la macchina uno e che voglia poi quotarne solo una parte andando in un secondo tempo a modificarne le quote, infine copia la definizione dello scaffale di destra creata per la macchina uno sullo scaffale di sinistra della macchina due.

L’operatore andrà poi ad eliminare prima un record selezionato in tabella poi tutti i record riferiti alla macchina uno inizialmente calcolati ed inseriti in tabella.

 

 

 



La prima operazione da fare è definire lo scaffale inserendo i dati in prima pagina, in questo esempio, come si vede dalla Form qui sotto, l’utente creerà la definizione per la macchina uno di uno scaffale di destra di dieci colonne  e dieci piani con due celle per colonna e tre posizioni e due profondità per ogni cella

 

 


 

 


Inseriti i dati ora siamo in grado di calcolare ed inserire le celle in tabella cliccando sul pulsante Calcola, unico attivo con pagina uno; al clic del comando se tutto va bene avremo in tabella 200.

 

 


 

 

 

 


Come si vede in tabella le celle per la macchina numero uno sono come previsto 200 con tre posizioni e due profondità a coordinate tutte a zero. Dopo l’ultima cella non compaiono più record perché quella inserita è l’unica definizione in tabella.

 

Ora l’operatore  va a quotare una parte dello scaffale considerando solo le celle comprese tra la terza e la settima colonna e tra il secondo e il quarto piano, quindi avremo una situazione in pagina due uguale a quella in figura qui sotto.

 


 

 

 


La quotazione partirà dalla posizione centrale anteriore della cella numero venticinque terza colonna secondo piano, questa posizione avrà coordinate uguali a zero per la prima profondità e Y e X in seconda profondità uguali a 500.

Terminerà alla posizione destra posteriore della novantaduesima cella quinto piano settima colonna

 

 

 

Ora in tabella avremo una situazione del genere

 


 

 

 


Come previsto il calcolo delle quote parte dalla posizione centrale anteriore della venticinquesima cella prima al secondo piano terza colonna con coordinate a zero e finirà alla novantaduesima seconda al quinto piano settima colonna.

Dalla tabella si può notare come le coordinate siano state calcolate in base al passo colonne e al numero celle per colonna.

 

 

 

Dopo avere inserito le coordinate si vuole modificarle. Grazie a pagina tre l’operatore sarà in grado di definire una parte dello scaffale per la modifica e sommare alle quote delle posizioni e profondità delle sue celle una costante o una variabile.

Nell’esempio qui sotto verranno considerate le celle comprese tra la prima e la quinta colonna e tra il primo e il quinto piano; alle quote X di tutte queste verrà sommato 100, mentre alle quote Y verrà fatta una somma incrementale, quindi alle celle del primo piano 100 a quelle del secondo 200 a quelle del terzo 300 a quelle del quarto 400 e a quelle del quinto 500.

 


 

 

 


Dalla Form qui sopra si nota la disabilitazione di X incrementale e di Y costante dovute ai valori rispettivamente di X costante e Y incrementale diversi da zero.

 

Quindi la tabella risulterà essere uguale a quella qui sotto, come si vede la coordinata X della cella 24 prima a zero ora è uguale alla costante sommata 100, come anche la posizione centrale della 25, mentre la posizione di sinistra prima uguale a –167 ora è uguale a –67.

La quota Y della cella 24 essendo al secondo piano è uguale a 200, mentre la Y in seconda profondità della 25 prima a 500 ora è uguale a 700; infatti la somma incrementale Y al primo piano sarà 100,al secondo piano sarà uguale a 200, al terzo 300 e così via.

 


 

 

 

 


Ora l’utente fa la copia della definizione sullo scaffale di sinistra della macchina due.

Come si vede dalla figura qui sotto il programma attraverso il clic del comando Copia creerà in tabella una definizione uguale a quella inserita in precedenza per lo scaffale di sinistra con prima cella 1000 per la macchina due

In figura si nota anche che il secondo spazio è disattivato, infatti non è stata selezionata la Casella di controllo attraverso la quale sarà possibile usufruire dei dati all’interno dello spazio.

 

 

 


 

 


In questo caso non è stata inserita la prima cella di sinistra della macchina sorgente perché in tabella non è presente per questa macchina uno scaffale di sinistra, altrimenti il programma non avendo la possibilità di distinguere tra scaffale di destra o di sinistra avrebbe fatto la copia di entrambi gli scaffali.

In figura qui sotto possiamo vedere come appare la tabella dopo aver fatto la copia, infatti possiamo notare che la definizione dello scaffale per la macchina due inizia dalla cella 1000, come voluto , con una tipologia di cella uguale a quella della macchina uno e stesse coordinate X, Y e Z.

 

 

 


 

 

 


La prima cella risulta essere la 1000 come abbiamo desiderato inserendo in prima cella dello scaffale di sinistra 1000, l’ultima rispecchiando la definizione della macchina uno sarà uguale a 1200

 

 

 

Ora vediamo come è possibile eliminare dalla tabella tutti i record riferiti ad una macchina. Per poter disporre di questa funzione prima di tutto bisognerà selezionare la Casella di controllo “Elimina solo una macchina” che abiliterà la Casella di testo per la macchina e il Comando Cancella, quindi inserendo in macchina uno e cliccando su Cancella il programma eliminerà dalla tabella tutti i record riferiti alla macchina uno.

 

 

 


 

 


Notiamo come alla selezione della Casella di controllo “Elimina solo una macchina” vengano abilitati la Casella di testo “Macchina” e il comando Cancella consentendo così questa funzione.


 

 


Prima della eliminazione l’operatore sarà informato della operazione in corso da un messaggio come quello sotto e sarà in grado di continuare o rinunciare alla operazione

 


 

 


Come si vede dalla tabella l’operazione è stata eseguita infatti sono stati eliminati tutti i record della macchina uno.