BdLm
asked on
Rave Reports : Print Table + 1 Recorde one Page
I have a TTable with 2 Strings , 2 XML Memo Fields and 2 Image Fields.
* new to create a report (with RAVE)
* one record one page
* must read and extract data from the XML, need a lot of code to to that
a)
found https://www.experts-exchange.com/questions/23374082/Delphi-Rave-Reports.html?sfQueryTermInfo=1+10+30+delphi+rave
but not sure : how to loop through the table
b) is RAVE a good choice ??
c) a I need to extract an calculate data from the XML , I feel I need a code based report
* new to create a report (with RAVE)
* one record one page
* must read and extract data from the XML, need a lot of code to to that
a)
found https://www.experts-exchange.com/questions/23374082/Delphi-Rave-Reports.html?sfQueryTermInfo=1+10+30+delphi+rave
but not sure : how to loop through the table
b) is RAVE a good choice ??
c) a I need to extract an calculate data from the XML , I feel I need a code based report
I on the other hand have never been a fun of Rave Reports, just wait until you want to create a multi-threaded application producing reports, You will get what I mean.
I prefer Quick Reports to Rave but thats just me
For the XML fields, you can just pre-calculate what you need and transform the data to a different dataset which you will actually use for the report
ASKER
would like to get here a code skelleton with the basic functions ... ideas to make a code based report like the demo page
paint--RAVE--REPORT.bmp
paint--RAVE--REPORT.bmp
Still no example data?!?
ASKER
yes, will accept a basic code sample as an answer - should be really a code based report
ASKER
@ developmentguru
can you do code based rave report for the borland sample database biolife.db // fishfacts project.
I complete do not understand how to work with dbbands ... from code based approach
can you do code based rave report for the borland sample database biolife.db // fishfacts project.
I complete do not understand how to work with dbbands ... from code based approach
ASKER
here come the skeleton i made for evaluation
unit Unit_LibraryReportTool;
{ *****************************************************************************
*
*
* DEMO DUMP the Content of the Borland biolife.db with RAVE reports
*
*****************************************************************************}
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, StdCtrls, DB, Grids,
DBGrids, DBTables, ComCtrls, ExtCtrls,
// RAVE
RpRave, RpDefine, RpCon, RpConDS,
RpBase, RpSystem, RpConBDE ;
type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
File1: TMenuItem;
Exit1: TMenuItem;
ReportTable: TTable;
DBGrid1: TDBGrid;
DataSource1: TDataSource;
LoadLibararyDB1: TMenuItem;
MainStatusBar: TStatusBar;
Report1: TMenuItem;
StartReport1: TMenuItem;
Panel1: TPanel;
Label1: TLabel;
ListBox1: TListBox;
RvTableConnection1: TRvTableConnection;
LibRvSystem: TRvSystem;
procedure Exit1Click(Sender: TObject);
procedure LoadLibararyDB1Click(Sender: TObject);
procedure StartReport1Click(Sender: TObject);
procedure LibRvSystemPrint(Sender: TObject);
private
{ Private-Deklarationen }
FLibraryFilename : String; /// the name of the table for report
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Exit1Click(Sender: TObject);
begin
close;
end;
procedure TForm1.LoadLibararyDB1Click(Sender: TObject);
begin
FLibraryFilename := 'e:\biolife.db';
ReportTable.Active := false;
ReportTable.TableName := FLibraryFilename;
ReportTable.Active := true;
end;
///
///
///
procedure TForm1.LibRvSystemPrint(Sender: TObject);
begin
with Sender as TBaseReport do
begin
SetFont('ARIAL',15);
GoToXY(1,1);
Print ('Welcome to the rave demo report project !!');
end;
end;
procedure TForm1.StartReport1Click(Sender: TObject);
begin
////
MainStatusBar.SimpleText := 'Start Simple Database Documentation';
LibRvSystem.Execute;
MainStatusBar.SimpleText := 'Documentation -> done ! ';
end;
end.
My point in all of what I have written so far is that you do NOT need to do a completely code based report! You can do some relatively simple Delphi code to prepare for a non-code based report.
1) Start by doing normal database programming in a loop going through your records...
While not MyDataset.EOF do
...
end;
For each record (...) you will do the extraction of the data needed by your report from the
XML in the individual dataset fields. There are an absolute TON of examples of extracting
data from XML, so I will not reproduce them now. If you want me to, I will add some XML
links. (This is the part where SEEING some of your XML data as an example would actually
allow an expert to show you how to do it).
Place the extracted data into an in memory dataset, or temporary dataset for use by RAVE.
2) Now that you have the data in the format that is easy for Rave to use, go into Rave and use the report wizard to get your report started.
1) Start by doing normal database programming in a loop going through your records...
While not MyDataset.EOF do
...
end;
For each record (...) you will do the extraction of the data needed by your report from the
XML in the individual dataset fields. There are an absolute TON of examples of extracting
data from XML, so I will not reproduce them now. If you want me to, I will add some XML
links. (This is the part where SEEING some of your XML data as an example would actually
allow an expert to show you how to do it).
Place the extracted data into an in memory dataset, or temporary dataset for use by RAVE.
2) Now that you have the data in the format that is easy for Rave to use, go into Rave and use the report wizard to get your report started.
One more time, in case you missed it, you are going about this the hard way! Doing a code based report is FAR more work than what I am suggesting.
ASKER
Ok, can you create a *.rav report file for 1 record one page and a style like the layout a proposed ?
I am going to have to create a custom database because the one you suggested has no "XML within fields" like you are looking for. I will do this first and give you some instructions on how to recreate it on your end, so we have some basis to work from. I will let you know...
What version of Delphi are you using? I have access to Delphi 2010 and Delphi XE.
ASKER
I can work with Delphi 2010 - no problem.
* meanwhile here at EE I could make the draft version - rave code based -
what I don't like here - it is the same ugly code as writing driectly to the printer -
no Objects- no classes - no structure
really interessted to see the difference
* meanwhile here at EE I could make the draft version - rave code based -
what I don't like here - it is the same ugly code as writing driectly to the printer -
no Objects- no classes - no structure
really interessted to see the difference
unit Unit_LibraryReportTool;
{ *****************************************************************************
*
*
* DEMO DUMP the Content of the Borland biolife.db with RAVE reports
*
*
* http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_26887858.html?cid=239#a35148858
* http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_26854889.html
* http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_26887858.html
*
*****************************************************************************}
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, StdCtrls, DB, Grids,
DBGrids, DBTables, ComCtrls, ExtCtrls,
// RAVE
RpRave, RpDefine, RpCon, RpConDS,
RPMEMO, RPDBUTIL,
RpBase, RpSystem, RpConBDE, DBCtrls ;
type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
File1: TMenuItem;
Exit1: TMenuItem;
ReportTable: TTable;
DataSource1: TDataSource;
LoadLibararyDB1: TMenuItem;
MainStatusBar: TStatusBar;
Report1: TMenuItem;
StartReport1: TMenuItem;
Panel1: TPanel;
Label1: TLabel;
ListBox1: TListBox;
RvTableConnection1: TRvTableConnection;
LibRvSystem: TRvSystem;
RvProject1: TRvProject;
ableReport1: TMenuItem;
PageControl1: TPageControl;
TabSheet1: TTabSheet;
TabSheet2: TTabSheet;
DBGrid1: TDBGrid;
DBImage1: TDBImage;
DBMemo1: TDBMemo;
ReportTableSpeciesNo: TFloatField;
ReportTableCategory: TStringField;
ReportTableCommon_Name: TStringField;
ReportTableSpeciesName: TStringField;
ReportTableLengthcm: TFloatField;
ReportTableLength_In: TFloatField;
ReportTableNotes: TMemoField;
ReportTableGraphic: TGraphicField;
procedure Exit1Click(Sender: TObject);
procedure LoadLibararyDB1Click(Sender: TObject);
procedure StartReport1Click(Sender: TObject);
procedure LibRvSystemPrint(Sender: TObject);
procedure LibRvSystemAfterPreviewPrint(Sender: TObject);
private
{ Private-Deklarationen }
FLibraryFilename : String; /// the name of the table for report
///
///
procedure RavePrintDBmemo ( PrintStart, PrintEnd : Real; YPos : Real ; AReport : TBasereport ) ;
procedure RavePrintDBmemo2 ( PrintStart, PrintEnd : Real; YPos : Real ; AReport : TBasereport ) ;
procedure RavePrintDBBitmap(XPOS, YPos, Xsize, YSize: Real; AReport: TBasereport);
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Exit1Click(Sender: TObject);
begin
close;
end;
procedure TForm1.LoadLibararyDB1Click(Sender: TObject);
begin
FLibraryFilename := 'e:\biolife.db';
ReportTable.Active := false;
ReportTable.TableName := FLibraryFilename;
ReportTable.Active := true;
end;
procedure TForm1.LibRvSystemAfterPreviewPrint(Sender: TObject);
begin
end;
///
///
///
procedure TForm1.LibRvSystemPrint(Sender: TObject);
const tab1=0.2;
tab2=1.7;
tab3=3.2;
tab4=4.0;
tab5=5.0;
var i : Integer;
dbstring : String;
begin
LibRvSystem.SystemPrinter.Orientation := poLandScape; // or poPortrait
with Sender as TBaseReport do
begin
SetFont('ARIAL',15);
Print ('Welcome to the rave demo report project (printing biolife.db) !!');
GoToXY(1,1);
NewLine;
NewLine;
ClearTabs;
SetTab(tab1,pjLeft,tab2, 0,0,0);
SetTab(tab2,pjLeft,tab3, 0,0,0);
SetTab(tab3,pjLeft,tab4, 0,0,0);
SetTab(tab4,pjLeft,tab5, 0,0,0);
Bold := true;
SetFont('ARIAL',10);
PrintTab('Species No');
PrintTab('Category');
PrintTab('Common_Name');
PrintTab('species Name ');
FinishTabBox(1);
Newline;
Bold := false;
for i:= 1 to ReportTable.RecordCount do
begin
// canvas.brush.color := clred;
// rectangle (0.1, 0.1, 6, 0.2);
newline;
dbstring := ReportTable.FieldByName('Species No').asstring;
PrintTab(dbstring);
dbstring := ReportTable.FieldByName('Category').asstring;
PrintTab(dbstring);
dbstring := ReportTable.FieldByName('Common_Name').asstring;
PrintTab(dbstring);
dbstring := ReportTable.FieldByName('Species Name').asstring;
PrintTab(dbstring);
// FinishTabBox(1);
NewLine;
RavePrintDBmemo(3,5, 1, (sender as Tbasereport) );
RavePrintDBBitmap(1,1,2,2, (sender as Tbasereport) );
// RavePrintDBmemo2(3,5, 1, (sender as Tbasereport) );
ReportTable.Next;
/// 1 record on 1 page
NewPage;
end;
end;
end;
procedure TForm1.RavePrintDBBitmap ( XPOS, YPos , Xsize, YSize : Real ; AReport : TBasereport );
var Bitmap : TBitmap;
TableGraphicField : TGraphicField;
begin
// TableGraphicField := ;
Bitmap := TBitmap.Create;
try
GraphicFieldToBitmap( ReportTableGraphic , Bitmap);
AReport.PrintBitmapRect(XPos,YPos,XPos + Xsize, YPos + YSize,Bitmap);
finally
Bitmap.Free;
end;
end;
procedure TForm1.RavePrintDBmemo ( PrintStart, PrintEnd : Real; YPos : Real ; AReport : TBasereport ) ;
var MemBuf : TDBMemoBuf;
dbstring : String;
i : Integer;
isEOL : Boolean;
begin
MemBuf := TDBMemoBuf.Create;
with ReportTable do
begin
YPos := YPos + 0.5;
AReport.GoToXY(PrintStart,YPos);
MemBuf.PrintStart := PrintStart;
MemBuf.PrintEnd := PrintEnd ;
MemBuf.text := Reporttable.FieldByName('Notes').AsString;
MemBuf.NoCRLF := False;
for I := 1 to 5 do
begin
dbstring := AReport.GetMemoLine(MemBuf, isEOL);
if dbstring <> '' then
begin
YPos := YPos + 0.15;
AReport.GoToXY(PrintEnd,YPos);
AReport.PrintLn(dbstring); // PrintTab
end;
end;
YPos := YPos + 0.2;
MemBuf.Free;
end;
end;
procedure TForm1.RavePrintDBmemo2 ( PrintStart, PrintEnd : Real; YPos : Real ; AReport : TBasereport ) ;
var Memobuf : TDBMemobuf;
Lines : Integer;
begin
With AReport do begin
try
Memobuf := TDBMemobuf.Create;
Memobuf.PrintStart := TabStart(3);
Memobuf.PrintEnd := TabEnd(3);
MemoBuf.text := Reporttable.FieldByName('Notes').AsString;; // Table1Notes is the name of the field "Notes" in the TTable
Lines := MemoLines(Memobuf);
If Lines < 8 then
begin
Lines := 8;
end;
PrintMemo(Memobuf,Lines,true);
finally
Memobuf.Free;
end;
end;
end;
procedure TForm1.StartReport1Click(Sender: TObject);
begin
////
MainStatusBar.SimpleText := 'Start Simple Database Documentation';
LibRvSystem.Execute;
MainStatusBar.SimpleText := 'Documentation -> done ! ';
end;
end.
I almost have the data example set up. I have two records that have the following fields:
<FIELD attrname="ID" fieldtype="i4" />
<FIELD attrname="Name" fieldtype="string" WIDTH="100" />
<FIELD attrname="Source" fieldtype="string" WIDTH="250" />
<FIELD attrname="NutritionFacts" fieldtype="bin.hex" SUBTYPE="Text" />
<FIELD attrname="Ingredients" fieldtype="bin.hex" SUBTYPE="Text" />
<FIELD attrname="Preparation" fieldtype="bin.hex" SUBTYPE="Text" />
<FIELD attrname="SmallImage" fieldtype="bin.hex" SUBTYPE="Graphics" />
<FIELD attrname="LargeImage" fieldtype="bin.hex" SUBTYPE="Graphics" />
I set them up in a TClientDataset and I have a small example program that allows me to load and save the data as XML. I had to come up with SOME FORM of example data that loosely matched your criteria since I had none to work with. This is a database of recipes where each record has a recipe name, a source field (used for URL), Nutrition Facts (XML), Ingredients (XML), Preparation (could be text or XML) and two image fields that I left unused to keep the transmission small.
My goal will be to show a simple way to create a report in RAVE using this data. One record per page, including data extracted from the XML field NutritionFacts.
Here is the DFM portion that sets up the CDS:
object cdsRecipes: TClientDataSet
Active = True
Aggregates = <>
Params = <>
Left = 432
Top = 8
Data = {
250100009619E0BD0100000018 0000000800 0000000003 0000002501 02494404
00010000000000044E616D6501 0049000000 0100055749 4454480200 02006400
06536F75726365010049000000 0100055749 4454480200 0200FA000E 4E757472
6974696F6E466163747304004B 0000000100 0753554254 5950450200 49000500
54657874000B496E6772656469 656E747304 004B000000 0100075355 42545950
4502004900050054657874000B 5072657061 726174696F 6E04004B00 00000100
07535542545950450200490005 0054657874 000A536D61 6C6C496D61 67650400
4B000000010007535542545950 4502004900 0900477261 7068696373 000A4C61
726765496D61676504004B0000 0001000753 5542545950 4502004900 09004772
617068696373000000}
object cdsRecipesID: TIntegerField
AutoGenerateValue = arAutoInc
FieldName = 'ID'
end
object cdsRecipesName: TStringField
FieldName = 'Name'
Size = 100
end
object cdsRecipesSource: TStringField
FieldName = 'Source'
Size = 250
end
object cdsRecipesNutritionFacts: TMemoField
FieldName = 'NutritionFacts'
BlobType = ftMemo
end
object cdsRecipesIngredients: TMemoField
FieldName = 'Ingredients'
BlobType = ftMemo
end
object cdsRecipesPreparation: TMemoField
FieldName = 'Preparation'
BlobType = ftMemo
end
object cdsRecipesSmallImage: TGraphicField
FieldName = 'SmallImage'
BlobType = ftGraphic
end
object cdsRecipesLargeImage: TGraphicField
FieldName = 'LargeImage'
BlobType = ftGraphic
end
end
<FIELD attrname="ID" fieldtype="i4" />
<FIELD attrname="Name" fieldtype="string" WIDTH="100" />
<FIELD attrname="Source" fieldtype="string" WIDTH="250" />
<FIELD attrname="NutritionFacts" fieldtype="bin.hex" SUBTYPE="Text" />
<FIELD attrname="Ingredients" fieldtype="bin.hex" SUBTYPE="Text" />
<FIELD attrname="Preparation" fieldtype="bin.hex" SUBTYPE="Text" />
<FIELD attrname="SmallImage" fieldtype="bin.hex" SUBTYPE="Graphics" />
<FIELD attrname="LargeImage" fieldtype="bin.hex" SUBTYPE="Graphics" />
I set them up in a TClientDataset and I have a small example program that allows me to load and save the data as XML. I had to come up with SOME FORM of example data that loosely matched your criteria since I had none to work with. This is a database of recipes where each record has a recipe name, a source field (used for URL), Nutrition Facts (XML), Ingredients (XML), Preparation (could be text or XML) and two image fields that I left unused to keep the transmission small.
My goal will be to show a simple way to create a report in RAVE using this data. One record per page, including data extracted from the XML field NutritionFacts.
Here is the DFM portion that sets up the CDS:
object cdsRecipes: TClientDataSet
Active = True
Aggregates = <>
Params = <>
Left = 432
Top = 8
Data = {
250100009619E0BD0100000018
00010000000000044E616D6501
06536F75726365010049000000
6974696F6E466163747304004B
54657874000B496E6772656469
4502004900050054657874000B
07535542545950450200490005
4B000000010007535542545950
726765496D61676504004B0000
617068696373000000}
object cdsRecipesID: TIntegerField
AutoGenerateValue = arAutoInc
FieldName = 'ID'
end
object cdsRecipesName: TStringField
FieldName = 'Name'
Size = 100
end
object cdsRecipesSource: TStringField
FieldName = 'Source'
Size = 250
end
object cdsRecipesNutritionFacts: TMemoField
FieldName = 'NutritionFacts'
BlobType = ftMemo
end
object cdsRecipesIngredients: TMemoField
FieldName = 'Ingredients'
BlobType = ftMemo
end
object cdsRecipesPreparation: TMemoField
FieldName = 'Preparation'
BlobType = ftMemo
end
object cdsRecipesSmallImage: TGraphicField
FieldName = 'SmallImage'
BlobType = ftGraphic
end
object cdsRecipesLargeImage: TGraphicField
FieldName = 'LargeImage'
BlobType = ftGraphic
end
end
Here is the XML that I persist to disk. This can be loaded and assigned to the cds.XMLData property to load the data in.
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
- <DATAPACKET Version="2.0">
- <METADATA>
- <FIELDS>
<FIELD attrname="ID" fieldtype="i4" />
<FIELD attrname="Name" fieldtype="string" WIDTH="100" />
<FIELD attrname="Source" fieldtype="string" WIDTH="250" />
<FIELD attrname="NutritionFacts" fieldtype="bin.hex" SUBTYPE="Text" />
<FIELD attrname="Ingredients" fieldtype="bin.hex" SUBTYPE="Text" />
<FIELD attrname="Preparation" fieldtype="bin.hex" SUBTYPE="Text" />
<FIELD attrname="SmallImage" fieldtype="bin.hex" SUBTYPE="Graphics" />
<FIELD attrname="LargeImage" fieldtype="bin.hex" SUBTYPE="Graphics" />
</FIELDS>
<PARAMS CHANGE_LOG="1 0 4 2 0 4" />
</METADATA>
- <ROWDATA>
<ROW RowState="4" ID="1" Name="Whole Grain Oatmeal" Source="http://www.bobsredmill.com/gluten-free-rolled-oats.html" NutritionFacts="<NutritionFacts> <ServingSize> 1/2 cup dry </ServingSize> <Calories> 190 </Calories> <Cholesterol> 0 mg </Cholesterol> <Sodium> 0 mg </Sodium> <Carbohydrate> 32 g <DietaryFiber> 5 g </DietaryFiber> <Sugars> 1 g </Sugars> </Carbohydrate> <Protein> 7 g </Protein> <VitaminA> 0% </VitaminA> <VitaminC> 0% </VitaminC> <Calcium> 2% </Calcium> <Iron> 15% </Iron> </NutritionFacts>" Ingredients="<Ingredients> <Ingredient> 1/2 cup whole grain oats </Ingredient> <Ingredient> 1 cup water </Ingredient> </Ingredients>" Preparation="<Preparation> </Preparatrion>" />
<ROW RowState="4" ID="2" Name="Long Grain Brown Rice" Source="http://www.bobsredmill.com/basmati-brown-rice.html" NutritionFacts="<NutritionFacts> <ServingSize> 1/4 cup </ServingSize> <Calories> 170 </Calories> <Cholesterol> 0 mg </Cholesterol> <Sodium> 0 mg </Sodium> <Carbohydrate> 38 g <DietaryFiber> 2 g </DietaryFiber> <Sugars> 0 g </Sugars> </Carbohydrate> <Protein> 4 g </Protein> <VitaminA> 0% </VitaminA> <VitaminC> 0% </VitaminC> <Calcium> 0% </Calcium> <Iron> 2% </Iron> </NutritionFacts>" Ingredients="<Ingredients> <Ingredient> 1/4 cup whole grain oats </Ingredient> <Ingredient> 5/8 cup water </Ingredient> </Ingredients>" Preparation="<Preparation> </Preparatrion>" />
</ROWDATA>
</DATAPACKET>
The first step was to generate the data that would be used. Trying to keep it simple I created this XML file. It is not optimized XML, nor is it complete data. It is just for an example here. I changed it slightly to make the example easier.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <DATAPACKET Version="2.0"><METADATA><FIELDS><FIELD attrname="ID" fieldtype="i4"/><FIELD attrname="Name" fieldtype="string" WIDTH="100"/><FIELD attrname="Source" fieldtype="string" WIDTH="250"/><FIELD attrname="NutritionFacts" fieldtype="bin.hex" SUBTYPE="Text"/><FIELD attrname="Ingredients" fieldtype="bin.hex" SUBTYPE="Text"/><FIELD attrname="Preparation" fieldtype="bin.hex" SUBTYPE="Text"/><FIELD attrname="SmallImage" fieldtype="bin.hex" SUBTYPE="Graphics"/><FIELD attrname="LargeImage" fieldtype="bin.hex" SUBTYPE="Graphics"/></FIELDS><PARAMS CHANGE_LOG="1 0 4 2 1 8 3 0 4"/></METADATA><ROWDATA><ROW RowState="5" ID="1" Name="Whole Grain Oatmeal" Source="http://www.bobsredmill.com/gluten-free-rolled-oats.html
http://www.bobsredmill.com/gluten-free-rolled-oats.html
http://www.bobsredmill.com/gluten-free-rolled-oats.html
"/><ROW RowState="12" ID="1" Name="Whole Grain Oatmeal" Source="http://www.bobsredmill.com/gluten-free-rolled-oats.html

