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