Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: petrusic - Febbraio 27, 2021, 05:26:37 pm

Titolo: [Risolto] matrici globali
Inserito da: petrusic - Febbraio 27, 2021, 05:26:37 pm
L'ostacolo di oggi si chiama
Citazione
frm2.pas(227,16) Error: Identifier not found "tbMovv"

tbMovv è una matrice che penso di avere dichiarata come globale.
Codice: [Seleziona]
unit frmmain;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, DB, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls,
  ExtCtrls, fpspreadsheet, laz_fpspreadsheet, Process, ZConnection, ZDataset,
  fpstypes; // , flcDynArrays; dovrebbe permettere di riordinare la seuenza degli elementi di un vettore

type

  { TForm1 }

  TForm1 = class(TForm)
    DataSource1: TDataSource;
    leInfoMov: TLabeledEdit;
    PulsFine: TButton;
    PulsAvvia: TButton;
    Label1: TLabel;
    lsDir: TListBox;
    ZConnection1: TZConnection;
    ZQuery1: TZQuery;
    procedure PulsFineClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure PulsAvviaClick(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}
uses
  frm2;
  //  frm2, tbComuni;
type
   TsSpreadsheetFormat = (sfExcel2, sfExcel5, sfExcel8, sfExcelXML, sfOOXML,
    sfOpenDocument, sfCSV, sfHTML, sfWikiTable_Pipes, sfWikiTable_WikiMedia, sfUser);

   TtbMovv = array of array of String;
   TtbResta = array of array of String;
   TtbRiep = array of array of String;

const
    dirFogli: string = '/media/dirdati/dativari/ContDom/';

var
//  MyWorkbook: TsWorkbook;   // dichiarazione necessaria per creare un'istanza della cartella di lavoro

  tbMovv: TtbMovv;
  tbResta: TtbResta;
  tbRiep: TtbRiep;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);                     

L'errore l'ho ricevuto all'interno della Unit "frm2".

Ieri però ho scritto tante righe dentro la frm2 ed ho anche avviato la compilazione del programma più volte, senza mai ricevere messaggi d'errore. Quindi non ho capito più se verament5e c'è un problema.
Riporto qui sotto il gruppo di istruzioni dove il compilatore ha segnalato l'errore:
Codice: [Seleziona]
procedure TForm2.FormCreate(Sender: TObject);
var
  frmain: TForm;

  i, n, nuRec, totRecQry: Integer;
  ixTbMovv, ixTbResta, ixTbRiep: Integer;
  nuRgTbMovv, nuRgTbResta, nuRgTbRiep: Integer;
begin
--- bla --- bla ---
  //-------------------------------------------- Verifica presenza di righe in "tbMovv", "tbResta" e in "tbRiep" ------------------------------------------
  nuRgTbMovv:= tbMovv.Count/5;     //  )
  nuRgTbRiep:= tbRiep.Count/4;       //  (    Righe segnalate con l'errore NOT found
  nuRgTbResta:= tbResta.Count/5;   //  )
  if (nuRgTbMovv > 0) then
  begin
    ixTbMovv:= 0;
  end                         

 ???
Titolo: Re:matrici globali
Inserito da: Stilgar - Febbraio 27, 2021, 10:18:27 pm
Non è visibile.L'hai dichiarata nell'implementation e non nell'interface del modulo che la esporta.
Così a prima vista
Stilgar
Titolo: Re:matrici globali
Inserito da: petrusic - Febbraio 28, 2021, 04:02:23 pm
Non è visibile.L'hai dichiarata nell'implementation e non nell'interface del modulo che la esporta.

Ah!
Io avevo capito che tutti i miei type e var andassero scritti dopo l'implementation.
Ora ho spostato le mie dichiarazioni nella sezione Interface della Unit frmmain, così:
Codice: [Seleziona]
unit frmmain;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, DB, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls,
  ExtCtrls, fpspreadsheet, laz_fpspreadsheet, Process, ZConnection, ZDataset,
  fpstypes; // , flcDynArrays; dovrebbe permettere di riordinare la seuenza degli elementi di un vettore
type
  { TForm1 }

  TForm1 = class(TForm)
    DataSource1: TDataSource;
    leInfoMov: TLabeledEdit;
    PulsFine: TButton;
    PulsAvvia: TButton;
    Label1: TLabel;
    lsDir: TListBox;
    ZConnection1: TZConnection;
    ZQuery1: TZQuery;
    procedure PulsFineClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure PulsAvviaClick(Sender: TObject);

   TtbMovv = array of array of String;
   TtbResta = array of array of String;
   TtbRiep = array of array of String;
  end;

var
  Form1: TForm1;

  tbMovv: TtbMovv;
  tbResta: TtbResta;
  tbRiep: TtbRiep;

implementation
{$R *.lfm}
uses
  frm2;
