[Catalyst-commits] r8587 - in Catalyst-Action-Serialize-SimpleExcel/1.000/trunk: . lib lib/Catalyst lib/Catalyst/Action lib/Catalyst/Action/Serialize t t/lib t/lib/TestApp t/lib/TestApp/Controller

caelum at dev.catalyst.perl.org caelum at dev.catalyst.perl.org
Tue Nov 11 11:57:18 GMT 2008


Author: caelum
Date: 2008-11-11 11:57:18 +0000 (Tue, 11 Nov 2008)
New Revision: 8587

Added:
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/Changes
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/MANIFEST.SKIP
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/META.yml
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/Makefile.PL
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/README
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/lib/
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/lib/Catalyst/
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/lib/Catalyst/Action/
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/lib/Catalyst/Action/Serialize/
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/lib/Catalyst/Action/Serialize/SimpleExcel.pm
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/00-load.t
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/excel.t
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/lib/
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/lib/TestApp.pm
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/lib/TestApp/
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/lib/TestApp/Controller/
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/lib/TestApp/Controller/REST.pm
   Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/pod.t
Log:
New module: Catalyst::Action::Serialize::SimpleExcel


Added: Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/Changes
===================================================================
--- Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/Changes	                        (rev 0)
+++ Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/Changes	2008-11-11 11:57:18 UTC (rev 8587)
@@ -0,0 +1,5 @@
+Revision history for Catalyst-Action-Serialize-SimpleExcel
+
+0.01_01  2008-11-11 03:34:23
+    svn deleted all my files then rebuilt it from screen scrollback buffers,
+    just as I was putting the finishing touches on the dist.

Added: Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/MANIFEST.SKIP
===================================================================
--- Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/MANIFEST.SKIP	                        (rev 0)
+++ Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/MANIFEST.SKIP	2008-11-11 11:57:18 UTC (rev 8587)
@@ -0,0 +1,7 @@
+\.swp\z
+.svn/
+blib
+pm_to_blib
+MANIFEST.bak
+Makefile\z
+Makefile.old\z

Added: Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/META.yml
===================================================================
--- Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/META.yml	                        (rev 0)
+++ Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/META.yml	2008-11-11 11:57:18 UTC (rev 8587)
@@ -0,0 +1,28 @@
+---
+abstract: 'Serialize tables to Excel files'
+author:
+  - 'Rafael Kitover <rkitover at cpan.org>'
+build_requires:
+  Spreadsheet::ParseExcel: 0
+  Test::Deep: 0
+  Test::More: 0
+distribution_type: module
+generated_by: 'Module::Install version 0.77'
+license: perl
+meta-spec:
+  url: http://module-build.sourceforge.net/META-spec-v1.4.html
+  version: 1.4
+name: Catalyst-Action-Serialize-SimpleExcel
+no_index:
+  directory:
+    - inc
+    - t
+requires:
+  Catalyst::Controller::REST: 0
+  Scalar::Util: 0
+  Spreadsheet::WriteExcel: 0
+  namespace::clean: 0
+  parent: 0
+resources:
+  license: http://dev.perl.org/licenses/
+version: 0.01_01

Added: Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/Makefile.PL
===================================================================
--- Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/Makefile.PL	                        (rev 0)
+++ Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/Makefile.PL	2008-11-11 11:57:18 UTC (rev 8587)
@@ -0,0 +1,20 @@
+use inc::Module::Install;
+
+name     'Catalyst-Action-Serialize-SimpleExcel';
+all_from 'lib/Catalyst/Action/Serialize/SimpleExcel.pm';
+author   'Rafael Kitover <rkitover at cpan.org>';
+license  'perl';
+
+requires 'Catalyst::Controller::REST';                                
+requires 'Spreadsheet::WriteExcel';                                   
+requires 'parent';                                                    
+requires 'namespace::clean';                                          
+requires 'Scalar::Util';                                              
+                                                                      
+test_requires 'Test::More';                                           
+test_requires 'Spreadsheet::ParseExcel';                              
+test_requires 'Test::Deep';                                           
+                                                                      
+auto_install;                                                         
+                                                                      
+WriteAll;                                                             

