BIFFwriter.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. // Original file header of PEAR::Spreadsheet_Excel_Writer_BIFFwriter (used as the base for this class):
  8. // -----------------------------------------------------------------------------------------
  9. // * Module written/ported by Xavier Noguer <xnoguer@rezebra.com>
  10. // *
  11. // * The majority of this is _NOT_ my code. I simply ported it from the
  12. // * PERL Spreadsheet::WriteExcel module.
  13. // *
  14. // * The author of the Spreadsheet::WriteExcel module is John McNamara
  15. // * <jmcnamara@cpan.org>
  16. // *
  17. // * I _DO_ maintain this code, and John McNamara has nothing to do with the
  18. // * porting of this code to PHP. Any questions directly related to this
  19. // * class library should be directed to me.
  20. // *
  21. // * License Information:
  22. // *
  23. // * Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets
  24. // * Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com
  25. // *
  26. // * This library is free software; you can redistribute it and/or
  27. // * modify it under the terms of the GNU Lesser General Public
  28. // * License as published by the Free Software Foundation; either
  29. // * version 2.1 of the License, or (at your option) any later version.
  30. // *
  31. // * This library is distributed in the hope that it will be useful,
  32. // * but WITHOUT ANY WARRANTY; without even the implied warranty of
  33. // * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  34. // * Lesser General Public License for more details.
  35. // *
  36. // * You should have received a copy of the GNU Lesser General Public
  37. // * License along with this library; if not, write to the Free Software
  38. // * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  39. // */
  40. class PHPExcel_Writer_Excel5_BIFFwriter
  41. {
  42. /**
  43. * The byte order of this architecture. 0 => little endian, 1 => big endian
  44. * @var integer
  45. */
  46. private static $byteOrder;
  47. /**
  48. * The string containing the data of the BIFF stream
  49. * @var string
  50. */
  51. public $_data;
  52. /**
  53. * The size of the data in bytes. Should be the same as strlen($this->_data)
  54. * @var integer
  55. */
  56. public $_datasize;
  57. /**
  58. * The maximum length for a BIFF record (excluding record header and length field). See addContinue()
  59. * @var integer
  60. * @see addContinue()
  61. */
  62. private $limit = 8224;
  63. /**
  64. * Constructor
  65. */
  66. public function __construct()
  67. {
  68. $this->_data = '';
  69. $this->_datasize = 0;
  70. // $this->limit = 8224;
  71. }
  72. /**
  73. * Determine the byte order and store it as class data to avoid
  74. * recalculating it for each call to new().
  75. *
  76. * @return int
  77. */
  78. public static function getByteOrder()
  79. {
  80. if (!isset(self::$byteOrder)) {
  81. // Check if "pack" gives the required IEEE 64bit float
  82. $teststr = pack("d", 1.2345);
  83. $number = pack("C8", 0x8D, 0x97, 0x6E, 0x12, 0x83, 0xC0, 0xF3, 0x3F);
  84. if ($number == $teststr) {
  85. $byte_order = 0; // Little Endian
  86. } elseif ($number == strrev($teststr)) {
  87. $byte_order = 1; // Big Endian
  88. } else {
  89. // Give up. I'll fix this in a later version.
  90. throw new PHPExcel_Writer_Exception("Required floating point format not supported on this platform.");
  91. }
  92. self::$byteOrder = $byte_order;
  93. }
  94. return self::$byteOrder;
  95. }
  96. /**
  97. * General storage function
  98. *
  99. * @param string $data binary data to append
  100. * @access private
  101. */
  102. protected function append($data)
  103. {
  104. if (strlen($data) - 4 > $this->limit) {
  105. $data = $this->addContinue($data);
  106. }
  107. $this->_data .= $data;
  108. $this->_datasize += strlen($data);
  109. }
  110. /**
  111. * General storage function like append, but returns string instead of modifying $this->_data
  112. *
  113. * @param string $data binary data to write
  114. * @return string
  115. */
  116. public function writeData($data)
  117. {
  118. if (strlen($data) - 4 > $this->limit) {
  119. $data = $this->addContinue($data);
  120. }
  121. $this->_datasize += strlen($data);
  122. return $data;
  123. }
  124. /**
  125. * Writes Excel BOF record to indicate the beginning of a stream or
  126. * sub-stream in the BIFF file.
  127. *
  128. * @param integer $type Type of BIFF file to write: 0x0005 Workbook,
  129. * 0x0010 Worksheet.
  130. * @access private
  131. */
  132. protected function storeBof($type)
  133. {
  134. $record = 0x0809; // Record identifier (BIFF5-BIFF8)
  135. $length = 0x0010;
  136. // by inspection of real files, MS Office Excel 2007 writes the following
  137. $unknown = pack("VV", 0x000100D1, 0x00000406);
  138. $build = 0x0DBB; // Excel 97
  139. $year = 0x07CC; // Excel 97
  140. $version = 0x0600; // BIFF8
  141. $header = pack("vv", $record, $length);
  142. $data = pack("vvvv", $version, $type, $build, $year);
  143. $this->append($header . $data . $unknown);
  144. }
  145. /**
  146. * Writes Excel EOF record to indicate the end of a BIFF stream.
  147. *
  148. * @access private
  149. */
  150. protected function storeEof()
  151. {
  152. $record = 0x000A; // Record identifier
  153. $length = 0x0000; // Number of bytes to follow
  154. $header = pack("vv", $record, $length);
  155. $this->append($header);
  156. }
  157. /**
  158. * Writes Excel EOF record to indicate the end of a BIFF stream.
  159. *
  160. * @access private
  161. */
  162. public function writeEof()
  163. {
  164. $record = 0x000A; // Record identifier
  165. $length = 0x0000; // Number of bytes to follow
  166. $header = pack("vv", $record, $length);
  167. return $this->writeData($header);
  168. }
  169. /**
  170. * Excel limits the size of BIFF records. In Excel 5 the limit is 2084 bytes. In
  171. * Excel 97 the limit is 8228 bytes. Records that are longer than these limits
  172. * must be split up into CONTINUE blocks.
  173. *
  174. * This function takes a long BIFF record and inserts CONTINUE records as
  175. * necessary.
  176. *
  177. * @param string $data The original binary data to be written
  178. * @return string A very convenient string of continue blocks
  179. * @access private
  180. */
  181. private function addContinue($data)
  182. {
  183. $limit = $this->limit;
  184. $record = 0x003C; // Record identifier
  185. // The first 2080/8224 bytes remain intact. However, we have to change
  186. // the length field of the record.
  187. $tmp = substr($data, 0, 2) . pack("v", $limit) . substr($data, 4, $limit);
  188. $header = pack("vv", $record, $limit); // Headers for continue records
  189. // Retrieve chunks of 2080/8224 bytes +4 for the header.
  190. $data_length = strlen($data);
  191. for ($i = $limit + 4; $i < ($data_length - $limit); $i += $limit) {
  192. $tmp .= $header;
  193. $tmp .= substr($data, $i, $limit);
  194. }
  195. // Retrieve the last chunk of data
  196. $header = pack("vv", $record, strlen($data) - $i);
  197. $tmp .= $header;
  198. $tmp .= substr($data, $i, strlen($data) - $i);
  199. return $tmp;
  200. }
  201. }