1 %# BEGIN BPS TAGGED BLOCK {{{
5 %# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
6 %# <jesse@bestpractical.com>
8 %# (Except where explicitly superseded by other copyright notices)
13 %# This work is made available to you under the terms of Version 2 of
14 %# the GNU General Public License. A copy of that license should have
15 %# been provided with this software, but in any event can be snarfed
18 %# This work is distributed in the hope that it will be useful, but
19 %# WITHOUT ANY WARRANTY; without even the implied warranty of
20 %# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 %# General Public License for more details.
23 %# You should have received a copy of the GNU General Public License
24 %# along with this program; if not, write to the Free Software
25 %# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 %# 02110-1301 or visit their web page on the internet at
27 %# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
30 %# CONTRIBUTION SUBMISSION POLICY:
32 %# (The following paragraph is not intended to limit the rights granted
33 %# to you to modify and distribute this software under the terms of
34 %# the GNU General Public License and is only of importance to you if
35 %# you choose to contribute your changes and enhancements to the
36 %# community by submitting them to Best Practical Solutions, LLC.)
38 %# By intentionally submitting any modifications, corrections or
39 %# derivatives to this work, or any other work intended for use with
40 %# Request Tracker, to Best Practical Solutions, LLC, you confirm that
41 %# you are the copyright holder for those contributions and you grant
42 %# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
43 %# royalty-free, perpetual, license to use, copy, create derivative
44 %# works based on those contributions, and sublicense and distribute
45 %# those contributions and any derivatives thereof.
47 %# END BPS TAGGED BLOCK }}}
54 use OpenOffice::OODoc;
56 if ( -w $RT::VarPath ) {
57 $tmpdir = File::Temp::tempdir( DIR => $RT::VarPath, CLEANUP => 1 );
58 } elsif (-w File::Spec->tmpdir) {
59 $tmpdir = File::Temp::tempdir( TMPDIR => 1, CLEANUP => 1 );
61 $RT::Logger->crit("Neither the RT var directory ($RT::VarPath) nor the system tmpdir (@{[File::Spec->tmpdir]}) are writable!");
63 my $tmpfile = File::Spec->catfile( $tmpdir, 'Results.ods' );
64 odfWorkingDirectory($tmpdir);
65 my $workbook = odfDocument(file => $tmpfile, create => 'spreadsheet') or die $!;
67 my $Tickets = RT::Tickets->new( $session{'CurrentUser'} );
68 $Tickets->FromSQL( $ARGS{'Query'} );
69 if ( $OrderBy =~ /\|/ ) {
72 my @OrderBy = split /\|/, $OrderBy;
73 my @Order = split /\|/, $Order;
74 $Tickets->OrderByCols(
75 map { { FIELD => $OrderBy[$_], ORDER => $Order[$_] } }
79 $Tickets->OrderBy( FIELD => $OrderBy, ORDER => $Order );
85 my @attrs = qw( id QueueObj->Name Subject Status TimeEstimated TimeWorked TimeLeft Priority FinalPriority OwnerObj->Name
86 Requestors->MemberEmailAddressesAsString Cc->MemberEmailAddressesAsString AdminCc->MemberEmailAddressesAsString
87 DueObj->ISO ToldObj->ISO CreatedObj->ISO ResolvedObj->ISO LastUpdatedObj->ISO);
89 $r->content_type('application/vnd.oasis.opendocument.spreadsheet');
90 while ( my $Ticket = $Tickets->Next()) {
92 foreach my $attr (@attrs) {
93 if ($attr =~ /(.*)->ISO$/ and $Ticket->$1->Unix <= 0) {
96 my $method = '$Ticket->'.$attr.'()';
97 $method =~ s/->ISO\(\)$/->ISO( Timezone => 'user' )/;
98 $row->{$attr} = eval $method;
99 if ($@) {die "Failed to find $attr - ". $@};
103 my $cfs = $Ticket->QueueObj->TicketCustomFields();
104 while (my $cf = $cfs->Next) {
105 $known_cfs{$cf->Id} = $cf->Name;
107 my $values = $Ticket->CustomFieldValues($cf->Id);
108 while (my $value = $values->Next) {
109 push @content, $value->Content;
111 $row->{'CustomField-'.$cf->Id} = join(', ',@content);
116 my $rows_count = scalar(@rows) + 1;
117 my $cols_count = scalar(@attrs) + scalar( keys %known_cfs );
119 $workbook->expandTable(0, $rows_count, $cols_count );
129 while ($dividend > 0 ) {
130 $modulo = ($dividend - 1) % 26;
131 $alpha = chr(65 + $modulo).$alpha;
132 $dividend = int(($dividend - $modulo) / 26);
139 my $xml = '<table:database-ranges><table:database-range table:name="AllRTTickets" table:target-range-address="Sheet1.A1:Sheet1.'.int_to_alpha($cols_count - 1).$rows_count.'"/></table:database-ranges>';
140 my $xmlpos = $workbook->getElement('//table:table', 0);
141 $workbook->insertElement ( $xmlpos, $xml, position => 'after');
146 foreach my $attr (@attrs) {
148 $label =~ s'Obj-.(?:AsString|Name|ISO)''g;
149 $label =~ s'-\>MemberEmailAddressesAsString''g;
150 Encode::_utf8_off($label);
151 $workbook->updateCell(0, 0, $ws_col, $label);
154 foreach my $id (sort keys %known_cfs) {
155 Encode::_utf8_off($known_cfs{$id});
156 $workbook->updateCell(0, 0, $ws_col, "CF-".$known_cfs{$id});
162 foreach my $row (@rows) {
165 foreach my $attr(@attrs) {
166 Encode::_utf8_off($row->{"$attr"});
167 $workbook->updateCell(0, $ws_row, $ws_col, $row->{"$attr"});
170 foreach my $id (sort keys %known_cfs) {
171 my $val = $row->{'CustomField-'.$id};
172 #$val =~ s/(\n|\r)//g;
173 Encode::_utf8_off($val);
174 $workbook->updateCell(0, $ws_row, $ws_col, $val);
180 open (ODT, $tmpfile);