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"
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?
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:
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:
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.
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
areafile:=TWorkBook.Create
try
...
for ixfile:=0 to n do
begin
areafile.ReadFromFile(...)
...
end;
...
finally
areafile.Free;
end;