TDBChart printed in automated background task
We have a command line program that runs via a Scheduled Task to automatically generate reports on a schedule.
These reports are made by end users in a different program. They write their own SQL and make their own RTMs (which are both then stored in our database).
When the command line program runs, it dynamically creates a TppReport, TppDBPipeline, TDataSource, and T*Qry, hooks them all up and generates the report.
This is all working fine.
Now our users have expressed a desire to put a TDBChart on their reports. At first I thought no problem, just add ppChrtDB, ppChrt, ppCTDsgn, to the uses clause. This lets it load up a report without error, but the data never gets hooked to the chart. The data can be shown via normal TppDBText and whatnot, but never to the chart.
I tried giving a username to the dynamically created TppDBPipeline that matches exactly the Username of the pipeline that was used to make the report. For example if the TDBChart looked like below, I gave the dynamically created pipeline the name "plQry":
Here's a minimal sample of the scheduled task:
These reports are made by end users in a different program. They write their own SQL and make their own RTMs (which are both then stored in our database).
When the command line program runs, it dynamically creates a TppReport, TppDBPipeline, TDataSource, and T*Qry, hooks them all up and generates the report.
This is all working fine.
Now our users have expressed a desire to put a TDBChart on their reports. At first I thought no problem, just add ppChrtDB, ppChrt, ppCTDsgn, to the uses clause. This lets it load up a report without error, but the data never gets hooked to the chart. The data can be shown via normal TppDBText and whatnot, but never to the chart.
I tried giving a username to the dynamically created TppDBPipeline that matches exactly the Username of the pipeline that was used to make the report. For example if the TDBChart looked like below, I gave the dynamically created pipeline the name "plQry":
object ppDPTeeChart1: TppDPTeeChart DesignLayer = ppDesignLayer1 UserName = 'DPTeeChart1' Border.mmPadding = 0 mmHeight = 52917 mmLeft = 2381 mmTop = 1588 mmWidth = 182034 BandType = 0 LayerName = Foreground object ppDPTeeChartControl1: TppDPTeeChartControl Left = 0 Top = 0 Width = 400 Height = 250 BackWall.Color = clWhite Title.Text.Strings = ( 'Chart') BackColor = clWhite MaxPointsPerPage = 0 Page = 1 ScaleLastPage = True BevelOuter = bvNone BorderStyle = bsNone Color = clWhite DefaultCanvas = 'TTeeCanvas3D' ColorPaletteIndex = 13 object Series1: TBarSeries DataSource = plQry XLabelsSource = 'TYPE' XValues.Name = 'X' XValues.Order = loAscending XValues.ValueSource = 'TheNumber' YValues.Name = 'Bar' YValues.Order = loNone YValues.ValueSource = 'TheNumber' end end end end
Here's a minimal sample of the scheduled task:
FReportQry := TAdsQuery.Create(FConn); FReportQry.AdsConnection := FConn; FReportQry.SQL.Add(WorkingOnThisReport.SQL); FReportQry.Open; FDS := TDataSource.Create(FReportQry); FDS.DataSet := FReportQry; plQry := TppDBPipeline.Create(FDS); plQry.UserName := 'plQry'; plQry.DataSource := FDS; FReport := TppReport.Create(nil); try FReport.Template.SaveTo := stDatabase; FReport.Template.DatabaseSettings.DataPipeline := PLReports; FReport.Template.DatabaseSettings.NameField := 'ReportName'; FReport.Template.DatabaseSettings.TemplateField := 'Report'; FReport.Template.DatabaseSettings.Name := WorkingOnThisReport.ReportName; try FReport.Template.LoadFromDatabase; except on E: Exception do begin Logging.DoLog('Exception loading the RTM: ' + E.Message, Preferences.LoggingMechanism); end; end; FReport.DataPipeline := plQry; FReport.ShowPrintDialog := False; FReport.ShowAutoSearchDialog := False; FReport.ShowCancelDialog := False; FReport.TextFileName := WorkingOnThisReport.FullReportPathAndName; FReport.DeviceType := WorkingOnThisReport.DeviceType; FReport.Print; finally FReport.Free; end;
Comments
My guess is that the connection to the chart is being lost at some point (likely as the template is loaded but no pipeline is assigned). I suggest re-assigning the Series.Datasource property after assigning the Report.DataPipeline property and see if that resolves the problem.
You could also try tracing into the TppDPTeeChartControl.RefreshData; routine to see if the pipeline is correct. (ppChrtDP.pas)
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Is there a way I can iterate over the report components after it has been loaded from the template and detect when a chart exists?
Another thought would be to use RAP/Calc Tab to assign the Series.DataSource, but I can't find a way to access the Series in RAP.
Looking closer at your code, it appears you are assigning the owner of your dynamic objects incorrectly.
TAdsQuery.Create(FConn);
TDataSource.Create(FReportQry);
TppDBPipeline.Create(FDS);
TppReport.Create(nil);
The owner of these components would typically be the same object (a form or a data module). Start by changing this and see if it helps the issue.
If not, take a look at a report object loop to find report components.
https://rbwiki.digital-metaphors.com/delphi-code/layouts-delphi-code/report-object-loop/
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com