fastreport returns blank page & unconnected header/footer - delphi-7

so I used fastreport for generating reports. I used a couple of them and it works just fine. however today I made another one and when being run, fast report return a blank page despite of having values inside.
I wonder what kind of error is that, so I made another in blank form. when being run, it returns error :
error : unconnected header/footer.
I don't know what happened. the error came suddenly. please help.

It seems you tried to rebuild report with vertical bands. You should reload report template for refreshing report with vertical bands, because of changing object's position on the vertical bands during report's preparing.
Create a second TfrxReport instance, load same report template to it and reload report template before refreshing
procedure TForm1.frxReport1Preview(Sender: TObject);
var Button: TSpeedButton;
begin
Button := TSpeedButton.Create(TfrxPreviewForm(TfrxReport(Sender).PreviewForm).ToolBar);
TfrxPreviewForm(TfrxReport(Sender).PreviewForm).ToolBar.InsertControl(Button);
Button.Caption := 'Refresh';
Button.Width := 60;
Button.OnClick := RefreshReport;
end;
procedure TForm1.RefreshReport(Sender: TObject);
var
idx: Integer;
begin
for idx := 0 to frxReport1.PagesCount - 1 do
if frxReport1.Pages[idx] is TfrxReportPage then
begin
frxReport1.Pages[idx].Clear;
frxReport1.Pages[idx].AssignAll(frxReport2.Pages[idx], True);
end;
TfrxPreviewForm(TSpeedButton(Sender).Owner.Owner).Report.ShowReport;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
frxReport2.AssignAll(frxReport1, True);
frxReport1.EngineOptions.DestroyForms := False;
frxReport1.ShowReport();
end;

Related

How to dislay correct x-axis (bottom axis) label from datasource using Teechart (Delphi)