type
   TsSpreadsheetFormat = (sfExcel2, sfExcel5, sfExcel8, sfExcelXML, sfOOXML,
    sfOpenDocument, sfCSV, sfHTML, sfWikiTable_Pipes, sfWikiTable_WikiMedia, sfUser);   // sfOpenDocument è il tipo di formato valido per OpenOffice/LibreOffice.ods
const
    dirFogli: string = '/media/dirdati/dativari/ContDom/';
var
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);               
...
Ebbene, in quest'ultima, come in altre prove di posizionamento dei type nella sezione Interface, ricevo sempre ERRORE, un errore diverso ma, pur sempre errore:
Citazione
frmmain.pas(30,4) Error: Fields cannot appear after a method or property definition, start a new visibility section first

Insomma, tirando le somme, non ho capito nè trovato, come mi capita quasi sempre, un esempio calzante per i miei errori di codifica.
Ma allora dove vanno scritte le dischiarazioni globali (type, const e var) ?

Esiste una guida testuale chiara, possibilmente in italiano, che accompagni passo dopo passo il principiante?

Capisco che certe domande non dovrebbero fare parte della vita di un forum. Sono dispiaciuto e privo di mordente.
 ::)
Titolo: Re:matrici globali
Inserito da: nomorelogic - Febbraio 28, 2021, 04:36:52 pm
l'errore ti spiega cona non va:

ti dice che un campo non può essere definito dopo un metodo od una proprietà
per ovviare puoi definire un'altra sezione di visibilità

ovvero puoi fare come segue:
Codice: [Seleziona]
TForm1 = class(TForm)
    DataSource1: TDataSource;
    leInfoMov: TLabeledEdit;
    PulsFine: TButton;
    PulsAvvia: TButton;
    Label1: TLabel;
    lsDir: TListBox;
    ZConnection1: TZConnection;
    ZQuery1: TZQuery;
    procedure PulsFineClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure PulsAvviaClick(Sender: TObject);
  private   // <- nuova sezione di visibilità, si può usare anche "public" o altra definizione di visibilità
   TtbMovv = array of array of String;
   TtbResta = array of array of String;
   TtbRiep = array of array of String;
  end;

oppure

Codice: [Seleziona]
TForm1 = class(TForm)
    DataSource1: TDataSource;
    leInfoMov: TLabeledEdit;
    PulsFine: TButton;
    PulsAvvia: TButton;
    Label1: TLabel;
    lsDir: TListBox;
    ZConnection1: TZConnection;
    ZQuery1: TZQuery;

   // field spostati prima dei metodi
   TtbMovv = array of array of String;
   TtbResta = array of array of String;
   TtbRiep = array of array of String;


    procedure PulsFineClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure PulsAvviaClick(Sender: TObject);
  end;


Edit:
La sequenza, la puoi trovare qui:
https://freepascal.org/docs-html/ref/refse34.html#x69-910006.1 (https://freepascal.org/docs-html/ref/refse34.html#x69-910006.1)

capisco che c'è da farci l'occhio... :)
Titolo: Re:matrici globali
Inserito da: petrusic - Febbraio 28, 2021, 05:20:34 pm
per ovviare puoi definire un'altra sezione di visibilità

Purtroppo non funzionano nemmeno i tuoi suggerimenti. Il secondo l'avevo già provato prima del mio precedente post.
Ho provato ora anche questo:
Codice: [Seleziona]
type

  { TForm1 }

  TForm1 = class(TForm)

    DataSource1: TDataSource;
    leInfoMov: TLabeledEdit;
    PulsFine: TButton;
    PulsAvvia: TButton;
    Label1: TLabel;
    lsDir: TListBox;
    ZConnection1: TZConnection;
    ZQuery1: TZQuery;
    procedure PulsFineClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure PulsAvviaClick(Sender: TObject);

private
// public
  TtbMovv = array of array of String;
  TtbResta = array of array of String;
  TtbRiep = array of array of String;

Ed ecco cosa ne pensa il compilatore:
Citazione
frmmain.pas(31,11) Fatal: Syntax error, ":" expected but "=" found
private o public è la stessa medesima  cosa. Lo stesso errore mi viene fornito se metto in campo il tuo 2° esempio.

Titolo: Re:matrici globali
Inserito da: nomorelogic - Febbraio 28, 2021, 06:17:43 pm
prova a portare la dichiarazione di "array of array" prima di TForm1

Codice: [Seleziona]

type
  TAoA = array of array of String;


  TForm1
     ...
  private
     TtbMovv : TAoa;
     ...
  end;
 
 

Titolo: Re:matrici globali
Inserito da: petrusic - Febbraio 28, 2021, 10:07:37 pm
prova a portare la dichiarazione di "array of array" prima di TForm1
Fatto, ma cambia solamente il messaggio d'errore:
Citazione
frm2.pas(69,13) Error: identifier idents no member "tbMovv"
Titolo: Re:matrici globali
Inserito da: bonmario - Marzo 01, 2021, 07:59:33 am
Ho il sospetto che tu stia usando "tbMovv", e non "Form1.tbMovv".

