Access violation in bands.
Hi,
We just bought the server version of Report builder hoping that an access
violation I was getting with the demo version would have cleared up.
Apparently NOT.
What I am doing is creating a TppReport object AT RUNTIME. Then loading a
template from the database given the name of the template which is stored as
a blob field.
Once I have the TppReport component with the loaded template, I show 3
report styles with the TppReport component. Basically, my report template
has a master
detail setup and at run time, I make visible or invisble the components I
need. Hence, one report is just a master report (i.e. one dataset) another
is detail report (with one
dataset) and then finally, the last report from the same template is a
master detail report (with two datasets). At run time I have to create the
pipelines and datasources
for each type of style I want. To sum up, one report template gives us 3
report formats/styles.
On my form I have 3 buttons which create the reports which work fine
individually (i.e. start application, press master button, report is shown,
close application, then repeat
sequence with other buttons).
However, if I do not close down the app and press the master button and then
the detail button, I get an access violation on free the TppReport object I
created.
When looking into the TppReport.Free, I found that the access violation
occurs in FreeBandsAnd Groups where lBand.Free occurs (see below). This only
occurs
in the detail case. When TppReport.Free is called for the master format, it
works fine.
At no point in my code am I freeing bands or creating bands. The bands exist
in the template and that is all.
I would appreaciate any help you can give me in tracking down what is
causing this problem.
Sham.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''
procedure TppCustomReport.FreeBandsAndGroups;
var
liBand: Integer;
lBand: TObject;
liGroup: Integer;
lGroup: TObject;
begin
{destroy non-group bands}
OutputDebugString(pChar(IntToStr(bandCount)));
for liBand := BandCount-1 downto 0 do
begin
lBand := Bands[liBand];
if (lBand is TppGroupBand) then
RemoveBand((lBand as TppBand))
else
lBand.Free;
end;
FBands.Clear;
{destroy groups (groups will then destroy their associated bands)}
for liGroup := GroupCount-1 downto 0 do
begin
lGroup := Groups[liGroup];
lGroup.Free;
end;
FGroups.Clear;
end;
We just bought the server version of Report builder hoping that an access
violation I was getting with the demo version would have cleared up.
Apparently NOT.
What I am doing is creating a TppReport object AT RUNTIME. Then loading a
template from the database given the name of the template which is stored as
a blob field.
Once I have the TppReport component with the loaded template, I show 3
report styles with the TppReport component. Basically, my report template
has a master
detail setup and at run time, I make visible or invisble the components I
need. Hence, one report is just a master report (i.e. one dataset) another
is detail report (with one
dataset) and then finally, the last report from the same template is a
master detail report (with two datasets). At run time I have to create the
pipelines and datasources
for each type of style I want. To sum up, one report template gives us 3
report formats/styles.
On my form I have 3 buttons which create the reports which work fine
individually (i.e. start application, press master button, report is shown,
close application, then repeat
sequence with other buttons).
However, if I do not close down the app and press the master button and then
the detail button, I get an access violation on free the TppReport object I
created.
When looking into the TppReport.Free, I found that the access violation
occurs in FreeBandsAnd Groups where lBand.Free occurs (see below). This only
occurs
in the detail case. When TppReport.Free is called for the master format, it
works fine.
At no point in my code am I freeing bands or creating bands. The bands exist
in the template and that is all.
I would appreaciate any help you can give me in tracking down what is
causing this problem.
Sham.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''
procedure TppCustomReport.FreeBandsAndGroups;
var
liBand: Integer;
lBand: TObject;
liGroup: Integer;
lGroup: TObject;
begin
{destroy non-group bands}
OutputDebugString(pChar(IntToStr(bandCount)));
for liBand := BandCount-1 downto 0 do
begin
lBand := Bands[liBand];
if (lBand is TppGroupBand) then
RemoveBand((lBand as TppBand))
else
lBand.Free;
end;
FBands.Clear;
{destroy groups (groups will then destroy their associated bands)}
for liGroup := GroupCount-1 downto 0 do
begin
lGroup := Groups[liGroup];
lGroup.Free;
end;
FGroups.Clear;
end;
This discussion has been closed.
Comments
After some extensive research and remembering what Nico said about looking
for components on a subReport, I changed the following code :
//var
// ppChildReport : TppChildReport;
//begin
// if FppReport.ObjectByName(iBand, iComponentIndex, 'ppSubReportDetail')
then
// begin
// ppChildReport :=
TppChildReport(TppSubReport(FppReport.Bands[iBand].Objects[iComponentIndex])
.Report);
// if ppChildReport.ObjectByName(iBand, iComponentIndex,
'ppForDetailLbl') then
// ppChildReport.Bands[iBand].Objects[iComponentIndex].Visible :=
False;
//
// if ppChildReport.ObjectByName(iBand, iComponentIndex,
'ppForDetailDBText') then
// begin
// ppChildReport.Bands[iBand].Objects[iComponentIndex].Visible :=
False;
// end;
// end;
// end
FOR:
var
iBand : Integer;
iComponentIndex : integer;
ppChildReport : TppCustomReport;
lObject : TObject;
i, j : integer;
begin
for iBand := 0 to FppReport.BandCount - 1 do
begin
for iComponentIndex := 0 to FppReport.bands[iBand].objectCount - 1 do
begin
lObject := FppReport.Bands[iBand].Objects[iComponentIndex];
if (lObject is TppSubReport) then
begin
ppChildReport := TppSubReport(lObject).Report;
for i := 0 to ppChildReport.BandCount - 1 do
begin
if ppChildReport.Bands[i] is TppTitleBand then
begin
for j := 0 to ppChildReport.Bands[i].ObjectCount - 1 do
begin
if ppChildReport.Bands[i].Objects[j] is TppLabel then
begin
if ppChildReport.Bands[i].Objects[j].Name = 'ppForDetailLbl'
then
ppChildReport.Bands[i].Objects[j].Visible := False;
end
else if ppChildReport.Bands[i].Objects[j] is TppDBText then
begin
if ppChildReport.Bands[i].Objects[j].Name = 'ppForDetailDBText'
then
ppChildReport.Bands[i].Objects[j].Visible := False;
end;
end;
end;
end;
end;
end;
end;
Both pieces of code work however, as mentioned on my last email, in
TppCustomReport I get access violations when
the bands are being freed by report builder (even though I do not create or
free any bands in my code).
The access violation seems to have disappeared for now.
Please can you tell me wha the difference in the code is which may cause the
access violation.
Regards
Sham.
I am not sure why you stopped receiving the AVs when you switched to the
report object loop method. Instead of creating and freeing new report
objects every time you need one, you should try creating one TppReport
object and load templates into that object. This way you will not have to
deal with freeing the report object once you have finished with it.
--
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
I can do what you have said. Just to finish with this, should I create
TppReport with owner as application and then when the application finishes
it will free the TppReport object?
However, I may still get AV when the application finishes or maybe not?
Thanks.
Sham.
This is correct, you will want to create a report with the owner being
'self' or 'application' but once the form is destroyed, the report will be
as well so there is no need to free the report object. There should be no
AV's if your application is structured this way.
--
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com