├── .gitignore
├── CHANGELOG
├── CONTRIBUTORS
├── LICENSE
├── README.md
├── demo
├── Demo.dpr
├── Demo.dproj
├── Demo.vrc
├── README.MD
├── uDemo.dfm
└── uDemo.pas
└── src
└── uHTMLBuilder.pas
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | *.dcu
3 | *.~1~
4 |
--------------------------------------------------------------------------------
/CHANGELOG:
--------------------------------------------------------------------------------
1 | ## [1.1] - 2017-07-18
2 |
3 | ### Added
4 | - THTMLReport.Clear clearing all objects added in report
5 |
6 | ### Changed
7 | - Method THTMLTable.SetDataSet support default value for empty value
8 | - Method THTMLTable.SetDataSet get DisplayName for header and DisplayText for cell values.
9 |
--------------------------------------------------------------------------------
/CONTRIBUTORS:
--------------------------------------------------------------------------------
1 | Contributors
2 |
3 | Guilherme Torres - github.com/guitorres
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 guitorres
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # htmlbuilder
2 | This unit allows building simplified html with Delphi.
3 |
4 | ## Hello world!
5 |
6 | ```delphi
7 | var
8 | html: THTMLReport;
9 | begin
10 | html := THTMLReport.Create;
11 | try
12 | html.Style := '*{font-size:15pt}';
13 | html.AddParagraph('Hello World!', '');
14 | ShowMessage(html.Build);
15 | finally
16 | html.Free;
17 | end;
18 | end;
19 | ```
20 |
21 | ```html
22 |
23 |
24 |
27 |
28 |
29 |
30 | Hello World!
31 |
32 |
33 |
34 | ```
35 |
36 | ## easy table
37 |
38 | ```delphi
39 | var
40 | html: THTMLReport;
41 | table: THTMLTable;
42 | row: THTMLRow;
43 | i,j: Integer;
44 | begin
45 | html := THTMLReport.Create;
46 | table := THTMLTable.Create;
47 | try
48 | html.Style := '*{font-size:15pt}';
49 | html.AddTable(table);
50 |
51 | for i := 1 to 100 do
52 | begin
53 | row := THTMLRow.Create;
54 | for j := 1 to 5 do
55 | row.AddCell(Format('Row %d Column %d', [i,j]), '');
56 | table.RowList.Add(row);
57 | end;
58 |
59 | ShowMessage(html.Build);
60 | finally
61 | html.Free;
62 | end;
63 | ```
64 |
65 | ```html
66 |
67 |
68 |
71 |
72 |
73 |
74 |
75 |
76 | Row 1 Column 1
77 |
78 |
79 | Row 1 Column 2
80 |
81 |
82 | Row 1 Column 3
83 |
84 |
85 | Row 1 Column 4
86 |
87 |
88 | Row 1 Column 5
89 |
90 |
91 |
92 |
93 |
94 | Row 100 Column 1
95 |
96 |
97 | Row 100 Column 2
98 |
99 |
100 | Row 100 Column 3
101 |
102 |
103 | Row 100 Column 4
104 |
105 |
106 | Row 100 Column 5
107 |
108 |
109 |
110 |
111 |
112 | ```
113 |
114 | ## dataset to table
115 |
116 | ```delphi
117 | table := THTMLTable.Create;
118 | table.SetDataSet(cdsTest);
119 | ShowMessage(table.Build);
120 | ```
121 |
122 | ## and more
123 |
124 | check the /demo directory
--------------------------------------------------------------------------------
/demo/Demo.dpr:
--------------------------------------------------------------------------------
1 | program Demo;
2 |
3 | uses
4 | Forms,
5 | uDemo in '..\demo\uDemo.pas' {frmDemo};
6 |
7 | {$R *.res}
8 |
9 | begin
10 | Application.Initialize;
11 | Application.CreateForm(TfrmDemo, frmDemo);
12 | Application.Run;
13 | end.
14 |
--------------------------------------------------------------------------------
/demo/Demo.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {345C6BB9-C2FA-4121-842D-3CC925BD19BC}
4 | Demo.dpr
5 | True
6 | Debug
7 | 1025
8 | Application
9 | VCL
10 | 18.1
11 | Win32
12 |
13 |
14 | true
15 |
16 |
17 | true
18 | Base
19 | true
20 |
21 |
22 | true
23 | Base
24 | true
25 |
26 |
27 | true
28 | Base
29 | true
30 |
31 |
32 | true
33 | Cfg_1
34 | true
35 | true
36 |
37 |
38 | true
39 | Base
40 | true
41 |
42 |
43 | true
44 | Cfg_2
45 | true
46 | true
47 |
48 |
49 | true
50 | Cfg_2
51 | true
52 | true
53 |
54 |
55 | 00400000
56 | Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace)
57 | ..\..\exe
58 | true
59 | 1046
60 | false
61 | 1
62 | Demo
63 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
64 | 1
65 | false
66 | vcl;rtl;vclx;indy;inet;xmlrtl;vclie;inetdbbde;inetdbxpress;dbrtl;dsnap;dsnapcon;vcldb;soaprtl;VclSmp;dbexpress;dbxcds;inetdb;bdertl;vcldbx;webdsnap;websnap;adortl;ibxpress;teeui;teedb;tee;dss;visualclx;visualdbclx;vclactnband;vclshlctrls;IntrawebDB_50_70;Intraweb_50_70;Rave50CLX;Rave50VCL;dclOfficeXP;AnyDAC_PhysSQLite_D7;AnyDAC_Phys_D7;AnyDAC_ComI_D7;AnyDAC_PhysPg_D7;AnyDAC_PhysIB_D7;AnyDAC_PhysADS_D7;AnyDAC_PhysASA_D7;AnyDAC_PhysODBC_D7;AnyDAC_PhysOracl_D7;AnyDAC_PhysMySQL_D7;AnyDAC_PhysDb2_D7;AnyDAC_PhysMSSQL_D7;AnyDAC_PhysMSAcc_D7;AnyDAC_GUIxForms_D7;AnyDAC_Comp_D7;RLibWinD7vcl;JclDeveloperTools;Jcl;JclVcl;JclContainers;JvCore;JvSystem;JvStdCtrls;JvAppFrm;JvBands;JvDB;JvDlgs;JvBDE;JvControls;JvCmp;JvCrypt;JvCustom;JvDocking;JvDotNetCtrls;JvGlobus;JvHMI;JvJans;JvManagedThreads;JvMM;JvNet;JvPageComps;JvPascalInterpreter;JvPluginSystem;JvPrintPreview;JvRuntimeDesign;JvTimeFramework;JvWizards;JvXPCtrls;$(DCC_UsePackage)
67 | false
68 | false
69 | ..\..\src;$(DCC_UnitSearchPath)
70 |
71 |
72 | $(BDS)\bin\default_app.manifest
73 | System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
74 | 1033
75 | Sample_Icon.ico
76 | true
77 | true
78 |
79 |
80 | Sample_Icon.ico
81 |
82 |
83 | false
84 | 0
85 | 0
86 | RELEASE;$(DCC_Define)
87 |
88 |
89 | true
90 | true
91 |
92 |
93 | true
94 | false
95 | DEBUG;$(DCC_Define)
96 |
97 |
98 | Debug
99 |
100 |
101 | 1033
102 | ..\exe
103 | true
104 | ..\src;$(DCC_UnitSearchPath)
105 | true
106 | true
107 |
108 |
109 |
110 | MainSource
111 |
112 |
113 |
114 |
115 |
116 | Cfg_2
117 | Base
118 |
119 |
120 | Base
121 |
122 |
123 | Cfg_1
124 | Base
125 |
126 |
127 |
128 | Delphi.Personality.12
129 |
130 |
131 |
132 |
133 | Demo.dpr
134 |
135 |
136 | Microsoft Office 2000 Sample Automation Server Wrapper Components
137 | Microsoft Office XP Sample Automation Server Wrapper Components
138 |
139 |
140 |
141 | True
142 | True
143 | False
144 |
145 |
146 |
147 |
148 | 1
149 |
150 |
151 | 1
152 |
153 |
154 |
155 |
156 | Contents\Resources
157 | 1
158 |
159 |
160 |
161 |
162 | classes
163 | 1
164 |
165 |
166 |
167 |
168 | Contents\MacOS
169 | 0
170 |
171 |
172 | 1
173 |
174 |
175 | Contents\MacOS
176 | 1
177 |
178 |
179 |
180 |
181 | 1
182 |
183 |
184 | 1
185 |
186 |
187 | 1
188 |
189 |
190 |
191 |
192 | res\drawable-xxhdpi
193 | 1
194 |
195 |
196 |
197 |
198 | library\lib\mips
199 | 1
200 |
201 |
202 |
203 |
204 | 1
205 |
206 |
207 | 1
208 |
209 |
210 | 0
211 |
212 |
213 | 1
214 |
215 |
216 | Contents\MacOS
217 | 1
218 |
219 |
220 | library\lib\armeabi-v7a
221 | 1
222 |
223 |
224 | 1
225 |
226 |
227 |
228 |
229 | 0
230 |
231 |
232 | Contents\MacOS
233 | 1
234 | .framework
235 |
236 |
237 |
238 |
239 | 1
240 |
241 |
242 | 1
243 |
244 |
245 | 1
246 |
247 |
248 |
249 |
250 | 1
251 |
252 |
253 | 1
254 |
255 |
256 | 1
257 |
258 |
259 |
260 |
261 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
262 | 1
263 |
264 |
265 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
266 | 1
267 |
268 |
269 |
270 |
271 | 1
272 |
273 |
274 | 1
275 |
276 |
277 | 1
278 |
279 |
280 |
281 |
282 | 1
283 |
284 |
285 | 1
286 |
287 |
288 | 1
289 |
290 |
291 |
292 |
293 | library\lib\armeabi
294 | 1
295 |
296 |
297 |
298 |
299 | 0
300 |
301 |
302 | 1
303 |
304 |
305 | Contents\MacOS
306 | 1
307 |
308 |
309 |
310 |
311 | 1
312 |
313 |
314 | 1
315 |
316 |
317 | 1
318 |
319 |
320 |
321 |
322 | res\drawable-normal
323 | 1
324 |
325 |
326 |
327 |
328 | res\drawable-xhdpi
329 | 1
330 |
331 |
332 |
333 |
334 | res\drawable-large
335 | 1
336 |
337 |
338 |
339 |
340 | 1
341 |
342 |
343 | 1
344 |
345 |
346 | 1
347 |
348 |
349 |
350 |
351 | ..\
352 | 1
353 |
354 |
355 | ..\
356 | 1
357 |
358 |
359 |
360 |
361 | res\drawable-hdpi
362 | 1
363 |
364 |
365 |
366 |
367 | library\lib\armeabi-v7a
368 | 1
369 |
370 |
371 |
372 |
373 | Contents
374 | 1
375 |
376 |
377 |
378 |
379 | ..\
380 | 1
381 |
382 |
383 |
384 |
385 | 1
386 |
387 |
388 | 1
389 |
390 |
391 | 1
392 |
393 |
394 |
395 |
396 | res\values
397 | 1
398 |
399 |
400 |
401 |
402 | res\drawable-small
403 | 1
404 |
405 |
406 |
407 |
408 | res\drawable
409 | 1
410 |
411 |
412 |
413 |
414 | 1
415 |
416 |
417 | 1
418 |
419 |
420 | 1
421 |
422 |
423 |
424 |
425 | 1
426 |
427 |
428 |
429 |
430 | res\drawable
431 | 1
432 |
433 |
434 |
435 |
436 | 0
437 |
438 |
439 | 0
440 |
441 |
442 | Contents\Resources\StartUp\
443 | 0
444 |
445 |
446 | 0
447 |
448 |
449 | 0
450 |
451 |
452 | 0
453 |
454 |
455 |
456 |
457 | library\lib\armeabi-v7a
458 | 1
459 |
460 |
461 |
462 |
463 | 0
464 | .bpl
465 |
466 |
467 | 1
468 | .dylib
469 |
470 |
471 | Contents\MacOS
472 | 1
473 | .dylib
474 |
475 |
476 | 1
477 | .dylib
478 |
479 |
480 | 1
481 | .dylib
482 |
483 |
484 |
485 |
486 | res\drawable-mdpi
487 | 1
488 |
489 |
490 |
491 |
492 | res\drawable-xlarge
493 | 1
494 |
495 |
496 |
497 |
498 | res\drawable-ldpi
499 | 1
500 |
501 |
502 |
503 |
504 | 0
505 | .dll;.bpl
506 |
507 |
508 | 1
509 | .dylib
510 |
511 |
512 | Contents\MacOS
513 | 1
514 | .dylib
515 |
516 |
517 | 1
518 | .dylib
519 |
520 |
521 | 1
522 | .dylib
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 | 12
536 |
537 |
538 |
539 |
540 |
541 |
--------------------------------------------------------------------------------
/demo/Demo.vrc:
--------------------------------------------------------------------------------
1 | /* ----- VS_VERSION.dwFileFlags ----- */
2 | #define VS_FF_DEBUG 0x00000001L
3 | #define VS_FF_PRERELEASE 0x00000002L
4 | #define VS_FF_PATCHED 0x00000004L
5 | #define VS_FF_PRIVATEBUILD 0x00000008L
6 | #define VS_FF_INFOINFERRED 0x00000010L
7 | #define VS_FF_SPECIALBUILD 0x00000020L
8 | #define VS_FFI_FILEFLAGSMASK 0x0000003FL
9 |
10 | /* ----- VS_VERSION.dwFileOS ----- */
11 | #define VOS_UNKNOWN 0x00000000L
12 | #define VOS_DOS 0x00010000L
13 | #define VOS_OS216 0x00020000L
14 | #define VOS_OS232 0x00030000L
15 | #define VOS_NT 0x00040000L
16 | #define VOS_WINCE 0x00050000L
17 |
18 | #define VOS__BASE 0x00000000L
19 | #define VOS__WINDOWS16 0x00000001L
20 | #define VOS__PM16 0x00000002L
21 | #define VOS__PM32 0x00000003L
22 | #define VOS__WINDOWS32 0x00000004L
23 |
24 | #define VOS_DOS_WINDOWS16 0x00010001L
25 | #define VOS_DOS_WINDOWS32 0x00010004L
26 | #define VOS_OS216_PM16 0x00020002L
27 | #define VOS_OS232_PM32 0x00030003L
28 | #define VOS_NT_WINDOWS32 0x00040004L
29 |
30 | /* ----- VS_VERSION.dwFileType ----- */
31 | #define VFT_UNKNOWN 0x00000000L
32 | #define VFT_APP 0x00000001L
33 | #define VFT_DLL 0x00000002L
34 | #define VFT_DRV 0x00000003L
35 | #define VFT_FONT 0x00000004L
36 | #define VFT_VXD 0x00000005L
37 | #define VFT_STATIC_LIB 0x00000007L
38 |
39 | 1 VERSIONINFO
40 | FILEVERSION 1, 0, 0, 0
41 | PRODUCTVERSION 1, 0, 0, 0
42 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
43 | FILEOS VOS__WINDOWS32
44 | FILETYPE VFT_APP
45 | {
46 | BLOCK "StringFileInfo"
47 | {
48 | BLOCK "040904E4"
49 | {
50 | VALUE "FileVersion", "1.0.0.0\000\000"
51 | VALUE "ProductVersion", "1.0.0.0\000\000"
52 | }
53 | }
54 | BLOCK "VarFileInfo"
55 | {
56 | VALUE "Translation", 1033, 1252
57 | }
58 | }
59 |
60 | 1 24 "Demo.$manifest"
61 | PLATFORMTARGETS RCDATA {1025}
62 |
--------------------------------------------------------------------------------
/demo/README.MD:
--------------------------------------------------------------------------------
1 | example project
2 |
--------------------------------------------------------------------------------
/demo/uDemo.dfm:
--------------------------------------------------------------------------------
1 | object frmDemo: TfrmDemo
2 | Left = 313
3 | Top = 176
4 | Caption = 'frmDemo'
5 | ClientHeight = 107
6 | ClientWidth = 199
7 | Color = clBtnFace
8 | Font.Charset = DEFAULT_CHARSET
9 | Font.Color = clWindowText
10 | Font.Height = -11
11 | Font.Name = 'MS Sans Serif'
12 | Font.Style = []
13 | OldCreateOrder = False
14 | OnCreate = FormCreate
15 | PixelsPerInch = 96
16 | TextHeight = 13
17 | object btnSampleDataSet: TButton
18 | Left = 24
19 | Top = 24
20 | Width = 150
21 | Height = 25
22 | Caption = 'DataSet'
23 | TabOrder = 0
24 | OnClick = btnSampleDataSetClick
25 | end
26 | object btnMultiHeader: TButton
27 | Left = 24
28 | Top = 64
29 | Width = 150
30 | Height = 25
31 | Caption = 'Multi Header'
32 | TabOrder = 1
33 | OnClick = btnMultiHeaderClick
34 | end
35 | object cdsProducts: TClientDataSet
36 | Aggregates = <>
37 | Params = <>
38 | Left = 168
39 | object cdsProductsproduct: TStringField
40 | FieldName = 'product'
41 | Size = 250
42 | end
43 | object cdsProductsprice: TStringField
44 | FieldName = 'price'
45 | Size = 10
46 | end
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/demo/uDemo.pas:
--------------------------------------------------------------------------------
1 | unit uDemo;
2 |
3 | interface
4 |
5 | uses
6 | Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
7 | Dialogs, StdCtrls, DB, DBClient, uHTMLBuilder, ShellAPI;
8 |
9 | type
10 | TfrmDemo = class(TForm)
11 | btnSampleDataSet: TButton;
12 | cdsProducts: TClientDataSet;
13 | cdsProductsproduct: TStringField;
14 | cdsProductsprice: TStringField;
15 | btnMultiHeader: TButton;
16 | procedure FormCreate(Sender: TObject);
17 | procedure btnSampleDataSetClick(Sender: TObject);
18 | procedure btnMultiHeaderClick(Sender: TObject);
19 | private
20 | { Private declarations }
21 | procedure PopulateDataSet(dataSet: TDataSet);
22 | procedure OpenHTMLDocument(report: THTMLReport);
23 | function GetReportStyle:string;
24 | public
25 | { Public declarations }
26 | end;
27 |
28 | var
29 | frmDemo: TfrmDemo;
30 |
31 | implementation
32 |
33 | uses Math;
34 |
35 | const
36 | cNUMBER_PRODUCT=50;
37 |
38 | {$R *.dfm}
39 |
40 | procedure TfrmDemo.PopulateDataSet(dataSet: TDataSet);
41 | var
42 | i: Integer;
43 | product, price: TField;
44 | begin
45 | product := dataSet.FieldByName('product');
46 | price := dataSet.FieldByName('price');
47 | for i := 1 to cNUMBER_PRODUCT do
48 | begin
49 | dataSet.Append;
50 | product.AsString := 'PRODUCT ' + FormatFloat('00', i);
51 | price.AsString := '$' + FormatFloat('#,###.00', RandomRange(1, cNUMBER_PRODUCT)*10);
52 | dataSet.Post;
53 | end;
54 | end;
55 |
56 | procedure TfrmDemo.OpenHTMLDocument(report: THTMLReport);
57 | var
58 | htmlFile: string;
59 | begin
60 | htmlFile := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName)) + 'teste.html';
61 | report.SaveToFile(htmlFile);
62 | ShellExecute(Handle, 'Open', 'iexplore.exe', PChar(htmlFile), '', SW_SHOWNORMAL);
63 | end;
64 |
65 | function TfrmDemo.GetReportStyle:string;
66 | var
67 | style: TStringList;
68 | begin
69 | style := TStringList.Create;
70 | try
71 | style.Clear;
72 | style.Add('* {font-family:Arial;font-size:11pt}');
73 | style.Add('html, body {height:100%;}');
74 | style.Add('table {width:100% ;border-collapse: collapse;}');
75 | Result := style.Text;
76 | finally
77 | style.Free;
78 | end;
79 | end;
80 |
81 | procedure TfrmDemo.FormCreate(Sender: TObject);
82 | begin
83 | cdsProducts.CreateDataSet;
84 | PopulateDataSet(cdsProducts);
85 | end;
86 |
87 | procedure TfrmDemo.btnSampleDataSetClick(Sender: TObject);
88 | const
89 | cPARAGRAPH_STYLE='style="font-weight:bold;font-size:15pt;text-align:center;"';
90 | var
91 | html: THTMLReport;
92 | table: THTMLTable;
93 | begin
94 | html := THTMLReport.Create(GetReportStyle);
95 | table := THTMLTable.Create;
96 | try
97 | table.SetDataSet(cdsProducts, '#909090', '#FFFFFF', '#D0D0D0');
98 | html.AddParagraph('Test using dataset', cPARAGRAPH_STYLE);
99 | html.AddTable(table);
100 | OpenHTMLDocument(html);
101 | finally
102 | FreeAndNil(html);
103 | end;
104 | end;
105 |
106 | procedure TfrmDemo.btnMultiHeaderClick(Sender: TObject);
107 | const
108 | cPARAGRAPH_STYLE='style="font-weight:bold;font-size:15pt;text-align:center;"';
109 | cHEADER_STYLE='style="font-weight:bold;background-color:silver"';
110 | var
111 | html: THTMLReport;
112 | table: THTMLTable;
113 | product, price: THTMLCell;
114 | discount10, discount5, fullprice: THTMLCell;
115 | priceValue: Integer;
116 | i: Integer;
117 | begin
118 | html := THTMLReport.Create(GetReportStyle);
119 | try
120 | table := THTMLTable.Create('border="1px solid black"');
121 | product := THTMLCell.Create('Product', 'rowspan=2 ' + cHEADER_STYLE);
122 | price := THTMLCell.Create('Price', 'colspan=3 align=center ' + cHEADER_STYLE);
123 | discount10 := THTMLCell.Create('10% discount', 'width="15%" ' + cHEADER_STYLE);
124 | discount5 := THTMLCell.Create('5% discount', 'width="15%" ' + cHEADER_STYLE);
125 | fullprice := THTMLCell.Create('full price', 'width="20%" ' + cHEADER_STYLE);
126 | //header
127 | table.AddRow([product, price], '');
128 | //sub header
129 | table.AddRow([fullprice, discount5, discount10], '');
130 | //lines
131 | for i := 1 to cNUMBER_PRODUCT do
132 | begin
133 | priceValue := RandomRange(1, cNUMBER_PRODUCT)*10;
134 | table.AddRow([THTMLCell.Create('PRODUCT'+IntToStr(i), ''),
135 | THTMLCell.Create('$' + FormatFloat('#,###.00', priceValue), ''),
136 | THTMLCell.Create('$' + FormatFloat('#,###.00', (priceValue*0.95)), ''),
137 | THTMLCell.Create('$' + FormatFloat('#,###.00', (priceValue*0.9)), '')], '');
138 | end;
139 |
140 | html.AddParagraph('Test using multi header', cPARAGRAPH_STYLE);
141 | html.AddTable(table);
142 | OpenHTMLDocument(html);
143 | finally
144 | FreeAndNil(html);
145 | end;
146 | end;
147 |
148 | end.
149 |
--------------------------------------------------------------------------------
/src/uHTMLBuilder.pas:
--------------------------------------------------------------------------------
1 | unit uHTMLBuilder;
2 |
3 | interface
4 |
5 | uses
6 | Classes, Contnrs, SysUtils, DB;
7 |
8 | type
9 | THTMLBase = class
10 | end;
11 |
12 | THTMLCell = class
13 | private
14 | Fstyle: string;
15 | FName: string;
16 | FItemList: TObjectList;
17 | procedure Initialize(cellName:string = ''; cellStyle: string = '');
18 | protected
19 | public
20 | property Style: string read FStyle write FStyle;
21 | property Name: string read FName write FName;
22 | property ItemList: TObjectList read FItemList write FItemList;
23 | function Build: string;
24 | constructor Create;overload;
25 | constructor Create(cellName, cellStyle: string);overload;
26 | destructor Destroy; override;
27 | end;
28 |
29 | TAfterAddRow = procedure (
30 | Table: THTMLBase;
31 | DataSet: TDataSet
32 | ) of object;
33 |
34 | THTMLItem = class
35 | private
36 | FHtml: TStringList;
37 | protected
38 | public
39 | property HTML: TStringList read FHtml write FHtml;
40 | function Build: string;
41 | constructor Create(itemHtml: string = '');
42 | destructor Destroy;override;
43 | end;
44 |
45 | THTMLParagraph = class
46 | private
47 | Fstyle: string;
48 | FName: string;
49 | FItemList: TObjectList;
50 | procedure Initialize(paragraphName:string = ''; style: string = '');
51 | protected
52 | public
53 | property Style: string read FStyle write FStyle;
54 | property Name: string read FName write FName;
55 | property ItemList: TObjectList read FItemList write FItemList;
56 | function Build: string;
57 | constructor Create;overload;
58 | constructor Create(paragraphName, style: string);overload;
59 | destructor Destroy;override;
60 | end;
61 |
62 | THTMLRow = class
63 | private
64 | Fstyle: string;
65 | FName: string;
66 | FCellList: TObjectList;
67 | procedure Initialize(rowCellList: array of THTMLCell; rowStyle: string = '');
68 | protected
69 | public
70 | property Style: string read FStyle write FStyle;
71 | property Name: string read FName write FName;
72 | property CellList: TObjectList read FCellList write FCellList;
73 | function Build: string;
74 | function AddCell(cellName,cellStyle:string): THTMLCell;
75 | constructor Create;overload;
76 | constructor Create(rowCellList: array of THTMLCell);overload;
77 | constructor Create(rowCellList: array of THTMLCell; rowStyle: string);overload;
78 | destructor Destroy;override;
79 | end;
80 |
81 | THTMLTable = class(THTMLBase)
82 | private
83 | FRowList: TObjectList;
84 | Fstyle: string;
85 | protected
86 | public
87 | property Style: string read FStyle write FStyle;
88 | property RowList: TObjectList read FRowList write FRowList;
89 | function AddRow ( cellList: array of THTMLCell; rowStyle: string ): THTMLRow;overload;
90 | function AddRow ( rowName, rowStyle: string ): THTMLRow;overload;
91 | function AddEmptyRow(rowStyle:string = '') : THTMLRow;
92 | function Build:string;
93 | procedure SetDataSet(dataSet: TDataSet;
94 | HeaderColor: string = '';
95 | EvenColor: string = '';
96 | OddColor: string = '';
97 | EmptyValue: string = '';
98 | AfterAddRow: TAfterAddRow = nil);
99 | constructor Create(tableStyle: string = '');
100 | destructor Destroy;override;
101 | end;
102 |
103 | THTMLReport = class
104 | private
105 | FHTMLItemList: TObjectList;
106 | FStyle: string;
107 | FStyleHTML: string;
108 | FHead:string;
109 | function BuildDefaultStyle: string;
110 | procedure Initialize(reportStyle: string = '');
111 | protected
112 | procedure SetStyle(value: string);
113 | public
114 | property HTMLItemList: TObjectList read FHTMLItemList write FHTMLItemList;
115 | property Style: string read FStyle write SetStyle;
116 | property StyleHTML: string read FStyleHTML write FStyleHTML;
117 | property Head: string read FHead write FHead;
118 | procedure AddTable(table: THTMLTable);
119 | procedure AddItem(item: THTMLItem);
120 | function AddParagraph(paragraphName, paragraphStyle: string): THTMLParagraph;
121 | function Build: string;
122 | procedure SaveToFile(fileName: string);
123 | procedure Clear;
124 | constructor Create;overload;
125 | constructor Create(reportStyle: string);overload;
126 | destructor Destroy;override;
127 | end;
128 |
129 | TBuild = class
130 | public
131 | class function Build(item: TObject):string;
132 | end;
133 |
134 | implementation
135 |
136 | { THTMLTable }
137 |
138 | function THTMLTable.AddRow(cellList: array of THTMLCell;
139 | rowStyle: string): THTMLRow;
140 | var
141 | row: THTMLrow;
142 | i: Integer;
143 | begin
144 | row := THTMLrow.Create;
145 | row.Style := rowStyle;
146 | for i := 0 to High(cellList) do
147 | row.CellList.Add(cellList[i]);
148 | FRowList.Add( row );
149 | Result := row;
150 | end;
151 |
152 | function THTMLTable.AddEmptyRow(rowStyle:string = ''): THTMLRow;
153 | var
154 | row: THTMLrow;
155 | begin
156 | row := THTMLrow.Create;
157 | row.Style := rowStyle;
158 | row.CellList.Add(THTMLCell.Create(' ', 'colspan="100%"'));
159 | FRowList.Add( row );
160 | Result := row;
161 | end;
162 |
163 | function THTMLTable.Build: string;
164 | var
165 | i: Integer;
166 | html: TStringList;
167 | begin
168 | html := TStringList.Create;
169 | try
170 | html.Clear;
171 | html.Add('');
172 | for i := 0 to FRowList.Count - 1 do
173 | //BUILD ROW
174 | html.Add(TBuild.Build(FRowList[i]));
175 | html.Add('
');
176 | Result := html.Text;
177 | finally
178 | FreeAndNil(html);
179 | end;
180 | end;
181 |
182 | constructor THTMLTable.Create(tableStyle: string = '');
183 | begin
184 | RowList := TObjectList.Create;
185 | Style := tableStyle;
186 | end;
187 |
188 | destructor THTMLTable.Destroy;
189 | begin
190 | FreeAndNil(FRowList);
191 | inherited Destroy;
192 | end;
193 |
194 | function THTMLTable.AddRow(rowName, rowStyle: string): THTMLRow;
195 | begin
196 | Result := THTMLRow.Create;
197 | Result.Name := rowName;
198 | Result.Style := rowStyle;
199 | RowList.Add(Result);
200 | end;
201 |
202 | procedure THTMLTable.SetDataSet(
203 | dataSet: TDataSet; HeaderColor: string = '';
204 | EvenColor: string = ''; OddColor: string = '';
205 | EmptyValue: string = ''; AfterAddRow: TAfterAddRow = nil);
206 | const
207 | StyleHeader='';
208 | StyleData='';
209 | var
210 | i: Integer;
211 | row: THTMLRow;
212 | cell: THTMLCell;
213 | begin
214 | //prototipo
215 | row := THTMLRow.Create;
216 | row.Style := 'bgcolor="' + HeaderColor + '"';
217 | for i := 0 to dataSet.FieldCount - 1 do
218 | if dataSet.Fields[i].Visible then
219 | row.AddCell('' + dataSet.Fields[i].DisplayName + ' ', StyleHeader);
220 | Self.RowList.Add(row);
221 | dataSet.DisableControls;
222 | try
223 | dataSet.First;
224 | while not dataSet.Eof do
225 | begin
226 | row := THTMLRow.Create;
227 | if ((dataSet.RecNo mod 2) <> 0) then
228 | row.Style := 'bgcolor="' + EvenColor + '"'
229 | else
230 | row.Style := 'bgcolor="' + OddColor + '"';
231 |
232 | for i := 0 to dataSet.FieldCount - 1 do
233 | if dataSet.Fields[i].Visible then
234 | begin
235 | if dataSet.FieldByName(dataSet.Fields[i].FieldName).DataType = ftMemo then
236 | cell := row.AddCell(dataSet.FieldByName(dataSet.Fields[i].FieldName).AsString, StyleData)
237 | else
238 | cell := row.AddCell(dataSet.FieldByName(dataSet.Fields[i].FieldName).DisplayText, StyleData);
239 |
240 | if cell.Name = EmptyStr then
241 | cell.Name := EmptyValue;
242 | end;
243 | Self.RowList.Add(row);
244 | if Assigned(AfterAddRow) then
245 | AfterAddRow(Self, dataSet);
246 |
247 | dataSet.Next;
248 | end;
249 | finally
250 | dataSet.EnableControls;
251 | end;
252 | end;
253 |
254 | { THTMLCell }
255 | constructor THTMLCell.Create(cellName, cellStyle: string);
256 | begin
257 | Initialize(cellName, cellStyle);
258 | end;
259 |
260 | function THTMLCell.Build: string;
261 | var
262 | html: TStringList;
263 | i: Integer;
264 | begin
265 | html := TStringList.Create;
266 | try
267 | html.Add(' ');
268 | if Self.Name <> '' then
269 | html.Add(' ' + Self.Name);
270 | //BUILD CHILD ITEM, HTML, CELL, ETC
271 | for i := 0 to Self.ItemList.Count - 1 do
272 | html.Add(' ' + TBuild.Build(Self.ItemList[i]));
273 | html.Add(' ');
274 | Result := html.Text;
275 | finally
276 | FreeAndNil(html);
277 | end;
278 | end;
279 |
280 | destructor THTMLCell.Destroy;
281 | begin
282 | FreeAndNil(FItemList);
283 | inherited Destroy;
284 | end;
285 |
286 | constructor THTMLCell.Create;
287 | begin
288 | Initialize;
289 | end;
290 |
291 | procedure THTMLCell.Initialize(cellName:string = ''; cellStyle: string = '');
292 | begin
293 | FItemList := TObjectList.Create;
294 | Name := cellName;
295 | Style := cellStyle;
296 | end;
297 |
298 | { THTMLRow }
299 |
300 | function THTMLRow.AddCell(cellName, cellStyle: string): THTMLCell;
301 | begin
302 | Result := THTMLCell.Create(cellName, cellStyle);
303 | CellList.Add(Result);
304 | end;
305 |
306 | function THTMLRow.Build: string;
307 | var
308 | i: Integer;
309 | html: TStringList;
310 | begin
311 | html := TStringList.Create;
312 | try
313 | html.Clear;
314 | //BUILD ROW
315 | html.Add(' ');
316 | for i := 0 to Self.CellList.Count - 1 do
317 | begin
318 | //BUILD CELL
319 | html.Add(TBuild.Build(Self.CellList[i]));
320 | end;
321 | html.Add(' ');
322 | Result := html.Text;
323 | finally
324 | FreeAndNil(html);
325 | end;
326 | end;
327 |
328 | constructor THTMLRow.Create;
329 | begin
330 | Initialize([]);
331 | end;
332 |
333 | constructor THTMLRow.Create(rowCellList: array of THTMLCell);
334 | begin
335 | Initialize(rowCellList);
336 | end;
337 |
338 | constructor THTMLRow.Create(rowCellList: array of THTMLCell;
339 | rowStyle: string);
340 | begin
341 | Initialize(rowCellList, rowStyle);
342 | end;
343 |
344 | destructor THTMLRow.Destroy;
345 | begin
346 | FreeAndNil(FCellList);
347 | inherited Destroy;
348 | end;
349 |
350 | procedure THTMLRow.Initialize(rowCellList: array of THTMLCell;
351 | rowStyle: string = '');
352 | var
353 | i: Integer;
354 | begin
355 | FCellList := TObjectList.Create;
356 | Self.Style := rowStyle;
357 | for i := 0 to High(rowCellList) do
358 | CellList.Add(rowCellList[i]);
359 | end;
360 |
361 | { THTMLReport }
362 |
363 | procedure THTMLReport.AddItem(item: THTMLItem);
364 | begin
365 | HTMLItemList.Add(item);
366 | end;
367 |
368 | function THTMLReport.AddParagraph(paragraphName,
369 | paragraphStyle: string): THTMLParagraph;
370 | begin
371 | Result := THTMLParagraph.Create(paragraphName, paragraphStyle);
372 | HTMLItemList.Add(Result);
373 | end;
374 |
375 | procedure THTMLReport.AddTable(table: THTMLTable);
376 | begin
377 | HTMLItemList.Add(table);
378 | end;
379 |
380 | function THTMLReport.Build: string;
381 | var
382 | i: Integer;
383 | html: TstringList;
384 | begin
385 | html := TStringList.Create;
386 | try
387 | html.Clear;
388 | html.Add('');
389 | html.Add(' ');
390 | html.Add(' ');
393 | html.Add(' '+Self.Head);
394 | //html.Add(' ');
395 | html.Add(' ');
396 | html.Add(' ');
397 | for i := 0 to HTMLItemList.Count - 1 do
398 | html.Add(TBuild.Build(HTMLItemList[i]));
399 | html.Add(' ');
400 | html.Add('');
401 | result := html.Text;
402 | finally
403 | FreeAndNil(html);
404 | end;
405 | end;
406 |
407 | constructor THTMLReport.Create;
408 | begin
409 | Initialize;
410 | end;
411 |
412 | function THTMLReport.BuildDefaultStyle: string;
413 | var
414 | html: TStringList;
415 | begin
416 | html := TStringList.Create;
417 | try
418 | html.Clear;
419 | html.Add('html, body {height:100%;}');
420 | html.Add('table {width:100% ;border-collapse: collapse;font-family:Arial;font-size:8pt}');
421 | Result := html.Text;
422 | finally
423 | FreeAndNil(html);
424 | end;
425 | end;
426 |
427 | procedure THTMLReport.Clear;
428 | begin
429 | FHTMLItemList.Clear;
430 | end;
431 |
432 | constructor THTMLReport.Create(reportStyle: string);
433 | begin
434 | Initialize(reportStyle);
435 | end;
436 |
437 | destructor THTMLReport.Destroy;
438 | begin
439 | FreeAndNil(FHTMLItemList);
440 | inherited Destroy;
441 | end;
442 |
443 | procedure THTMLReport.SaveToFile(fileName: string);
444 | var
445 | toFile: TStringList;
446 | begin
447 | toFile := TStringList.Create;
448 | try
449 | toFile.Text := Self.Build;
450 | toFile.SaveToFile(fileName);
451 | finally
452 | FreeAndNil(toFile);
453 | end;
454 | end;
455 |
456 | procedure THTMLReport.SetStyle(value: string);
457 | begin
458 | if value = '' then
459 | FStyle := BuildDefaultStyle
460 | else
461 | FStyle := value;
462 | end;
463 |
464 | procedure THTMLReport.Initialize(reportStyle: string = '');
465 | begin
466 | FHTMLItemList := TObjectList.Create;
467 | Style := reportStyle;
468 | StyleHTML := '';
469 | Head := '';
470 | end;
471 |
472 | { THTMLItem }
473 |
474 | function THTMLItem.Build: string;
475 | begin
476 | Result := HTML.Text;
477 | end;
478 |
479 | constructor THTMLItem.Create(itemHtml: string);
480 | begin
481 | fHTML := TStringList.Create;
482 | fHTML.Clear;
483 | fHTML.Text := itemHtml;
484 | end;
485 |
486 | destructor THTMLItem.Destroy;
487 | begin
488 | FreeAndNil(fHTML);
489 | inherited Destroy;
490 | end;
491 |
492 | { TBuild }
493 |
494 | class function TBuild.Build(item: TObject): string;
495 | begin
496 | if item is THTMLReport then
497 | Result := THTMLReport(item).Build
498 | else if item is THTMLTable then
499 | Result := THTMLTable(item).Build
500 | else if item is THTMLRow then
501 | Result := THTMLRow(item).Build
502 | else if item is THTMLCell then
503 | Result := THTMLCell(item).Build
504 | else if item is THTMLItem then
505 | Result := THTMLItem(item).Build
506 | else if item is THTMLParagraph then
507 | Result := THTMLParagraph(item).Build;
508 | end;
509 |
510 | { THTMLParagraph }
511 |
512 | constructor THTMLParagraph.Create;
513 | begin
514 | Initialize;
515 | end;
516 |
517 | function THTMLParagraph.Build: string;
518 | var
519 | html: TStringList;
520 | i: Integer;
521 | begin
522 | html := TStringList.Create;
523 | try
524 | html.Clear;
525 | html.Add('');
526 | html.Add(Self.Name);
527 | for i := 0 to Self.ItemList.Count - 1 do
528 | html.Add(TBuild.Build(Self.ItemList[i]));
529 | html.Add('
');
530 | Result := html.Text;
531 | finally
532 | FreeAndNil(html);
533 | end;
534 | end;
535 |
536 | constructor THTMLParagraph.Create(paragraphName, style: string);
537 | begin
538 | Initialize(paragraphName, style);
539 | end;
540 |
541 | destructor THTMLParagraph.Destroy;
542 | begin
543 | FreeAndNil(FItemList);
544 | inherited Destroy;
545 | end;
546 |
547 | procedure THTMLParagraph.Initialize(paragraphName: string = ''; style: string = '');
548 | begin
549 | FItemList := TObjectList.Create;
550 | Self.Name := paragraphName;
551 | Self.Style := style;
552 | end;
553 |
554 | end.
555 |
--------------------------------------------------------------------------------