Added: Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/README
===================================================================
--- Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/README	                        (rev 0)
+++ Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/README	2008-11-11 11:57:18 UTC (rev 8587)
@@ -0,0 +1,39 @@
+Catalyst-Action-Serialize-SimpleExcel
+
+INSTALLATION
+
+To install this module, run the following commands:
+
+	perl Makefile.PL
+	make
+	make test
+	make install
+
+SUPPORT AND DOCUMENTATION
+
+After installing, you can find documentation for this module with the
+perldoc command.
+
+    perldoc Catalyst::Action::Serialize::SimpleExcel
+
+You can also look for information at:
+
+    RT, CPAN's request tracker
+        http://rt.cpan.org/NoAuth/Bugs.html?Dist=Catalyst-Action-Serialize-SimpleExcel
+
+    AnnoCPAN, Annotated CPAN documentation
+        http://annocpan.org/dist/Catalyst-Action-Serialize-SimpleExcel
+
+    CPAN Ratings
+        http://cpanratings.perl.org/d/Catalyst-Action-Serialize-SimpleExcel
+
+    Search CPAN
+        http://search.cpan.org/dist/Catalyst-Action-Serialize-SimpleExcel/
+
+
+COPYRIGHT AND LICENCE
+
+Copyright (c) 2008 Rafael Kitover
+
+This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.

Added: Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/lib/Catalyst/Action/Serialize/SimpleExcel.pm
===================================================================
--- Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/lib/Catalyst/Action/Serialize/SimpleExcel.pm	                        (rev 0)
+++ Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/lib/Catalyst/Action/Serialize/SimpleExcel.pm	2008-11-11 11:57:18 UTC (rev 8587)
@@ -0,0 +1,206 @@
+package Catalyst::Action::Serialize::SimpleExcel;
+
+use strict;
+use warnings;
+no warnings 'uninitialized';
+use parent 'Catalyst::Action';
+use Spreadsheet::WriteExcel ();
+use Scalar::Util 'reftype';
+use namespace::clean;
+
+=head1 NAME
+
+Catalyst::Action::Serialize::SimpleExcel - Serialize tables to Excel files
+
+=head1 VERSION
+
+Version 0.01_01
+
+=cut
+
+our $VERSION = '0.01_01';
+
+=head1 SYNOPSIS
+
+Serializes tabular data to an Excel file. Not terribly configurable, but should
+suffice for simple purposes.
+
+In your REST Controller:
+
+    package MyApp::Controller::REST;
+
+    use parent 'Catalyst::Controller::REST';
+    use POSIX 'strftime';
+
+    __PACKAGE__->config->{map}{'application/vnd.ms-excel'} = 'SimpleExcel';
+
+    sub books : Local ActionClass('REST') {}
+
+    sub books_GET {
+        my ($self, $c) = @_;
+
+        my $rs = $c->model('MyDB::Book')->search({}, {
+            order_by => 'author,title'
+        });
+
+        my @t = map {
+            my $row = $_;
+            [ map $row->$_, qw/author title/ ]
+        } $rs->all;
+
+        my $entity = {
+            header => ['Author', 'Title'], # will be bold
+            column_widths => [30, 50], # in characters
+            rows => \@t,
+    # the part before .xls, which is automatically appended
+            filename => 'myapp-books-'.strftime('%m-%d-%Y', localtime)
+        };
+
+        $self->status_ok(
+            $c,
+            entity => $entity
+        );
+    }
+
+In your javascript, to initiate a file download:
+
+    // this uses jQuery
+    function export_to_excel() {
+        $('<iframe '
+         +'src="/rest/books?content-type=application%2Fvnd.ms-excel">')
+        .hide().appendTo('body');
+    }
+
+Note, the content-type query param is required if you're just linking to the
+action. It tells C::C::REST what you're serializing the data as.
+
+=head1 DESCRIPTION
+
+Your entity should be either an array of arrays, or the more embellished format
+described in the L</SYNOPSIS>.
+
+=cut
+
+sub execute {
+    my $self = shift;
+    my ($controller, $c) = @_;
+
+    my $stash_key = (
+            $controller->config->{'serialize'} ?
+                $controller->config->{'serialize'}->{'stash_key'} :
+                $controller->config->{'stash_key'}
+        ) || 'rest';
+
+    my $data = $c->stash->{$stash_key};
+
+    $data = { rows => $data } if reftype $data eq 'ARRAY';
+
+    open my $fh, '>', \my $buf;
+    my $workbook = Spreadsheet::WriteExcel->new($fh);
+    my $worksheet = $workbook->add_worksheet;
+
+    my ($row, $col) = (0,0);
+
+# Set column widths
+    if (exists $data->{column_widths}) {
+        for my $width (@{ $data->{column_widths} }) {
+            $worksheet->set_column($col, $col++, $width);
+        }
+# Have to set the width of column 0 again, otherwise Excel loses it!
+# I don't know why...
+        $worksheet->set_column(0, 0, $data->{column_widths}[0]);
+        $col = 0;
+    }
+
+# Write Header
+    if (exists $data->{header}) {
+        my $header_format = $workbook->add_format;
+        $header_format->set_bold;
+        for my $header (@{ $data->{header} }) {
+            $worksheet->write($row, $col++, $header, $header_format);
+        }
+        $row++;
+        $col = 0;
+    }
+
+# Write data
+    for my $the_row (@{ $data->{rows} }) {
+        for my $the_col (@$the_row) {
+            $worksheet->write($row, $col++, $the_col);
+        }
+        $row++;
+        $col = 0;
+    }
+
+# Write the file
+    my $filename = $data->{filename} || 'data';
+
+    $workbook->close;
+    $c->res->content_type('application/octet-stream');
+    $c->res->header('Content-Disposition' =>
+     "attachment; filename=${filename}.xls");
+    $c->res->output($buf);
+
+    1;
+}
+
+=head1 AUTHOR
+
+Rafael Kitover, C<< <rkitover at cpan.org> >>
+
+=head1 BUGS
+
+Please report any bugs or feature requests to C<bug-catalyst-action-serialize-simpleexcel at rt.cpan.org>, or through
+the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Catalyst-Action-Serialize-SimpleExcel>.  I will be notified, and then you'll
+automatically be notified of progress on your bug as I make changes.
+
+=head1 TODO
+
+=over 4
+
+=item * Split into mutliple overridable methods.
+
+=item * Multiple sheet support.
+
+=item * Autofit support (would require a macro.)
+
+=back
+
+=head1 SUPPORT
+
+You can find documentation for this module with the perldoc command.
+
+    perldoc Catalyst::Action::Serialize::SimpleExcel
+
+You can also look for information at:
+
+=over 4
+
+=item * RT: CPAN's request tracker
+
+L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Catalyst-Action-Serialize-SimpleExcel>
+
+=item * AnnoCPAN: Annotated CPAN documentation
+
+L<http://annocpan.org/dist/Catalyst-Action-Serialize-SimpleExcel>
+
+=item * CPAN Ratings
+
+L<http://cpanratings.perl.org/d/Catalyst-Action-Serialize-SimpleExcel>
+
+=item * Search CPAN
+
+L<http://search.cpan.org/dist/Catalyst-Action-Serialize-SimpleExcel/>
+
+=back
+
+=head1 COPYRIGHT & LICENSE
+
+Copyright (c) 2008 Rafael Kitover
+
+This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+=cut
+
+1; # End of Catalyst::Action::Serialize::SimpleExcel

