Eksport danych (np z StringGrida) do PDF

0

Witam.

Próbuje wyeksportować (w Lazarusie) dane z StringGrida do PDF.
Próbowałem Fortes4lazarus - pojawiły się problemy m.in. z polskimi znakami (a właściwie ich brakiem) - pisałem o tym w oddzielnym wątku.
Próbowałem PowerPDF - taka sama sytuacja.

Czy robił ktoś z Was coś podobnego i może polecić jakieś sprawdzone metody ?

Z góry dziękuję i pozdrawiam

0

korzystam z Lazreport+Cairo export

0

Mogę zapytać skąd pobierałeś Cairo ?
Pobrałem z SVN http://luipack.googlecode.com/svn jednak mam problem z instalacją (na początku brakowało kilku bibliotek, ściągnąłem je i niby poszło dalej) teraz przy instalacji luicontrols pokazuje błąd przy kompilacji Error: identifier idents no member "FindPath"

4

W załączniku masz potrzebne dll-ki oraz komponenty cairocanvas i lazreport.
instalujesz pakiety:

  • cairocanvas/cairocanvas_pkg.lpk
  • lazreport/source/lazreport.lpk
  • lazreport/source/addons/cairoexport/lrcairoexport.lpk
    Biblioteki wrzucasz do katalogu głównego lazarusa.

Aktualnie korzystam z Lazarusa 1.2.0 z fpc 2.6.4

0

@Paweł Dmitruk wielkie dziękuję !

Dzięki Twojej pomocy udało mi się dokończyć projekt tworząc eksport do pdf'a.

0
Paweł Dmitruk napisał(a):

korzystam z Lazreport+Cairo export

Witam