I would like to ask some help on displaying my datasource’s clientname at the bottom of my stacked bar chart. It seems from all the examples that I researched, the bottom chart axis label is set "automatically" by TeeChart looking at the datasource. However I cant seem to get it to work. Below is a picture of what I am trying to achieve.
Picture of what I am trying to achieve
I have three series' which I use to build the stacked chart. I have included a picture of each datasource I use for each query.
Datasources for three series' queries
From my research it seems I can also use the DBChart1GetAxisLabel() to custom set the labels. But I am struggling to understand how to ensure that the correct custom label name is associated with the correct "clientname" from my queries.
Here is a code sample of how I build the charts:
procedure TfrmSupplierAnalytics.btnOKClick(Sender: TObject);
var
S,NewTypeStr, test, clientSql : string;
var seriasNormalOrders:TBarSeries;
var seriasCreditNoteOrders:TBarSeries;
var seriasPartialOrders:TBarSeries;
N, i : integer;
begin
qCreditNoteOrders.Close;
qNormalOrders.Close;
qPartialOrders.Close;
qGetClientIdFromName.Close;
qClients.Close;
DBChart1.CleanupInstance;
DBChart1.ClearChart;
try
for N := 0 to clbClients.Items.Count-1 do
if clbClients.State[N] = cbChecked then begin
test := string(clbClients.Items[N]);
NewTypeStr := NewTypeStr + '(E.clientid = '+
IntToStr(FindClientID(test)) + ')';
clientSql := clientSql + NewTypeStr;
NewTypeStr := ' or ';
end;
except
on E : Exception do
ShowMessage(E.ClassName+' error raised, with message :
'+E.Message);
end;
OpenQueryCreditNoteOrders(clientSql);
OpenQueryPartialOrders(clientSql);
OpenQueryNormalOrders(clientSql);
seriasNormalOrders :=TBarSeries.Create(self);
DBChart1.AddSeries(seriasNormalOrders);
seriasCreditNoteOrders :=TBarSeries.Create(self);
DBChart1.AddSeries(seriasCreditNoteOrders);
seriasPartialOrders :=TBarSeries.Create(self);
DBChart1.AddSeries(seriasPartialOrders);
seriasNormalOrders.MultiBar := mbStacked;
seriasCreditNoteOrders.MultiBar := mbStacked;
seriasPartialOrders.MultiBar := mbStacked;
seriasNormalOrders.Marks.Visible := true;
seriasNormalOrders.MarksLocation:= mlCenter;
seriasNormalOrders.MarksOnBar := True;
seriasNormalOrders.YValues.ValueSource := 'NormalOrders';
seriasNormalOrders.DataSource := qNormalOrders;
seriasNormalOrders.Title := 'Correct Orders';
seriasNormalOrders.Marks.Visible := True;
seriasNormalOrders.Marks.AutoPosition := true;
seriasCreditNoteOrders.YValues.ValueSource := 'CreditNoteOrders';
seriasCreditNoteOrders.DataSource := qCreditNoteOrders;
seriasCreditNoteOrders.Title := 'Credit Note Orders';
seriasPartialOrders.YValues.ValueSource := 'PartialOrders';
seriasPartialOrders.DataSource := qPartialOrders;
seriasPartialOrders.Title := 'Short Orders';
seriasNormalOrders.CheckDataSource;
seriasCreditNoteOrders.CheckDataSource;
seriasPartialOrders.CheckDataSource;
end;
So, just to sum up, is there some setting in my code which I am missing that would show the "clientname" below each stacked bar, or must I use custom labels?
If I must use custom labels, I would appreciate some direction on how to ensure that I replace the correct "clientname" from the datasource to the correct ValueIndex in the DBChart1GetAxisLabel?
Thanks in advance.
I managed to get an answer.
You could set the XLabelsSource to show the text from the DataSource and then set the series Marks.Style to smsValue to force it showing values instead of showing the labels. Ie:
<pre>
procedure TForm1.FormCreate(Sender: TObject);
var ADOQuery1: TADOQuery;
i: Integer;
begin
ADOQuery1:=TADOQuery.Create(Self);
with ADOQuery1 do
begin
ConnectionString:='Provider=MSDASQL.1;Persist Security Info=False;Data
Source=TeeChart Pro Database';
SQL.Add('SELECT SALARY, LASTNAME from Employee WHERE LASTNAME='#39'Smith'#39);
end;
for i:=0 to 1 do
with DBChart1.AddSeries(TBarSeries) as TBarSeries do
begin
XLabelsSource:='LASTNAME';
DataSource:=ADOQuery1;
MultiBar:=mbStacked;
YValues.ValueSource:='SALARY';
Marks.Style:=smsValue;
end;
ADOQuery1.Open;
end;
</pre>
I tested it in my project and it works.

Lazarus find control under cursor

I am using the following code from this posting.
Code from Checked Answer
I need to get the Control (Label.Caption) under the mouse cursor from one of several TLabel and it worked fine when the Label was on the Main From. I put the Labels on a Panel on the Main form and now this only finds the Panel. I only want this to work on a select few of the Labels of the many that are on the Panel.
I tried changing the Z-Order for the Labels as "Bring To Front" but it made no difference, still got the Panel. How can I again find a Label under the cursor now that they are on the Panel?
Lazarus does not appear to have FindVCLWindow or ObjectAtPoint.
procedure TForm1.Button1Click(Sender: TObject);
var
ctrl : TControl;
point : TPoint;
begin
point := Mouse.CursorPos; // Mouse pos at screen
Dec(point.X, Left); // Adjust for window.
Dec(point.Y, Top);
Dec(point.Y, GetSystemMetrics(SM_CYCAPTION)); // Adjust to client area.
ctrl := ControlAtPos(point, True, True, True);
// I added the following
tStr:=ctrl.Name; // DEBUG: This now shows "Panel2"
aStr:=(ctrl as TLabel).Caption; // This used to work
end;
Try:
procedure TForm1.Button1Click(Sender: TObject);
var
ctrl: TControl;
pt: TPoint;
begin
pt := ScreenToClient(Mouse.CursorPos);
ctrl := ControlAtPos(pt, [capfRecursive, capfAllowWinControls]);
if Assigned(ctrl) then
Caption := ctrl.Name
else
Caption := Format('%d, %d', [pt.x, pt.y]);
end;

How to jump to page on on button click?

I need a simple thing: have advance and normal installation buttons. For normal case it is all simple - I used default next button with some logic on NextButtonClick to set a condition variable and skeep some pages using ShouldSkipPage . Yet for advanced setup I created a new button and all I need it to do on click is to open next installer page:
procedure CurPageChanged(CurPageID : Integer);
begin
if CurPageID = wpWelcome then begin
AdvancedButton := TButton.Create(WizardForm);
AdvancedButton.Caption := 'Advanced Install';
AdvancedButton.Left := WizardForm.InfoAfterPage.Left + 10;
AdvancedButton.Top := WizardForm.InfoAfterPage.Height + 88;
AdvancedButton.Parent := WizardForm.NextButton.Parent;
# AdvancedButton.OnClick := What shall I call to open say next page (or some page by given PageID value)
end
else begin
AdvancedButton.Visible := False;
end;
end;
So What shall I call to open say next page (or some page by given PageID value) on my button click (could not find any NextPage or some SetPage function in Inno API)?
There is no such thing as "Direct jump to page" in Inno Setup.
All you need is to quietly skip certain pages in 'Advanced mode'.
Simply do the same as in regular installer. Set one variable for holding 'Advanced mode'. After clicking the Advance button:
[Code]
var
IsAdvanced: Boolean;
procedure AdvancedButtonClick(Sender: TObject);
begin
IsAdvanced := True;
WizardForm.NextButton.OnClick(nil);
end;
procedure InitializeWizard;
var
AdvancedButton: TNewButton;
begin
// not necessary; just for sure
IsAdvanced := False;
// create the button
AdvancedButton := TNewButton.Create(WizardForm);
AdvancedButton.Caption := 'Advanced Install';
AdvancedButton.Left := WizardForm.InfoAfterPage.Left + 10;
AdvancedButton.Top := WizardForm.InfoAfterPage.Height + 88;
AdvancedButton.Parent := WizardForm.NextButton.Parent;
AdvancedButton.OnClick := #AdvancedButtonClick;
end;
function ShouldSkipPage(PageID: Integer): Boolean;
begin
// the <page where you want to end up> fill with the wizard page constant
// of the page where you want to end up, e.g. wpReady
Result := IsAdvanced and (PageID <> <page where you want to end up>);
end;
With this logic you can simulate quiet 'jump' to certain page.

How to change picture delphi timage in run time

I use a timage in a form which load a background image.
The problem is when i choose another picture in run time and change it by
Img_Bk.Picture.LoadFromFile( SaveFileName );
It doesnt work (Picture did n't change ). I mean it shows previous picture and doesn't show the new image during run time. Id like to change application background image during run time in my company by users which main form is a mdi form .
I use delphi 7 .
try
Img_Bk.Picture := nil ;
if FileSize > 100 then
begin
Img_Bk.Picture.LoadFromFile( SaveFileName );
end;
Img_Bk.Stretch := True ;
except
end;
LoadFromFile is known to work. So there must be a more prosaic explanation.
The first possible explanation is that FileSize is not greater than 100 and the if condition evaluates false.
Another possible explanation is that the image in the file that you specify is not the one you are expecting.
Otherwise, your code has a swallow all exception handler. And so when the call to LoadFromFile fails and raises an exception, your code ignores that and carries on as if nothing un-toward had happened. Remove the try/except, and deal with the error that will be revealed.
The real lesson for you to learn is never to write such an exception handler again.
This program should prove to you that LoadFromFile is just fine:
program ImageDemo;
uses
Types, Math, IOUtils, SHFolder, Forms, Controls, StdCtrls, ExtCtrls, jpeg;
var
Form: TForm;
Image: TImage;
Timer: TTimer;
ImageIndex: Integer = -1;
MyPictures: string;
Images: TStringDynArray;
type
THelper = class
class procedure Timer(Sender: TObject);
end;
class procedure THelper.Timer(Sender: TObject);
begin
inc(ImageIndex);
if ImageIndex>high(Images) then
ImageIndex := 0;
if ImageIndex>high(Images) then
exit;
Image.Picture.LoadFromFile(Images[ImageIndex]);
end;
function GetMyPictures: string;
var
Str: array[0..260] of Char;
begin
if SHGetFolderPath(0, CSIDL_MYPICTURES, 0, 0, Str) = S_OK then
Result := Str;
end;
procedure BuildForm;
begin
Form.ClientWidth := 700;
Form.ClientHeight := 500;
Image := TImage.Create(Form);
Image.Parent := Form;
Image.Align := alClient;
Image.Stretch := True;
Timer := TTimer.Create(Form);
Timer.OnTimer := THelper.Timer;
Timer.Interval := 100;
end;
begin
MyPictures := GetMyPictures;
Images := TDirectory.GetFiles(MyPictures, '*.jpg', TSearchOption.soAllDirectories);
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm, Form);
BuildForm;
Application.Run;
end.
I had the same problem today. After the call of LoadFromFile() the image does not change. I have tried Refresh, Repaint, Invalidate and Update -> nothing helped. Then I found that resizing the from immediately updated the image.
Finally I found that setting property Visible to false and back to true updates the image, too.
FormMain.Image1.Visible := false;
FormMain.Image1.Picture.LoadFromFile(newImageFileName);
FormMain.Image1.Visible := true;
Perhaps not the best but it works for me.

Add function execution into installer progress of inno setup

I'm making a patch for an old game (Command & Conquer 1, Win95 edition), and in some cases, executing the patch requires going through a function written in the Pascal script that could take quite a while.
At the moment, I execute this at the moment the page is changed to the "installing" page, so, after the user has selected all options and confirmed to install, right before the installer starts actually adding (and deleting) files.
procedure CurPageChanged(CurPageID: Integer);
begin
if (CurPageID = wpInstalling) then
begin
// Rename all saveg_hi.### files to savegame.###
renameSaveGames();
// clean up the ginormous files mess left behind if the game was installed from the 'First Decade' compilation pack
cleanupTFD();
end;
end;
But since the process could be rather long, I'd prefer to somehow add it to the actual install progress bar. Is there any way to accomplish this?
You can control the ProgressGauge from the install page of the WizardForm. In the following script is shown how to update the progress bar from a loop (which you'll just replace with your actions). For safety are progress bar values like min, max and position saved before the custom actions are performed and restored when they're done.
[Code]
procedure CurPageChanged(CurPageID: Integer);
var
I: Integer;
ProgressMin: Longint;
ProgressMax: Longint;
ProgressPos: Longint;
begin
if CurPageID = wpInstalling then
begin
// save the original "configuration" of the progress bar
ProgressMin := WizardForm.ProgressGauge.Min;
ProgressMax := WizardForm.ProgressGauge.Max;
ProgressPos := WizardForm.ProgressGauge.Position;
// output some status and setup the min and max progress values
WizardForm.StatusLabel.Caption := 'Doing my own pre-install...';
WizardForm.ProgressGauge.Min := 0;
WizardForm.ProgressGauge.Max := 100;
// here will be your time consuming actions with the progress update
for I := 0 to 100 do
begin
WizardForm.FilenameLabel.Caption := 'I''m on ' + IntToStr(I) + '%';
WizardForm.ProgressGauge.Position := I;
Sleep(50);
end;
// restore the original "configuration" of the progress bar
WizardForm.ProgressGauge.Min := ProgressMin;
WizardForm.ProgressGauge.Max := ProgressMax;
WizardForm.ProgressGauge.Position := ProgressPos;
end;
end;

Resources