Rave Reports - raportowanie za pomocą kodu
Artur
W tym artykule postaram się przybliżyć ideę raportowania w Delphi za pomocą Rave Reports. Wielu uzytkowników przyzwyczajonych do Quick Reports z poprzednich wersji Delphi ma spore trudności w tworzeniu raportów za pomocą Delphi 7, bowiem w tej wersji zrezygnowano z Quick Reports i wprowadzono nową ideę raportowania za pomocą RAve Reports (Sposób działania Rave jest zupełnie inny niż Quick Reports). W tym artykule zaprezentuję sposoby tworzenia raportów za pomocą kodu (drugim sposobem raportowania za pomocą Rave jest wykorzystanie narzędzia Visual Designer - o tym moze będzie kolejny artykuł:) )
A więc zaczynamy
Spróbujmy stworzyć najprostszy raport, który wyświetli nam jakiś tekst, powiedzmy "To jest pierwszy raport stworzony za pomocą Rave Reports"
Otwieramy Delphi 7 Enterprise (bo chyba w pozostałych wersjach nie ma Rave - trzeba wtedy pobrać ze strony http://www.borland.com)
przechodzimy na zakładkę Rave i umieszczamy na formie komponent RvSystem1, oraz przycisk Button1 z zakładki Standard (możemy zmianić właściwosć Caption Buttona na "Raport")
Ok, to interfejs już mamy:)
Teraz zajmijmy się kodowaniem
Stwórzmy procedurę, która będzie odpowiedzialna za wygląda raportu
W sekcji private Formy umieścmy nagłówek procedury
procedure DrukujRaport(Report: TBaseReport);
i pod słowem implementation napiszmy kod procedury
procedure TForm1.DrukujRaport(Report: TBaseReport);
begin
with Report do
begin
SetFont('Times New Roman', 20); //ustawiamy czcionkę na times New Roman o rozmiarze 20
GotoXY(1,1); //przechodzimy do pola 1, 1 na raporcie
Print('To jest pierwszy raport stworzony za pomocą Rave Reports'); //wyświetlamy na raporcie tekst
end;
end;
Parametr Sender wskazuje na raport, który właśnie tworzymy; może tu użyć obiekt klasy TBaseReport. Zawiera on wszystkie metody, których będziemy potrzebować potrzebować, by przesłać informacje do tego konkretnego raportu.
SetFont określa typ i krój czcionki. Instrukcja gotoxy ustawia kursor w punkcie o współrzędnych (1,1). Współrzędne te wyrażone są w jednostkach określonych we właściwościach SystemPrinter.Units komponentu RvSystem, zaś domyślną jednostką są cale. Możemy to zmienić na bardziej polską jednostkę - na centymetry. W tym celu należy ustawić właściwość SystemPrinter.Units komponentu RvSystem na unCM i możemy wybrać wielkość tej jednostki we właściwosci SystemPrinter.UnitsFector. Ustawmy tę wielkość na 2. Dla przykładu, gdy wartość UnitsFactor jest ustawiona na 2, wówczas 1 jednostka odpowiada 2 centymetrom.
Teraz musimy wywołać napisana przez nas procedurę w zdarzeniu onPrint komponentu RvSystem1. Robimy to w następujacy sposób
procedure TForm1.RvSystem1Print(Sender: TObject);
begin
DrukujRaport(Sender as TBaseReport);
end;
I na koniec musimy napisać kod zdarzenia dla naciśnięcia przycisku - po naciśnięciu Button1 ma być generowany raport. Robimy to w następujacy sposób
procedure TForm1.Button1Click(Sender: TObject);
begin
RvSystem1.Execute
end;
I już możemy testować nasz program do generowania raportów. Poniżej przedstawiam cały kod programu
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, RpDefine, RpBase, RpSystem;
type
TForm1 = class(TForm)
RvSystem1: TRvSystem;
Button1: TButton;
procedure RvSystem1Print(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure DrukujRaport(Report: TBaseReport);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.DrukujRaport(Report: TBaseReport);
begin
with Report do
begin
SetFont('Times New Roman', 20);
GotoXY(1,1);
Print('To jest pierwszy raport stworzony za pomocą Rave Reports');
end;
end;
procedure TForm1.RvSystem1Print(Sender: TObject);
begin
DrukujRaport(Sender as TBaseReport);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
RvSystem1.Execute
end;
end.
No to nadszedł czas na bardziej rozbudowane raporty.
ZAłóżmy, że mamy plik tekstowy zawierajacy informacje o naszych kolegach/koleżankach w takiej postaci:
imie
nazwisko
e-mail
wiek
np. ja utworzyłem sobie plik tekstowy koledzy.txt i wpisałem do niego:
Asia
Abacka
abac_as@wp.pl
21
Basia
Babacka
basiaaaaaa@o2.pl
20
Szymon
Cabacki
szymek_c@interia.pl
19
Wiola
Dabacka
viola_d@onet.pl
18
Chcę teraz wyświetlić raport, który wypisze mi dane moich znajomych w postaci kolumn. A wiec zaczynamy tworzenie interfejsu. Tak jak poprzednio umieszczamy na Formie RvSystem1 i Button1. No i już mamy interfejs:) Teraz pora napisać kod naszej aplikacji. W sekcji private Formy umieszczamy deklarację procedury, która będzie nam generować raport.
procedure Raportkolegow(Report : TBaseReport);
Następnie orpogramowujemy zdarzenia onPrint dla komponentu RvSystem1 i onClick dla Buttona. Są one identyczne jak w poprzednim przykładzie, więc nie będę ich omawiał, umieszczam tylko ich kod.
procedure TFormMain.RvSystemPrint(Sender: TObject);
begin
Raportkolegow(Sender as TBaseReport);
end;
procedure TFormMain.Button1Click(Sender: TObject);
begin
RvSystem.Execute;
end;
Zostało nam jeszcze oprogramowanie procedury Raportkolegow. Robimy to w następujacy sposób:
procedure TFormMain.Raportkolegow(Report: TBaseReport);
var
f:TextFile; //zmienna plikowa
imie,nazwisko,e_mail,wiek:string; //zmienne łańcuchowe, które będziemy czytać z pliku
begin
Report.SetFont('Arial', 15);//ustawiamy czcionkę na arial o wielkości 15
Report.NewLine; //przechodzimy do nowej linii
Report.PrintCenter('Dane moich znajomych', 4);//tytuł raportu, 4 oznacza że tytuł będzie 4 cale od lewego brzegu raportu
Report.NewLine; //przechodzimy do nowej linii
Report.NewLine; //jeszcze raz przechodzimy do nowej linii
Report.ClearTabs; //będziemy tworzyć nowy raport tabularyczny, więc ta instrukcja jest konieczna
//ustawiamy właściwości kolumn, jednostkami są cale
Report.SetTab(0.2, pjLeft, 1.7, 0, 0, 0);{kulumna zaczyna się 0,2 cala od lewego brzegu raportu, będzie wyrównana do lewej i długość jej będzie wynosić 1,7 cala, pierwsze zero określa, że tekst w kolumnach nie będzie miał marginesów, drugie zero oznacza, że nie będzie żadnego obramowania kolumny, wpisując rózne liczby uzyskujemy rózne obramowanie, ostatnie zero określa, że tło kolumny będzie białe, jeśli wpiszemy wartośc 25 uzyskamy szare tło, jeśli 100, tło będzie czarne}
Report.SetTab(1.9, pjLeft, 2.1, 0, 0, 0);
Report.SetTab(4.0, pjLeft, 2.5, 0, 0, 0);
Report.SetTab(6.5, pjRight, 1.5, 0, 0, 0);
Report.SetFont('Arial', 10); //ustawiamy wielkość czcionki dla nagłówków kolumn
Report.Bold := True; //nagłówki będą pisane czcionką pogrubioną
//tworzymy odpowiednie nagłówki
Report.PrintTab('Imię'); //nagłówek pierwszej kolumny
Report.PrintTab('Nazwisko'); //nagłowek drugiej kolumny
Report.PrintTab('Adres e-mail'); //nagłówek trzeciej kolumny
Report.PrintTab('Wiek'); //nagłowek czwartej kolumny
Report.Bold := False; //reszta będzie pisana czcionką "niepogrubioną" czyli normalną
Report.NewLine; //przechodzimy do nowej linii
//teraz będziemy odczytywać z pliku dane i umieszczać je w raporcie
assignfile(f,'koledzy.txt');//kojarzymy zmienną plikową z plikiem koledzy.txt
reset(f); //otwieramy plik
while not eof(f) do //dopóki są dane w pliku
begin
readln(f,imie); //czytaj z pliku imię
Report.PrintTab(imie); //umieść w 1 kolumnie raportu imię
readln(f,nazwisko); //czytaj z pliku nazwisko
Report.PrintTab(nazwisko); //umieść nazwisko w 2 kolumnie
readln(f,e_mail); //czytaj z pliku e-mail
Report.PrintTab(e_mail); //umieść e-mail w 3 kolumnie
readln(f,wiek); //czytaj z pliku wiek
Report.PrintTab(wiek); //umieść wiek w 4 kolumnie
Report.NewLine; //przejdź do nowej linii
end;
closefile(f); //zamykamy plik
end;
I już możemy generować raporty dotyczące naszych znajomych.
Zauważ, że zastosowaliśmy inne podejście: zamiast specyfikować koordynaty każdego elementu wydruku, posłużyłem się liniami i kolumnami jako wielkościami odniesienia. Wysokość linii zależy od wielkości użytej czcionki: każda jednostka to 1/72 cala(bo w tym projekcie używaliśmy cali), a więc linia drukowana czcionką o rozmiarze 10 będzie miała wysokość około 0,138 cala. Przeskok do kolejnej linii następuje po komendzie NewLine. Kolumny są zdefiniowane przez odwołania do metody SetTabs, a metoda PrintTab powoduje drukowanie tekstu w bieżącej kolumnie z przeskokiem do następnej kolumny.
Poniżej umieszczam cały kod programu
unit MainForm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, RpDefine, RpBase, RpSystem, StdCtrls, ExtCtrls;
type
TFormMain = class(TForm)
RvSystem: TRvSystem;
Button1: TButton;
procedure RvSystemPrint(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
procedure Raportkolegow(Report : TBaseReport);
public
{ Public declarations }
end;
var
FormMain: TFormMain;
implementation
{$R *.dfm}
procedure TFormMain.RvSystemPrint(Sender: TObject);
begin
Raportkolegow(Sender as TBaseReport);
end;
procedure TFormMain.Button1Click(Sender: TObject);
begin
RvSystem.Execute;
end;
procedure TFormMain.Raportkolegow(Report: TBaseReport);
var
f:TextFile;
imie,nazwisko,e_mail,wiek:string;
begin
Report.SetFont('Arial', 15);
Report.NewLine;
Report.PrintCenter('Dane moich znajomych', 4);
Report.NewLine;
Report.NewLine;
Report.ClearTabs;
Report.SetTab(0.2, pjLeft, 1.7, 0, 0, 0);
Report.SetTab(1.9, pjLeft, 2.1, 0, 0, 0);
Report.SetTab(4.0, pjLeft, 2.5, 0, 0, 0);
Report.SetTab(6.5, pjRight, 1.5, 0, 0, 0);
Report.SetFont('Arial', 10);
Report.Bold := True;
Report.PrintTab('Imię');
Report.PrintTab('Nazwisko');
Report.PrintTab('Adres e-mail');
Report.PrintTab('Wiek');
Report.Bold := False;
Report.NewLine;
assignfile(f,'koledzy.txt');
reset(f);
while not eof(f) do
begin
readln(f,imie);
Report.PrintTab(imie);
readln(f,nazwisko);
Report.PrintTab(nazwisko);
readln(f,e_mail);
Report.PrintTab(e_mail);
readln(f,wiek);
Report.PrintTab(wiek);
Report.NewLine;
end;
closefile(f);
end;
end.
Za pomocą Reve Reports można także w raportach umieszczać obrazki. Zróbmy teraz raport naszych znajomych ze zdjeciami. Załóżmy, że mamy plik tekstowy Koledzy.txt o następującej strukturze
imię
nazwisko
e-mail
wiek
fotka (nazwa pliku *.bmp)
Ja na przykład mam taki plik
Asia
Abacka
abac_as@wp.pl
21
asia.bmp
Basia
Babacka
basiaaaaaa@o2.pl
20
basia.bmp
Zosia
Cabacka
zosia_c@interia.pl
19
zosia.bmp
Wiola
Dabacka
viola_d@onet.pl
18
wiola.bmp
Przygotowałem sobie również bitmapy znajomych (asia.bmp, basia.bmp, zosia.bmp, wiola.bmp), które znajdują się w katalogu bieżącym aplikacji.
No to zabieramy sie za tworzenie interfejsu aplikacji - będzie on taki sam jak poprzednio - na Formie umieść RvSystem1 i Button1
Teraz nadszedł czas oprogramować zdarzenia.
W sekcji private Formy wpisz
procedure Raportkolegowzfotkami(Report : TBaseReport);
Następnie oprogramuj zdarzenia onPrint RvSystem1 i onClick Button1
procedure TFormMain.RvSystemPrint(Sender: TObject);
begin
Raportkolegowzfotkami(Sender as TBaseReport);
end;
procedure TFormMain.Button1Click(Sender: TObject);
begin
RvSystem.Execute;
end;
Tu nic się nie zmieniło. I nadszedł czas napisać procedurę Raportkolegowzfotkami
procedure TFormMain.Raportkolegowzfotkami(Report: TBaseReport);
var
f:TextFile;//zmienna plikowa
imie,nazwisko,e_mail,wiek,fotka:string;//zmienne tekstowe - bedziemy czytać z pliku
Bitmap:TBitmap;//zmienna przechowywać będzie bitmapę
i:double;//zmienna liczbowa
begin
Report.SetFont('Arial', 15);//ustawiamy czcionkę na arial o wielkości 15
Report.NewLine; //przechodzimy do nowej linii
Report.PrintCenter('Dane moich znajomych', 3.5);//tytuł raportu, 4 oznacza że tytuł będzie 4 cale od lewego brzegu raportu
Report.NewLine; //przechodzimy do nowej linii
Report.NewLine; //jeszcze raz przechodzimy do nowej linii
Report.SetFont('Arial', 10);//ustawiamy wielkosć czcionki kolumn
Report.Bold := True;//nagłówek pogrubiamy
//tworzymy nagłowki kolumn - tym razem za pomocą PrintXY
Report.PrintXY(0.2,0.7,'Imię');//na pozycji x=0.2 y=0.7 umieszczamy tekst Imię
Report.PrintXY(1.2,0.7,'Nazwisko');
Report.PrintXY(2.7,0.7,'Adres e-mail');
Report.PrintXY(4.7,0.7,'Wiek');
Report.PrintXY(5.7,0.7,'Fotka');
Report.Bold := False;//reszta kolumn będzie niepogrubiona - normalna
Report.NewLine;
assignfile(f,'koledzy.txt');//kojarzymy zmienną plikową z plikiem
reset(f);//otwieramy plik
i:=0;//zmienna i będzie nam potrzebna do ustawiania wielkości y w kolejnych wierszach tabeli
while not eof(f) do //dopóki nie ma końca pliku
begin
readln(f,imie); //czytamy imię z pliku
Report.PrintXY(0.2,0.9+i,imie); //wyświetlamy imię na pozycji x=0.2, y=0.9+i
readln(f,nazwisko); //czytamy nazwisko z pliku
Report.PrintXY(1.2,0.9+i,nazwisko); wyświetlamy nazwisko na pozycji x=1.2, y=0.9+i
readln(f,e_mail); //czytamy e-maila z pliku
Report.PrintXY(2.7,0.9+i,e_mail); //wyświetlamy e-maila na pozycji x=2.7, y=0.9+i
readln(f,wiek); //czytamy wiek z pliku
Report.PrintXY(4.7,0.9+i,wiek); //wyświetlamy wiek na pozycji x=4.7, y=0.9+i
readln(f,fotka); //czytamy nazwę pliku fotki z pliku
Bitmap := TBitmap.Create; //dynamicznie tworzymy obiekt przechowujący bitmapę
try
Bitmap.LoadFromFile(fotka); //załadowywujemy odpowiednią fotke do obiektu Bitmap
Report.PrintBitmap(5.7,0.9+i,1,1,Bitmap); //wyświetlamy bitmapę na pozycji x=5.7 y=0.9+i
finally
Bitmap.Free; //zwalniamy pamięć
end;
i:=i+1.5; //zwiększamy i o 1.5 - następny wiersz tabeli będzie 1.5 cala niżej
end;
closefile(f);//zamykamy plik
end;
Tak wyglada nasz raport
A oto cały kod programu
unit MainForm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, RpDefine, RpBase, RpSystem, StdCtrls, ExtCtrls;
type
TFormMain = class(TForm)
RvSystem: TRvSystem;
Button1: TButton;
procedure RvSystemPrint(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
procedure Raportkolegowzfotkami(Report : TBaseReport);
public
{ Public declarations }
end;
var
FormMain: TFormMain;
implementation
{$R *.dfm}
procedure TFormMain.RvSystemPrint(Sender: TObject);
begin
Raportkolegowzfotkami(Sender as TBaseReport);
end;
procedure TFormMain.Button1Click(Sender: TObject);
begin
RvSystem.Execute;
end;
procedure TFormMain.Raportkolegowzfotkami(Report: TBaseReport);
var
f:TextFile;
imie,nazwisko,e_mail,wiek,fotka:string;
Bitmap:TBitmap;
i:double;
begin
Report.SetFont('Arial', 15);
Report.NewLine;
Report.PrintCenter('Dane moich znajomych', 3.5);
Report.NewLine;
Report.NewLine;
Report.SetFont('Arial', 10);
Report.Bold := True;
Report.PrintXY(0.2,0.7,'Imię');
Report.PrintXY(1.2,0.7,'Nazwisko');
Report.PrintXY(2.7,0.7,'Adres e-mail');
Report.PrintXY(4.7,0.7,'Wiek');
Report.PrintXY(5.7,0.7,'Fotka');
Report.Bold := False;
Report.NewLine;
assignfile(f,'koledzy.txt');
reset(f);
i:=0;
while not eof(f) do
begin
readln(f,imie);
Report.PrintXY(0.2,0.9+i,imie);
readln(f,nazwisko);
Report.PrintXY(1.2,0.9+i,nazwisko);
readln(f,e_mail);
Report.PrintXY(2.7,0.9+i,e_mail);
readln(f,wiek);
Report.PrintXY(4.7,0.9+i,wiek);
readln(f,fotka);
Bitmap := TBitmap.Create;
try
Bitmap.LoadFromFile(fotka);
Report.PrintBitmap(5.7,0.9+i,1,1,Bitmap);
finally
Bitmap.Free;
end;
i:=i+1.5;
end;
closefile(f);
end;
end.
Ok, to by było na tyle - jak znajdę czas to następny artykuł napiszę o tworzeniu raportów za pomocą narzędzia Visual Designer. W załączniku są pliki trzeciego programu
Witam, artykuł fainy ale powtarzam pytanie za gilbert3 , nie mogę się doczytać jak zrobić automatyvzny podział na strony i dlaczego w podglądzie widzę tylko jedną stronę.
Siedzę już drugi dzień w sieci i nie mogę nicznaleźć.
AS
Bradzo ladna kopia :}
Artur nie dodałeś małej aczkolwiek pomocnej rzeczy. Mój raport powinien być na cirka 80 stron, tymczasem nie mogę znaleźć jak wykryć koniec strony i przejść do następnej. Kto podpowie?
mpedzik: musisz umieścić na formie komponent RvSystem i w SystemSetups ustawić aaAlowSetup na False. W RvProject jako Engine ustawić RvSystem. Teraz o tym gdzie pójdzie wydruk decyduje parametr DefaultDest w RvSystem.
Ciachu: zobacz tutaj http://www.nevrona.com/Default.aspx?tabid=73
Jeśli chodzi o polskie litery to ustawiam, we właściwościach czcionki, skrypt europejski i są polskie czcionki.
Aha, jeśli ktoś nie lubi podawać położenia kontrolek w calach to można to oczywiście zmienić przy pomocy właściwości TBaseReport.Units na unMM (milimetry) unCM (centymetry)
Artykul przyjemny, w zasadzie nauczyl mnie tego co chailem :-) Ale czy ktos wie jakiego polecenia trzeba uzyc, aby wrzucic do raportu obiekt typu TChart ???
Ja jeszcze nie poradziłem sobie z polskimi literami w Rave - zawsze te polskie litery przeszkadzają:) (że też Polacy musieli cos takiego wymyśleć) a jeśli chodzi o to, żeby podgląd przerobić tak żeby wszystkie funkcje menu i opcje były napisane w języku polskim - to jeszcze czegoś takiego nie widziałem - jak do czegoś dojdę w tych sprawach to napiszę:)
A czy ktos moze mi powiedziec jak sobie poradzic z polskimi literami z RaveReports? Pach 5_0_8 nie pomaga...
Witam
A czy jest możliwość aby okno podglądu przerobić tak żeby wszystkie funkcje menu i opcje były napisane w języku polskim ??? Albo czy chociaż jest możliwość wydrukowania raportu bezpośrednio na drukarkę, bez uprzedniego podglądu ??
Dzięki za komentarze, cieszę się, że artykuł podoba Wam się. Adam dzieki za ocenę - stylu pisania uczyłem się czytajac twoje książki (a mam ich 3) :)
Fajne masz znajome :)
5 za rozbudowany artykuł na popularny (ale nie jeśli chodzi o odpowiedzi :>) temat.
Pięknie, ładnie opisane na przykładach. Brawo z tego przynajmniej można zrozumieć o co biega.
Ode mnie też 5 - podoba mi się. Wybrałeś temat deficytowy na 4p :)
Ode mnie piąteczka :) Fajny artykul.