Raw content of BioMart::Formatter::XLS # # BioMart module for BioMart::Formatter::XLS # # You may distribute this module under the same terms as perl # itself. # POD documentation - main docs before the code. =head1 NAME BioMart::Formatter::XLS =head1 SYNOPSIS The XLS Formatter returns XLS format data for a BioMart querys ResultTable =head1 DESCRIPTION When given a BioMart::ResultTable containing the results of a BioMart::Query the XLS Formatter will return XLS file, open in the browser if it supports xls mime type. =head1 AUTHOR - Syed Haider, Damian Smedley =head1 CONTACT This module is part of the BioMart project http://www.biomart.org Questions can be posted to the mart-dev mailing list: mart-dev@ebi.ac.uk =head1 METHODS =cut package BioMart::Formatter::XLS; use strict; use warnings; use Readonly; use Spreadsheet::WriteExcel; use Spreadsheet::WriteExcel::Big; use Digest::SHA qw (sha256_base64); # Extends BioMart::FormatterI use base qw(BioMart::FormatterI); sub _new { my ($self) = @_; $self->SUPER::_new(); } sub getXlsString { my $self = shift; return $self->get('xlsString'); } sub processQuery { my ($self, $query) = @_; $self->set('original_attributes',[@{$query->getAllAttributes()}]) if ($query->getAllAttributes()); $query = $self->setHTMLAttributes($query); $self->set('query',$query); return $query; } sub printResults { my ($self, $filehandle, $lines, $uniqueResults) = @_; # on web26 the filehandle was getting lost/corrupted so best to create from scratch - not necessary if using # just WriteExcel for some reason. HOWEVER this fix broke all other setups so revert - to be investigated # in the future if it appears anywhere else # $filehandle = IO::File->new(); # my $tie = ref tied( *STDOUT );# always 'Apache' even for gz on web26 - hence don't get zipped output # tie *$filehandle, $tie; # binmode($filehandle); my $workbook = Spreadsheet::WriteExcel::Big->new($filehandle); #---------------------------------------- worksheet properties #binmode(STDOUT); #my $workbook = Spreadsheet::WriteExcel::Big->new("/homes/syed/Desktop/temp9/biomart-web/lib/BioMart/Formatter/perl.xls"); #my $workbook = Spreadsheet::WriteExcel::Big->new(\*STDOUT); #tie *XLS => $r; # Tie to the Apache::RequestRec object #binmode(*XLS); #my $workbook = Spreadsheet::WriteExcel::Big->new(\*XLS); # Add a worksheet my $worksheet = $workbook->add_worksheet(); $self->attr('workbook', $workbook); $self->attr('worksheet', $worksheet); $self->attr('rows', 0); $self->attr('columns', 0); my $format = $self->get('workbook')->addformat(); $format->set_align('left'); $format->set_bg_color('white'); $format->set_color('black'); $self->attr('format', $format); $self->attr('colWidth', undef); #------------------------------------------------------------- my @displayNames = $self->getTextDisplayNames(); my $formatDisplay = $self->get('workbook')->addformat(); $formatDisplay->set_bold(); $formatDisplay->set_align('centre'); $formatDisplay->set_bg_color('black'); $formatDisplay->set_color('white'); my $width; foreach(@displayNames) { $width->{$self->get('columns')} = length($_) * 1.2 ; $self->get('worksheet')->set_column($self->get('columns'), $self->get('columns'), $width->{$self->get('columns')}); $self->get('worksheet')->write($self->get('rows'), $self->get('columns'), $_, $formatDisplay); $self->set('columns', $self->get('columns') + 1); } $self->set('rows', $self->get('rows') + 1); $self->get('worksheet')->freeze_panes(1, 0); # Freeze the first row $self->set('colWidth', $width); #------------------------------------------------------------------------------------ my $new_row; my $new_row_contents; my $rtable = $self->get('result_table'); my $counter = 0; my $row; my %collisions; while ($rtable->hasMoreRows) { $self->set('columns',0); $new_row = (); $row = $rtable->nextRow; if ($uniqueResults) { no warnings 'uninitialized'; my $hash = sha256_base64("@{$row}"); next if exists $collisions{$hash}; $collisions{$hash} = undef; } $counter++; if (!$row || ($lines && $counter > $lines)) { $self->closeWorkBook; return; } map { $_ ||= q{}; } @$row; my $attribute_positions = $self->get('attribute_positions'); my $attribute_url_positions = $self->get('attribute_url_positions'); my $attribute_url = $self->get('attribute_url'); for (my $i = 0; $i < @{$attribute_positions}; $i++) { if ($$attribute_url[$i]) { my @url_data = map {$$row[$_]} @{$$attribute_url_positions[$i]}; my $url_string = sprintf($$attribute_url[$i],@url_data); #push @{$new_row}, $url_string, $$row[$$attribute_positions[$i]]; $new_row_contents->{value} = $$row[$$attribute_positions[$i]]; $new_row_contents->{URL} = $url_string; } else { $new_row_contents->{value} = $$row[$$attribute_positions[$i]]; $new_row_contents->{URL} = undef; } push @{$new_row}, $new_row_contents; $new_row_contents = (); } #------------------------------------------------------------------------------ # Enclose non-numeric values in double quotes & escape the quotes already in them foreach(@{$new_row}) { if($self->get('colWidth')->{$self->get('columns')} < length($_->{value}) ) { if ( length($_->{value}) > 200) { $self->get('colWidth')->{$self->get('columns')} = 200; # maximum column display length $self->get('worksheet')->set_column($self->get('columns'), $self->get('columns'), 200); } else { $self->get('colWidth')->{$self->get('columns')} = length($_->{value}); $self->get('worksheet')->set_column($self->get('columns'), $self->get('columns'), length($_->{value})); } } if($_->{URL}) { ## tab below with $_->{value} is prepended to handle hyperlinks on numeric values. $self->get('worksheet')->write_url($self->get('rows'), $self->get('columns'), $_->{URL}, $_->{value} ); # , $self->get('format')); } else { $self->get('worksheet')->write($self->get('rows'), $self->get('columns'), $_->{value} ); # , $self->get('format')); } $self->set('columns', $self->get('columns') + 1); } #------------------------------------------------------------------------------ $self->set('rows', $self->get('rows') + 1); } $self->closeWorkBook; return; } sub getDisplayNames { return undef; } sub closeWorkBook { my $self = shift; $self->get('workbook')->close; } sub getFileType { return 'xls'; } sub getMimeType { return 'application/vnd.ms-excel'; } sub isBinary { return 1; } 1;