Możesz podać jakiś jakiś przykład "wywołania" CairoExport do wygenerowania pdfa z pliku raportu (.lrf). Ciężko znaleźć jakąś dokumentację, a przykład podany w dokumentacji (http://wiki.freepascal.org/LazReport_Documentation#Export_Filters) LazReport'u także wydaje się nie mieć zastosowania do CairoExport...

1
frReport1.LoadFromFile('plik_raportu.lrf');
if frReport1.PrepareReport then
frReport1.ExportTo(TlrCairoExportFilter, 'c:\eksport_raportu.pdf');
0

Chyba najwyższa pora iść do okulisty...
Dzięki WIELKIE!

0

Witam

Mam jeszcze jedno pytanie, co prawda trochę nieco z innej beczki:

Do raportu przesyłam zmienne używając:

if ParName='nazwa_przekazywanej_zmiennej' then
  ParValue:=wartosc_zmiennej;

W raporcie LazReport mam osadzone także 4 grafiki, ale podobnie jak zmienne, za każdym razem będą to inne pliki (.jpg). W jaki sposób przekazać do raportu dane tych plików jpg (domniemywam, że pewnie w postaci ścieżek)?

pozdrawiam

Wojtek

1

w raporcie dla pola ze zdjęciem nadajesz nazwę w inspektorze obiektów - np. zdjecie (w edytorze raportów), a nastepnie do komponentu frReport dla zdarzenia OnEnterRect przypisujesz:

procedure TForm1.raportEnterRect(Memo: TStringList; View: TfrView);
begin
  if UpperCase(View.Name)='ZDJECIE' then
  TFrPictureView(View).Picture.LoadFromFile('c:\aaa.jpg'); //scieżkę możesz załadować np. z listy lub z bazy danych
end;      
0

Witam ponownie

Coś mi nie działa... :(

W pliku formularza osadziłem "pustą" grafikę o nazwie
foto1
W programie, do komponentu frReport o nazwie
frReport1
dla zdarzenia
OnEnterRect
przypisałem procedurę:

procedure TfOknoProgramu.frReport1EnterRect(Memo: TStringList; View: TfrView);
begin
  if UpperCase(View.Name)='foto1' then
  TFrPictureView(View).Picture.LoadFromFile('C:\sciezka\foto_id_3_nr_1.jpg');
end;

a dla tego komponentu, dla zdarzenia
OnGetValue
mam przypisaną procedurę

procedure TfOknoProgramu.frReport1GetValue(const ParName: String;
  var ParValue: Variant);
begin
  if ParName='id' then
  ParValue:=StringGrid1.Cells[0,StringGrid1.Selection.Top];
  if ParName='stan' then
  ParValue:=lab_stan.Caption;
  if ParName='producent' then
  ParValue:=lab_producent.Caption;
  if ParName='typ' then
  ParValue:=lab_typ.Caption;
end;

która przekazuje parametry "tekstowe" do pól w pliku formularza (nie z bazy danych lecz z elementów formy).

Podgląd wydruku wywołuję poprzez przycisk z procedurą:

procedure TfOknoProgramu.btnDrukujKarteKatalogowaClick(Sender: TObject);
begin
frreport1.LoadFromFile(AppendPathDelim(ExtractFilePath(Application.ExeName))+'config\stany_magazynowe_karta_katalogowa.lrf');
  frreport1.ShowReport;
end;

Co robię nie tak?

1

tutaj masz błąd, przez który na pewno nie ładuje zdjęcia:

procedure TfOknoProgramu.frReport1EnterRect(Memo: TStringList; View: TfrView);
begin
  if UpperCase(View.Name)='foto1' then //uppercase - zamień na "duże" litery, więc powinno być tak:
  //if UpperCase(View.Name)='FOTO1' then  
  //lub: 
  //if View.Name='foto1' then
  TFrPictureView(View).Picture.LoadFromFile('C:\sciezka\foto_id_3_nr_1.jpg');
end;
0

Witam

Jeden problem rozwiązany ale pojawiły się 2 ;) kolejne:

  1. W istocie problem był tam gdzie wskazałeś. Teraz wszystko działa ok, przy generowaniu raportu. Niemniej jednak korzystam także z Cairo do generowania pdfów i tutaj pojawia się problem. Mianowicie w pliku raportu mam osadzone 4 grafiki. Tyle ich może maks. w nim występować. Może ale nie musi, bo równie dobrze dla danego raportu może w ogóle nie być zdjęć. Przed "wysłaniem" zdjęcia do raportu program sprawdza czy dany plik jpg istnieje. Jeśli tak - "wysyła" go, jeśli nie - nic się nie dzieje (w raporcie wówczas jest brak jpga w "przeznaczonej" dla niego grafice). Niemniej jednak dla Cairo stanowi to problem, gdyż jeśli są wszystkie pliki jpg na jakie jest "miejsce" w raporcie, to problemu nie ma, ale jeśli choć jedna grafika w raporcie nie została "obsadzona" (brak dla niej przeznaczonego pliku jpg) to przy generowaniu pdfa program wyrzuca błąd:

Access violation.
Press OK to ignore and risk data corruption.
Press Cancel to kill the program.

Plik pdf co prawda się generuje, ale jest uszkodzony (pojemność 0 bajtów) i nie daje się otworzyć.
Da się to jakoś poprawić?

  1. W programie generuję także drugi raport, na podstawie danych ze StringGrida. Dla OnGetValue w jego komponencie (Report2) jest przypisana procedura:
procedure TfOknoProgramu.frReport2GetValue(const ParName: String;
  var ParValue: Variant);
begin
  if ParName='id' then
  ParValue:=StringGrid1.Cells[0, lp];
  if ParName='stan' then
  ParValue:=StringGrid1.Cells[1, lp];
  if ParName='producent' then
  ParValue:=StringGrid1.Cells[3, lp];
  if ParName='typ' then
  ParValue:=StringGrid1.Cells[4, lp];
  if ParName='wykonanie' then
  ParValue:=StringGrid1.Cells[5, lp];
  if ParName='moc_znam' then
  ParValue:=StringGrid1.Cells[6, lp];
  if ParName='nap_gn' then
  ParValue:=StringGrid1.Cells[7, lp];
  if ParName='nap_dn' then
  ParValue:=StringGrid1.Cells[9, lp];
  if ParName='wyposazenie' then
  ParValue:=StringGrid1.Cells[22, lp];
end;

Dla powiązanego z nim komponentu UserDataset mam procedury:

procedure TfOknoProgramu.frUserDataset1CheckEOF(Sender: TObject;
  var Eof: Boolean);
begin
  eof:=lp>StringGrid1.RowCount-1;
end;

procedure TfOknoProgramu.frUserDataset1First(Sender: TObject);
begin
  lp:=1;
end;

procedure TfOknoProgramu.frUserDataset1Next(Sender: TObject);
begin
  Inc(lp);
end;

W StringGridzie nie ma nigdzie ścieżki do pliku jpg który chciałbym także osadzić w tym raporcie. Dany plik jpg ma natomiast zawsze w nazwie unikalny identyfikator danego wiersza ze StringGrida (komórka o adresie: StringGrid1.cells[0, wiersz]) i po nim chciałbym go przypisywać. Np wiersz ma id=12, a plik jpg ma nazwę foto_id_12_nr_1.jpg
Podobnie jak w przypadku 1, plik jpg może występować ale nie musi (problem przy generowaniu pdfa przez Cairo).
Jak ugryźć ten temat?

1

Ad.1 Musisz sprawdzić czy plik istnieje, i jeżeli nie to ukryć obiekt ze zdjęciem, w przeciwnym wypadku pokazać.

procedure TfOknoProgramu.frReport1EnterRect(Memo: TStringList; View: TfrView); 
begin
  if UpperCase(View.Name)='FOTO1' then
  begin
    if FileExistsUTF8('C:\sciezka\foto_id_'+StringGrid1.Cells[0, lp]+'_nr_1.jpg') then
    begin
      View.Visible:=True; 
      
TPictureView(View).Picture.LoadFromFile('C:\sciezka\foto_id_'+StringGrid1.Cells[0, lp]+'_nr_1.jpg'); //to rozwiązuje Ci też problem plików 
      //powiązanych z id ze StringGrid1
    end
    else
    View.Visible:=True;
  end;
end;
0

Witam

Po drobnych poprawkach ;) działa:

