public function handleSupbook($data) { # aka EXTERNALBOOK in OOo docs $this->supbook_types[] = Null; Helper::debug("SUPBOOK:"); Helper::debug(Helper::as_hex($data)); # <H list($num_sheets) = array_values(unpack('v', substr($data, 0, 2))); Helper::debug("num_sheets = %d", $num_sheets); $sbn = $this->supbook_count; $this->supbook_types++; if (substr($data, 2, 2) == "") { $this->supbook_types[-1] = SUPBOOK_INTERNAL; $this->supbook_locals_inx = $this->supbook_count - 1; Helper::debug("SUPBOOK[%d]: internal 3D refs; %d sheets", $sbn, $num_sheets); Helper::debug(" _all_sheets_map %s", join(', ', $this->all_sheets_map)); return; } if (substr($data, 0, 4) == ":") { $this->supbook_types[-1] = SUPBOOK_ADDIN; $this->supbook_addins_inx = $this->supbook_count - 1; Helper::debug("SUPBOOK[%d]: add-in functions", $sbn); return; } list($url, $pos) = Helper::unpack_unicode_update_pos($data, 2, 2); if ($num_sheets == 0) { $this->supbook_types[-1] = SUPBOOK_DDEOLE; Helper::debug("SUPBOOK[%d]: DDE/OLE document = %s", $sbn, $url); return; } $this->supbook_types[-1] = SUPBOOK_EXTERNAL; Helper::debug("SUPBOOK[%d]: url = %s", $sbn, $url); $sheet_names = []; for ($x = 0; $x < $num_sheets; $x++) { # #### FIX ME #### # Should implement handling of CONTINUE record(s) ... list($shname, $pos) = Helper::unpack_unicode_update_pos($data, $pos, 2); $sheet_names[] = $shname; Helper::debug(" sheetx=%d namelen=%d name=%s (next pos=%d)", $x, strlen($shname), $shname, $pos); } }
/** * @param $data * @param $txos MSTxo[] */ public function handle_note($data, $txos) { $o = new Note(); $data_len = strlen($data); if ($this->biff_version < 80) { # <HHH list($o->rowx, $o->colx, $expected_bytes) = array_values(unpack("v3", substr($data, 0, 6))); $nb = strlen($data) - 6; assert($nb <= $expected_bytes); $pieces = [substr($data, 6)]; $expected_bytes -= $nb; while ($expected_bytes > 0) { list($rc2, $data2_len, $data2) = $this->book->readRecordParts(); assert($rc2 == XL_NOTE); list($dummy_rowx, $nb) = array_values(unpack('v2/x/va', substr($data2, 0, 6))); assert($dummy_rowx == 0xffff); assert($nb == $data2_len - 6); $pieces[] = substr($data2, 6); $expected_bytes -= $nb; } assert($expected_bytes == 0); $enc = $this->book->encoding ?: $this->book->deriveEncoding(); $o->text = join('', $pieces); $o->rich_text_runlist = [[0, 0]]; $o->show = 0; $o->row_hidden = 0; $o->col_hidden = 0; $o->author = ''; $o->_object_id = Null; $this->cell_note_map[$o->rowx][$o->colx] = $o; return; } # Excel 8.0+ # <HHHH list($o->rowx, $o->colx, $option_flags, $o->_object_id) = array_values(unpack("v4", substr($data, 0, 8))); $o->show = $option_flags >> 1 & 1; $o->row_hidden = $option_flags >> 7 & 1; $o->col_hidden = $option_flags >> 8 & 1; # XL97 dev kit book says NULL [sic] bytes padding between string count and string data # to ensure that string is word-aligned. Appears to be nonsense. list($o->author, $endpos) = Helper::unpack_unicode_update_pos($data, 8, 2); # There is a random/undefined byte after the author string (not counted in the # string length). # Issue 4 on github: Google Spreadsheet doesn't write the undefined byte. assert(in_array($data_len - $endpos, [0, 1])); if (isset($txos[$o->_object_id])) { $txo = $txos[$o->_object_id]; $o->text = $txo->text; $o->rich_text_runlist = $txo->rich_text_runlist; $this->cell_note_map[$o->rowx][$o->colx] = $o; } }