Added: Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/00-load.t
===================================================================
--- Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/00-load.t	                        (rev 0)
+++ Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/00-load.t	2008-11-11 11:57:18 UTC (rev 8587)
@@ -0,0 +1,9 @@
+#!perl -T
+
+use Test::More tests => 1;
+
+BEGIN {
+	use_ok( 'Catalyst::Action::Serialize::SimpleExcel' );
+}
+
+diag( "Testing Catalyst::Action::Serialize::SimpleExcel $Catalyst::Action::Serialize::SimpleExcel::VERSION, Perl $], $^X" );

Added: Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/excel.t
===================================================================
--- Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/excel.t	                        (rev 0)
+++ Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/excel.t	2008-11-11 11:57:18 UTC (rev 8587)
@@ -0,0 +1,66 @@
+#!perl
+
+use strict;
+use warnings;
+use FindBin '$Bin';
+use lib "$Bin/lib";
+use Catalyst::Test 'TestApp';
+use Spreadsheet::ParseExcel ();
+
+use Test::More tests => 10;
+use Test::Deep;
+
+ok((my $file  = get '/rest/a_o_a?content-type=application%2Fvnd.ms-excel'),
+    'received file');
+ok((my $excel = Spreadsheet::ParseExcel::Workbook->Parse(\$file)),
+    'parsed file');
+my $sheet = $excel->{Worksheet}[0];
+
+cmp_deeply(
+    read_sheet($sheet),
+    [[1,2,3],[4,5,6]],
+    'array_of_array -> sheet'
+);
+
+ok((my $resp = request '/rest/fancy?content-type=application%2Fvnd.ms-excel'),
+    'received response');
+
+is($resp->header('Content-Type'), 'application/octet-stream', 'Content-Type');
+
+is($resp->header('Content-Disposition'), 'attachment; filename=mtfnpy.xls', 'Content-Disposition');
+
+ok(($file = $resp->content), 'received file');
+
+ok(($excel = Spreadsheet::ParseExcel::Workbook->Parse(\$file)), 'parsed file');
+
+$sheet = $excel->{Worksheet}[0];
+
+cmp_deeply(
+# internal representation of column widths is as floats
+# and for some reason there's a width set on the column beyond the last
+    [ map int, @{ $sheet->{ColWidth} }[0..1] ],
+    [ 10, 20 ],
+    'column_widths'
+);
+
+cmp_deeply(
+    read_sheet($sheet),
+    [ [qw/Foo Bar/], [1,2], [3,4] ],
+    'with options -> sheet'
+);
+
+sub read_sheet {
+    my $sheet = shift;
+    my $res;
+    $sheet->{MaxRow} ||= $sheet->{MinRow};
+    foreach my $row ($sheet->{MinRow} .. $sheet->{MaxRow}) {
+        $sheet->{MaxCol} ||= $sheet->{MinCol};
+        foreach my $col ($sheet->{MinCol} ..  $sheet->{MaxCol}) {
+            my $cell = $sheet->{Cells}[$row][$col];
+            if ($cell) {
+                $res->[$row][$col] = $cell->{Val};
+            }
+        }
+    }
+    $res
+}

