⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 workbook.php

📁 完美的在线教育系统
💻 PHP
📖 第 1 页 / 共 4 页
字号:
        $data              .= pack("v", $itab);        $data              .= pack("C", $cchCustMenu);        $data              .= pack("C", $cchDescription);        $data              .= pack("C", $cchHelptopic);        $data              .= pack("C", $cchStatustext);        $data              .= pack("C", $rgch);        $data              .= pack("C", $unknown03);        $data              .= pack("v", $unknown04);        $data              .= pack("v", $unknown05);        $data              .= pack("v", $unknown06);        $data              .= pack("v", $unknown07);        $data              .= pack("v", $unknown08);        $data              .= pack("v", $index);        $data              .= pack("v", $index);        $data              .= pack("v", $rowmin);        $data              .= pack("v", $rowmax);        $data              .= pack("C", $colmin);        $data              .= pack("C", $colmax);        $this->_append($header . $data);    }    /**    * Store the NAME record in the long format that is used for storing the repeat    * rows and columns when both are specified. This shares a lot of code with    * _storeNameShort() but we use a separate method to keep the code clean.    * Code abstraction for reuse can be carried too far, and I should know. ;-)    *    * @param integer $index Sheet index    * @param integer $type  Built-in name type    * @param integer $rowmin Start row    * @param integer $rowmax End row    * @param integer $colmin Start colum    * @param integer $colmax End column    * @access private    */    function _storeNameLong($index, $type, $rowmin, $rowmax, $colmin, $colmax)    {        $record          = 0x0018;       // Record identifier        $length          = 0x003d;       // Number of bytes to follow        $grbit           = 0x0020;       // Option flags        $chKey           = 0x00;         // Keyboard shortcut        $cch             = 0x01;         // Length of text name        $cce             = 0x002e;       // Length of text definition        $ixals           = $index + 1;   // Sheet index        $itab            = $ixals;       // Equal to ixals        $cchCustMenu     = 0x00;         // Length of cust menu text        $cchDescription  = 0x00;         // Length of description text        $cchHelptopic    = 0x00;         // Length of help topic text        $cchStatustext   = 0x00;         // Length of status bar text        $rgch            = $type;        // Built-in name type        $unknown01       = 0x29;        $unknown02       = 0x002b;        $unknown03       = 0x3b;        $unknown04       = 0xffff-$index;        $unknown05       = 0x0000;        $unknown06       = 0x0000;        $unknown07       = 0x1087;        $unknown08       = 0x8008;        $header             = pack("vv",  $record, $length);        $data               = pack("v", $grbit);        $data              .= pack("C", $chKey);        $data              .= pack("C", $cch);        $data              .= pack("v", $cce);        $data              .= pack("v", $ixals);        $data              .= pack("v", $itab);        $data              .= pack("C", $cchCustMenu);        $data              .= pack("C", $cchDescription);        $data              .= pack("C", $cchHelptopic);        $data              .= pack("C", $cchStatustext);        $data              .= pack("C", $rgch);        $data              .= pack("C", $unknown01);        $data              .= pack("v", $unknown02);        // Column definition        $data              .= pack("C", $unknown03);        $data              .= pack("v", $unknown04);        $data              .= pack("v", $unknown05);        $data              .= pack("v", $unknown06);        $data              .= pack("v", $unknown07);        $data              .= pack("v", $unknown08);        $data              .= pack("v", $index);        $data              .= pack("v", $index);        $data              .= pack("v", 0x0000);        $data              .= pack("v", 0x3fff);        $data              .= pack("C", $colmin);        $data              .= pack("C", $colmax);        // Row definition        $data              .= pack("C", $unknown03);        $data              .= pack("v", $unknown04);        $data              .= pack("v", $unknown05);        $data              .= pack("v", $unknown06);        $data              .= pack("v", $unknown07);        $data              .= pack("v", $unknown08);        $data              .= pack("v", $index);        $data              .= pack("v", $index);        $data              .= pack("v", $rowmin);        $data              .= pack("v", $rowmax);        $data              .= pack("C", 0x00);        $data              .= pack("C", 0xff);        // End of data        $data              .= pack("C", 0x10);        $this->_append($header . $data);    }    /**    * Stores the COUNTRY record for localization    *    * @access private    */    function _storeCountry()    {        $record          = 0x008C;    // Record identifier        $length          = 4;         // Number of bytes to follow        $header = pack('vv',  $record, $length);        /* using the same country code always for simplicity */        $data = pack('vv', $this->_country_code, $this->_country_code);        $this->_append($header . $data);    }    /**    * Stores the PALETTE biff record.    *    * @access private    */    function _storePalette()    {        $aref            = $this->_palette;        $record          = 0x0092;                 // Record identifier        $length          = 2 + 4 * count($aref);   // Number of bytes to follow        $ccv             =         count($aref);   // Number of RGB values to follow        $data = '';                                // The RGB data        // Pack the RGB data        foreach ($aref as $color) {            foreach ($color as $byte) {                $data .= pack("C",$byte);            }        }        $header = pack("vvv",  $record, $length, $ccv);        $this->_append($header . $data);    }    /**    * Calculate    * Handling of the SST continue blocks is complicated by the need to include an    * additional continuation byte depending on whether the string is split between    * blocks or whether it starts at the beginning of the block. (There are also    * additional complications that will arise later when/if Rich Strings are    * supported).    *    * @access private    */    function _calculateSharedStringsSizes()    {        /* Iterate through the strings to calculate the CONTINUE block sizes.           For simplicity we use the same size for the SST and CONTINUE records:           8228 : Maximum Excel97 block size             -4 : Length of block header             -8 : Length of additional SST header information         = 8216        */        $continue_limit     = 8216;        $block_length       = 0;        $written            = 0;        $this->_block_sizes = array();        $continue           = 0;        foreach (array_keys($this->_str_table) as $string) {            $string_length = strlen($string);            // Block length is the total length of the strings that will be            // written out in a single SST or CONTINUE block.            $block_length += $string_length;            // We can write the string if it doesn't cross a CONTINUE boundary            if ($block_length < $continue_limit) {                $written      += $string_length;                continue;            }            // Deal with the cases where the next string to be written will exceed            // the CONTINUE boundary. If the string is very long it may need to be            // written in more than one CONTINUE record.            while ($block_length >= $continue_limit) {                // We need to avoid the case where a string is continued in the first                // n bytes that contain the string header information.                $header_length   = 3; // Min string + header size -1                $space_remaining = $continue_limit - $written - $continue;                /* TODO: Unicode data should only be split on char (2 byte)                boundaries. Therefore, in some cases we need to reduce the                amount of available                */                if ($space_remaining > $header_length) {                    // Write as much as possible of the string in the current block                    $written      += $space_remaining;                    // Reduce the current block length by the amount written                    $block_length -= $continue_limit - $continue;                    // Store the max size for this block                    $this->_block_sizes[] = $continue_limit;                    // If the current string was split then the next CONTINUE block                    // should have the string continue flag (grbit) set unless the                    // split string fits exactly into the remaining space.                    if ($block_length > 0) {                        $continue = 1;                    } else {                        $continue = 0;                    }                } else {                    // Store the max size for this block                    $this->_block_sizes[] = $written + $continue;                    // Not enough space to start the string in the current block                    $block_length -= $continue_limit - $space_remaining - $continue;                    $continue = 0;                }                // If the string (or substr) is small enough we can write it in the                // new CONTINUE block. Else, go through the loop again to write it in                // one or more CONTINUE blocks                if ($block_length < $continue_limit) {                    $written = $block_length;                } else {                    $written = 0;                }            }        }        // Store the max size for the last block unless it is empty        if ($written + $continue) {            $this->_block_sizes[] = $written + $continue;        }        /* Calculate the total length of the SST and associated CONTINUEs (if any).         The SST record will have a length even if it contains no strings.         This length is required to set the offsets in the BOUNDSHEET records since         they must be written before the SST records        */        $total_offset = array_sum($this->_block_sizes);        // SST information        $total_offset += 8;        if (!empty($this->_block_sizes)) {            $total_offset += (count($this->_block_sizes)) * 4; // add CONTINUE headers        }        return $total_offset;    }    /**    * Write all of the workbooks strings into an indexed array.    * See the comments in _calculate_shared_string_sizes() for more information.    *    * The Excel documentation says that the SST record should be followed by an    * EXTSST record. The EXTSST record is a hash table that is used to optimise    * access to SST. However, despite the documentation it doesn't seem to be    * required so we will ignore it.    *    * @access private    */    function _storeSharedStringsTable()    {        $record  = 0x00fc;  // Record identifier        // sizes are upside down        $this->_block_sizes = array_reverse($this->_block_sizes);        $length = array_pop($this->_block_sizes) + 8; // First block size plus SST information        // Write the SST block header information        $header      = pack("vv", $record, $length);        $data        = pack("VV", $this->_str_total, $this->_str_unique);        $this->_append($header . $data);        // Iterate through the strings to calculate the CONTINUE block sizes        $continue_limit = 8216;        $block_length   = 0;        $written        = 0;        $continue       = 0;        /* TODO: not good for performance */        foreach (array_keys($this->_str_table) as $string) {            $string_length = strlen($string);            $encoding      = 0; // assume there are no Unicode strings            $split_string  = 0;            // Block length is the total length of the strings that will be            // written out in a single SST or CONTINUE block.            //            $block_length += $string_length;            // We can write the string if it doesn't cross a CONTINUE boundary            if ($block_length < $continue_limit) {                $this->_append($string);                $written += $string_length;                continue;            }            // Deal with the cases where the next string to be written will exceed            // the CONTINUE boundary. If the string is very long it may need to be            // written in more than one CONTINUE record.            //            while ($block_length >= $continue_limit) {                // We need to avoid the case where a string is continued in the first                // n bytes that contain the string header information.                //                $header_length   = 3; // Min string + header size -1                $space_remaining = $continue_limit - $written - $continue;                // Unicode data should only be split on char (2 byte) boundaries.                // Therefore, in some cases we need to reduce the amount of available                if ($space_remaining > $header_length) {                    // Write as much as possible of the string in the current block                    $tmp = substr($string, 0, $space_remaining);                    $this->_append($tmp);                    // The remainder will be written in the next block(s)                    $string = substr($string, $space_remaining);                    // Reduce the current block length by the amount written                    $block_length -= $continue_limit - $continue;                    // If the current string was split then the next CONTINUE block                    // should have the string continue flag (grbit) set unless the                    // split string fits exactly into the remaining space.                    //                    if ($block_length > 0) {                        $continue = 1;                    } else {                        $continue = 0;                    }                } else {                    // Not enough space to start the string in the current block                    $block_length -= $continue_limit - $space_remaining - $continue;                    $continue = 0;                }                // Write the CONTINUE block header                if (!empty($this->_block_sizes)) {                    $record  = 0x003C;                    $length  = array_pop($this->_block_sizes);                    $header  = pack('vv', $record, $length);                    if ($continue) {                        $header .= pack('C', $encoding);                    }                    $this->_append($header);                }                // If the string (or substr) is small enough we can write it in the                // new CONTINUE block. Else, go through the loop again to write it in                // one or more CONTINUE blocks                //                if ($block_length < $continue_limit) {                    $this->_append($string);                    $written = $block_length;                } else {                    $written = 0;                }            }        }    }}?>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -