From b7325c637b480c4c8866de71f5b93f5cd11cb38f Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Tue, 4 Feb 2014 13:26:54 +0100 Subject: [PATCH] Bug 11679: Add ods as a format for reports This patch adds the ability to export the data generated by a report into a ods file. Test plan: Install csv2ods (cf commit message from bug 11603 for the install instructions) and verify you are able to generate an ods file from a report result. Signed-off-by: Aurelie Fichot --- .../en/modules/reports/guided_reports_start.tt | 3 + reports/guided_reports.pl | 52 +++++++++++++++++--- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tt index 63608f7..3a36adf 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tt @@ -814,6 +814,9 @@ canned reports and writing custom SQL reports.

diff --git a/reports/guided_reports.pl b/reports/guided_reports.pl index b9c49ad..394fadf 100755 --- a/reports/guided_reports.pl +++ b/reports/guided_reports.pl @@ -21,6 +21,7 @@ use CGI qw/-utf8/; use Text::CSV; use URI::Escape; +use File::Temp; use C4::Reports::Guided; use C4::Auth qw/:DEFAULT get_session/; use C4::Output; @@ -761,6 +762,13 @@ elsif ($phase eq 'Run this report'){ else { push @errors, { no_sql_for_id => $report_id }; } + my $csv2ods_cmd = qx|which csv2ods|; + chomp $csv2ods_cmd; + my $csv2ods_is_installed = + ( not $csv2ods_cmd or not -f $csv2ods_cmd ) + ? 0 + : 1; + $template->param( csv2ods_is_installed => $csv2ods_is_installed ); } elsif ($phase eq 'Export'){ @@ -771,30 +779,58 @@ elsif ($phase eq 'Export'){ my $format = $input->param('format'); my ($sth, $q_errors) = execute_query($sql); unless ($q_errors and @$q_errors) { - print $input->header( -type => 'application/octet-stream', - -attachment=>"reportresults.$format" - ); + my ( $type, $content ); if ($format eq 'tab') { - print join("\t", header_cell_values($sth)), "\n"; + $type = 'application/octet-stream'; + $content .= join("\t", header_cell_values($sth)) . "\n"; while (my $row = $sth->fetchrow_arrayref()) { - print join("\t", @$row), "\n"; + $content .= join("\t", @$row) . "\n"; } } else { - my $csv = Text::CSV->new({binary => 1}); + my $delimiter = C4::Context->preference('delimiter') || ','; + my $csv_content = q||; + my $csv = Text::CSV->new({binary => 1, sep_char => $delimiter}); $csv or die "Text::CSV->new({binary => 1}) FAILED: " . Text::CSV->error_diag(); if ($csv->combine(header_cell_values($sth))) { - print $csv->string(), "\n"; + $csv_content .= $csv->string(). "\n"; } else { push @$q_errors, { combine => 'HEADER ROW: ' . $csv->error_diag() } ; } while (my $row = $sth->fetchrow_arrayref()) { if ($csv->combine(@$row)) { - print $csv->string(), "\n"; + $csv_content .= $csv->string() . "\n"; } else { push @$q_errors, { combine => $csv->error_diag() } ; } } + if ( $format eq 'csv' ) { + $type = 'application/csv'; + $content = $csv_content; + } + elsif ( $format eq 'ods' ) { + $type = 'application/vnd.oasis.opendocument.spreadsheet'; + my $csv_fh = File::Temp->new(); + my $ods_fh = File::Temp->new(); + print $csv_fh $csv_content; + my $csv_filepath = $csv_fh->filename; + my $ods_filepath = $ods_fh->filename; + + my $csv2ods_cmd = qx|which csv2ods|; + chomp $csv2ods_cmd; + qx| + $csv2ods_cmd -i $csv_filepath -o $ods_filepath -d '$delimiter' + |; + + binmode(STDOUT); + $content .= $_ while <$ods_fh>; + } } + print $input->header( + -type => $type, + -attachment=>"reportresults.$format" + ); + print $content; + foreach my $err (@$q_errors, @errors) { print "# ERROR: " . (map {$_ . ": " . $err->{$_}} keys %$err) . "\n"; } # here we print all the non-fatal errors at the end. Not super smooth, but better than nothing. -- 1.7.2.5