Bug 21560: create Koha::Util::OpenDocument with subroutine for ODS generation

There is nearly the same code in misc/cronjobs/gather_print_notices.pl and reports/guided_reports.pl.
This patch creates a new module with subroutine called by both scripts.

If file path or content is undefined, subroutine will just return undef.
If content is an empty arrayref, empty ods file is still generated.

Unicode encoding is kept outisde because it may not be necessary.

Note that for print notices the first line of message is always the column names so it is extracted only from first message.

Test plan :
Run previous patches test plans and check ODS files are the same.

Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
This commit is contained in:
Fridolin Somers 2019-02-18 17:33:37 +01:00 committed by root
parent 5d4f80feac
commit ffb40290f8
3 changed files with 133 additions and 77 deletions

95
Koha/Util/OpenDocument.pm Normal file
View file

@ -0,0 +1,95 @@
package Koha::Util::OpenDocument;
# Copyright 2019 Biblibre
#
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 3 of the License, or (at your option) any later
# version.
#
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Koha; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
use Modern::Perl;
use Encode qw( decode );
use File::Temp;
use File::Basename qw( dirname );
use OpenOffice::OODoc;
use parent qw( Exporter );
our @EXPORT = qw(
generate_ods
);
=head1 NAME
Koha::Util::OpenDocument - utility class to manage filed in Open Document Format aka OpenDocument
=head1 METHODS
=head2 generate_ods
Generate an Open Document Sheet
Arguments are file path and content as an arrayref of lines containing arrayrefs of cells.
=cut
sub generate_ods {
my ( $filepath, $content ) = @_;
unless ( $filepath && $content ) {
return;
}
my @input_rows = @$content;
my $nb_rows = scalar @input_rows;
my $nb_cols;
if ($nb_rows) {
$nb_cols= scalar @{ $input_rows[0] };
}
# Create document
my $wdir = dirname($filepath);
odfWorkingDirectory($wdir);
my $odf_doc = odfDocument( file => $filepath, create => 'spreadsheet' );
if ($nb_rows) {
# Prepare sheet
my $odf_sheet = $odf_doc->expandTable( 0, $nb_rows + 1, $nb_cols );
my @odf_rows = $odf_doc->getTableRows($odf_sheet);
# Writing
for ( my $i = 0 ; $i < $nb_rows ; $i++ ) {
for ( my $j = 0 ; $j < $nb_cols ; $j++ ) {
my $cellval = $input_rows[$i][$j];
$odf_doc->cellValue( $odf_rows[$i], $j, $cellval );
}
}
}
# Done
$odf_doc->save();
return $odf_doc;
}
1;
__END__
=head1 AUTHOR
Koha Development Team <http://koha-community.org/>
Fridolin Somers <fridolin.somers@biblibre.com>
=cut

View file