" NutritionFacts="<NutritionFacts>
 <ServingSize>
 1/2 cup dry
 </ServingSize>
 <Calories>
 190
 </Calories>
 <Cholesterol>
 0 mg
 </Cholesterol>
 <Sodium>
 0 mg
 </Sodium>
 <Carbohydrate>
 32 g
 </Carbohydrate>
 <DietaryFiber>
 5 g
 </DietaryFiber>
 <Sugars>
 1 g
 </Sugars>
 <Protein>
 7 g
 </Protein>
 <VitaminA>
 0%
 </VitaminA>
 <VitaminC>
 0%
 </VitaminC>
 <Calcium>
 2%
 </Calcium>
 <Iron>
 15%
 </Iron>
</NutritionFacts>" Ingredients="<Ingredients>
 <Ingredient>
 1/2 cup whole grain oats
 </Ingredient>
 <Ingredient>
 1 cup water
 </Ingredient>
</Ingredients>" Preparation="<Preparation>
</Preparatrion>"/><ROW RowState="4" ID="2" Name="Long Grain Brown Rice" Source="http://www.bobsredmill.com/basmati-brown-rice.html" NutritionFacts="<NutritionFacts>
 <ServingSize>
 1/4 cup
 </ServingSize>
 <Calories>
 170
 </Calories>
 <Cholesterol>
 0 mg
 </Cholesterol>
 <Sodium>
 0 mg
 </Sodium>
 <Carbohydrate>
 38 g
 </Carbohydrate>
 <DietaryFiber>
 2 g
 </DietaryFiber>
 <Sugars>
 0 g
 </Sugars>
 <Protein>
 4 g
 </Protein>
 <VitaminA>
 0%
 </VitaminA>
 <VitaminC>
 0%
 </VitaminC>
 <Calcium>
 0%
 </Calcium>
 <Iron>
 2%
 </Iron>