Puoi eventualmente postare il codice della dichiarazione attuale di TForm1, e quello che hai scritto per usare "tbMovv" dal Fom2?

Ciao, Mario
Titolo: Re:matrici globali
Inserito da: nomorelogic - Marzo 01, 2021, 08:24:34 am
puoi pubblicare tutta la unit o almeno la parte implemenatation?

Edit:
pardon, la parte interface
Titolo: Re:matrici globali
Inserito da: petrusic - Marzo 01, 2021, 04:35:36 pm
Ho il sospetto che tu stia usando "tbMovv", e non "Form1.tbMovv".
Puoi eventualmente postare il codice della dichiarazione attuale di TForm1, e quello che hai scritto per usare "tbMovv" dal Fom2?
Quello che succede è esattamente il contrario di quanto sospetti tu. Infatti, usandoi tbMovv soltanto non da errore, mentre Form1.tbMovv da errore.

L'errore si è manifestato infatti sulle righe che avevo modificato prima dell'ultima modifica suggerita da nomorelogic e che avevo dimenticato di ripristinare (senza Form1.)

Ecco le righe di  Form1 che mi avete chiesto, tu e nomorelogic :
Codice: [Seleziona]
unit frmmain;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, DB, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls,
  ExtCtrls, fpspreadsheet, laz_fpspreadsheet, Process, ZConnection, ZDataset,
  fpstypes; // , flcDynArrays; dovrebbe permettere di riordinare la seuenza degli elementi di un vettore

type

  { TForm1 }
  TtbMovv = array of array of String;
  TtbResta = array of array of String;
  TtbRiep = array of array of String;

  TForm1 = class(TForm)

    DataSource1: TDataSource;
    leInfoMov: TLabeledEdit;
    PulsFine: TButton;
    PulsAvvia: TButton;
    Label1: TLabel;
    lsDir: TListBox;
    ZConnection1: TZConnection;
    ZQuery1: TZQuery;
    procedure PulsFineClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure PulsAvviaClick(Sender: TObject);




  end;

var
  Form1: TForm1;

  tbMovv: TtbMovv;
  tbResta: TtbResta;
  tbRiep: TtbRiep;
implementation                                                           

ecoo anche del passo di Form2, dove si verificava l'errore:
Codice: [Seleziona]
procedure CarRgTbMovv(ixTab, rgCorr,  n: Integer);
var
  coVoce: Integer;

  coVoceEdt, dtprec, sql, voCassa: String;
begin
  if (tbMovv[ixTab, 5] <> 'TOTALE') THEN
  begin
    Form2.GridMovv.Cells[1,rgCorr]:= tbMovv[ixTab, 5];  // Descrizione del movimento contabile
    coVoce:= StrToInt(tbMovv[ixTab, 1]);
    coVoceEdt:= EdtCoVo(coVoce);
    Form2.GridMovv.Cells[2,rgCorr]:= coVoceEdt;         // Es.:'1.01.600.005';
    coVoce:= coVoce div 1000;
    coVoce:= coVoce * 1000;
    sql := 'SELECT NomeVoce FROM piancont WHERE NumVoce = ' + IntToStr(coVoce);
    Form1.ZQuery1.SQL.Text := sql;                                                         

Col codice modificato, come riportato sopra, non da più errore.
Titolo: Re:matrici globali
Inserito da: bonmario - Marzo 01, 2021, 04:53:11 pm
Per forza ... con l'ultimo sorgente che ha postato, "tbMovv" lìhai dichiarata al di fuori di "TForm1", quindi quello che stai usando adesso, con il sorgente in queste condizioni, è il codice corretto.

Ciao, Mario
Titolo: Re:matrici globali
Inserito da: petrusic - Marzo 02, 2021, 03:42:25 pm
Per forza ... con l'ultimo sorgente che ha postato, "tbMovv" lìhai dichiarata al di fuori di "TForm1", quindi quello che stai usando adesso, con il sorgente in queste condizioni, è il codice corretto.
Non posso dire di avere capito.