@ -19,7 +19,6 @@ use Pod::Usage;
use Getopt::Long;
use C4::Log;
use File::Basename qw( dirname );
use Koha::DateUtils;
use MIME::Lite;
@ -181,7 +180,7 @@ sub print_notices {
filepath => $filepath,
});
} elsif ( $format eq 'ods' ) {
generate_ods ({
_generate_ods ({
messages => $branch_messages,
filepath => $filepath,
});
@ -249,57 +248,36 @@ sub generate_csv {
}
}
sub generate_ods {
sub _generate_ods {
my ( $params ) = @_;
my $messages = $params->{messages};
my $filepath = $params->{filepath};
# Create document
use OpenOffice::OODoc;
my $tmpdir = dirname $filepath;
odfWorkingDirectory( $tmpdir );
my $doc = odfDocument( file => $filepath, create => 'spreadsheet' );
my $ods_filepath = $params->{filepath};
# Prepare sheet
my @headers;
my @rows;
my $i = 0;
my $ods_content;
my $has_headers;
foreach my $message ( @$messages ) {
my @lines = split /\n/, $message->{content};
chomp for @lines;
# We don't have headers, get them
unless ( @headers ) {
@headers = split $delimiter, $lines[0];
my $nb_cols = scalar @headers;
my $nb_rows = scalar @$messages;
my $sheet = $doc->expandTable( 0, $nb_rows + 1, $nb_cols );
@rows = $doc->getTableRows($sheet);
# Write headers row
my $row = $rows[0];
my $j = 0;
for my $header ( @headers ) {
$doc->cellValue( $row, $j, Encode::encode( 'UTF8', $header ) );
$j++;
}
$i = 1;
my @message_lines = split /\n/, $message->{content};
chomp for @message_lines;
# Get headers from first message
if ($has_headers) {
shift @message_lines;
} else {
$has_headers = 1;
}
# Write all rows
shift @lines; # remove headers
for my $line ( @lines ) {
my @row_data = split $delimiter, $line;
my $row = $rows[$i];
# Note scalar(@$row_data) should be equal to $nb_cols
for ( my $j = 0 ; $j < scalar(@row_data) ; $j++ ) {
my $value = Encode::encode( 'UTF8', $row_data[$j] );
$doc->cellValue( $row, $j, $value );
foreach my $message_line ( @message_lines ) {
my @content_row;
my @message_cells = split $delimiter, $message_line;
foreach ( @message_cells ) {
push @content_row, Encode::encode( 'UTF8', $_ );
}
$i++;
push @$ods_content, \@content_row;
}
}
$doc->save();
# Process
use Koha::Util::OpenDocument;
generate_ods($ods_filepath, $ods_content);
}
sub send_files {

View file

@ -23,7 +23,6 @@ use Text::CSV::Encoded;
use Encode qw( decode );
use URI::Escape;
use File::Temp;
use File::Basename qw( dirname );
use C4::Reports::Guided;
use Koha::Reports;
use C4::Auth qw/:DEFAULT get_session/;
@ -922,43 +921,27 @@ elsif ($phase eq 'Export'){
$type = 'application/vnd.oasis.opendocument.spreadsheet';
my $ods_fh = File::Temp->new( UNLINK => 0 );
my $ods_filepath = $ods_fh->filename;
my $ods_content;
# Create document
use OpenOffice::OODoc;
my $tmpdir = dirname $ods_filepath;
odfWorkingDirectory( $tmpdir );
my $doc = odfDocument( file => $ods_filepath, create => 'spreadsheet' );
# First line is headers
my @headers = header_cell_values($sth);
push @$ods_content, \@headers;
# Prepare sheet
my @headers = header_cell_values( $sth );
my $rows = $sth->fetchall_arrayref();
my ( $nb_rows, $nb_cols ) = ( 0, 0 );
$nb_rows = @$rows;
$nb_cols = @headers;
my $sheet = $doc->expandTable( 0, $nb_rows + 1, $nb_cols );
my @rows = $doc->getTableRows($sheet);
# Write headers row
my $row = $rows[0];
my $j = 0;
for my $header ( @headers ) {
$doc->cellValue( $row, $j, $header );
$j++;
}
# Write all rows
my $i = 1;
for ( @$rows ) {
$row = $rows[$i];
for ( my $j = 0 ; $j < $nb_cols ; $j++ ) {
my $value = Encode::encode( 'UTF8', $rows->[$i - 1][$j] );
$doc->cellValue( $row, $j, $value );
# Other line in Unicode
my $sql_rows = $sth->fetchall_arrayref();
foreach my $sql_row ( @$sql_rows ) {
my @content_row;
foreach my $sql_cell ( @$sql_row ) {
push @content_row, Encode::encode( 'UTF8', $sql_cell );
}
$i++;
push @$ods_content, \@content_row;
}
# Done
$doc->save();
# Process
use Koha::Util::OpenDocument;
generate_ods($ods_filepath, $ods_content);
# Output
binmode(STDOUT);
open $ods_fh, '<', $ods_filepath;
$content .= $_ while <$ods_fh>;