Se il tuo oggetto TfrReport si chiama MyReport puoi generare il pdf come segue. Nella form devi trascinare un oggetto TfrTNPDFExport (che chiami frTNPDFExport1) e anche un oggetto TSaveDialog (che chiami SaveDialog1)
poi con un codice simile dovresti riuscirci
MyReport.LoadFromFile(qui metti il path del file lrf);
if MyReport.PrepareReport then
begin
SaveDialog1.Filter:='PDF files (*.pdf)|*.pdf';
SaveDialog1.FileName:='Album_' + StringReplace(DateToStr(Now()),'/','', [rfReplaceAll]) + '_' + StringReplace(TimeToStr(Now()) ,':','.', [rfReplaceAll]);
if SaveDialog1.Execute then
begin
if uppercase(ExtractFileExt(SaveDialog1.FileName))='.PDF' then
begin
//non faccio niente, il nome è già corretto
NomePDF:=SaveDialog1.FileName;
end
else
begin
//il nome non è corretto, quindi ci aggiungo il .pdf alla fine
NomePDF:=SaveDialog1.FileName + '.pdf';
end;
Screen.Cursor := crHourglass;
MyReport.ExportTo(TFrTNPDFExportFilter, NomePDF);
Screen.Cursor := crDefault;
ShowMessage('Creazione del file PDF terminata.');
end;
end;
Nell'esempio ricevuto leggo:
Mgriglia.Append; --> prepara l'oggetto TMemDataSet a ricevere l'accodamento di dati?
Mgriglia.Edit; --> serve a preparare la formattazione dei valori float o per rendere visibile il TMemDataSet?
Mgriglia.FieldByName('dare').Value := strtofloat(stringgrid1.Cells[2, i]); --> perché é necessaria la conversione in float ?
Poi ho visto che nelle proprietà del TMemDataSet mancano i parametrisul dimensionamento delle celle e non solo.
Forse l'impostazione di detti parametri è presa in automatico attraverso le istruzioni di caricamento dei dati dalla StringGrid alla MemDataSet?
Scusa se ti chiedo qualche chiarimento, ma mi serve solo per capire. Infatti, non ho trovato documentazione in merito.
@ tito_livio
Ho preparato quasi tutto l'occorrente per produrre il modulo PDF, ma ho difficoltà nell'inserire i nomi delle colonne nella finestra di disegno del freport, finestra che ho riportato come allegato per farmi capire.
Nel tuo esempio sono caricati. Io non riesco a farlo, perché, cliiccando all'interno del quadrato bianco e cominciando a scrivere si apre una finestrella dove riesco a vedere quello che scrivo. Però, dopo avere scritto la testata della 1a colonna (Es. Data), premendo |INVIO|, la finestrella scompare e quello che ho scritto non viene riportato nel quadrato grande, dove invece come pensavo che finisse.
Ed infatti il programma, al momento in cui dovrebbe compilare le celle della griglia finale, va in ERRORE, perchè non trova il nome campo che si aspetta. Ecco il codice scritto per la compilazione della griglia finale:
procedure TForm6.BpulStamPdfClick(Sender: TObject);
var i, nuRg: integer;
begin
nuRg := GridStmp.RowCount;
if MGridPdf1.Active then
MGridPdf1.Close;
MGridPdf1.Clear(False);
MGridPdf1.Open;
for i := 1 to nuRg - 1 do
begin
MGridPdf1.Append;
MGridPdf1.Edit;
MGridPdf1.FieldByName('PR.').Text := GridStmp.Cells[1, i]; // quando esegue questa riga va in Errore
MGridPdf1.FieldByName('DATA').Text := GridStmp.Cells[2, i];
MGridPdf1.FieldByName('DESCRIZIONE').Text := GridStmp.Cells[3, i];
MGridPdf1.FieldByName('D A R E').Text := GridStmp.Cells[4, i];
MGridPdf1.FieldByName('A V E R E').Text := GridStmp.Cells[5, i];
MGridPdf1.FieldByName('S A L D O').Text := GridStmp.Cells[6, i];
end;
frreport1.LoadFromFile('pdfOrd.lrf');
frreport1.ShowReport;
end;
Non capisco. Mi manca ancora qualche componente?
oltre che per il Lazreport anche per altri tipi di strumenti per reportistica, le band costituiscono le parti di una stampa. Così ci può essere una band per l'intestazione, una per i dati ed una per i totali parziali o complessivi.
All'interno della band poi si devono mettere delle cose da stampare che sono i memo. I memo potranno contenere delle stringhe o dei riferimenti a dei campi di una tabella.
Questi due strumenti si devono prendere dalla parte sinistra del designer e posizionare sul foglio che rappresenta la stampa.
Si, ai due strumenti Includi Intestazioni e Includi Bande ci sono arrivato , seguendo anche più attentamente la guida (https://wiki-freepascal-org.translate.goog/LazReport_Documentation?_x_tr_sl=en&_x_tr_tl=it&_x_tr_hl=it&_x_tr_pto=op,sc) del wiki, al paragrafo "Report Designer"
Dopo avere ripercorso, con la guida a portata di mano, il lavoro fatto ed avere aggiunto il file xxx.lrf ho avviato l'esecuzione del mio programma.
Riporto la parte del programma relativa all'evento BpulStamPdfClick
procedure TForm6.BpulStamPdfClick(Sender: TObject);
. . .
begin
. . .
for i := 1 to nuRg - 1 do
begin
MGridPdf1.Append;
MGridPdf1.Edit;
MGridPdf1.FieldByName('nuProg').Text := GridStmp.Cells[0, i];
MGridPdf1.FieldByName('data').Text := GridStmp.Cells[1, i];
MGridPdf1.FieldByName('descriz').Text := GridStmp.Cells[2, i];
MGridPdf1.FieldByName('dare').Text := GridStmp.Cells[3, i];
MGridPdf1.FieldByName('avere').Text := GridStmp.Cells[4, i];
MGridPdf1.FieldByName('saldo').Text := GridStmp.Cells[5, i];
end;
frreport1.LoadFromFile('pdfOrd.lrf');
frreport1.ShowReport;
Il ciclo for viene eseguito apparentemente bene. Alla fine però fallisce l'esecuzione dell'istruzione
frreport1.LoadFromFile('pdfOrd.lrf');
con questo tipo di Errore:
Il progetto DomusRatio ha sollevato una eccezione di classe 'ElazReportException' con messaggio : Erroire while loading report: File not found (pdfOrd.lrf).
Non capisco l'errore perchè ho creato il file .lrf nella stessa directory del programma, così come riportato nella guida:
petrus@petrus-pc:/media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/DomusRatio$ ls
Appunti_programma frm2.pas frmmain.pas
backup frm3.lfm griglia_e_matita.jpg
DomusRatioForm2.png frm3.pas grigliaMovvCto_2.png
DomusRatio.ico frm4.lfm grigliaMovvCto.png
DomusRatio.lpi frm4.pas grigliaMovv.png
DomusRatio.lpr frm5.lfm img1_domuRatio.png
DomusRatio.lps frm5.pas img_domuRatio2.png
DomusRatio.res frm6.lfm img_domuRatio.jpg
DomusRatio.tar.xz frm6.pas img_domuRatio.png
ErroreOpen_piancont frm7.lfm
pdfOrd.lrf
frm2_20211026.pas frm7.pas Querymovimgg.ods
frm2.lfm frmmain.lfm
Riporto anche in allegato la finestra del Report Designer dove ho lavorato oggi.
Penso però che ti puoi chiarire meglio le idee con un dei tanti video su youtube che parlano del lazreport.
Ho trovato solo guide in lingua inglese. Non sono adatte alla mia quasi non conoscenza della lingua inglese.
Ciao,
dalla lista di file che hai postato mi sembra che tu abbia salvato il report col nome " pdfOrd.lrf" e non "pdfOrd".lrf". C'è uno spazio prima del nome del file.
Non capisco da dove tu abbia dedotto quanto hai citato.
Comunque, visto che in esecuzione non viene trovato il nome del file, ho modificato l'istruzione
frreport1.LoadFromFile('pdfOrd.lrf');
impostando il percorso completo:
frreport1.LoadFromFile('/media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/DomusRatio/pdfOrd.lrf');
ed ha funzionato, come puoi vedere dall'allegato.
Non capisco perchè sia successo ciò, nè come sia possibile che il programma d'esempio che mi hai passato funzioni ed il mio ha bisogno di tutto il percorso per trovare il file .lrf.
Nella pagina di anteprima, ho trovato il pulsantino per ottenere la stampa del documento, vi ho cliccato sopra e la stampa s'è avviata in maniera perfettamente trasparente.
Resterebbe quindi soltanto da capire se e come si può evitare di indicare tutto il percorso del file .lrf.
Forse indicazione stupida, ma conoscendo Linux (sono sarcastico ;) ) potrebbe essere che il file lo devi identificare come './pdfOrd.lrf'
In alternativa, la directory completa potresti ottenerla con:
var Percorso, FileReport: string;
Percorso := ExtractfilePath(Application.ExeName);
FileReport := Percorso + 'pdfOrd.lrf';
N.B.: non ricordo se in Linux c'è l'ExtractFilePath, però c'è nel forum una discussione (vado a memoria) su questo.
Ciao
Non capisco perchè sia successo ciò, nè come sia possibile che il programma d'esempio che mi hai passato funzioni ed il mio ha bisogno di tutto il percorso per trovare il file .lrf.
ciao
giusto per curiosità, prima di fare il LoadFromFile, potresti visualizzare il risultato di:
ExpandFileName('pdfOrd.lrf');
giusto per curiosità, prima di fare il LoadFromFile, potresti visualizzare il risultato di:
ExpandFileName('pdfOrd.lrf');
Eccolo
/media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/bin/x86_64-linux/pdfOrd.lrf
Ma non è corretto (vedi allegato)
quello corretto è
petrus@petrus-pc:/media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/DomusRatio$ ls
Appunti_programma frm2.pas frmmain.pas
backup frm3.lfm griglia_e_matita.jpg
DomusRatioForm2.png frm3.pas grigliaMovvCto_2.png
DomusRatio.ico frm4.lfm grigliaMovvCto.png
DomusRatio.lpi frm4.pas grigliaMovv.png
DomusRatio.lpr frm5.lfm img1_domuRatio.png
DomusRatio.lps frm5.pas img_domuRatio2.png
DomusRatio.res frm6.lfm img_domuRatio.jpg
DomusRatio.tar.xz frm6.pas img_domuRatio.png
ErroreOpen_piancont frm7.lfm pdfOrd.lrf
frm2_20211026.pas frm7.pas Querymovimgg.ods
frm2.lfm frmmain.lfm
??? (**?**)
Forse indicazione stupida, ma conoscendo Linux (sono sarcastico ;) ) potrebbe essere che il file lo devi identificare come './pdfOrd.lrf'
In alternativa, la directory completa potresti ottenerla con:
la directory completa potresti ottenerla con:
var Percorso, FileReport: string;
Percorso := ExtractfilePath(Application.ExeName);
FileReport := Percorso + 'pdfOrd.lrf';
1a prova:
percorso:= ExtractfilePath(Application.ExeName);
fileReport:= percorso + 'pdfOrd.lrf';
WriteLn('fileReport= |' + fileReport + '|');
frreport1.LoadFromFile(fileReport);
fileReport= |/media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/bin/x86_64-linux/pdfOrd.lrf|
L'istruzione do LoadFromFile da Errore d'eccezione di classe "Error While loading report: File not found(/media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/bin/x86_64-linux/pdfOrd.lrf) , per le regioni che ho spiegate nel mio post precedente.
2a prova:
frreport1.LoadFromFile('./pdfOrd.lrf');
Anche quest'istruzione produce un Errore d'eccesione per file NON trovato.
Mi pare che'unica via sicura percorribile sia quella di indicare il percorso completo del file .lrf
Ho rivisto le impostazioni interni alla finestra Opzioni Progetto -> Percorsi che ho modificato per puntare sempre alla directory del progetto corrente (DomusRatio) ed allego le immagini relative al suo contenuto di prima e dopo.
Spero che non ci sia altro da modificare.
Poi ho riportato l'istruzione LoadFromFile allo stato iniziale:
frreport1.LoadFromFile('pdfOrd.lrf');
ed ho riavviato il progetto per verificarne il funzionamento.
Ora non da più Errore per file pdfOrd.lrf non trovato.
Quando lanci un eseguibile lo stesso usa per default la cartella dove ESISTE per fare tutte le attività "standard", come ricerca delle librerie dinamiche, apertura e chiusura di file, database, etc ....
Questa cartella la trovi a RUNTIME con:
var Percorso: string;
Percorso := ExtractfilePath(Application.ExeName);
Percorso, in esecuzione varrà (per esempio nel tuo caso):
/media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/DomusRatio/
perchè il file eseguibile si trova li.
Se tu lo copiassi in "/tmp" ad esempio e lanciassi il file da "/tmp" la variabile avrebbe come valore "/tmp/"
Quindi, se tu a runtime davanti al nome dei file che devi aprire di preponi la variabile "Percorso" non avrai problem perchè aprirai i file nella stessa cartella dell'eseguibile, ovunque sia.
Nel tuo caso accadrebbe che:
var Percorso, FileReport: string;
Percorso := ExtractfilePath(Application.ExeName);
FileReport := Percorso + 'pdfOrd.lrf';
aprirebbe il file /media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/DomusRatio/pdfOrd.lrf"
Se invece lo lanci da "/tmp" (ovviamente eseguibile e lrf devono esistere in "/tmp") il codice sarà uguale ma:
var Percorso, FileReport: string;
Percorso := ExtractfilePath(Application.ExeName); <---- Percorso varrebbe '/tmp/'
FileReport := Percorso + 'pdfOrd.lrf';
aprirebbe il file
A runtime quindi puoi avere la "path" assoluta semplicemente nel modo che ti ho indicato. Vale per tutto e in tutte le condizioni.
Ora, aggiungendo un passo in più, per PULIZIA dell'ambiente è opportuno che il file "pdfOrd.lrf" non stia nella cartella dell'eseguibile a in una sottocartella (ad esempio Dati). In questo caso dovrai cambiare in Lazreport (PER LA PARTE PROGETTUALE) la directory di destinazione del LRF e cambiare il tuo codice affinchè a runtime vi ci acceda in:
var Percorso, FileReport: string;
Percorso := ExtractfilePath(Application.ExeName);
FileReport := Percorso + 'Dati/pdfOrd.lrf';
Ma questo è un passo in più.
Ciao
Poi setta pure come hai fatto le path nelle opzioni progetto. Però, secondo me, METTI il file ".lrf" in una sottodirectory. Il tutto verrà più pulito, con l'eseguibile e le eventuali librerie dinamiche in una cartella, e in una sottocartella il file lrf, eventuali DB e altri file di ausilio (json, xml, ini).
Ad esempio, seguendo quello che hai riportato:
/media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/DomusRatio/ <---- File di Progetto
/media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/DomusRatio/bin/DomusRatio <---- Eseguibile
/media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/DomusRatio/bin/DomusRatio/Dati/ <---- Dati (come .lrf, DB, .xml, .ini)
Copiando solo la cartella "bin" e le sottocartelle avrai così il "binario" del tuo progetto che girerà ovunque tu lo metta.
Ho fatto come mi hai consigliato. Ho però dovuto impostare il percorso di destinazione dell'eseguibile, perchè ho provato a non impostarlo ed ho notato che l'eseguibile è stato salvato in:
/media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/bin/x86_64-linux.
Riporto pertanto in allegato l'immagine relativa alla finestra Opzioni progetto > Percorsi
riporto qui sotto la tree della direcotry DomusRatio, dove puoi vedere l'organizzazione data alla varie sottodirectory
petrus@petrus-pc:~$ tree /media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/DomusRatio
/media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/DomusRatio
├── Appunti_programma
│ ├── BilancioFineAnnoù.odt
│ ├── ContDomgli.ods
│ └── PianoConti_struttura_teorica.pdf
├── backup
│ ├── DomusRatio.lpi
│ ├── DomusRatio.lpi.bak
│ ├── DomusRatio.lpr
│ ├── DomusRatio.lps
│ ├── DomusRatio.lps.bak
│ ├── frm21.lfm
│ ├── frm21.pas
│ ├── frm21.pas.bak
│ ├── frm2_20211026.pas
│ ├── frm2.lfm
│ ├── frm2.pas
│ ├── frm2ricmovv.lfm
│ ├── frm2ricmovv.pas
│ ├── frm2RicMovv.pas
│ ├── frm3.lfm
│ ├── frm3.pas
│ ├── frm4.lfm
│ ├── frm4.pas
│ ├── frm5.lfm
│ ├── frm5.lfm.bak
│ ├── frm5.pas
│ ├── frm5.pas.bak
│ ├── frm6.lfm
│ ├── frm6.pas
│ ├── frm6.pas.bak
│ ├── frm7.lfm
│ ├── frm7.pas
│ ├── frmmain.lfm
│ ├── frmmain.lfm.bak
│ ├── frmmain.pas
│ └── frmmain.pas.bak
├── bin
│ └── DomusRatio
│ ├── Dati
│ │ └── pdfOrd.lrf
│ ├── DomusRatioRun
│ └── DomusRatioRun.dbg
├── DomusRatioForm2.png
├── DomusRatio.ico
├── DomusRatio.lpi
├── DomusRatio.lpr
├── DomusRatio.lps
├── DomusRatio.res
├── frm2_20211026.pas
├── frm2.lfm
├── frm2.pas
├── frm3.lfm
├── frm3.pas
├── frm4.lfm
├── frm4.pas
├── frm5.lfm
├── frm5.pas
├── frm6.lfm
├── frm6.pas
├── frm7.lfm
├── frm7.pas
├── frmmain.lfm
├── frmmain.pas
├── griglia_e_matita.jpg
├── grigliaMovvCto_2.png
├── grigliaMovvCto.png
├── grigliaMovv.png
├── imgdef_domusRatio.png
└── img_domuRatio.jpg
5 directories, 64 files
Devo chiederti tuttavia qual'é l'utilità di destinare l'eseguibile in fondo al percorso: /media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/DomusRatio/bin/DomusRatio <---- Eseguibile
No sarebbe bastato fare:
/media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/DomusRatio/bin
/media/dirdati/dativari/lazarus_progetti/lazarus_progetti_miei/DomusRatio/Dati/ <---- Dati (come .lrf, DB, .xml, .ini)
::)
Ciao,
per creare le variabili nel designer del report devi cliccare: file | lista delle variabili | variabili.
Qui poi devi scrivere una riga con il nome del gruppo di variabili che vuoi creare e poi nelle righe sottostanti i nomi delle variabili.
I nomi delle variabili devono essere precedute da uno spazio.
Una volta create le variabili le puoi inserire nel memo tramite il bottone variabile.
A questo punto nel progetto devi scrivere il codice necessario al riempimento delle variabili. Per fare questo devi andare nell'evento OnGetValue del report, e potrai scrivere per esempio:
if parname='nome_stampa' then
parvalue:=frreport1.Title;
dove nome_stampa è il nome della variabile.
Ti allego il progetto, che ho allegato prima, modificato per l'aggiunta dell'uso delle variabili nel report.
Grazie Lilvio.
Ho compreso il tuo messaggio e l'ho messo in pratica con successo.
Tuttavia, non riesco a fare comparire nella colonna della data il valore relativo, nonostante che venga regolarmente compilato nella rispettiva cella di ciascuna riga.
il codice di caricamento è:
procedure TForm6.BpulStamPdfClick(Sender: TObject);
var
i, nuRg: integer;
fileReport, striMia, titolo: String;
begin
nuRg := GridStmp.RowCount;
if MGridPdf1.Active then
MGridPdf1.Close;
MGridPdf1.Clear(False);
MGridPdf1.Open;
for i := 1 to nuRg - 1 do
begin
MGridPdf1.Append;
MGridPdf1.Edit;
MGridPdf1.FieldByName('nuProg').Text := GridStmp.Cells[0, i];
MGridPdf1.FieldByName('dtCont').Text := GridStmp.Cells[1, i]; // <-- sembra NON funzionare
MGridPdf1.FieldByName('descriz').Text := GridStmp.Cells[2, i];
MGridPdf1.FieldByName('dare').Text := GridStmp.Cells[3, i];
MGridPdf1.FieldByName('avere').Text := GridStmp.Cells[4, i];
MGridPdf1.FieldByName('saldo').Text := GridStmp.Cells[5, i];
WriteLn('MGridPdf1.nuProg= ' + MGridPdf1.FieldByName('nuProg').Text);
WriteLn('GridStmp.Cells[1, '+ IntToStr(i) + ']= ' + GridStmp.Cells[1, i]);
WriteLn('MGridPdf1.dtCont= ' + MGridPdf1.FieldByName('dtCont').Text);
end;
fileReport:= percorso + '/Dati/pdfComune.lrf';
frReport1.LoadFromFile(fileReport);
frReport1.ShowReport;
MGridPdf1.nuProg= 1 -----------------> cella valorizzata correttamente
GridStmp.Cells[1, 1]= 05/01/2022
MGridPdf1.dtCont= -----------------> cella NON valorizzatA
MGridPdf1.nuProg= 2
GridStmp.Cells[1, 2]= 05/01/2022
MGridPdf1.dtCont=
MGridPdf1.nuProg= 3
GridStmp.Cells[1, 3]=
Inizialmente funzionava.
Dopo quasi una settimana di prove e riprove, mi sono arreso: Io non vedo anomalie.