Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: petrusic - Gennaio 15, 2021, 10:10:26 pm

Titolo: [Risolto] aprire un file miofoglio.ods e leggerne il contenuto
Inserito da: petrusic - Gennaio 15, 2021, 10:10:26 pm
Mi trovo ad affrontare la seguente tematica:
Caricare il contenuto delle celle di alcuni fogli elettronici, costruiti da me anni fa e contenenti valori contabili.
Poi dovrei tasfreririli nel corrispondente mio DB Sqlite3.
Non  avendo alcuna idea di come aprire un file LibreOffice.ods, ho cercato una risposta sul wiki. Non ho trovato però specificatamente ciò che mi serve, perche qui (http://translate.google.com/translate?hl=it&sl=auto&tl=it&u=https%3A%2F%2Fwiki.freepascal.org%2FFPSpreadsheet_tutorial%3A_Writing_a_mini_spreadsheet_application&anno=2&sandbox=1) (per esempio) viene trattato di come fare funzionare il foglio elettronico denro un programma Lazarus ed a me non interessa.
Io, infatti dovrei solamente accedere alk contenuto della celle e costruire, nel mio progetto, un array strutturato a modo mio per riversarlo poi nelle opportune tabelle del mio DB.

Ho scaricato fpspreadsheet-1.12.zip e, dopo averlo estratto, ho creato un nuovo progetto dove ho aggiunto la use "fpspreadsheet"
Codice: [Seleziona]
unit daContoDom_aDomusRatio;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, fpspreadsheet;

type
  TForm1 = class(TForm)
  private

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

end.                           
Ora dovrei aprire un file.ods e leggerne il contenuto, ma non ho capito
Ho  cercato guide o esempi di utilizzo per l'accesso a fogli elettronici, ma non niente di calzante.
E allora, come procedere?
Titolo: Re: aprire un file miofoglio.ods e leggerne il contenuto
Inserito da: nomorelogic - Gennaio 16, 2021, 08:44:51 am
ciao

in effetti quello è un tutotial per scrivere una applicazione tipo foglio elettronico.
Però fpSpreadsheet comprende sia i componenti visuali (per sviluppo GUI) che i componenti non visuali, che sono quelli che ti servono.

Leggi questa pagina wiki
https://wiki.lazarus.freepascal.org/FPSpreadsheet
nella sezione Basic viene spiegato il funzionamento di questo package, leggi bene soprattutto le classi TsWorkbook e TsWorkSheet poiché è da li che devi partire.

Io uso questo package da tempo è realmente stabile e potente ma soprattutto non usa OLE/Activex per accedere ai fogli elettronici!

Ciao
nomorelogic
Titolo: Re: aprire un file miofoglio.ods e leggerne il contenuto
Inserito da: tito_livio - Gennaio 17, 2021, 01:12:24 am
Ciao, se non ho capito male il tuo problema è solo convertire i dati.
SE è così, potresti salvare i fogli elettronici in csv e poi li leggi come un file di testo.
Titolo: Re: aprire un file miofoglio.ods e leggerne il contenuto
Inserito da: petrusic - Gennaio 17, 2021, 04:58:27 pm
Ciao, se non ho capito male il tuo problema è solo convertire i dati.
SE è così, potresti salvare i fogli elettronici in csv e poi li leggi come un file di testo.
Si, è vero. Dovrei però convertire i miei file.ods, ciascuno con 4 fogli elettronici al suo interno, in altrettanti file.csv. Per farlo dovrei affidarmi ad un convertitore specifico, magari on-line. Non so, sono alquanto scettico.
Comunque, grazie per il suggerimento. Vi potrò ricorrere qualora dovessi fallire con FPSpreadsheet.
Titolo: Re: aprire un file miofoglio.ods e leggerne il contenuto
Inserito da: tito_livio - Gennaio 17, 2021, 10:29:39 pm
Non serve nessun programma esterno. I fogli elettronici li salvi in csv con il tuo programma per i fogli elettronici, per esempio LibreOffice. Nel salvare gli dici, per esempio che devi separare i campi con il ; .
Titolo: Re: aprire un file miofoglio.ods e leggerne il contenuto
Inserito da: petrusic - Gennaio 19, 2021, 04:19:21 pm
Leggi questa pagina wiki
https://wiki.lazarus.freepascal.org/FPSpreadsheet
nella sezione Basic viene spiegato il funzionamento di questo package, leggi bene soprattutto le classi TsWorkbook e TsWorkSheet poiché è da li che devi partire.
Avevo già letto la pagina prima di scrivere, ma riconosco di averlo fatto senza il necessario approfondimento. Purtroppo io ho mai simpatizzato con la lingua inglese.
Meno male che oggi esistono strumenti fantastici.

Sono andato avanti fino a costruire una ListBox, dove ho caricato, tramite la libreria "TSearchRec", i nomi dei file.ods/xls che dovrei leggere singolarmente in modo da trasferire il contenuto delle celle di ciascun foglio, interno al file-cartella, in una matrice mia per la successiva scansione estrattiva.:
Riporto qui il mio programmino così come l'ho scritto fino ad ora:
Codice: [Seleziona]
unit frmmain;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls,
  fpspreadsheet, laz_fpspreadsheet;

type

  { TForm1 }

  TForm1 = class(TForm)
    PulsAvvia: TButton;
    Label1: TLabel;
    lsDir: TListBox;
    procedure FormCreate(Sender: TObject);
    procedure PulsAvviaClick(Sender: TObject);
  private

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

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
  MyWorkbook: TsWorkbook;   // dichiarazione necessaria per creare un'istanza della cartella di lavoro

{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
var
  Esito: TSearchRec;

  begin
    If FindFirst(dirFogli + 'ContDom*.*', faAnyFile,  Esito)=0 then
    begin
      Label1.Caption:= 'Directory corrente:' + chr(10) + dirFogli;
  repeat
   begin
     lsDir.Items.Add(Esito.Name);
   end;
   Until FindNext(Esito) <> 0;
   FindClose(Esito);
   PulsAvvia.Caption:='AVVIO' + chr(10) + 'LAVORO';
  end;
end;

procedure TForm1.PulsAvviaClick(Sender: TObject);

var
  ixFile, ixFoglio, n, nuFogli: Integer;

  nomeFilCorr, striMia: String;

  areaFile: TsWorkbook;
  foglioCorr: TsWorksheet;
begin
  striMia:= lsDir.Name;
  n:= lsDir.Items.Count - 1 ;
  for ixFile:= 0 to n do
  begin
    nomeFilCorr:= dirFogli + lsDir.Items[ixFile];
    areaFile:= TsWorkbook.Create;
    areaFile.ReadFromFile (nomeFilCorr);
    nuFogli:=  areaFile.GetWorksheetCount - 1;   // estraggo il numero dei fogli elettronici interni al file-cartella dirFogli + lsDir.Items[ixFile]
    ShowMessage('il file-cartella corre contiene n.' + IntToStr(nuFogli) + ' fogli elettronici');
    striMia:='il file-cartella corrente è' + nomeFilCorr +' e contiene n.' + IntToStr(nuFogli + 1) + ' fogli elettronici' + chr(10) + ' così denominati:';
    foglioCorr:= areaFile.GetFirstWorksheet;
    for ixFoglio:= 1 to nuFogli do
    begin
     striMia:= striMia + fogliocorr.Name + ', ';
     foglioCorr:= areaFile.GetNextWorksheet(foglioCorr);
     striMia:= striMia + fogliocorr.Name + ', ';
    end;
    ShowMessage(striMia);
    areaFile.newinstance;
  end;
  areaFile.Free;
  Application.Terminate;
end;

end.                                                                                                     

Di tutto il codice desidero commentare le due righe seguenti:
Citazione
areaFogli.ReadFromFile (dirFogli + lsDir.Items[0]);
  foglioCorr:=areaFogli.GetFirstWorksheet;
 
Infatti, se ho capito bene,
- la prima serve  a trasferire tutto il file letto all'interno di "areaFogli", alla quale però non posso accedere direttamente, ma solamente attraverso una successiva istruzione.
- la seconda è un esempio di creazione dell'insieme  "foglioCorr" coi valori del 1° foglio di "areaFogli"

Penso, a questo punto di avere capito come muovermi. Il cammino purtroppo è sempre lungo e faticoso.
Con pazienza e costanza, spero di farcela.
A presto.
Titolo: Re: aprire un file miofoglio.ods e leggerne il contenuto
Inserito da: petrusic - Gennaio 20, 2021, 12:14:02 pm
Sono di nuovo qui perchè la gioia del risultato ottenuto è durata poco.
Come si capisce dal codice che ho incluso nel mio precedente post, eseguo una lettura sequenziale di tutti i file.ods/xls presenti nella directory che li contiene.
Riesco a rilevare i nomi dei singoli fogli di calcolo, però, dopo avere terminato anche l'ultima istanza sull'ultimo file, il programma ferma in pausa, come se avessi comandato un stop di debug.
cliccando sul pulsnate "||", per farlo ripartire si apre una finestra "Assembler" per un possibile ERRORE che non capisco.
Ho provato a fermare l'avvio di una nuova istanza subito dopo la prima, è succede la stessa cosa.
Può essere perchè manca il richiamo di un distruttore dell'oggetto TsWorkbook?
L'ho cercato ma non ho saputo trovarlo. Ho pensato allora di utilizzare "areaFile.Free", nella speranza che fosse quello a svolgere la funzione di distruttore, ma non ho risolto.
L'errore c'è sempre ed il programma non termina.
Titolo: Re: aprire un file miofoglio.ods e leggerne il contenuto
Inserito da: nomorelogic - Gennaio 21, 2021, 01:15:21 am
credo ci sia un errore di concetto da correggere
TWorkBook.Create dovrebbe essere richiamato 1 sola volta prima del loop for

da quello che si vede nell'immagine crei una istanza ad ogni iterazione del for + una nuova istanza poco prima della fine del loop con newinstance
dopo il loop c'è una sola Free.

quindi, premesso che di newinstance non c'è bisogno, il codice dovrebbe essere qualcosa di simile
Codice: [Seleziona]
areafile:=TWorkBook.Create
try
   ...
   for ixfile:=0 to n do
   begin
      areafile.ReadFromFile(...)
      ...
   end;
   ...
finally
  areafile.Free;
end;

Titolo: Re: aprire un file miofoglio.ods e leggerne il contenuto
Inserito da: petrusic - Gennaio 21, 2021, 11:46:31 am
TWorkBook.Create dovrebbe essere richiamato 1 sola volta prima del loop for

 :-[ Che sbadato!
Hai ragione, era proprio quello il problema.
Grazie!