Per stampare in pdf da lazreport devi usare trascinare sulla form il componente TfrTNPDFExport (ad esempio con il nome frTNPDFExport1), per farlo devi avere installato il pacchetto che trovi nella directory directory_dove_è_installato_lazarus\components\lazreport\source\addons\pdfexport\lazreportpdfexport.lpk
Detto questo poi ipotizzando che il tuo oggetto TfrReport si chiami MyReport ed hai già provveduto a disegnarlo, devi fare quanto segue
if MyReport.PrepareReport then
begin
SaveDialog1.Filter:='PDF files (*.pdf)|*.pdf';
SaveDialog1.FileName:='NomeDelFile_' + 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;
Detto questo poi rispondo anche alla tua domanda di come mandare in stampa senza passare dalla preview, io ipotizzo che tu usi il comando
MyReport.ShowReport
che apre la preview, se vuoi mandare direttamente in stampa usa il seguente codice
if GedDefaultPrinter(NomeStampante)=FALSE then
begin
ShowMessage('Nessuna stampante predefinita.');
end
else
begin
MyReport.ChangePrinter(printer.PrinterIndex, -1);
if MyReport.PrepareReport then
begin
MyReport.PrintPreparedReport('',1) {Primo parametro è il numero di pagina, se è vuoto le fa tutte, il secondo è il numero di copie}
end
else
begin
ShowMessage('Stampante non raggiungibile.');
end;
end;
Ti ricordo poi che quando l'eseguibile è in esecuzione puoi sempre lanciare il desiger report con il comando
MyReport.DesignReport;
Spero di essere stato esaustivo. Ciao e buon lavoro
Semplicemente puoi usare la funzione OpenDocument
uses
..., LCLIntf;
procedure ...
begin
OpenDocument('nome_file.pdf');
end;
Che ti permette di lanciare dei documenti con il programma predefinito per il sistema operativo.
Sto cercando di impostare il report di stampa, ma ho ancora qualche difficoltà:
- Ho scorso il contenuto del file .lrf prodotto durante il disegno del modulo di report, ma non trovato i riferimenti alla dimensione di pagina di tipo A5 (le dimensioni che vi ho trovate mi sembrano uguali a quelle di default, quindi A4)
. . .
<Page1>
<Name Value="Page1"/>
<ClassName Value="TfrPageReport"/>
<Visible Value="True"/>
<Width Value="595"/>
<Height Value="842"/>
<Script Value=""/>
<PgSize Value="9"/>
<Margins>
<left Value="0"/>
<Top Value="0"/>
<Right Value="0"/>
<Bottom Value="0"/>
</Margins>
<Orientation Value="poPortrait"/>
<UseMargins Value="True"/>
<PrintToPrevPage Value="False"/>
<ColCount Value="0"/>
<ColGap Value="0"/>
<LayoutOrder Value="loColumns"/>
. . .
ho cercato anche di vedere l'impostazione di pagina nella finestra Designer, m andando in File -> opzioni pagina, si accende il messaggio d'Errore "Paper "A4 210 x 297 mm" not supported!", riportato nell'allegato, però ieri sono riuscito ad andare avanti fino a selezionare la dimensione pagina A5.
Per il dimensionamento della pagina di stampa, ho trovato che tutti i dimensionamenti selezionabili sono presenti nel file /usr/share/lazarus/2.2.4/components/lazreport/source/lr_prntr.pas
Nel file ho rilevato poi le impostazioni relative:
- A4: X:595; Y:842
- A5: X:420; Y:595
Quindi, per correggere le attuali impostazioni presenti nel file mioReportA5.lrf, dovrei:
<Page1>
<Name Value="Page1"/>
<ClassName Value="TfrPageReport"/>
<Visible Value="True"/>
<Width Value="595"/> <--- cambiare 595 in 420
<Height Value="842"/> <--- cambiare 842 in 595
Così facendo, penso che lo scopo è raggiunto. Vorrei aggiungere un commento, ma non so come si fa.
Non ricordavo l'icona relativa all'inserimento delle Memo, ma poi l'ho individuata.
Per il dimensionamento della pagina di stampa, ho trovato che tutti i dimensionamenti selezionabili sono presenti nel file /usr/share/lazarus/2.2.4/components/lazreport/source/lr_prntr.pas
Nel file ho rilevato poi le impostazioni relative:
- A4: X:595; Y:842
- A5: X:420; Y:595
Quindi, per correggere le attuali impostazioni presenti nel file mioReportA5.lrf, dovrei:
<Page1>
<Name Value="Page1"/>
<ClassName Value="TfrPageReport"/>
<Visible Value="True"/>
<Width Value="595"/> <--- cambiare 595 in 420
<Height Value="842"/> <--- cambiare 842 in 595
Così facendo, penso che lo scopo è raggiunto. Vorrei aggiungere un commento, ma non so come si fa.
Invece non ha funzionato, perchè, alla prima modifica in Report Designer, i valori che ho impostati manualmente nel file mioReport.lrf vengono sempre alterati con valori assurdi che, probabilmente, provocano poi l'errore "Paper "A4 210 x 297 mm" not supported!",
Ecco le prime righe del file, dove è riscontrabile l'alterazione appena indicata:
<?xml version="1.0" encoding="utf-8"?>
<CONFIG>
<LazReport>
<Version Value="31"/>
<Title Value=""/>
<Subject Value=""/>
<KeyWords Value=""/>
<Comments Value=""/>
<ReportCreateDate Value="1899-12-30 00:00:00"/>
<ReportLastChange Value="2023-02-25 23:12:44"/>
<ReportVersionBuild Value=""/>
<ReportVersionMajor Value=""/>
<ReportVersionMinor Value=""/>
<ReportVersionRelease Value=""/>
<ReportAutor Value=""/>
<Script Value=""/>
<Pages>
<PrintToDefault Value="False"/>
<DoublePass Value="False"/>
<SelectedPrinter Value="HP_OfficeJet_Pro_6960_C12CFC_USB"/>
<PageCount Value="1"/>
<Page1>
<Name Value="Page1"/>
<ClassName Value="TfrPageReport"/>
<Visible Value="True"/>
<Width Value="2100"/> <--- ???
<Height Value="2970"/> <--- ???
<Script Value=""/>
<PgSize Value="9"/>
<Margins>
<left Value="0"/>
<Top Value="0"/>
<Right Value="0"/>
<Bottom Value="0"/>
</Margins>
<Orientation Value="poPortrait"/>
<UseMargins Value="True"/>
<PrintToPrevPage Value="False"/>
<ColCount Value="0"/>
<ColGap Value="0"/>
<LayoutOrder Value="loColumns"/>
Non nascondo le mie difficoltà a creare questo nuovo report. Sto faticando forse più della prima volta ed ancora non ho finito.
Forse, sapendo come costruire il file manualmente, si farebbe prima e meglio. Il guaio è però che non so dove attingere le informazioni necessarie per realizzare praticamente il mio pensiero.
:-\
Per stampare in pdf da lazreport devi usare trascinare sulla form il componente TfrTNPDFExport (ad esempio con il nome frTNPDFExport1), per farlo devi avere installato il pacchetto che trovi nella directory directory_dove_è_installato_lazarus\components\lazreport\source\addons\pdfexport\lazreportpdfexport.lpk
Detto questo poi ipotizzando che il tuo oggetto TfrReport si chiami MyReport ed hai già provveduto a disegnarlo, devi fare quanto segue
if MyReport.PrepareReport then
begin
SaveDialog1.Filter:='PDF files (*.pdf)|*.pdf';
SaveDialog1.FileName:='NomeDelFile_' + 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;
Ho quasi superato le difficoltà per disegnare la pagina in formato A5 del report.
Ora dovrei aggiungere le istruzioni che mi hai indicato per produrre il documento pdf, ma non ho capito dove aggiungerle:
Riporto qui la procedura che avvia la preview di stampa:
procedure TForm9.BPulsStampaClick(Sender: TObject);
var
i, k, nuRg: integer;
cellaSel, fileReport, striMia, titolo: String;
begin
WriteLn('procedure TForm9.BPulsStampaClick');
nuRg:= GridChiuStmp.RowCount;
if MGridPdf9.Active then
begin
MGridPdf9.Close;
end;
MGridPdf9.Clear(False);
MGridPdf9.Open;
for i:= 1 to nuRg - 1 do
begin
MGridpdf9.Append;
MGridpdf9.Edit;
MGridpdf9.FieldByName('voceSotCto').Text:= GridChiuStmp.Cells[2, i];
MGridpdf9.FieldByName('entrate').Text:= GridChiuStmp.Cells[3, i];
MGridpdf9.FieldByName('uscite').Text:= GridChiuStmp.Cells[4, i];
end;
fileReport:= percorso + '/Dati/pdfEntrUsc.lrf';
frReport1.LoadFromFile(fileReport);
frReport1.ShowReport;
if frReport1.PrepareReport then <------- Gruppo istruzioni per produrre il modulo in PDF
begin
SaveDialog1.Filter:='PDF files (*.pdf)|*.pdf';
SaveDialog1.FileName:='NomeDelFile_' + StringReplace(DateToStr(Now()),'/','', [rfReplaceAll]) + '_' + StringReplace(TimeToStr(Now()) ,':','.', [rfReplaceAll]);
. . .
end;
end;
???
Devi metterle al posto della ShowReport. O se proprio vuoi fare prima l'anteprima e alla sua chiusura il salvataggio in pdf sposta la showreport all'interno dell'if del preparereport.
Perfetto. Ha funzionato quasi magnificamente.
Io ho preferito formare il file in pdf prima di mostrare l'anteprima, ma niente toglie che possa cambiare idea, oppure, potrei riscriverlo sempre su se stesso, qualora togliessi dal nome del file la data e l'ora di creazione.
Riporto la parte di codice riguardante la creazione del file pdf, perchè avrei bisogno di capire meglio cosa succede:
DomusRatioPDF:=SaveDialog1.FileName + '.pdf';
è l'istruzione che crea il file .pdf, ma prima di farlo apre una finestra per la conferma del nome file (ho capito)
Se è come ho capito, vorrei capire anche se è possibile NON mostrare la finestra e proseguire, prendendo sempre buono il nome già impostato nel programma
poi:
Screen.Cursor := crHourglass;
frReport1.ExportTo(TFrTNPDFExportFilter, DomusRatioPDF);
Screen.Cursor := crDefault;
Ho provato a disinibirle ed ho visto che il file .pdf è stato già creato. Ma allora a cosa servono ?
Scusa xinyiman se chiedo magari concetti scontati, ma preferisco chiedere, piuittosto che andare avanti senza rendermi conto.
Riporto la parte di codice riguardante la creazione del file pdf, perchè avrei bisogno di capire meglio cosa succede:
DomusRatioPDF:=SaveDialog1.FileName + '.pdf';
è l'istruzione che crea il file .pdf, ma prima di farlo apre una finestra per la conferma del nome file (ho capito)
Se è come ho capito, vorrei capire anche se è possibile NON mostrare la finestra e proseguire, prendendo sempre buono il nome già impostato nel programma
No, quella riga prende solo il nome del file pdf che vuoi creare, in quanto ti permette di modificarlo manualmente dalla Save Dialog.
Per non mostrare la finestra cambi il mio codice da così
SaveDialog1.Filter:='PDF files (*.pdf)|*.pdf';
SaveDialog1.FileName:='NomeDelFile_' + 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;
a così
NomePDF:='NomeDelFile_' + StringReplace(DateToStr(Now()),'/','', [rfReplaceAll]) + '_' + StringReplace(TimeToStr(Now()) ,':','.', [rfReplaceAll]);
Screen.Cursor := crHourglass;
MyReport.ExportTo(TFrTNPDFExportFilter, NomePDF);
Screen.Cursor := crDefault;
ShowMessage('Creazione del file PDF terminata.');
poi:
Screen.Cursor := crHourglass;
frReport1.ExportTo(TFrTNPDFExportFilter, DomusRatioPDF);
Screen.Cursor := crDefault;
Ho provato a disinibirle ed ho visto che il file .pdf è stato già creato. Ma allora a cosa servono ?
Scusa xinyiman se chiedo magari concetti scontati, ma preferisco chiedere, piuittosto che andare avanti senza rendermi conto.
La prima riga cambia la grafica del puntatore del mouse in una clessidra, la seconda riga esporta in pdf il tuo report e la terza riga riporta la grafica del puntatore del mouse al tuo cursore di default.
Non scusarti, è giusto voler capire.
E' arrivato il momento di aggiungere l'anno nella Memo di testa nella pagina.
Ho trovato un suggerimento che sfrutta l'evento OnGetValue del report frReport1 ed ho scritto:
procedure TForm9.frReport1GetValue(const ParName: String; var ParValue: Variant
);
begin
Writeln('TForm9.frReport1GetValue');
begin
if ParName = 'TestataEntrusc' then // TestataEntrusc è una variabile della categoria TitoloPaginaA5
begin
ParValue := Eanno.Text;
Writeln('ParValue= ' + ParValue);
end;
end;
end;
Ebbene, a me non ha funzionato. In Console ho trovato il seguente Errore:
[WARNING] SetAlphaBlend called without handle for frProgressForm(TfrProgressForm)
TForm9.frReport1GetValue
ParValue= 2019
Ho trovato qualcosa che dice di copiare il file .lrf, generato automaticamente da Lazarus nella cartella /DomusRatio/bin/Dati, nella cartella /DomusRatio/bin, ma non mi sembra logico, altrimenti sarebbe stato Lazarus a crearlo direttamente nella /bin.
In definitiva, anche se l'Errore è un Warning, io non riesco ad aggiungere l'anno di riferimento nella riga di testa, nella pagina del report.
Commenta le righe del writeln
Non capisco, comunque, ci provo:
- la prima riga (Writeln('TForm9.frReport1GetValue'); ) è una riga che uso abitualmente come prima istruzione di una procedure o di una function per creare una sorta di trace a mio uso e consumo: mi serve per capire se la procedura viene avviata e se un'eventuale errore si verfica quindi prima che si avvii la procedure cronologicamente successiva.
- la prima riga (Writeln('ParValue= ' + ParValue); ) mi è servita per capire se il campo ParValue (parametro della procedure TForm9.frReport1GetValue(const ParName: String; var ParValue: Variant );), viene valorizzato bene. Ho visto che è stato valorizzato bene.
Non so se era quello che volevi sapere.
No intendo dire di commentare/togliere le righe del writeln (secondo me danno fastidio)
procedure TForm9.frReport1GetValue(const ParName: String; var ParValue: Variant
);
begin
//Writeln('TForm9.frReport1GetValue');
begin
if ParName = 'TestataEntrusc' then // TestataEntrusc è una variabile della categoria TitoloPaginaA5
begin
ParValue := Eanno.Text;
//Writeln('ParValue= ' + ParValue);
end;
end;
end;