Added: Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/lib/TestApp/Controller/REST.pm
===================================================================
--- Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/lib/TestApp/Controller/REST.pm	                        (rev 0)
+++ Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/lib/TestApp/Controller/REST.pm	2008-11-11 11:57:18 UTC (rev 8587)
@@ -0,0 +1,42 @@
+package TestApp::Controller::REST;
+
+use strict;
+use warnings;
+use parent 'Catalyst::Controller::REST';
+
+__PACKAGE__->config->{map}{'application/vnd.ms-excel'} = 'SimpleExcel';
+
+sub a_o_a : Local ActionClass('REST') {}
+
+sub a_o_a_GET {
+    my ($self, $c) = @_;
+
+    $self->status_ok(
+        $c,
+        entity => [
+            [1,2,3],
+            [4,5,6]
+        ]
+    );
+}
+
+sub fancy : Local ActionClass('REST') {}
+
+sub fancy_GET {
+    my ($self, $c) = @_;
+
+    $self->status_ok(
+        $c,
+        entity => {
+            header => [qw/Foo Bar/],
+            column_widths => [10, 20],
+            rows => [
+                [1,2],
+                [3,4]
+            ],
+            filename => 'mtfnpy'
+        }
+    );
+}
+
+1;

Added: Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/lib/TestApp.pm
===================================================================
--- Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/lib/TestApp.pm	                        (rev 0)
+++ Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/lib/TestApp.pm	2008-11-11 11:57:18 UTC (rev 8587)
@@ -0,0 +1,8 @@
+package TestApp;
+
+use Catalyst::Runtime '5.70';
+use parent 'Catalyst';
+
+__PACKAGE__->setup;
+
+1;

Added: Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/pod.t
===================================================================
--- Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/pod.t	                        (rev 0)
+++ Catalyst-Action-Serialize-SimpleExcel/1.000/trunk/t/pod.t	2008-11-11 11:57:18 UTC (rev 8587)
@@ -0,0 +1,12 @@
+#!perl -T
+
+use strict;
+use warnings;
+use Test::More;
+
+# Ensure a recent version of Test::Pod
+my $min_tp = 1.22;
+eval "use Test::Pod $min_tp";
+plan skip_all => "Test::Pod $min_tp required for testing POD" if $@;
+
+all_pod_files_ok();




More information about the Catalyst-commits mailing list