Hello,
Thanks to everyone on this list and the developers for providing
great software and a great support resource.
I'd like to request some comments/criticism for a new module I'm
working on, CGI::Application::Plugin::XSV. This module provides a
simple method for producing csv output via Text::CSV_XS.
# in a cgiapp subclass...
use CGI::Application::Plugin::XSV;
# in some runmode...
# $sth is a prepared DBI statement handle
my $members= $sth->selectall_arrayref( {} );
return $self->xsv_report_web(
values => $members,
csv_opts => { sep_char => "\t" },
);
This will send csv output to the browser with a content-type
header of 'application/x-csv' and a content-disposition header of
'attachment' with a provided filename. This will (usually?)
prompt the user to save the attachment via a Save As dialog box
in his browser.
The pod is inline below. Please let me know if you have any
questions. You can download the entire distribution at the
following URL:
http://zacks.org/cgiapp-xsv/CGI-Application-Plugin-XSV-0.01.tar.gz
You can also read the documentation or browse the
distribution online:
http://zacks.org/cgiapp-xsv/pod.html
http://zacks.org/cgiapp-xsv/CGI-Application-Plugin-XSV-0.01/
Thanks,
-E
NAME
CGI::Application::Plugin::XSV - generate XSV output from a CGI::App
runmode
SYNOPSIS
use CGI::Application::Plugin::XSV;
...
# in some runmode...
# $sth is a prepared DBI statement handle
my $members= $sth->selectall_arrayref( {} );
my @headers= qw( member_id first_name last_name ... );
return $self->xsv_report_web({
fields => [EMAIL PROTECTED],
values => $members,
csv_opts => { sep_char => "\t" },
});
DESCRIPTION
"CGI::Application::Plugin::XSV" provides xsv-related routines useful for
web applications.
A method, "xsv_report_web" is exported by default. Three other
functions, "xsv_report", "clean_field_names", and "add_to_xsv" are
available for optional export.
You may export all four routines by specifying the export tag ":all":
use CGI::Application::Plugin::XSV qw(:all);
METHODS
xsv_report_web
# in a runmode
my @members= (
{ member_id => 1,
first_name => 'Chuck',
last_name => 'Barry', },
...
);
my @headers= ("Member ID", "First Name", "Last Name");
my @fields = qw(member_id first_name last_name);
return $self->xsv_report_web({
fields => [EMAIL PROTECTED],
headers => [EMAIL PROTECTED],
values => [EMAIL PROTECTED],
csv_opts => { sep_char => "\t" },
});
This method generates an XSV file that is sent directly to the
user's web browser. It sets the content-type header to
'application/x-csv' and sets the content-disposition header to
'attachment'.
It should be invoked through a CGI::Application(3) subclass object.
It takes a reference to a hash of named parameters. All except for
"values" are optional:
fields A reference to an array of field names or array indices.
This parameter specifies the order of fields in each row of
output.
If "fields" is not supplied, a list will be generated using
the first entry in the "values" list. Note, however, that in
this case, if the "values" parameter is a list of hashes,
the field order will be random because the field names are
extracted from a hash. If the "values" parameter is a list
of lists, the field order will be the same as the data
provided.
headers A reference to an array of column headers to be used as the
first row of the xsv report.
If "headers" is not supplied (and "include_headers" is not
set to a false value), "headers_cb" will be called with
"fields" as a parameter to generate column headers.
headers_cb
A reference to a subroutine used to generate column headers
from the field names.
A default routine is provided in "clean_field_names". This
function is passed the list of fields ("fields") as a
parameter.
include_headers
A true or false value indicating whether to include
"headers" (or automatically generated headers) as the first
row of output.
The default is true.
values A reference to an array of hash references (such as that
returned by "DBI::selectall_arrayref( {} )", or a reference
to an array of list references.
This argument is required.
get_row_cb
A reference to a subroutine used to generate each row of
output (other than the header row). Default routines are
provided that return each row of "values" in the order
specified by "headers".
This subroutine is passed two parameters for each row:
* the current row (reference to an array)
* the field list ("fields" - reference to an
array)
FUNCTIONS
add_to_xsv
# $sth is a prepared DBI statement handle
my $values= $sth->fetchall_arrayref( {} );
my @headers= qw/foo bar baz/;
my $output;
# $csv is a Text::CSV_XS object
foreach( @$values ) {
$output .= add_to_xsv( $csv, [ @[EMAIL PROTECTED] ], "\r\n" );
}
This function, used internally by "xsv_report"/"xsv_report_web",
formats a list of values for inclusion an xsv file. The return value
is from "$csv->string()", where $csv is a Text::CSV_XS(3) object.
It takes three parameters:
* A Text::CSV_XS(3) object
* A reference to a list of values
* The line ending
On an error from Text::CSV_XS(3), the function raises an exception.
On receiving an empty list of values, the function returns the line
ending only.
XXX should this return a formatted list of empty fields?
clean_field_names
my $fields= [ qw/first_name foo bar baz/ ];
my $headers= clean_field_names( $fields );
# $headers is now [ 'First Name', 'Foo', 'Bar', 'Baz' ]
This function takes a reference to a list of strings and returns a
reference to a new list in which the strings are reformatted as
such:
1. Underscores ('_') are changed to spaces
2. The first letter of each word is capitalized
This function is used by "xsv_report" and "xsv_report_web" if the
"headers_cb" parameter is not supplied.
xsv_report
# $sth is a prepared DBI statement handle
my $members= $sth->selectall_arrayref( {} );
my @headers= qw( member_id first_name last_name ... );
my $output= $self->xsv_report({
fields => [EMAIL PROTECTED],
values => $members,
csv_opts => { sep_char => "\t" },
});
# do something with $output
This function generates a string containing XSV data and returns it.
This may be useful when you want to do some manipulation of the data
before sending it to the user's browser or elsewhere. It takes the
same named parameters (via a reference to a hash) as
"xsv_report_web" except for "filename", which is not applicable to
this function.
EXAMPLES
Specify (almost) everything
return $self->xsv_report_web({
values => [
{ first_name => 'Jack',
last_name => 'Tors',
phone => '555-1212' },
{ first_name => 'Frank',
last_name => 'Rizzo',
phone => '555-1515' },
],
headers => [ "First Name", "Last Name", "Phone" ],
fields => [ qw(first_name last_name phone) ],
include_headers => 1,
line_ending => "\n",
csv_opts => { sep_char => "\t" },
});
__END__
"First Name" "Last Name" Phone
Jack Tors 555-1212
Frank Rizzo 555-1515
Use defaults
# ends up with same options and output as above
return $self->xsv_report_web({
values => [
{ first_name => 'Jack',
last_name => 'Tors',
phone => '555-1212' },
{ first_name => 'Frank',
last_name => 'Rizzo',
phone => '555-1515' },
],
headers => [ "First Name", "Last Name", "Phone" ],
fields => [ qw(first_name last_name phone) ],
});
Use header generation provided by module
# headers generated will be [ "First Name", "Last Name", "Phone" ]
# same output as above
return $self->xsv_report_web({
values => [
{ first_name => 'Jack',
last_name => 'Tors',
phone => '555-1212' },
{ first_name => 'Frank',
last_name => 'Rizzo',
phone => '555-1515' },
],
fields => [ qw(first_name last_name phone) ],
});
Use custom header generation
# headers generated will be [ "first", "last", "phone" ]
return $self->xsv_report_web({
values => [
{ first_name => 'Jack',
last_name => 'Tors',
phone => '555-1212' },
{ first_name => 'Frank',
last_name => 'Rizzo',
phone => '555-1515' },
],
fields => [ qw(first_name last_name phone) ],
headers_cb => sub {
my @h= @{ +shift };
s/_name$// foreach @h;
return [EMAIL PROTECTED];
},
});
__END__
first,last,phone
Jack,Tors,555-1212
Frank,Rizzo,555-1515
If order of fields doesn't matter
# headers and fields will be in random order (but consistent
# throughout data processing) due to extraction from hash
# (headers will be generated automatically)
return $self->xsv_report_web({
values => [
{ first_name => 'Jack',
last_name => 'Tors',
phone => '555-1212' },
{ first_name => 'Frank',
last_name => 'Rizzo',
phone => '555-1515' },
],
});
__END__
Phone,"Last Name","First Name"
555-1212,Tors,Jack
555-1515,Rizzo,Frank
No header row
return $self->xsv_report_web({
values => [
{ first_name => 'Jack',
last_name => 'Tors',
phone => '555-1212' },
{ first_name => 'Frank',
last_name => 'Rizzo',
phone => '555-1515' },
],
fields => [ qw(first_name last_name phone) ],
include_headers => 0,
});
__END__
Jack,Tors,555-1212
Frank,Rizzo,555-1515
Filter data as it is processed
sub plus_one {
my( $row, $fields )= @_;
return [ map { $_ + 1 } @[EMAIL PROTECTED] ];
}
# each row (other than header row) will be
# passed through plus_one()
return $self->xsv_report_web({
fields => [ qw(foo bar baz) ],
values => [ { foo => 1, bar => 2, baz => 3 }, ],
get_row_cb => \&plus_one,
});
__END__
2,3,4
Pass list of lists (instead of hashes)
# each row will be processed in order
# since fields parameter is omitted
$self->xsv_report_web({
include_headers => 0,
values => [
[ 1, 2, 3 ],
[ 4, 5, 6 ],
],
});
__END__
1,2,3
4,5,6
ERROR HANDLING
The function "add_to_xsv" will raise an exception when
"Text::CSV_XS->combine" fails. Please see the Text::CSV_XS(3)
documentation for details about what type of input causes a failure.
AUTHOR
Evan A. Zacks <[EMAIL PROTECTED]>
SEE ALSO
Text::CSV_XS(3), CGI::Application(3)
COPYRIGHT AND LICENSE
Copyright (c) 2005 CommonMind, LLC. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
REVISION
$Id: XSV.pm 2 2005-09-09 20:19:19Z zackse $
---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/[email protected]/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]