Nei primi passi, avevo capito che le mie variabili dovevano essere dichiarate sempre nella sezione Implementation ( le locali dentro le procedure, le globali prima della prima procedure/function.

Ho scoperto da poco che le variabili globali devono fare parte della sezione Interface. Mi sono detto, allora: va bene, ho capito male prima. Ora sta venendo fuori, praticamente, che, addirittura, devo dichiararle prima della Form1.
Ma io, prima della Classe Tform1 ho dichiarato i type delle matrici, mentre le variabili sono dichiarate nella sezione var, dopo la Form1.
Quiindi, se fra variabili globali dovessi disporre anche di una stringa "campoGlobale", non avendo bisogno di dichiarare anche il corrispondente type, potrei farlo benissimo, fra le var, dopo la Form1?

Credo di avere raggiunto un livello abbastanza disordinato e confuso nelle mie conoscenza di base su questo linguaggio.
*?*  ???  *?*
Titolo: Re:matrici globali
Inserito da: bonmario - Marzo 02, 2021, 04:41:59 pm
Sei capisce dalle domande che fai che hai le idee confuse !!!

Tutto dipende dalla "Visibilità" che devi dare alla variabili, ed all'uso che ne devi fare.

Facendo riferimento ai nomi che hai usato tu nel codice che hai postato:
- se tbMovv la devi usare SOLO nelle procedure che hai nella "implementation", la puoi dichiarare nella implementation
- se tbMovv la devi usare nei sorgenti che usano la unit dove la stai dichiarando, la DEVI dichiarare prima della implementation. Occhio però: in questo modo avrai una sola variabile di nome tbMovv. Se nella unit di Form2, usi 2 variabili, Pippo e Pluto, entrambe di tipo TForm1, entrambe punteranno alla stessa tbMovv
- se invece vuoi dichiarare 2 variabili Pippo e Pluto di tipo TForm1, ed ognuna di loro deve avere la sua tbMovv, la devi dichiarare all'interno della "public" della dichiarazione di TForm1

Spero di non aver dimenticato nulla ...

P.S. Naturalmente, queste considerazioni valgono sempre, ho solo usato i nomi che hai dato tu, per cercare di essere più chiaro.


Ciao, Mario
Titolo: Re:matrici globali
Inserito da: petrusic - Marzo 02, 2021, 11:09:24 pm
Facendo riferimento ai nomi che hai usato tu nel codice che hai postato:
- (se tbMovv la devi usare SOLO nelle procedure che hai nella "implementation", la puoi dichiarare nella implementation)
- se tbMovv la devi usare nei sorgenti che usano la unit dove la stai dichiarando, la DEVI dichiarare prima della implementation. Occhio però: in questo modo avrai una sola variabile di nome tbMovv. Se nella unit di Form2, usi 2 variabili, Pippo e Pluto, entrambe di tipo TForm1, entrambe punteranno alla stessa tbMovv
il 1° criterio d'uso è chiaro.
il  2° è proprio quello che devo mettere in pratica.
Però mi viene difficile capire il perchè, oltre alla sezione var, devo tenere conto di una strana posizione, a mio avviso,  dei type relativi alle variabili. Nei type dichiaro le classi di appartenenza delle variabili. Allora non dovrei scrivere tali dichiarazioni pure sotto il type TForm1?
Es.:
Codice: [Seleziona]
type

  { TForm1 }
  TForm1 = class(TForm)

  TtbMovv = array of array of String;
  TtbResta = array of array of String;
  TtbRiep = array of array of String;

    DataSource1: TDataSource;
    leInfoMov: TLabeledEdit;                         
...
var
  Form1: TForm1;

  tbMovv: TtbMovv;
  tbResta: TtbResta;
  tbRiep: TtbRiep;

implementation               
 
Invece, per fare funzionare il riconoscimento da parte del compilatore, ho dovute scrivere:
Codice: [Seleziona]
type

  { TForm1 }
  TtbMovv = array of array of String;
  TtbResta = array of array of String;
  TtbRiep = array of array of String;

  TForm1 = class(TForm)                 
...
:o


Titolo: Re:matrici globali
Inserito da: nomorelogic - Marzo 03, 2021, 12:27:48 am
quando dichiari tipi o variabili nella sezione interface e/o implementation
queste dichiarazioni hanno visibilità relativa all'intera unit
come già detto:
- interface = visibilità anche all'esterno della unit (tramite clausola uses si ottiene visibilità)
- implementation = visibilità solo all'interno della unit stessa


ciò che invece dichiari all'interno di una classe definisce una visibilità esclusiva alla classe
se metti la dichiarazione "TtbMovv = array of array of String" all'interno della classe TForm1, questo tipo non sarà visibile all'esterno della classe
infatti nell'esempio che non ti funziona, dichiaravi in var delle variabili ma var è esterna alla dichiarazione di TForm1 e quindi TtbMovv  non è visibile
la regola è semplice: i tipi incapsulati nella dichiarazione di una classe sono visibili esclusivamente nella classe stessa

spostando la dichiarazione sopra TForm1 in realtà hai postato la dichiarazione fuori dalla classe ma all'interno della unit
è per questo che in var diventano visibili



Titolo: Re:matrici globali
Inserito da: petrusic - Marzo 03, 2021, 04:52:10 pm
@nomorelogic
@bonmario

Grazie per la vostra paziente ed abbondante spiegazione.
 :)