procedure TfOknoProgramu.frReport1EnterRect(Memo: TStringList; View: TfrView); 
begin
  if UpperCase(View.Name)='FOTO1' then
  begin
    if FileExistsUTF8('C:\sciezka\foto_id_'+StringGrid1.Cells[0, lp]+'_nr_1.jpg') then
    begin
      View.Visible:=True; 
      TFrPictureView(View).Picture.LoadFromFile('C:\sciezka\foto_id_'+StringGrid1.Cells[0, lp]+'_nr_1.jpg');
    end
    else
    View.Visible:=False;
  end;
end;

W istocie ten fragment:

TFrPictureView(View).Picture.LoadFromFile('C:\sciezka\foto_id_'+StringGrid1.Cells[0, lp]+'_nr_1.jpg');

rozwiązał mi także kwestię podstawiania grafiki do drugiego raportu (ze StringGrid'a), ale nie do końca. Jeśli użyję zmiennej lp, program, przy generowaniu raportu, zgłasza mi błąd związany z większą o 1 ilością wierszy w StringGridzie od rzeczywistej (wierszy z danymi jest 32):

An error occurred during calculation
ID
Report: frReport2
Memo: Memo14
Band: ColumnHeader1
Index Out of range Cell[Col=0 Row=33]

Jeśli podstawię w ścieżce do pliku jpg lp-1 jest ok, ale grafika powiązana z rekordem n StringGrida jest w raporcie przypisywana do danych rekordu n+1 ze StringGrida. Dla danych "tekstowych" się tak nie dzieje...

Co znowu skopałem?

0
wotik napisał(a):

Co znowu skopałem?

raczej tak, w załązczniku masz przykład i jak widzisz działa bez problemu. może wdefinicji raportu masz coś nie tak.

0

Chciałem zobaczyć jak wygląda Twój raport, ale przy próbie otwarcia pliku raport.lrf otrzymuję w Lazarusie komunikat "Błąd podczas ładowania raportu"...
Po skompilowaniu programu, przy próbie wywołania podglądu, otrzymuję komunikat "Error while loading report"...
Lazarus 1.4.2, FPC 2.6.4, LazReport 0.9.9

0

Nie za bardzo już wiem w czym może być problem. Po kilkudniowych próbach doszedłem do tego, że kiedy na raporcie umieszczę bandę "Nagłówek główny" wraz z polami tekstowymi oraz bandę "Dane główne" ze wskazanym źródłem danych oraz polami tekstowymi z zawartościami [nazwa_zmiennej] i pustym obrazkiem o nazwie "foto" wszystko działa bez problemu. Problemu nie ma gdy na raporcie umieszczę np. PUSTĄ bandę "Nagłówek strony" czy "Stopka strony". Problem pojawia się gdy na nich umieszczę jakikolwiek inny element typu pole tekstowe czy nawet linię. Wówczas program przy generowaniu raportu wyrzuca komunikat (tutaj akurat linia w stopce strony):

An error occurred during calculation
Report: frReport2
Memo: lina
Band: PageFooter1
Index Out of range Cell[Col=0 Row=32]

Może problem tkwi w tym, że któryś komponent powinien mieć ustawioną jakąś specyficzną właściwość?

0

Problem rozwiązałem zmieniając procedury przy zdarzeniach:

procedure TfOknoProgramu.frUserDataset1CheckEOF(Sender: TObject;
  var Eof: Boolean);
begin
//  eof:=lp>StringGrid1.RowCount-1;
  If frUserDataSet1.RecNo=StringGrid1.RowCount-1 then Eof:=true;
end;

procedure TfOknoProgramu.frUserDataset1First(Sender: TObject);
begin
//  lp:=1;
  StringGrid1.Row:=1;
end;

procedure TfOknoProgramu.frUserDataset1Next(Sender: TObject);
begin
//  Inc(lp);
  StringGrid1.Row:=StringGrid1.Row+1;
end; 

Teraz działa ok.

Mam jednak jeszcze jeden problem. Mianowicie w raporcie, dla wstawionej grafiki "foto" mam wartości KeepAspect oraz Stretched ustawione na True. Grafika jest umieszczona w polu tekstowym. Wysokość grafiki, jeśli występuje, jest za każdym razem taka sama (110) i jest przekazywana w procedurze:

procedure TfOknoProgramu.frReport2EnterRect(Memo: TStringList; View: TfrView);
begin
  SciezkaFoto:=ExtractFilePath(Application.ExeName)+'pliki\stany_magazynowe\foto\foto_id_'+StringGrid1.Cells[0, StringGrid1.Row]+'_nr_1.jpg';
   if View.Name='foto' then
     begin
       if FileExistsUTF8(SciezkaFoto) then
       begin
         View.Visible:=True;
         TFrPictureView(View).Picture.LoadFromFile(SciezkaFoto);
         View.Height:=110;
       end
       else
       begin
         View.Visible:=False;
       end;
     end;
end;

Problem polega na tym, że w sytuacji gdy grafika jest wyższa niż wysokość tekstu w innych komórkach tego wiersza, pole tekstowe w którym się ona znajduje, nie dopasowuje się do wysokości grafiki i grafika zachodzi na kolejny wiersz poniżej. Dla bandy na której znajdują się dane mam zaznaczoną opcję "Rozciągnięcie".
Jak to można poprawić?

1 użytkowników online, w tym zalogowanych: 0, gości: 1