c6f0d4436039b97519644a57e94f08c915baae3d
[fa-stable.git] / reporting / includes / excel_report.inc
1 <?php
2 /**********************************************************************
3     Copyright (C) FrontAccounting, LLC.
4         Released under the terms of the GNU General Public License, GPL, 
5         as published by the Free Software Foundation, either version 3 
6         of the License, or (at your option) any later version.
7     This program is distributed in the hope that it will be useful,
8     but WITHOUT ANY WARRANTY; without even the implied warranty of
9     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
10     See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
11 ***********************************************************************/
12 include_once($path_to_root . "/reporting/includes/Workbook.php");
13 include_once($path_to_root . "/admin/db/company_db.inc");
14 include_once($path_to_root . "/admin/db/fiscalyears_db.inc");
15 include_once($path_to_root . "/config.php");
16 // xls version
17 class FrontReport extends Spreadsheet_Excel_Writer_Workbook
18 {
19         var $size;
20         var $company;
21         var $user;
22         var $host;
23         var $fiscal_year;
24         var $title;
25         var $filename;
26         var $unique_name;
27         var $path;
28         var $code;
29         var $bottomMargin = 0;
30         var $lineHeight;
31         var $leftMargin = 0;
32         var $pageWidth;         // dummy
33         var $rightMargin;       // dummy
34
35         var $cols;
36         var $params;
37         var $headers;
38         var $aligns;
39         var $headers2;
40         var $aligns2;
41         var $cols2;
42         var $fontSize;
43         var $oldFontSize;
44         var $currency;
45         var $row = 9999999;
46         var $y;
47         var $numcols;
48         var $excelColWidthFactor;
49         var $endLine;
50
51         var $formatTitle;
52         var $formatDateTime;
53         var $formatDate;
54         var $formatHeaderLeft;
55         var $formatHeaderRight;
56         var $formatFooter;
57         var $formatAmount = array();
58         var $headerFunc;
59         
60         var $sheet;
61
62         function FrontReport($title, $filename, $size = 'A4', $fontsize = 9, $orientation = 'P', $margins = NULL, $excelColWidthFactor = 6.5)
63         {
64                 global $SysPrefs, $page_security;
65
66                 if (!$_SESSION["wa_current_user"]->can_access_page($page_security))
67                 {
68                         display_error(_("The security settings on your account do not permit you to print this report"));
69                         end_page();
70                         exit;
71                 }
72                 $this->size = $size;
73                 $this->title = $title;
74                 $this->lineHeight = 12;
75                 $this->endLine = 760;
76                 $this->SetFontSize($fontsize);
77                 $this->oldFontSize = 0;
78                 $this->y = 0;
79                 $this->currency = '';
80                 $this->excelColWidthFactor = $excelColWidthFactor;
81                 $rtl = ($_SESSION['language']->dir == 'rtl');
82                 $this->code = strtolower($_SESSION['language']->encoding);
83                 $this->filename = $filename.".xls";
84                 $this->unique_name = random_id().".xls";
85                 $this->path = company_path(). '/pdf_files';
86                 $this->Spreadsheet_Excel_Writer_Workbook($this->path."/".$this->unique_name);
87                 if ($this->code != "iso-8859-1")
88                         $this->setVersion(8); // set biff version to 8 (0x0006 internal)
89                 $this->sheet =& $this->addWorksheet($this->worksheetNameGenerator($this->title));
90                 if ($this->code != "iso-8859-1")
91                         $this->sheet->setInputEncoding($this->code); // set sheet encoding
92                 if ($rtl)
93                         $this->sheet->setRTL();
94                 $this->formatTitle =& $this->addFormat();       
95                 $this->formatTitle->setSize(16);
96                 $this->formatTitle->setBold();
97                 $this->formatTitle->setAlign($rtl ? 'right' : 'left');
98                 $this->formatTitle->setTop(2);
99                 $this->formatTitle->setTopColor('gray');
100
101                 $how = user_date_format();
102                 $sep = $SysPrefs->dateseps[user_date_sep()];
103                 if ($sep == '.')
104                         $sep = "\\.";
105                 if ($how == 0)
106                 {
107                         $dateformat_long = "mm{$sep}dd{$sep}yyyy\ \ hh:mm\ am/pm";
108                         $dateformat = "mm{$sep}dd{$sep}yyyy";
109                 }       
110                 elseif ($how == 1)      
111                 {
112                         $dateformat_long = "dd{$sep}mm{$sep}yyyy\ \ hh:mm";
113                         $dateformat = "dd{$sep}mm{$sep}yyyy";
114                 }       
115                 else    
116                 {
117                         $dateformat_long = "yyyy{$sep}mm{$sep}dd\ \ hh:mm";
118                         $dateformat = "yyyy{$sep}mm{$sep}dd";
119                 }       
120                 $this->formatDateTime =& $this->addFormat();
121                 $this->formatDateTime->setNumFormat($dateformat_long);
122                 $this->formatDateTime->setAlign($rtl ? 'right' : 'left');
123                 $this->formatDate =& $this->addFormat();
124                 $this->formatDate->setNumFormat($dateformat);
125                 $this->formatDate->setAlign($rtl ? 'right' : 'left');
126                 $this->formatRight =& $this->addFormat();
127                 $this->formatRight->setAlign($rtl ? 'left' : 'right');
128                 $this->formatLeft =& $this->addFormat();
129                 $this->formatLeft->setAlign($rtl ? 'right' : 'left');
130                 
131                 $this->formatHeaderLeft =& $this->addFormat();
132                 $this->formatHeaderLeft->setItalic();
133                 $this->formatHeaderLeft->setTop(2);
134                 $this->formatHeaderLeft->setTopColor('gray');
135                 $this->formatHeaderLeft->setBottom(2);
136                 $this->formatHeaderLeft->setBottomColor('gray');
137                 $this->formatHeaderLeft->setAlign('vcenter');
138                 $this->formatTopHeaderLeft =& $this->addFormat();
139                 $this->formatTopHeaderLeft->setItalic();
140                 $this->formatTopHeaderLeft->setTop(2);
141                 $this->formatTopHeaderLeft->setTopColor('gray');
142                 $this->formatTopHeaderLeft->setAlign('vcenter');
143                 $this->formatBottomHeaderLeft =& $this->addFormat();
144                 $this->formatBottomHeaderLeft->setItalic();
145                 $this->formatBottomHeaderLeft->setBottom(2);
146                 $this->formatBottomHeaderLeft->setBottomColor('gray');
147                 $this->formatBottomHeaderLeft->setAlign('vcenter');
148                 $this->formatDate->setAlign($rtl ? 'right' : 'left');
149                 $this->formatHeaderRight =& $this->addFormat();
150                 $this->formatHeaderRight->setItalic();
151                 $this->formatHeaderRight->setTop(2);
152                 $this->formatHeaderRight->setTopColor('gray');
153                 $this->formatHeaderRight->setBottom(2);
154                 $this->formatHeaderRight->setBottomColor('gray');
155                 $this->formatHeaderRight->setAlign('vcenter');
156                 $this->formatHeaderRight->setAlign('right');
157                 $this->formatTopHeaderRight =& $this->addFormat();
158                 $this->formatTopHeaderRight->setItalic();
159                 $this->formatTopHeaderRight->setTop(2);
160                 $this->formatTopHeaderRight->setTopColor('gray');
161                 $this->formatTopHeaderRight->setAlign('vcenter');
162                 $this->formatTopHeaderRight->setAlign('right');
163                 $this->formatBottomHeaderRight =& $this->addFormat();
164                 $this->formatBottomHeaderRight->setItalic();
165                 $this->formatBottomHeaderRight->setBottom(2);
166                 $this->formatBottomHeaderRight->setBottomColor('gray');
167                 $this->formatBottomHeaderRight->setAlign('vcenter');
168                 $this->formatBottomHeaderRight->setAlign('right');
169                 $this->formatFooter =& $this->addFormat();
170                 $this->formatFooter->setTop(2);
171                 $this->formatFooter->setTopColor('gray');
172                 $this->SetHeaderType("header");
173         }
174         
175
176         /*
177                 Set header handler
178         */
179         function SetHeaderType($name) {
180                 $this->headerFunc = $name;
181         }
182         // Check a given name to see if it's a valid Excel worksheet name,
183         // and fix if necessary
184         function worksheetNameGenerator($name)
185         {
186                 // First, strip out characters which aren't allowed
187                 $illegal_chars = array(':', '\\', '/', '?', '*', '[', ']');
188                 for ($i = 0; $i < count($illegal_chars); $i++)
189                         $name = str_replace($illegal_chars[$i], '', $name);
190                 // Now, if name is longer than 31 chars, truncate it
191                 if (strlen($name) > 31)
192                         $name = substr($name, 0, 31);
193                 return $name;
194         }
195         
196         function NumFormat($dec) 
197         {
198                 if (!isset($this->formatAmount[$dec]))
199                 {
200                         $dec = (int)$dec;
201                         $tsep = ',';
202                         $dsep = '.';
203                         $format = "###{$tsep}###{$tsep}###{$tsep}##0";
204                         if ($dec>0)
205                                 $format .= "{$dsep}".str_repeat('0',$dec);
206                         $this->formatAmount[$dec] =& $this->addFormat();
207                         $this->formatAmount[$dec]->setNumFormat($format);
208                         $this->formatAmount[$dec]->setAlign('right');
209                 }
210                 return $this->formatAmount[$dec];
211         }
212
213         function Font($fontname = '', $style = 'normal')
214         {
215         }
216         
217         function SetFontSize($size)
218         {
219                 $this->fontSize = $size;
220         }
221
222         function Info($params, $cols, $headers, $aligns,
223                 $cols2 = null, $headers2 = null, $aligns2 = null)
224         {
225                 $this->company = get_company_prefs();
226                 $year = get_current_fiscalyear();
227                 if ($year['closed'] == 0)
228                         $how = _("Active");
229                 else
230                         $how = _("Closed");
231                 $this->fiscal_year = sql2date($year['begin']) . " - " . sql2date($year['end']) . "  " . "(" . $how . ")";
232                 $this->user = $_SESSION["wa_current_user"]->name;
233                 $this->host = $_SERVER['SERVER_NAME'];
234                 $this->params = $params;
235                 $this->cols = $cols;
236                 $this->headers = $headers;
237                 $this->aligns = $aligns;
238                 $this->cols2 = $cols2;
239                 $this->headers2 = $headers2;
240                 $this->aligns2 = $aligns2;
241                 $this->numcols = count($this->headers);
242                 $tcols = count($this->headers2);
243                 if ($tcols > $this->numcols)
244                         $this->numcols = $tcols;
245                 for ($i = 0; $i < $this->numcols; $i++)
246                         $this->sheet->setColumn($i, $i, $this->px2units($this->cols[$i + 1] - $this->cols[$i]));
247         }
248
249         function Header()
250         {
251                 $tcol = $this->numcols - 1;
252                 $this->sheet->setRow($this->y, 20);
253                 for ($i = 0; $i < $this->numcols; $i++)
254                         $this->sheet->writeBlank($this->y, $i, $this->formatTitle);
255                 $this->sheet->writeString($this->y, 0, $this->title, $this->formatTitle);
256                 $this->sheet->mergeCells($this->y, 0, $this->y, $tcol);
257                 $this->NewLine();
258                 $str = _("Print Out Date") . ':';
259                 $this->sheet->writeString($this->y, 0, $str, $this->formatLeft);
260                 $this->sheet->writeString($this->y, 1, Today() . "  ".Now(), $this->formatLeft);
261                 $this->sheet->writeString($this->y, $tcol-1, $this->company['coy_name'], $this->formatLeft);
262                 $this->sheet->mergeCells($this->y, $tcol-1, $this->y, $tcol);
263                 $this->NewLine();
264                 $str = _("Fiscal Year") . ':';
265                 $this->sheet->writeString($this->y, 0, $str, $this->formatLeft);
266                 $str = $this->fiscal_year;
267                 $this->sheet->writeString($this->y, 1, $str, $this->formatLeft);
268                 $this->sheet->writeString($this->y, $tcol-1, $this->host, $this->formatLeft);
269                 $this->sheet->mergeCells($this->y, $tcol-1, $this->y, $tcol);
270                 for ($i = 1; $i < count($this->params); $i++)
271                 {
272                         if ($this->params[$i]['from'] != '')
273                         {
274                                 $this->NewLine();
275                                 $str = $this->params[$i]['text'] . ':';
276                                 $this->sheet->writeString($this->y, 0, $str);
277                                 $str = $this->params[$i]['from'];
278                                 if ($this->params[$i]['to'] != '')
279                                         $str .= " - " . $this->params[$i]['to'];
280                                 $this->sheet->writeString($this->y, 1, $str, $this->formatLeft);
281                                 if ($i == 1)
282                                 {
283                                         $this->sheet->writeString($this->y, $tcol-1, $this->user, $this->formatLeft);
284                                         $this->sheet->mergeCells($this->y, $tcol-1, $this->y, $tcol);
285                                 }       
286                         }
287                 }
288                 if ($this->params[0] != '') // Comments
289                 {
290                         $this->NewLine();
291                         $str = _("Comments") . ':';
292                         $this->sheet->writeString($this->y, 0, $str, $this->formatLeft);
293                         $this->sheet->writeString($this->y, 1, $this->params[0], $this->formatLeft);
294                 }
295                 $this->NewLine();
296                 if ($this->headers2 != null)
297                 {
298                         for ($i = 0, $j = 0; $i < $this->numcols; $i++)
299                         {
300                                 if ($this->cols2[$j] >= $this->cols[$i] && $this->cols2[$j] <= $this->cols[$i + 1])
301                                 {
302                                         if ($this->aligns2[$j] == "right")
303                                                 $this->sheet->writeString($this->y, $i, $this->headers2[$j], $this->formatHeaderRight);
304                                         else    
305                                                 $this->sheet->writeString($this->y, $i, $this->headers2[$j], $this->formatHeaderLeft);
306                                         $j++;   
307                                 }
308                                 else
309                                         $this->sheet->writeString($this->y, $i, "", $this->formatHeaderLeft);
310                         }               
311                         $this->NewLine();
312                 }
313
314                 for ($i = 0; $i < $this->numcols; $i++)
315                 {
316                         if (!isset($this->headers[$i]))
317                                 $header = "";
318                         else
319                                 $header = $this->headers[$i];
320                         if ($this->aligns[$i] == "right")
321                                 $this->sheet->writeString($this->y, $i, $header, $this->formatHeaderRight);
322                         else    
323                                 $this->sheet->writeString($this->y, $i, $header, $this->formatHeaderLeft);
324                 }
325                 $this->NewLine();
326         }
327
328         function Header2($myrow, $branch, $sales_order, $bankaccount, $doctype)
329         {
330                 return;
331         }
332
333         // Alternate header style - primary differences are for PDFs
334         function Header3()
335         {
336                 // Flag to make sure we only print the company name once
337                 $companyNamePrinted = false;
338                 
339                 $this->y = 0;
340                 $tcol = $this->numcols - 1;
341                 $this->sheet->setRow($this->y, 20);
342                 // Title
343                 for ($i = 0; $i < $this->numcols; $i++)
344                         $this->sheet->writeBlank($this->y, $i, $this->formatTitle);
345                 $this->sheet->writeString($this->y, 0, $this->title, $this->formatTitle);
346                 $this->sheet->mergeCells($this->y, 0, $this->y, $tcol);
347
348                 // Dimension 1 - optional
349                 // - only print if available and not blank
350                 if (count($this->params) > 3)
351                         if ($this->params[3]['from'] != '')
352                         {
353                                 $this->NewLine();
354                                 $str = $this->params[3]['text'] . ':';
355                                 $this->sheet->writeString($this->y, 0, $str, $this->formatLeft);
356                                 $this->sheet->writeString($this->y, 1, $this->params[3]['from'], $this->formatLeft);
357                                 // Company Name - at end of this row
358                                 if (!$companyNamePrinted)
359                                 {
360                                         $this->sheet->writeString($this->y, $tcol-1, $this->company['coy_name'], $this->formatLeft);
361                                         $this->sheet->mergeCells($this->y, $tcol-1, $this->y, $tcol);
362                                         $companyNamePrinted = true;
363                                 }
364                         }
365
366
367                 // Dimension 2 - optional
368                 // - only print if available and not blank
369                 if (count($this->params) > 4)
370                         if ($this->params[4]['from'] != '')
371                         {
372                                 $this->NewLine();
373                                 $str = $this->params[4]['text'] . ':';
374                                 $this->sheet->writeString($this->y, 0, $str, $this->formatLeft);
375                                 $this->sheet->writeString($this->y, 1, $this->params[4]['from'], $this->formatLeft);
376                                 // Company Name - at end of this row
377                                 if (!$companyNamePrinted)
378                                 {
379                                         $this->sheet->writeString($this->y, $tcol-1, $this->company['coy_name'], $this->formatLeft);
380                                         $this->sheet->mergeCells($this->y, $tcol-1, $this->y, $tcol);
381                                         $companyNamePrinted = true;
382                                 }
383                         }
384                         
385                 // Tags - optional
386                 // TBD!!!               
387         
388                 // Report Date - time period covered
389                 // - can specify a range, or just the end date (and the report contents
390                 //   should make it obvious what the beginning date is)
391                 $this->NewLine();
392                 $str = _("Report Date") . ':';
393                 $this->sheet->writeString($this->y, 0, $str, $this->formatLeft);
394                 $str = '';
395                 if ($this->params[1]['from'] != '')
396                         $str = $this->params[1]['from'] . ' - ';
397                 $str .= $this->params[1]['to'];
398                 $this->sheet->writeString($this->y, 1, $str, $this->formatLeft);
399                 // Company Name - at end of this row
400                 if (!$companyNamePrinted)
401                 {
402                         $this->sheet->writeString($this->y, $tcol-1, $this->company['coy_name'], $this->formatLeft);
403                         $this->sheet->mergeCells($this->y, $tcol-1, $this->y, $tcol);
404                         $companyNamePrinted = true;
405                 }
406                         
407                 // Timestamp of when this copy of the report was generated 
408                 $this->NewLine();
409                 $str = _("Generated At") . ':';
410                 $this->sheet->writeString($this->y, 0, $str, $this->formatLeft);
411                 $this->sheet->writeString($this->y, 1, Today() . "  ".Now(), $this->formatLeft);
412
413                 // Name of the user that generated this copy of the report
414                 $this->NewLine();
415                 $str = _("Generated By") . ':';
416                 $this->sheet->writeString($this->y, 0, $str, $this->formatLeft);
417                 $str = $this->user;
418                 $this->sheet->writeString($this->y, 1, $str, $this->formatLeft);
419
420                 // Comments - display any user-generated comments for this copy of the report
421                 if ($this->params[0] != '')
422                 {
423                         $this->NewLine();
424                         $str = _("Comments") . ':';
425                         $this->sheet->writeString($this->y, 0, $str, $this->formatLeft);
426                         $this->sheet->writeString($this->y, 1, $this->params[0], $this->formatLeft);
427                 }
428                 $this->NewLine();
429
430                 if ($this->headers2 != null)
431                 {
432                         for ($i = 0, $j = 0; $i < $this->numcols; $i++)
433                         {
434                                 if ($this->cols2[$j] >= $this->cols[$i] && $this->cols2[$j] <= $this->cols[$i + 1])
435                                 {
436                                         if ($this->aligns2[$j] == "right")
437                                                 $this->sheet->writeString($this->y, $i, $this->headers2[$j], $this->formatTopHeaderRight);
438                                         else    
439                                                 $this->sheet->writeString($this->y, $i, $this->headers2[$j], $this->formatTopHeaderLeft);
440                                         $j++;   
441                                 }
442                                 else
443                                         $this->sheet->writeString($this->y, $i, "", $this->formatTopHeaderLeft);
444                         }               
445                         $this->NewLine();
446                 }
447
448                 for ($i = 0; $i < $this->numcols; $i++)
449                 {
450                         if (!isset($this->headers[$i]))
451                                 $header = "";
452                         else
453                                 $header = $this->headers[$i];
454                         if ($this->aligns[$i] == "right")
455                                 if ($this->headers2 == null)
456                                         $this->sheet->writeString($this->y, $i, $header, $this->formatHeaderRight);
457                                 else
458                                         $this->sheet->writeString($this->y, $i, $header, $this->formatBottomHeaderRight);
459                         else    
460                                 if ($this->headers2 == null)
461                                         $this->sheet->writeString($this->y, $i, $header, $this->formatHeaderLeft);
462                                 else
463                                         $this->sheet->writeString($this->y, $i, $header, $this->formatBottomHeaderLeft);
464                 }
465                 $this->NewLine();
466         }
467
468         /**
469          * Format a numeric string date into something nicer looking.
470          *
471          * @param string $date Date string to be formatted.
472          * @param int $input_format Format of the input string.  Possible values are:<ul><li>0: user's default (default)</li></ul>
473          * @param int $output_format Format of the output string.  Possible values are:<ul><li>0: Month (word) Day (numeric), 4-digit Year - Example: January 1, 2000 (default)</li><li>1: Month 4-digit Year - Example: January 2000</li><li>2: Month Abbreviation 4-digit Year - Example: Jan 2000</li></ul>
474          * @access public
475          */
476         function DatePrettyPrint($date, $input_format = 0, $output_format = 0)
477         {
478                 if ($date != '')
479                 {
480                         $date = date2sql($date);
481                         $year = (int) (substr($date, 0, 4));
482                         $month = (int) (substr($date, 5, 2));
483                         $day = (int) (substr($date, 8, 2));
484                         if ($output_format == 0)
485                                 return(date('F j, Y', mktime(12, 0, 0, $month, $day, $year)));
486                         elseif ($output_format == 1)
487                                 return(date('F Y', mktime(12, 0, 0, $month, $day, $year)));
488                         elseif ($output_format == 2)
489                                 return(date('M Y', mktime(12, 0, 0, $month, $day, $year)));
490                 }
491                 else
492                         return $date;
493         }
494                 
495         function AddImage($logo, $x, $y, $w, $h)
496         {
497                 return;
498         }
499
500         function SetDrawColor($r, $g, $b)
501         {
502                 return;
503         }
504
505         function SetTextColor($r, $g, $b)
506         {
507                 return;
508         }
509
510         function SetFillColor($r, $g, $b)
511         {
512                 return;
513         }
514         
515         function GetCellPadding()
516         {
517                 return 0;
518         }
519         
520         function SetCellPadding($pad)
521         {
522                 return;
523         }
524         
525         function Text($c, $txt, $n=0, $corr=0, $r=0, $align='left', $border=0, $fill=0, $link=NULL, $stretch=0)
526         {
527                 return;
528         }
529
530         function TextWrap($xpos, $ypos, $len, $str, $align = 'left', $border = 0, $fill = 0, $link = NULL, $stretch = 0)
531         {
532                 return;
533         }
534
535         function TextCol($c, $n, $txt, $corr=0, $r=0, $border=0, $fill=0, $link=NULL, $stretch=0)
536         {
537                 $txt = html_entity_decode($txt);        
538                 if ($this->aligns[$c] == 'right')
539                         $this->sheet->writeString($this->y, $c, $txt, $this->formatRight);
540                 else    
541                         $this->sheet->writeString($this->y, $c, $txt, $this->formatLeft);
542                 if ($n - $c > 1)
543                         $this->sheet->mergeCells($this->y, $c, $this->y, $n - 1);
544         }
545
546         function AmountCol($c, $n, $txt, $dec=0, $corr=0, $r=0, $border=0, $fill=0, $link=NULL, $stretch=0, $color_red=false) 
547         { 
548                 if (!is_numeric($txt))
549                         $txt = 0;
550                 $this->sheet->writeNumber($this->y, $c, $txt, $this->NumFormat($dec)); 
551         }
552         
553         function AmountCol2($c, $n, $txt, $dec=0, $corr=0, $r=0, $border=0, $fill=0, $link=NULL, $stretch=0, $color_red=false, $amount_locale = NULL, $amount_format = NULL) 
554         { 
555                 if (!is_numeric($txt))
556                         $txt = 0;
557                 $this->sheet->writeNumber($this->y, $c, $txt, $this->NumFormat($dec)); 
558         }
559         
560         function DateCol($c, $n, $txt, $conv=false, $corr=0, $r=0, $border=0, $fill=0, $link=NULL, $stretch=0) 
561         {
562                 if (!$conv)
563                         $txt = date2sql($txt);
564                 list($year, $mo, $day) = explode("-", $txt);
565                 $date = $this->ymd2date((int)$year, (int)$mo, (int)$day);
566                 $this->sheet->writeNumber($this->y, $c, $date, $this->formatDate);
567         }
568
569         function TextCol2($c, $n, $txt, $corr=0, $r=0, $border=0, $fill=0, $link=NULL, $stretch=0)
570         {
571                 $txt = html_entity_decode($txt);        
572                 $this->sheet->writeString($this->y, $c, $txt, $this->formatLeft);
573                 if ($n - $c > 1)
574                         $this->sheet->mergeCells($this->y, $c, $this->y, $n - 1);
575         }
576
577         function TextColLines($c, $n, $txt, $corr=0, $r=0, $border=0, $fill=0, $link=NULL, $stretch=0)
578         {
579                 return;
580         }
581
582         function TextWrapLines($c, $width, $txt, $align='left', $border=0, $fill=0, $link=NULL, $stretch=0)
583         {
584                 return;
585         }
586
587         /**
588          * Crude text wrap calculator based on PDF version.
589          */
590         function TextWrapCalc($txt, $width, $spacebreak=false)
591         {
592                 // Assume an average character width
593                 $avg_char_width = 5;
594                 $ret = "";
595                 $txt2 = $txt;
596                 $w = strlen($txt) * $avg_char_width;
597                 if ($w > $width && $w > 0 && $width != 0)
598                 {
599                         $n = strlen($txt);
600                         $k = intval($n * $width / $w);
601                         if ($k > 0 && $k < $n)
602                         {
603                                 $txt2 = substr($txt, 0, $k);
604                                 if ($spacebreak && (($pos = strrpos($txt2, " ")) !== false))
605                                 {
606                                         $txt2 = substr($txt2, 0, $pos);
607                                         $ret = substr($txt, $pos+1);
608                                 }
609                                 else
610                                         $ret = substr($txt, $k);
611                         }
612                 }
613                 return array($txt2, $ret);
614         }
615
616         function SetLineStyle($style)
617         {
618                 return;
619         }
620
621         function SetLineWidth($width)
622         {
623                 return;
624         }
625         
626         function LineTo($from, $row, $to, $row2)
627         {
628                 return;
629         }
630
631         function Line($row, $height = 0)
632         {
633                 return;
634         }
635
636         function UnderlineCell($c, $r = 0, $type = 1, $linewidth = 0, $style = array())
637         {
638                 return;
639         }
640         
641         function NewLine($l=1, $np=0, $h=NULL)
642         {
643                 $this->y += $l;
644         }
645         
646         function NewPage()
647         {
648                 if (method_exists($this, $this->headerFunc))    // draw predefined page layout if any
649                         $this->{$this->headerFunc}();
650         }
651         
652         function ymd2Date($year, $mon, $day) // XLS internal date representation is a number between 1900-01-01 and 2078-12-31
653         {                                                                               // if we need the time part too, we have to add this value after a decimalpoint.
654         $mo = array(0,31,28,31,30,31,30,31,31,30,31,30,31);
655         $BASE = 1900;
656                 $MAXYEAR = 2075;
657                 if (($year % 4) == 0)
658                 $mo[2]++;
659         if ($mon < 1)
660             $mon = 1;
661         elseif ($mon > 12)
662             $mon = 12;
663         if ($day < 1)
664             $day = 1;
665         elseif ($day > $mo[$mon])
666             $day = $mo[$mon];
667         if ($year < $BASE)
668             $year = $BASE;
669         elseif ($year > $MAXYEAR)
670             $year = $MAXYEAR;
671         $jul = (int)$day;
672         for ($n = 1; $n < $mon; $n++)
673         {
674             $jul += $mo[$n];
675         }
676         for ($n = $BASE; $n < $year; $n++)
677         {
678             $jul += 365;
679             if (($n % 4) == 0)
680                 $jul++;
681         }
682         return $jul;
683         }
684   
685         function px2units($px) // XLS app conversion. Not bulletproof.
686         {
687                 $excel_column_width_factor = 256;
688                 $unit_offset_length = $this->excelColWidthFactor;
689                 return ($px / $unit_offset_length);
690         }       
691
692         function End($email=0, $subject='')
693         {
694                 global $path_to_root;
695                 ++$this->y;
696                 for ($i = 0; $i < $this->numcols; $i++)
697                         $this->sheet->writeBlank($this->y, $i, $this->formatFooter);
698                 $this->sheet->mergeCells($this->y, 0, $this->y, $this->numcols - 1);
699                 $this->close();
700                 // first have a look through the directory, 
701                 // and remove old temporary pdfs
702                 if ($d = @opendir($this->path)) {
703                         while (($file = readdir($d)) !== false) {
704                                 if (!is_file($this->path.'/'.$file) || $file == 'index.php') continue;
705                                 // then check to see if this one is too old
706                                 $ftime = filemtime($this->path.'/'.$file);
707                                 // seems 3 min is enough for any report download, isn't it?
708                                 if (time()-$ftime > 180){
709                                         unlink($this->path.'/'.$file);
710                                 }
711                         }
712                         closedir($d);
713                 }
714
715                 meta_forward($path_to_root.'/reporting/prn_redirect.php', "xls=1&filename=$this->filename&unique=$this->unique_name");
716                 exit();
717         }
718 }
719