Merge branch 'patch-1' of https://github.com/gjones2/Freeside
[freeside.git] / httemplate / search / report_tax-xls.cgi
1 <%init>
2 my $htmldoc = include('report_tax.cgi');
3
4 my ($title) = ($htmldoc =~ /<title>\s*(.*)\s*<\/title>/i);
5
6 # do this first so we can override the format if it's too many rows
7 # attribs option: how to locate the table?  It's the only one with class="grid".
8 my $te = HTML::TableExtract->new(attribs => {class => 'grid'});
9 $te->parse($htmldoc);
10 my $table = $te->first_table_found;
11
12 my $override = ($table->row_count >= 65536 ? 'XLSX' : '');
13 my $format = $FS::CurrentUser::CurrentUser->spreadsheet_format($override);
14 my $filename = 'report_tax'.$format->{extension};
15
16 http_header('Content-Type' => $format->{mime_type});
17 http_header('Content-Disposition' => qq!attachment;filename="$filename"! );
18
19 my $data = '';
20 my $XLS = new IO::Scalar \$data;
21 my $workbook = $format->{class}->new($XLS)
22   or die "Error opening .xls file: $!";
23
24 # hardcoded formats, this could be handled better
25 my $light_gray = $workbook->set_custom_color(63, '#eeeeee');
26 my %format = (
27   title => {
28     size      => 24,
29     align     => 'center',
30     bg_color  => 'silver',
31   },
32   colhead => {
33     size      => 11,
34     bold      => 1,
35     align     => 'center',
36     valign    => 'vcenter',
37     text_wrap => 1,
38   },
39   rowhead => {
40     size      => 11,
41     valign    => 'bottom',
42     text_wrap => 1,
43   },
44   amount  => {
45     size      => 11,
46     align     => 'right',
47     valign    => 'bottom',
48     num_format=> 8,
49   },
50   'size-1' => {
51     size      => 7.5,
52     align     => 'center',
53     valign    => 'vcenter',
54     bold      => 1,
55     text_wrap => 1,
56   },
57   'size+1' => {
58     size      => 12,
59     align     => 'center',
60     valign    => 'vcenter',
61     bold      => 1,
62   },
63   text => {
64     size      => 11,
65     text_wrap => 1,
66   },
67 );
68 my %default = (
69   font      => 'Calibri',
70   bg_color  => $light_gray,
71   border    => 1,
72 );
73 my @widths = ( #ick
74   18, (10.5, 3) x 6, 10.5, 10.5, 3, 10.5, 3, 10.5, 3, 10.5
75 );
76 foreach (keys(%format)) {
77   my %f = (%default, %{$format{$_}});
78   $format{$_} = $workbook->add_format(%f);
79   $format{"m_$_"} = $workbook->add_format(%f); # for merged cells
80   $format{"t_$_"} = $workbook->add_format(%f, bg_color => 'yellow'); # totals
81 }
82 my $ws = $workbook->add_worksheet('taxreport');
83
84 my @sheet;
85 $sheet[0][0] = {
86   text    => $title,
87   format  => 'title',
88   colspan => '18',
89 };  
90 # excel position
91 my $x = 0;
92 my $y = 3;
93 foreach my $row ($table->rows()) {
94   $x = 0;
95   $sheet[$y] = [];
96   foreach my $cell (@$row) {
97     if ($cell and ref($cell) eq 'HTML::ElementTable::DataElement') {
98       my $f = 'text';
99       if ( $cell->as_HTML =~ /font/i ) {
100         my ($el) = $cell->content_list;
101         $f = 'size'.$el->attr('size') if $el->attr('size');
102       }
103       elsif ( $cell->as_text =~ /^\$/ ) {
104         $f = 'amount'
105       }
106       elsif ( $cell->tag eq 'th' ) {
107         $f = 'colhead';
108       }
109       elsif ( $x == 0 ) {
110         $f = 'rowhead';
111       }
112       $sheet[$y][$x] = {
113         text    => $cell->as_text,
114         format  => $f,
115         rowspan => $cell->attr('rowspan'),
116         colspan => $cell->attr('colspan'),
117       };
118     }
119     $x++;
120   } #for $cell
121   $y++;
122 }
123
124 $y = 0;
125 foreach my $row (@sheet) {
126   $x = 0;
127   my $t_row = 1 if($row->[0]->{'text'} eq 'Total');
128   foreach my $cell (@$row) {
129     if ($cell) {
130       my $f = $cell->{format};
131       if ($cell->{rowspan} > 1 or $cell->{colspan} > 1) {
132         my $range = xl_range_formula(
133           'Taxreport', 
134           $y,
135           $y - 1 + ($cell->{rowspan} || 1),
136           $x,
137           $x - 1 + ($cell->{colspan} || 1)
138         );
139         $ws->merge_range($range, $cell->{text}, $format{"m_$f"});
140       }
141       else {
142         $f = "t_$f" if $t_row;
143         $ws->write($y, $x, $cell->{text}, $format{$f});
144       }
145     } #if $cell
146     $x++;
147   }
148   $y++;
149 }
150
151 for my $x (0..scalar(@widths)-1) {
152   $ws->set_column($x, $x, $widths[$x]);
153 }
154
155 $workbook->close;
156
157 http_header('Content-Length' => length($data));
158 $m->print($data);
159 </%init>