</NutritionFacts>" Ingredients="<Ingredients>
 <Ingredient>
 1/4 cup whole grain oats
 </Ingredient>
 <Ingredient>
 5/8 cup water
 </Ingredient>
</Ingredients>" Preparation="<Preparation>
</Preparatrion>"/></ROWDATA></DATAPACKET>
Save the data as Recipes.XML in the directory you intend to run the program from (again for simplicity). Here is the DFM and PAS for the program as it stands now. If you need help with this portion, let me know.
---DFM---
object fInputMain: TfInputMain
Left = 0
Top = 0
Caption = 'Recipes'
ClientHeight = 529
ClientWidth = 612
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
Menu = MainMenu1
OldCreateOrder = False
OnCreate = FormCreate
OnDestroy = FormDestroy
PixelsPerInch = 96
TextHeight = 13
object Splitter1: TSplitter
Left = 0
Top = 120
Width = 612
Height = 3
Cursor = crVSplit
Align = alTop
ExplicitWidth = 344
end
object Splitter2: TSplitter
Left = 0
Top = 241
Width = 612
Height = 3
Cursor = crVSplit
Align = alTop
ExplicitTop = 128
ExplicitWidth = 900
end
object Splitter3: TSplitter
Left = 0
Top = 379
Width = 612
Height = 3
Cursor = crVSplit
Align = alTop
ExplicitTop = 249
end
object DBGrid1: TDBGrid
Left = 0
Top = 0
Width = 612
Height = 120
Align = alTop
DataSource = dsRecipes
TabOrder = 0
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'Tahoma'
TitleFont.Style = []
Columns = <
item
Expanded = False
FieldName = 'ID'
Visible = True
end
item
Expanded = False
FieldName = 'Name'
Title.Caption = 'Recipe Name'
Width = 200
Visible = True
end
item
Expanded = False
FieldName = 'Source'
Width = 200
Visible = True
end
item
Expanded = False
FieldName = 'NutritionFacts'
Visible = False
end
item
Expanded = False
FieldName = 'Ingredients'
Visible = False
end
item
Expanded = False
FieldName = 'SmallImage'
Visible = False
end
item
Expanded = False
FieldName = 'LargeImage'
Visible = False
end>
end
object Panel1: TPanel
Left = 0
Top = 123
Width = 612
Height = 118
Align = alTop
TabOrder = 1
object Label2: TLabel
Left = 1
Top = 1
Width = 610
Height = 13
Align = alTop
AutoSize = False
Caption = 'Nutrition Facts'
ExplicitTop = 5
ExplicitWidth = 70
end
object DBMemo1: TDBMemo
Left = 1
Top = 14
Width = 610
Height = 103
Align = alClient
DataField = 'NutritionFacts'
DataSource = dsRecipes
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Courier'
Font.Style = []
ParentFont = False
TabOrder = 0
ExplicitLeft = 0
ExplicitTop = 13
end
end
object Panel2: TPanel
Left = 0
Top = 244
Width = 612
Height = 135
Align = alTop
TabOrder = 2
object Label1: TLabel
Left = 1
Top = 1
Width = 610
Height = 13
Align = alTop
AutoSize = False
Caption = 'Ingredients XML'
ExplicitTop = 5
ExplicitWidth = 77
end
object DBMemo2: TDBMemo
Left = 1
Top = 14
Width = 610
Height = 120
Align = alClient
DataField = 'Ingredients'
DataSource = dsRecipes
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Courier'
Font.Style = []
ParentFont = False
TabOrder = 0
end
end
object Panel3: TPanel
Left = 0
Top = 382
Width = 612
Height = 147
Align = alClient
TabOrder = 3
object Label3: TLabel
Left = 1
Top = 1
Width = 610
Height = 13
Align = alTop
AutoSize = False
Caption = 'Preparation'
ExplicitLeft = 0
ExplicitTop = -5
end
object DBMemo3: TDBMemo
Left = 1
Top = 14
Width = 610
Height = 132
Align = alClient
DataField = 'Preparation'
DataSource = dsRecipes
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Courier'
Font.Style = []
ParentFont = False
TabOrder = 0
end
end
object dsRecipes: TDataSource
DataSet = cdsRecipes
Left = 496
Top = 8
end
object cdsRecipes: TClientDataSet
Active = True
Aggregates = <>
Params = <>
Left = 432
Top = 8
Data = {
250100009619E0BD010000001800000008000000000003000000250102494404
00010000000000044E616D650100490000000100055749445448020002006400
06536F75726365010049000000010005574944544802000200FA000E4E757472
6974696F6E466163747304004B00000001000753554254595045020049000500
54657874000B496E6772656469656E747304004B000000010007535542545950
4502004900050054657874000B5072657061726174696F6E04004B0000000100
075355425459504502004900050054657874000A536D616C6C496D6167650400
4B000000010007535542545950450200490009004772617068696373000A4C61
726765496D61676504004B000000010007535542545950450200490009004772
617068696373000000}
object cdsRecipesID: TIntegerField
AutoGenerateValue = arAutoInc
FieldName = 'ID'
end
object cdsRecipesName: TStringField
FieldName = 'Name'
Size = 100
end
object cdsRecipesSource: TStringField
FieldName = 'Source'
Size = 250
end
object cdsRecipesNutritionFacts: TMemoField
FieldName = 'NutritionFacts'
BlobType = ftMemo
end
object cdsRecipesIngredients: TMemoField
FieldName = 'Ingredients'
BlobType = ftMemo
end
object cdsRecipesPreparation: TMemoField
FieldName = 'Preparation'
BlobType = ftMemo
end
object cdsRecipesSmallImage: TGraphicField
FieldName = 'SmallImage'
BlobType = ftGraphic
end
object cdsRecipesLargeImage: TGraphicField
FieldName = 'LargeImage'
BlobType = ftGraphic
end
end
object MainMenu1: TMainMenu
Left = 552
Top = 8
object File1: TMenuItem
Caption = '&File'
object Save1: TMenuItem
Caption = '&Save'
OnClick = Save1Click
end
object Print1: TMenuItem
Caption = '&Print...'
OnClick = Print1Click
end
object Exit1: TMenuItem
Caption = 'E&xit'
OnClick = Exit1Click
end
end
object Edit1: TMenuItem
Caption = '&Edit'
object NewRecipe1: TMenuItem
Caption = '&New Recipe'
ShortCut = 45
OnClick = NewRecipe1Click
end
object DeleteRecipe1: TMenuItem
Caption = 'Delete Recipe'
ShortCut = 46
OnClick = DeleteRecipe1Click
end
end
end
object XMLDocument1: TXMLDocument
Options = [doAttrNull, doAutoPrefix, doNamespaceDecl]
Left = 432
Top = 64
DOMVendorDesc = 'MSXML'
end
object RaveDSConn: TRvDataSetConnection
RuntimeVisibility = rtDeveloper
Left = 432
Top = 144
end
end
--PAS---
unit frmInputMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, DBClient, Grids, DBGrids, StdCtrls, DBCtrls, ExtCtrls, Menus,
xmldom, XMLIntf, msxmldom, XMLDoc, RpDefine, RpCon, RpConDS;
type
TfInputMain = class(TForm)
DBGrid1: TDBGrid;
dsRecipes: TDataSource;
Splitter1: TSplitter;
Panel1: TPanel;
DBMemo1: TDBMemo;
Label2: TLabel;
Splitter2: TSplitter;
Panel2: TPanel;
DBMemo2: TDBMemo;
Label1: TLabel;
cdsRecipes: TClientDataSet;
cdsRecipesID: TIntegerField;
cdsRecipesName: TStringField;
cdsRecipesSource: TStringField;
cdsRecipesNutritionFacts: TMemoField;
cdsRecipesIngredients: TMemoField;
cdsRecipesPreparation: TMemoField;
cdsRecipesSmallImage: TGraphicField;
cdsRecipesLargeImage: TGraphicField;
Panel3: TPanel;
Label3: TLabel;
DBMemo3: TDBMemo;
MainMenu1: TMainMenu;
File1: TMenuItem;
Save1: TMenuItem;
Print1: TMenuItem;
Exit1: TMenuItem;
Edit1: TMenuItem;
NewRecipe1: TMenuItem;
DeleteRecipe1: TMenuItem;
Splitter3: TSplitter;
XMLDocument1: TXMLDocument;
RaveDSConn: TRvDataSetConnection;
procedure Exit1Click(Sender: TObject);
procedure Save1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure NewRecipe1Click(Sender: TObject);
procedure DeleteRecipe1Click(Sender: TObject);
procedure Print1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
fDirectory : string;
fFileName : string;
function StripWhiteSpace(Value : string) : string;
public
cdsReport : TClientDataset;
end;
var
fInputMain: TfInputMain;
implementation
{$R *.dfm}
procedure TfInputMain.DeleteRecipe1Click(Sender: TObject);
begin
if cdsRecipes.State <> dsBrowse then
cdsRecipes.Post;
if MessageDlg('Are you sure you want to delete this recipe?', mtConfirmation,
[mbOK, mbCancel], 0) = mrOK then
cdsRecipes.Delete;
end;
procedure TfInputMain.Exit1Click(Sender: TObject);
begin
Close;
end;
procedure TfInputMain.FormCreate(Sender: TObject);
var
S : string;
SL : TStringList;
begin
fDirectory := ExtractFilePath(ParamStr(0));
fFileName := fDirectory + '\Recipes.XML';
if FileExists(fFileName) then
begin
SL := TStringList.Create;
try
SL.LoadFromFile(fFileName);
S := SL.Text;
cdsRecipes.XMLData := S;
finally
SL.Free;
end;
end;
end;
procedure TfInputMain.FormDestroy(Sender: TObject);
begin
FreeAndNil(cdsReport);
end;
procedure TfInputMain.NewRecipe1Click(Sender: TObject);
begin
cdsRecipes.Append;
end;
procedure TfInputMain.Print1Click(Sender: TObject);
var
Bookmark1 : integer;
X, Calories, Protein, Carbs : string;
Doc : IXMLNode;
begin
{code based portion of the report}
if cdsRecipes.State <> dsBrowse then
cdsRecipes.Post;
Bookmark1 := cdsRecipesID.AsInteger; {prepare to move back to this record}
{Disable visual control updates for controls attached to this CDS.}
cdsRecipes.DisableControls;
{This will do nothing if cdsReport is nil. Destroying it here, and when the
form is destroyed will allow the Rave report designer to work with it
freely when the program is running (an aid to easily designing the report)}
FreeAndNil(cdsReport);
{create the client dataset to be passed to the report}
cdsReport := TClientDataset.Create(nil);
try
cdsReport.FieldDefs.Add('RecipeName', ftString, 100);
cdsReport.FieldDefs.Add('Source', ftString, 250);
cdsReport.FieldDefs.Add('Calories', ftString, 10);
cdsReport.FieldDefs.Add('Protein', ftString, 10);
cdsReport.FieldDefs.Add('Carbs', ftString, 10);
cdsReport.CreateDataSet;
{roll through the records extracting data to cdsReport}
cdsRecipes.First;
while not cdsRecipes.Eof do
begin
cdsReport.Append;
cdsReport.FieldByName('RecipeName').AsString := cdsRecipesName.AsString;
cdsReport.FieldByName('Source').AsString := cdsRecipesSource.AsString;
{Here is where the XML extraction is done...}
X := cdsRecipesNutritionFacts.AsString;
XMLDocument1.LoadFromXML(X);
Doc := XMLDocument1.DocumentElement;
Calories := StripWhiteSpace(Doc.ChildValues['Calories']);
Protein := StripWhiteSpace(Doc.ChildValues['Protein']);
Carbs := StripWhiteSpace(Doc.ChildValues['Carbohydrate']);
XMLDocument1.Active := false;
cdsReport.FieldByName('Calories').AsString := Calories;
cdsReport.FieldByName('Protein').AsString := Protein;
cdsReport.FieldByName('Carbs').AsString := Carbs;
cdsReport.Post;
cdsRecipes.Next;
end;
{at this point we have the report ready data}
RaveDSConn.DataSet := cdsReport;
finally
{go back to the bookmarked record}
cdsRecipes.Locate('ID', VarArrayOf([Bookmark1]), []);
{re-enable the visual controls attached to the CDS}
cdsRecipes.EnableControls;
end;
end;
procedure TfInputMain.Save1Click(Sender: TObject);
var
S : string;
SL : TStringList;
begin
if cdsRecipes.State <> dsBrowse then
cdsRecipes.Post;
S := cdsRecipes.XMLData;
SL := TStringList.Create;
try
SL.Text := S;
SL.SaveToFile(fFileName);
finally
SL.Free;
end;
end;
function TfInputMain.StripWhiteSpace(Value: string): string;
var
First, C, Last : PWideChar;
R : string;
begin
First := @Value[1];
while (First <> #0) and CharInSet(First^, [' ', #9, #10, #13]) do
First := StrNextChar(First);
C := StrNextChar(First);
while C^ <> #0 do
begin
if not CharInSet(C^, [' ', #9, #10, #13]) then
Last := C;
C := StrNextChar(C);
end;
C := First;
R := '';
while C <> Last do
begin
R := R + C^;
C := StrNextChar(C);
end;
R := R + Last^;
Result := R;
end;
end.
ASKER
@ devguru : thanks for your efforts, I'll continue with your stuff the following week,
@ other readers : the code based report is ready in a draft version , here are the links on EE
*
* https://www.experts-exchange.com/questions/26887858/rave-reports-print-memo-field.html?cid=239&anchorAnswerId=35148858#a35148858
* https://www.experts-exchange.com/questions/26854889/Rave-Reports-Print-Table-1-Recorde-one-Page.html
* https://www.experts-exchange.com/questions/26887858/rave-reports-print-memo-field.html
* https://www.experts-exchange.com/questions/26897777/Rave-report-render-to-pdf.html
*
@ other readers : the code based report is ready in a draft version , here are the links on EE
*
* https://www.experts-exchange.com/questions/26887858/rave-reports-print-memo-field.html?cid=239&anchorAnswerId=35148858#a35148858
* https://www.experts-exchange.com/questions/26854889/Rave-Reports-Print-Table-1-Recorde-one-Page.html
* https://www.experts-exchange.com/questions/26887858/rave-reports-print-memo-field.html
* https://www.experts-exchange.com/questions/26897777/Rave-report-render-to-pdf.html
*
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Once the report is done you would save it where you need to in order to incorporate it into your program. From this point you would just place the non-visual controls as usual and add the code to the File | Print to actually call it up.
ASKER
I received a further request to my report.
On the right side bitmap , i have to mark several postions by a circle or a cross symbol.
In the XML DB memo field is the information - how many points should be marked , where to draw the marks ....
Can I extent your code in principle to that functionality ?
In Rave the functionality of selecting a bitmap based on a data field value is quite simple using scripting. The scripting is in a pascal script, so it is quite easy for someone used to Delphi. Since my code shows how to extract any fields from the XML into a flat style dataset for use in the Rave report, the new requests should pose no problems.
I would need to see some graphical representation of the desired output in order to have any more comment...
I would need to see some graphical representation of the desired output in order to have any more comment...
ASKER
@ devguru : thanks for your help and code
1) Read the data in as usual and parse each record to extract the XML you need. I do not know how many fields / totals / etc you may need from this, more info would help. I would have a TClientDataset or a temp table set up to handle the data as you generate it. This will allow you to provide Rave with fields to work with instead of sub-datasets within other fields. This portion is the code based approach you mentioned you thought you would need.
2) With step 1 done, all the data is ready for Rave to process in an easy, RAD, way.
Have fun :-)
(If you need more help, I would need more specifics on EXACTLY what types of data you are processing. Example data would also help)