<?php
/******************************************************************************
* Script : class BiffWriter
* Author : Christian Novak - cnovak@gmx.net
* Copyright : (c) 2001 Christian Novak
* History : rev 1.5 bugfix byte order on non Intel cpu's submitted by
* : John O'Donnel - johno@innismaggiore.com
*
* Documentation : http://home.arcor.de/cnovak
*
*
* This library is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser
* General Public License as published by the Free Software
* Foundation
*
* This library is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE.
*
*******************************************************************************/
class BiffWriter {
var $picture = array ('', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '' );
var $parse_order = array (
ID_BOF_REC,
ID_BACKUP_REC,
ID_PRINTROWHEADERS_REC,
ID_PRINTGRIDLINES_REC,
ID_FONT_REC,
ID_HEADER_REC,
ID_FOOTER_REC,
ID_LEFT_MARGIN_REC,
ID_RIGHT_MARGIN_REC,
ID_TOP_MARGIN_REC,
ID_BOTTOM_MARGIN_REC,
ID_COL_WIDTH,
ID_FORMAT_COUNT,
ID_FORMAT_REC,
ID_CELL_TEXT,
ID_CELL_NUMBER,
ID_IS_PROTECT_REC,
ID_IS_PASSWORD_REC,
ID_EOF_REC
);
var $eof = array(0x26, 0x41, 0x28, 0xa9, 0x29, 0x20, 0x62, 0x79, 0x20, 0x63, 0x6e, 0x6f, 0x76, 0x61, 0x6b, 0x40, 0x67, 0x6d, 0x78, 0x2e, 0x6e, 0x65, 0x74);
var $stream = array();
var $outfile = string;
var $maxcolwidth = array();
var $err_level = int;
var $fonts = int;
// ***** constructor *****
function BiffWriter() {
define('FONT_0', 0); define('FONT_1', 0x40); define('FONT_2', 0x80); define('FONT_3', 0xC0);
// ***** cell alignment properties & border properties, bit 0 & 1 is exclusive, bit 2..7 added *****
define('ALIGN_GENERAL', 0x0); define('ALIGN_LEFT', 0x1);
define('ALIGN_CENTER', 0x2); define('ALIGN_RIGHT', 0x3);
define('CELL_FILL', 0x4); define('CELL_LEFT_BORDER', 0x8);
define('CELL_RIGHT_BORDER', 0x10); define('CELL_TOP_BORDER', 0x20);
define('CELL_BOTTOM_BORDER',0x40); define('CELL_BOX_BORDER', 0x78);
define('CELL_SHADED', 0x80);
// cell font index, maximum 4 fonts per worksheet
define('FONT_NORMAL', 0x0); define('FONT_BOLD', 0x1); define('FONT_ITALIC', 0x2);
define('FONT_UNDERLINE', 0x4); define('FONT_STRIKEOUT', 0x8);
// ***** cell hidden/locked attributes *****
define('CELL_LOCKED', 0x40); define('CELL_HIDDEN', 0x80);
define('XLS_DATE', 2415033);
// ***** BIFF stream record definitions *****
define('ID_BOF_REC', 9); define('LEN_BOF_REC', 4); define('VERSION', 2); define('TYPE', 10);
define('ID_BACKUP_REC', 64); define('LEN_BACKUP_REC', 2);
define('ID_PRINTROWHEADERS_REC', 42); define('LEN_PRINTROWHEADERS_REC', 2);
define('ID_PRINTGRIDLINES_REC', 43); define('LEN_PRINTGRIDLINES_REC', 2);
define('ID_HEADER_REC', 20); define('LEN_HEADER_REC', 1);
define('ID_FOOTER_REC', 21); define('LEN_FOOTER_REC', 1);
define('ID_LEFT_MARGIN_REC', 38); define('ID_RIGHT_MARGIN_REC', 39);
define('ID_TOP_MARGIN_REC', 40); define('ID_BOTTOM_MARGIN_REC', 41);
define('LEN_MARGIN_REC', 8);
define('ID_IS_PASSWORD_REC' , 19); define('LEN_PASSWORD_REC', 2);
define('ID_IS_PROTECT_REC', 18);
define('ID_FONT_REC', 49); define('LEN_FONT_REC', 5);
define('ID_FORMAT_COUNT', 0x1F); define('LEN_FORMAT_COUNT', 2);
define('ID_FORMAT_REC', 30); define('LEN_FORMAT_REC', 1);
define('ID_EOF_REC', 0xA);
define('ID_CELL_TEXT', 4); define('LEN_CELL_TEXT', 8);
define('ID_CELL_NUMBER', 3); define('LEN_CELL_NUMBER', 0xF);
define('ID_COL_WIDTH', 36); define('LEN_COL_WIDTH', 4);
define('MAX_ROWS', 65535); define('MAX_COLS', 255);
define('MAX_FONTS', 4);
$this->outfile = 'sample.xls';
$this->err_level = 1; // turn warnings on
$this->fonts = 0;
$this->BOF();
} // end constructor
function xlsAddFormat($picstring) {
array_push($this->picture, $picstring);
return(count($this->picture) -1);
} // end func
function xlsPrintMargins($left = .5, $right = .5, $top = .5, $bottom = .5) {
array_push($this->stream, ID_LEFT_MARGIN_REC);
array_push($this->stream, pack('v', ID_LEFT_MARGIN_REC) . pack('v', LEN_MARGIN_REC) . pack('d', $left));
array_push($this->stream, ID_RIGHT_MARGIN_REC);
array_push($this->stream, pack('v', ID_RIGHT_MARGIN_REC) . pack('v', LEN_MARGIN_REC) . pack('d', $right));
array_push($this->stream, ID_TOP_MARGIN_REC);
array_push($this->stream, pack('v', ID_TOP_MARGIN_REC) . pack('v', LEN_MARGIN_REC) . pack('d', $top));
array_push($this->stream, ID_BOTTOM_MARGIN_REC);
array_push($this->stream, pack('v', ID_BOTTOM_MARGIN_REC) . pack('v', LEN_MARGIN_REC) . pack('d', $bottom));
} // end func
// ***** print FOOTER *****
function xlsFooter($foot) {
array_push($this->stream, ID_FOOTER_REC);
foreach($this->eof as $x) {$foot .= chr($x); }
$len = strlen($foot);
array_push($this->stream, pack('v', ID_FOOTER_REC) . pack('v', LEN_FOOTER_REC + $len) . pack('C', $len) . $foot);
} // end func
// ***** print header *****
function xlsHeader($head) {
array_push($this->stream, ID_HEADER_REC);
$len = strlen($head);
array_push($this->stream, pack('v', ID_HEADER_REC) . pack('v', LEN_HEADER_REC + $len) . pack('C', $len) . $head);
} // end func
// ***** set print grid lines flag *****
function xlsSetPrintGridLines() {
array_push($this->stream, ID_PRINTGRIDLINES_REC);
array_push($this->stream, pack('v', ID_PRINTGRIDLINES_REC) . pack('v', LEN_PRINTGRIDLINES_REC) . pack('v', 1));
} // end func
// ***** set print row headers flag *****
function xlsSetPrintHeaders() {
array_push($this->stream, ID_PRINTROWHEADERS_REC);
array_push($this->stream, pack('v', ID_PRINTROWHEADERS_REC) . pack('v', LEN_PRINTROWHEADERS_REC) . pack('v', 1));
} // end func
// ***** set backup file flag *****
function xlsSetBackup() {
array_push($this->stream, ID_BACKUP_REC);
array_push($this->stream, pack('v', ID_BACKUP_REC) . pack('v', LEN_BACKUP_REC) . pack('v', 1));
} // end func
// ***** set file and cell protection *****
function xlsProtectSheet($fpass = FALSE, $fprot = FALSE) {
if ($fpass) {
array_push($this->stream, ID_IS_PASSWORD_REC);
array_push($this->stream, pack('v', ID_IS_PASSWORD_REC) . pack('v', LEN_PASSWORD_REC) . pack('v', 1));
}
if ($fprot) {
array_push($this->stream, ID_IS_PROTECT_REC);
array_push($this->stream, pack('vvv', ID_IS_PROTECT_REC, 0x2, 1));
}
} // end func
// ***** create 4 generic fonts *****
function xlsSetDefFonts() {
$this->xlsSetFont('Arial', 10, FONT_NORMAL);
$this->xlsSetFont('Courier New', 10, FONT_NORMAL);
$this->xlsSetFont('Times New Roman', 10, FONT_NORMAL);
$this->xlsSetFont('System', 10, FONT_NORMAL);
}
function xlsSetColWidth($row1, $row2, $width) {
for ($x = $row1; $x <= $row2; $x++) {
$this->maxcolwidth[$x] = $width;
}
} // end func
function SetColWidth($firstrow, $lastrow, $width) {
$width++;
array_push($this->stream, ID_COL_WIDTH);
array_push($this->stream, pack('v', ID_COL_WIDTH).
pack('v', LEN_COL_WIDTH).
pack('C', $firstrow).
pack('C', $lastrow).
pack('v', $width * 256));
} // end func
function BOF() {
array_push($this->stream, ID_BOF_REC);
array_push($this->stream, pack('vvvv', ID_BOF_REC, LEN_BOF_REC, VERSION, TYPE));
}
function EOF() {
array_push($this->stream, ID_EOF_REC);
array_push($this->stream, pack('v', ID_EOF_REC));
}
function xlsParse() {
// ***** set column width's *****
foreach($this->maxcolwidth as $key => $value) {
$this->SetcolWidth($key, $key, $value);
}
$this->EOF();
$this->SetDefFormat();
header("Expires: Mon, 1 Apr 1974 05:00:00 GMT" );
header("Last-Modified: " . gmdate("D,d M YH:i:s" ) . " GMT" );
header("Cache-Control: no-cache, must-revalidate" );
header("Pragma: no-cache" );
header("Content-Disposition: attachment; filename=$this->outfile\r\n\r\n" );
header("Content-Type: application/octet-stream" );
$len = count($this->parse_order);
for ($x = 0 ; $x < $len; $x++) {
$code = array_shift($this->parse_order);
$key = constant($code);
$match = array_keys($this->stream, $key);
foreach($match as $value) {
print $this->stream[$value + 1];
}
}
} // end func
function xlsWriteText($row, $col, $value, $col_width = 0, $cell_picture = 0, $cell_font = 0, $cell_alignment = ALIGN_GENERAL, $cell_status = 0) {
$len = strlen($value);
if ($row > MAX_ROWS AND $this->err_level > 0) {
trigger_error('xlsWriteText: MAX_ROWS exceeded', E_USER_ERROR);
}
if ($col > MAX_COLS AND $this->err_level > 0) {
trigger_error('xlsWriteText: MAX_COLS exceeded', E_USER_ERROR);
}
if ($len > 256 AND $this->err_level > 0 ) {
trigger_error('xlsWriteText: too many chars', E_USER_ERROR);
}
if ($col_width > 0) {
$this->maxcolwidth[$col] = $col_width;
}
if ($col_width == 0) {
if ($this->maxcolwidth[$col] < $len) {
$this->maxcolwidth[$col] = $len;
}
}
array_push($this->stream, ID_CELL_TEXT);
array_push($this->stream, pack('v', ID_CELL_TEXT).
pack('v', LEN_CELL_TEXT + $len).
pack('v', $row).
pack('v', $col).
pack('C', $cell_status).
pack('C', $$cell_picture + $cell_font).
pack('C', $cell_alignment).
pack('C', $len).
$value);
}
function xlsWriteNumber($row, $col, $value, $col_width = 0, $cell_picture = 0, $cell_font = 0, $cell_alignment = ALIGN_RIGHT, $cell_status = 0) {
if ($row > MAX_ROWS AND $this->err_level > 0) {
trigger_error('xlsWriteText: MAX_ROWS exceeded', E_USER_ERROR);
}
if ($col > MAX_COLS AND $this->err_level > 0) {
trigger_error('xlsWriteText: MAX_COLS exceeded', E_USER_ERROR);
}
$len = strlen(strval($value));
if ($col_width > 0) {
$this->maxcolwidth[$col] = $col_width;
}
if ($col_width == 0) {
if ($this->maxcolwidth[$col] < $len) {
$this->maxcolwidth[$col] = $len;
}
}
array_push($this->stream, ID_CELL_NUMBER);
array_push($this->stream, pack('v', ID_CELL_NUMBER).
pack('v', LEN_CELL_NUMBER).
pack('v', $row).
pack('v', $col).
pack('C', $cell_status).
pack('C', $cell_picture + $cell_font).
pack('C', $cell_alignment).
pack('d', $value));
} // end func
function SetDefFormat() {
$y = count($this->picture);
array_push($this->stream, ID_FORMAT_COUNT);
array_push($this->stream, pack('v', ID_FORMAT_COUNT).
pack('v', LEN_FORMAT_COUNT).
pack('v', 0x15));
for ($x = 0; $x < $y; $x++) {
$len_format_str = strlen($this->picture[$x]);
array_push($this->stream, ID_FORMAT_REC);
array_push($this->stream, pack('v', ID_FORMAT_REC).
pack('v', LEN_FORMAT_REC + $len_format_str).
pack('C', $len_format_str).
$this->picture[$x]);
}
}
function xlsSetFont($font_name, $font_size = 10, $font_format = FONT_NORMAL) {
if ($this->fonts > 3 AND $this->err_level > 0) {
trigger_error('BIFFWRITER ERROR: too many fonts', E_USER_ERROR);
}
$len = strlen($font_name);
array_push($this->stream, ID_FONT_REC);
array_push($this->stream, pack('v', ID_FONT_REC).
pack('v', LEN_FONT_REC + $len).
pack('v', $font_size * 20).
pack('C', $font_format).
pack('C', 0x0).
pack('C', $len).
$font_name);
$this->fonts++;
} // end func
// return date integer based on 1.1.1900 count not on Unix timestamp
function xlsDate($month, $day, $year) {
return(juliantojd($month, $day, $year) - XLS_DATE + 1);
} // end func
} // end class
?>
Voilà tout le code de biff.php...