Home General
New Blog Posts: Merging Reports - Part 1 and Part 2

Code Snippets for Images

edited March 2002 in General
I promised this to a few threads in this newsgroup, and also at the Oregon
DUG meeting.

This is code I use so I do not have to include TCharts in my reports--only
in my application. This way when either I make changes to the charts in my
software, or a user makes changes (eg the ability to have pie or bar series
in a given chart, or color), the reports reflect the changes made in the
application.

Some notes:

1) My application is a MDI app. All children in the app have a common
decendant, e.g.
TMyAppForm = class(TForm)
In this class I have an abstract method called GetGraphics(aChartList:
TList).

2) I save all of my reports to a Paradox table. The user can select which
report(s) the want to print. Then they are loaded into one report and
printed.

2) After loading the reports, I see what images are loaded:

function PopulateReportGraphicList (aList: TList): Boolean;
var
I: integer;
lReportGraphic: TReportGraphic;
lImg: TppImage;
begin
for I := ComponentCount-1 downto 0 do
if (Components[I] is TppImage) and
(not (TppImage(Components[I]).Band is TppPageStyle)) and
(TppImage(Components[I]).Picture.Width = 0) and
(Pos('COVER', UpperCase(TppImage(Components[I]).UserName)) = 0)
then
begin
lReportGraphic :=
TReportGraphic.Create(TppImage(Components[I]).UserName);
lImg := TppImage(Components[I]);
lReportGraphic.Rect := Rect(0, 0, Trunc(lImg.mmWidth),
Trunc(lImg.mmHeight));
aList.Add(lReportGraphic);
end;
Result := aList.Count > 0;
end;

I check to be sure it is not the cover page, as that can have images that I
do not want to overwrite. (I should probably changes this to something more
obvious, but haven't).

This creates a list of TReportGraphic objects. The implementation of
TReportGraphic object is:

TReportGraphic = class
private
FID: integer;
FMetafile: TMetafile;
FRect: TRect;
FName: string;
FScale: integer;
function GetPRect: Pointer;
public
constructor Create (aName: String);
destructor Destroy; override;
property Name: String read FName;
property ID: integer read FID write FID;
property Rect: TRect read FRect write FRect;
property PRect: Pointer read GetPRect;
property Metafile: TMetafile read FMetafile;
property Scale: integer read FScale write FScale;
end;

..
constructor TReportGraphic.Create(aName: String);
var
I: Integer;
lPos: Integer;
begin
FName := aName;
FMetafile := TMetafile.Create;

lPos := -1;
for I := 1 to Length(aName) do // Iterate
if (Copy(aName, I, 1) >= '0') and (Copy(aName, I, 1) <= '9') then
begin
lPos := I;
break;
end;
if lPos > 0 then
begin
try
FScale := StrToInt(Copy(aName, lPos, MaxInt));
if FScale < 100 then
FScale := 1000;

FName := Copy(aName, 1, lPos-1);
except
FScale := 1000;
end;
end
else
FScale := 1000;
end;

The 'scale' feature has made life a lot easier to customize the scale to the
size of chart.

I then pass the list to the active child window. That window uses the name
of the TReportGraphic to determine which chart is assigned. It calls the
method AssignChartToMetafile:




--
Ed Dressel

Some plan for retirement
Few plan for eternity.
It does little good to gain the world
Yet lose a soul.

Comments

  • edited March 2002
    Send before I was finished....

    procedure AssignChartToMetafile(aChart: TChart; aReportGraphic:
    TReportGraphic);
    var
    I: Integer;
    lMetafile: TMetafile;
    lRect: TRect;
    lChart : TChart;
    lSeries: TChartSeries;

    begin
    lChart := TChart.Create(nil);
    try
    lChart.Assign(aChart);
    for I := 0 to aChart.SeriesCount -1 do // Iterate
    begin
    lSeries :=
    TChartSeriesClass(aChart.Series[I].ClassType).Create(lChart);
    lSeries.Assign(aChart.Series[I]);
    lSeries.ParentChart := lChart;
    lSeries.Marks.Font.Size := 15;
    lSeries.OnGetMarkText := aChart.Series[I].OnGetMarkText;
    if (lSeries is TPieSeries) then
    begin
    // if Config.System.PieChartsIn2D then
    // lChart.View3D := False;
    TPieSeries(lSeries).Circled := True;
    end;
    end; // for

    lChart.BottomAxis.LabelsFont.Size := 20;
    lChart.OnGetAxisLabel := aChart.OnGetAxisLabel;
    lChart.Gradient.Visible := False;
    lChart.Color := clWhite;
    lChart.Title.Font.Size := 25;
    lChart.BottomAxis.Title.Font.Size := 25;
    lChart.LeftAxis.LabelsFont.Size := 20;
    lChart.LeftAxis.Title.Font.Size := 25;
    lChart.Foot.Font.Size := 14;
    lChart.Legend.Font.Size := 14;

    lChart.BevelOuter := bvNone;

    lRect := aReportGraphic.Rect;
    lRect.Right := Trunc((lRect.Right * aReportGraphic.Scale) /
    lRect.Bottom);
    lRect.Bottom := aReportGraphic.Scale;

    lMetafile := lChart.TeeCreateMetafile(False, lRect);
    try
    aReportGraphic.Metafile.Assign(lMetafile);
    finally
    lMetafile.Free;
    end;
    finally
    lChart.Free;
    // aChart.Gradient.StartColor := lColorStart;
    // aChart.Gradient.EndColor := lColorEnd;

    end;
    end;

    I then repopulate the images in the program with the TMetafiles.

    HTH,
    Ed Dressel
    Team DM
This discussion has been closed.