1Data::Report(3) User Contributed Perl Documentation Data::Report(3)
2
3
4
6 Data::Report - Framework for flexible reporting
7
9 use Data::Report;
10
11 # Create a new reporter.
12 my $rep = Data::Report::->create(type => "text"); # or "html", or "csv", ...
13
14 # Define the layout.
15 $rep->set_layout
16 ([ { name => "acct", title => "Acct", width => 6 },
17 { name => "desc", title => "Description", width => 40, align => "<" },
18 { name => "deb", title => "Debet", width => 10, align => ">" },
19 { name => "crd", title => "Credit", width => 10, align => ">" },
20 ]);
21
22 # Start the reporter.
23 $rep->start;
24
25 # Add data, row by row.
26 $rep->add({ acct => 1234, desc => "Received", deb => "242.33" });
27 $rep->add({ acct => 5678, desc => "Paid", crd => "699.45" });
28 $rep->add({ acct => 1259, desc => "Taxes", deb => "12.00", crd => "244.00" });
29 $rep->add({ desc => "TOTAL", deb => "254.33", crd => "943.45" });
30
31 # Finish the reporter.
32 $rep->finish;
33
35 Data::Report is a flexible, plugin-driven reporting framework. It makes
36 it easy to define reports that can be produced in text, HTML and CSV.
37 Textual ornaments like extra empty lines, dashed lines, and cell lines
38 can be added in a way similar to HTML style sheets.
39
40 The Data::Report framework consists of three parts:
41
42 The plugins
43 Plugins implement a specific type of report. Standard plugins
44 provided are "Data::Report::Plugin::Text" for textual reports,
45 "Data::Report::Plugin::Html" for HTML reports, and
46 "Data::Report::Plugin::Csv" for CSV (comma-separated) files.
47
48 Users can, and are encouraged, to develop their own plugins to
49 handle different styles and types of reports.
50
51 The base class
52 The base class "Data::Report::Base" implements the functionality
53 common to all reporters, plus a number of utility functions the
54 plugins can use.
55
56 The factory
57 The actual "Data::Report" module is a factory that creates a
58 reporter for a given report type by selecting the appropriate
59 plugin and returning an instance thereof.
60
62 Note that except for the "create" method, all other methods are
63 actually handled by the plugins and their base class.
64
65 create
66 Reporter objects are created using the class method "create". This
67 method takes a hash (or hashref) of arguments to initialise the
68 reporter object.
69
70 The actual reporter object is implemented by one of the plugin modules,
71 selected by the "type" argument. Standard plugins are provided for
72 "text", "HTML" and "CSV" report types. The default type is "text".
73
74 When looking for a plugin to support report type "foo", the "create"
75 method will first try to load a module "My::Package::Foo" where
76 "My::Package" is the invocant class. If this module cannot be loaded,
77 it will fall back to "Data::Report::Plugin::Foo". Note that, unless
78 subclassed, the current class will be "Data::Report".
79
80 All other initialisation arguments correspond to attribute setting
81 methods provided by the plugins. For example, the hypothetical call
82
83 my $rpt = Data::Report->create(foo => 1, bar => "Hello!");
84
85 is identical to:
86
87 my $rpt = Data::Report->create;
88 $rpt->set_foo(1);
89 $rpt->set_bar("Hello!");
90
91 You can choose any combination at your convenience.
92
93 start
94 This method indicates that all setup has been completed, and starts the
95 reporter. Note that no output is generated until the "add" method is
96 called.
97
98 "start" takes no arguments.
99
100 Although this method could be eliminated by automatically starting the
101 reporter upon the first call to "add", it turns out that an aplicit
102 "start" makes the API much cleaner and makes it easier to catch
103 mistakes.
104
105 add
106 This method adds a new entry to the report. It takes one single
107 argument, a hash ref of column names and the corresponding values.
108 Missing columns are left blank.
109
110 In addition to the column names and values, you can add the special key
111 "_style" to designate a particular style for this entry. What that
112 means depends on the plugin that implements this reporter. For example,
113 the standard HTML reporter plugin prefixes the given style with "r_" to
114 form the class name for the row. The style name should be a simple
115 name, containing letters, digits and underscores, starting with a
116 letter.
117
118 Example
119
120 $rpt->add({ date => "2006-04-31",
121 amount => 1000,
122 descr => "First payment",
123 _style => "plain" });
124
125 finish
126 This method indicates that report generation is complete. After this,
127 you can call "start" again to initiate a new report.
128
129 "finish" takes no arguments.
130
131 close
132 This is a convenience method. If the output stream was set up by the
133 reporter itself (see "set_output", below), the stream will be closed.
134 Otherwise, this method will be a no-op.
135
136 "close" takes no arguments.
137
139 get_type
140 The reporter type.
141
142 set_layout
143 This is the most important attribute, since it effectively defines the
144 report layout.
145
146 This method takes one argument, an array reference. Each element of the
147 array is a hash reference that corresponds to one column in the report.
148 The order of elements definines the order of the columns in the report,
149 but see "set_fields" below.
150
151 The following keys are possible in the hash reference:
152
153 "name"
154 The name of this column. The name should be a simple name,
155 containing letters, digits and underscores, starting with a letter.
156
157 The standard HTML reporter plugin uses the column name to form a
158 class name for each cell by prefixing with "c_". Likewise, the
159 classes for the table headings will be formed by prefixing the
160 column names with "h_". See "ADVANCED EXAMPLES", below.
161
162 "title"
163 The title of this column. This title is placed in the column
164 heading.
165
166 "width"
167 The width of this column. Relevant for textual reporters only.
168
169 By default, if a value does not fit in the given width, it will be
170 spread over multiple rows in a pseudo-elegant way. See also the
171 "truncate" key, below.
172
173 "align"
174 The alignment of this column. This can be either "<" for left-
175 aligned columns, or ">" to indicate a right-aligned column.
176
177 "truncate"
178 If true, the values in this column will be truncated to fit the
179 width of the column. Relevant for textual reporters only.
180
181 set_style
182 This method can be used to set an arbitrary style (a string) whose
183 meaning depends on the implementing plugin. For example, a HTML plugin
184 could use this as the name of the style sheet to use.
185
186 The name should be a simple name, containing letters, digits and
187 underscores, starting with a letter.
188
189 get_style
190 Returns the style, or "default" if none.
191
192 set_output
193 Designates the destination for the report. The argument can be
194
195 a SCALAR reference
196 All output will be appended to the designated scalar.
197
198 an ARRAY reference
199 All output lines will be pushed onto the array.
200
201 a SCALAR
202 A file will be created with the given name, and all output will be
203 written to this file. To close the file, use the "close" method
204 described above.
205
206 anything else
207 Anything else will be considered to be a file handle, and treated
208 as such.
209
210 set_stylist
211 The stylist is a powerful method to control the appearance of the
212 report at the row and cell level. The basic idea is taken from HTML
213 style sheets. By using a stylist, it is possible to add extra spaces
214 and lines to rows and cells in a declarative way.
215
216 When used, the stylist should be a reference to a possibly anonymous
217 subroutine with three arguments: the reporter object, the style of a
218 row (as specified with "_style" in the "add" method), and the name of a
219 column as defined in the layout. For table headings, the row name
220 "_head" is used.
221
222 The stylist routine will be repeatedly called by the reporter to obtain
223 formatting properties for rows and cells. It should return either
224 nothing, or a hash reference with properties.
225
226 When called with only the "row" argument, it should return the
227 properties for this row.
228
229 When called with row equal to "*" and a column name, it should return
230 the properties for the given column.
231
232 When called with a row and a column name, it should return the
233 properties for the given row/column (cell).
234
235 All appropriate properties are merged to form the final set of
236 properties to apply.
237
238 The following row properties are recognised. Between parentheses the
239 backends that support them.
240
241 "skip_before"
242 (Text) Produce an empty line before printing the current row.
243
244 "skip_after"
245 (Text) Produce an empty line after printing the current row, but
246 only if other data follows.
247
248 "line_before"
249 (Text) Draw a line of dashes before printing the current row.
250
251 "line_after"
252 (Text) Draw a line of dashes after printing the current row.
253
254 "cancel_skip"
255 (Text) Cancel the effect of a pending "skip_after"
256
257 "ignore"
258 (All) Ignore this row. Useful for CSV backends where only the raw
259 data matters, and not the totals and such.
260
261 The following cell properties are recognised. Between parentheses the
262 backends that support them.
263
264 "indent"
265 (Text) Indent the contents of this cell with the given amount.
266
267 "wrap_indent"
268 (Text) Indent wrapped contents of this cell with the given amount.
269
270 "truncate"
271 (Text) If true, truncate the contents of this cell to fit the
272 column width.
273
274 "line_before"
275 (Text) Draw a line in the cell before printing the current row. The
276 value of this property indicates the symbol to use to draw the
277 line. If it is 1, dashes are used.
278
279 "line_after"
280 (Text) Draw a line in the cell after printing the current row. The
281 value of this property indicates the symbol to use to draw the
282 line. If it is 1, dashes are used.
283
284 "raw_html"
285 (Html) Do not escape special HTML characters, allowing pre-prepared
286 HTML code to be placed in the output. Use with care.
287
288 "ignore"
289 (All) Ignore this column. Note that to prevent surprising results,
290 the column must be ignored in all applicable styles, including the
291 special style "_head" that controls the heading.
292
293 "class"
294 (Html) Class name to be used for this cell. Default class name is
295 "h_CNAME" for table headings and "c_CNAME" for table rows, where
296 CNAME is the name of the column.
297
298 Example:
299
300 $rep->set_stylist(sub {
301 my ($rep, $row, $col) = @_;
302
303 unless ( $col ) {
304 return { line_after => 1 } if $row eq "total";
305 return;
306 }
307 return { line_after => 1 } if $col eq "amount";
308 return;
309 });
310
311 Each reporter provides a standard (dummy) stylist called
312 "_std_stylist". Overriding this method is equivalent to using
313 "set_stylist".
314
315 get_stylist
316 Returns the current stylist, if any.
317
318 set_topheading
319 Headings consist of two parts, the top heading, and the standard
320 heading. Bij default, the top heading is empty, and the standard
321 heading has the names of the columns with a separator line (depnendent
322 on the plugin used).
323
324 This method can be used to designate a subroutine that will provide the
325 top heading of the report.
326
327 Example:
328
329 $rpt->set_topheading(sub {
330 my $self = shift;
331 $self->_print("Title line 1\n");
332 $self->_print("Title line 2\n");
333 $self->_print("\n");
334 });
335
336 Note the use of the reporter provided "_print" method to produce
337 output.
338
339 When subclassing a reporter, a method "_top_heading" can be defined to
340 provide the top heading. This is equivalent to an explicit call to
341 "set_topheading", but doesn't need to be repeatedly and explicitly
342 executed for each new reporter.
343
344 get_topheading
345 Returns the current top heading routine, if any.
346
347 set_heading
348 This method can be used to designate a subroutine that provides the
349 standard heading of the report.
350
351 In normal cases using this method is not necessary, since setting the
352 top heading will be sufficient.
353
354 Each reporter plugin provides a standard heading, implemented in a
355 method called "_std_header". This is the default value for the
356 "heading" attribute. A user-defined heading can use
357
358 $self->SUPER::_std_header;
359
360 to still get the original standard heading produced.
361
362 Example:
363
364 $rpt->set_heading(sub {
365 my $self = shift;
366 $self->_print("Title line 1\n");
367 $self->_print("Title line 2\n");
368 $self->_print("\n");
369 $self->SUPER::_std_heading;
370 $self->_print("\n");
371 });
372
373 Note the use of the reporter provided "_print" method to produce
374 output.
375
376 When subclassing a reporter, the method "_std_heading" can be
377 overridden to provide a customized top heading. This is equivalent to
378 an explicit call to "set_topheading", but doesn't need to be repeatedly
379 and explicitly executed for each new reporter.
380
381 get_heading
382 Returns the current standard heading routine, if any.
383
384 set_fields
385 This method can be used to define what columns (fields) should be
386 included in the report and the order they should appear. It takes an
387 array reference with the names of the desired columns.
388
389 Example:
390
391 $rpt->set_fields([qw(descr amount date)]);
392
393 get_fields
394 Returns the current set of selected columns.
395
396 set_width
397 This method defines the width for one or more columns. It takes a hash
398 reference with column names and widths. The width may be an absolute
399 number, a relative number (to increase/decrease the width, or a
400 percentage.
401
402 Example:
403
404 $rpt->set_width({ amount => 10, desc => '80%' });
405
406 get_widths
407 Returns a hash with all column names and widths.
408
410 This example subclasses Data::Report with an associated plugin for type
411 "text". Note the use of overriding "_top_heading" and "_std_stylist" to
412 provide special defaults for this reporter.
413
414 package POC::Report;
415
416 use base qw(Data::Report);
417
418 package POC::Report::Text;
419
420 use base qw(Data::Report::Plugin::Text);
421
422 sub _top_heading {
423 my $self = shift;
424 $self->_print("Title line 1\n");
425 $self->_print("Title line 2\n");
426 $self->_print("\n");
427 }
428
429 sub _std_stylist {
430 my ($rep, $row, $col) = @_;
431
432 if ( $col ) {
433 return { line_after => "=" }
434 if $row eq "special" && $col =~ /^(deb|crd)$/;
435 }
436 else {
437 return { line_after => 1 } if $row eq "total";
438 }
439 return;
440 }
441
442 It can be used as follows:
443
444 my $rep = POC::Report::->create(type => "text");
445
446 $rep->set_layout
447 ([ { name => "acct", title => "Acct", width => 6 },
448 { name => "desc", title => "Report", width => 40, align => "<" },
449 { name => "deb", title => "Debet", width => 10, align => "<" },
450 { name => "crd", title => "Credit", width => 10, align => ">" },
451 ]);
452
453 $rep->start;
454
455 $rep->add({ acct => "one", desc => "two", deb => "three", crd => "four", _style => "normal" });
456 $rep->add({ acct => "one", desc => "two", deb => "three", crd => "four", _style => "normal" });
457 $rep->add({ acct => "one", desc => "two", deb => "three", crd => "four", _style => "special"});
458 $rep->add({ acct => "one", desc => "two", deb => "three", crd => "four", _style => "total" });
459
460 $rep->finish;
461
462 The output will look like:
463
464 Title line 1
465 Title line 2
466
467 Acct Report Debet Credit
468 ------------------------------------------------------------------------
469 one two three four
470 one two three four
471 one two three four
472 ========== ==========
473 one two three four
474 ------------------------------------------------------------------------
475
476 This is a similar example for a HTML reporter:
477
478 package POC::Report;
479
480 use base qw(Data::Report);
481
482 package POC::Report::Html;
483
484 use base qw(Data::Report::Plugin::Html);
485
486 sub start {
487 my $self = shift;
488 $self->{_title1} = shift;
489 $self->{_title2} = shift;
490 $self->{_title3} = shift;
491 $self->SUPER::start;
492 }
493
494 sub _top_heading {
495 my $self = shift;
496 $self->_print("<html>\n",
497 "<head>\n",
498 "<title>", $self->_html($self->{_title1}), "</title>\n",
499 '<link rel="stylesheet" href="css/', $self->get_style, '.css">', "\n",
500 "</head>\n",
501 "<body>\n",
502 "<p class=\"title\">", $self->_html($self->{_title1}), "</p>\n",
503 "<p class=\"subtitle\">", $self->_html($self->{_title2}), "<br>\n",
504 $self->_html($self->{_title3}), "</p>\n");
505 }
506
507 sub finish {
508 my $self = shift;
509 $self->SUPER::finish;
510 $self->_print("</body>\n</html>\n");
511 }
512
513 Note that it defines an alternative "start" method, that is used to
514 pass in additional parameters for title fields.
515
516 The method "_html" is a convenience method provided by the framework.
517 It returns its argument with sensitive characters escaped by HTML
518 entities.
519
520 It can be used as follows:
521
522 package main;
523
524 my $rep = POC::Report::->create(type => "html");
525
526 $rep->set_layout
527 ([ { name => "acct", title => "Acct", width => 6 },
528 { name => "desc", title => "Report", width => 40, align => "<" },
529 { name => "deb", title => "Debet", width => 10, align => "<" },
530 { name => "crd", title => "Credit", width => 10, align => ">" },
531 ]);
532
533 $rep->start(qw(Title_One Title_Two Title_Three_Left&Right));
534
535 $rep->add({ acct => "one", desc => "two", deb => "three", crd => "four", _style => "normal" });
536 $rep->add({ acct => "one", desc => "two", deb => "three", crd => "four", _style => "normal" });
537 $rep->add({ acct => "one", desc => "two", deb => "three", crd => "four", _style => "normal" });
538 $rep->add({ acct => "one", desc => "two", deb => "three", crd => "four", _style => "total" });
539
540 $rep->finish;
541
542 The output will look like this:
543
544 <html>
545 <head>
546 <title>Title_One</title>
547 <link rel="stylesheet" href="css/default.css">
548 </head>
549 <body>
550 <p class="title">Title_One</p>
551 <p class="subtitle">Title_Two<br>
552 Title_Three_Left&Right</p>
553 <table class="main">
554 <tr class="head">
555 <th align="left" class="h_acct">Acct</th>
556 <th align="left" class="h_desc">Report</th>
557 <th align="right" class="h_deb">Debet</th>
558 <th align="right" class="h_crd">Credit</th>
559 </tr>
560 <tr class="r_normal">
561 <td align="left" class="c_acct">one</td>
562 <td align="left" class="c_desc">two</td>
563 <td align="right" class="c_deb">three</td>
564 <td align="right" class="c_crd">four</td>
565 </tr>
566 <tr class="r_normal">
567 <td align="left" class="c_acct">one</td>
568 <td align="left" class="c_desc">two</td>
569 <td align="right" class="c_deb">three</td>
570 <td align="right" class="c_crd">four</td>
571 </tr>
572 <tr class="r_normal">
573 <td align="left" class="c_acct">one</td>
574 <td align="left" class="c_desc">two</td>
575 <td align="right" class="c_deb">three</td>
576 <td align="right" class="c_crd">four</td>
577 </tr>
578 <tr class="r_total">
579 <td align="left" class="c_acct">one</td>
580 <td align="left" class="c_desc">two</td>
581 <td align="right" class="c_deb">three</td>
582 <td align="right" class="c_crd">four</td>
583 </tr>
584 </table>
585 </body>
586 </html>
587
588 See also the examples in "t/09poc*.t".
589
591 Johan Vromans, "<jvromans at squirrel.nl>"
592
594 Disclaimer: This module is derived from actual working code, that I
595 turned into a generic CPAN module. During the process, some features
596 may have become unstable, but that will be cured in time. Also, it is
597 possible that revisions of the API will be necessary when new
598 functionality is added.
599
600 Please report any bugs or feature requests to "bug-data-report at
601 rt.cpan.org", or through the web interface at
602 <http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Data-Report>. I will
603 be notified, and then you'll automatically be notified of progress on
604 your bug as I make changes.
605
607 Development of this module takes place on GitHub:
608 <https://github.com/sciurius/perl-Data-Report>.
609
610 After installing, you can find documentation for this module with the
611 perldoc command.
612
613 perldoc Data::Report
614
615 Please report any bugs or feature requests using the issue tracker on
616 GitHub.
617
620 Copyright 2006,2008,2020 Squirrel Consultancy, all rights reserved.
621
622 This program is free software; you can redistribute it and/or modify it
623 under the same terms as Perl itself.
624
625
626
627perl v5.32.0 2020-07-28 Data::Report(3)