Tommy 碎碎念

Tommy Wu's blog

Google
 

« 上一篇 | 下一篇 »

使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案
post by tommy @ 11 八月, 2006 19:22
PEAR 中, 有個可以讓 PHP 產生 Excel 檔案的東西: Spreadsheet_Excel_Writer, 透過這個物件, 我們可以產生一個正確的 Excel 檔案出來. 而在 0.9.0 版中, 加上了 Unicode 的支援, 我們只要把 BIFF 的版本設為 8, 然後用 setInputEncoding() 指定要使用的編碼就可以存成一個 UNICODE 的 Excel 檔案.

不過, 我們發現, 在資料筆數較少, 檔案較小的時候, 運作十分正常. 不過, 當筆數大到一定的大小之後, 所產生的檔案, 使用 Microsoft Excel 打開時, 會出現損毀的情形, 其中的內容是正確無誤, 不過格式都會不見. (據說用 OpenOffice 打開時會告知是 SST 錯誤)

今天在 PEAR 的網站中, 看到幾個月之前, 有人提出了一個解決方法, 修改 Workbook.php 中的下列兩個 function 如下:

    /**
* 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
-8 : Arbitrary number to keep within _add_continue() limit
= 8208
*/
$continue_limit = 8208;
$block_length = 0;
$written = 0;
$this->_block_sizes = array();
$continue = 0;

foreach (array_keys($this->_str_table) as $string) {
$string_length = strlen($string);
$headerinfo = unpack("vlength/Cencoding", $string);
$encoding = $headerinfo["encoding"];
$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) {
$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
*/
$align = 0;

# Only applies to Unicode strings
if ($encoding == 1) {
# Min string + header size -1
$header_length = 4;

if ($space_remaining > $header_length) {
# String contains 3 byte header => split on odd boundary
if (!$split_string && $space_remaining % 2 != 1) {
$space_remaining--;
$align = 1;
}
# Split section without header => split on even boundary
else if ($split_string && $space_remaining % 2 == 1) {
$space_remaining--;
$align = 1;
}

$split_string = 1;
}
}


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 - $align;

// Store the max size for this block
$this->_block_sizes[] = $continue_limit - $align;

// 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
*/

$tmp_block_sizes = array();
$tmp_block_sizes = $this->_block_sizes;

$length = 12;
if (!empty($tmp_block_sizes)) {
$length += array_shift($tmp_block_sizes); # SST
}
while (!empty($tmp_block_sizes)) {
$length += 4 + array_shift($tmp_block_sizes); # CONTINUEs
}

return $length;
}

/**
* 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
$length = 0x0008; // Number of bytes to follow
$total = 0x0000;

// Iterate through the strings to calculate the CONTINUE block sizes
$continue_limit = 8208;
$block_length = 0;
$written = 0;
$continue = 0;

// sizes are upside down
$tmp_block_sizes = $this->_block_sizes;
// $tmp_block_sizes = array_reverse($this->_block_sizes);

# The SST record is required even if it contains no strings. Thus we will
# always have a length
#
if (!empty($tmp_block_sizes)) {
$length = 8 + array_shift($tmp_block_sizes);
}
else {
# No strings
$length = 8;
}



// Write the SST block header information
$header = pack("vv", $record, $length);
$data = pack("VV", $this->_str_total, $this->_str_unique);
$this->_append($header . $data);




/* TODO: not good for performance */
foreach (array_keys($this->_str_table) as $string) {

$string_length = strlen($string);
$headerinfo = unpack("vlength/Cencoding", $string);
$encoding = $headerinfo["encoding"];
$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
// space by 1 byte to ensure the correct alignment.
$align = 0;

// Only applies to Unicode strings
if ($encoding == 1) {
// Min string + header size -1
$header_length = 4;

if ($space_remaining > $header_length) {
// String contains 3 byte header => split on odd boundary
if (!$split_string && $space_remaining % 2 != 1) {
$space_remaining--;
$align = 1;
}
// Split section without header => split on even boundary
else if ($split_string && $space_remaining % 2 == 1) {
$space_remaining--;
$align = 1;
}

$split_string = 1;
}
}


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 - $align;

// 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_shift($tmp_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;
}
}
}
}
 

我們試用後, 目前看起來一切都正常.

Del.icio.us Furl HEMiDEMi Technorati MyShare
commons icon [1] 請問如何輸出成字串 ?? [ 回覆 ]

請問一下, Excel 產生後, 要如何轉成字串,
才能用Email 的方式寄出!
我上網找了很久,都沒找到!
因為轉成字串, 就能每天自動跑報表出來,Email給所有人
!!

commons icon [2] [ 回覆 ]

都用 pear 的 Spreadsheet_Excel_Writer 了, 應該也不差再用一個 Mail_mime 物件.
http://pear.php.net/manual/en/package.mail.mail-mime.php

commons icon [3] [ 回覆 ]

http://tw.myblog.yahoo.com/c9993/article?mid=20&prev=157&next=155&l=f&fid=7

搭配一下應該就OK了

commons icon [4] PEAR 的 Excel 檔案 的問題 [ 回覆 ]

tommy~
請問一下你試用後正常~那你的檔案有測到多大的呢??
我有用你介紹的方式執行,初期正常,但我今天檔案到54kb就又出現原來的問題~!故有此一問!!謝謝!

commons icon [5] [ 回覆 ]

幾百 K 吧, 可能有上到幾 MB 吧. 我們的客戶之後都沒反應過有不正常的情形了.
如果只是 54K 就有問題, 比較像是沒改之前的情形.

我記得我們沒改之前, 當初好像多數在 200K 左右會出問題.

commons icon [6] [ 回覆 ]

謝謝!這讓我頭痛了半天......

commons icon [7] RE:PEAR 的 Excel 檔案 的問題 [ 回覆 ]

sorry~!!我打錯了~!
是154kb~!!
謝謝tommy的提醒,確實是我沒有改過去!現在ok了(我一直以為我有改過!)

commons icon [8] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

tommy 您好:

當我在使用 Spreadsheet_Excel_Writer 時,
每當把 *.xls 下載完後,想要直接開啟,
都會出現一個 Microsoft Excel 的警告視窗,
內容為
"Microsoft Excel 無法使用 *.xls , 可能是因為這個檔案是唯讀的,或者存放它的地方是唯讀的,或是伺服器沒有回應"

當我按"取消"的時候,會出現 2 個狀況,

1.直接修復,並且提示"Excel 嘗試回復您的公式和數值,但是部份資料可能已經遺失或損毀",但是檔案內容都正確;

2.修復失敗,我得使用開啟舊檔,選擇"開啟並修復"-->"抽選資料"-->"復原公式",
之後 Excel 直接修復,並出現 敘述 1 的狀況;

我的測試程式

require_once 'Spreadsheet/Excel/Writer.php';

// Creating a workbook
$workbook = new Spreadsheet_Excel_Writer();
// Creating a worksheet
$worksheet =& $workbook->addWorksheet('Reporter');
$workbook->setVersion(8);
$worksheet->setInputEncoding('utf-8');

$x = 0;
$y = 0;
$worksheet->write($x, $y++, '群組');
$worksheet->write($x, $y++, '報表月份');
$worksheet->write($x, $y++, '應發獎金');

// hide gridlines so they don't mess with our Excel art.
$worksheet->hideGridLines();

// sending HTTP headers
$workbook->send('sales_reporter.xls');

$workbook->close();

這個狀況我一直處理不掉,請問這個狀況該如何處理呢??

commons icon [9] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

我用你上頭寫的程式, 在我的環境並不會有問題.
不過建議 $workbook->setVersion(8); 寫在產生 worksheet 之前 (不過好像之後也不會有問題).

另外, 下載的檔案, 不要直接用 excel 打開來, 先存起來. 然後再看看格式是不是正確的 excel 檔案.
也許用 notepad 先看一下, 也許是你的系統的 php 會有些錯誤 (警告? 提示?) 訊息出來吧, 這樣子會變成在那 excel 檔案前面出現那些字串, 格式自然會有問題.

commons icon [10] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

對了, 程式我放這兒, 可以自己試看看:
http://www.teatime.com.tw/~tommy/test/excel.php
source code 可以用這個看 (只是一個 soft link 到同一個檔案):
http://www.teatime.com.tw/~tommy/test/excel.phps

commons icon [11] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

tommy 您好:

真的是ok;
怪事了,為什麼在我的環境卻是有問題的,
請問可否給我一些想法呢???

是否安裝pear套件時,有什麼地方應該注意的呢??

謝謝您;

commons icon [12] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

另外補充:
我都是先存檔之後再開啟檔案的;

commons icon [13] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

我有使用notepad打開檔案,
開頭是
"俵遄??",
看不出是否是錯誤...

commons icon [14] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

我猜測是你的那個 php 檔案因為是 UTF-8 編碼的, 在 Windows 下頭, 多數的編輯器會在檔案前面加上 BOM 字元 (3 bytes), 而那些字元會被送出, 所以產生的 excel 檔案會多那幾個 bytes, 格式自然也就不對了.

如果你確定不是因為 BOM 造成的問題. 就把你有問題的檔案與我這兒產生正常的檔案用 binary mode 比較一下看看吧. 或者把有問題的檔案 email 給我看看吧.

commons icon [15] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

謝謝您寶貴的意見,我再試試看..

commons icon [16] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

非常感謝....問題解決!!!!

commons icon [17] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

Tommy大大你好
請教,如何在Linux環境安裝Spreadsheet_Excel_Writer
我server上已用yum安裝了PHP,也download了OLE及Spreadsheet_Excel_Writer的tar檔
查了google都是教人用win環境安裝,Linux環境要怎麼安裝呢?
謝謝

commons icon [18] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

linux 下頭與 window 下沒什麼不同吧.
如果你是用 tarball 裝的, 那只好裝了一個之後跑看看有少什麼再裝缺的東西吧. 或者學著用 pear 裝吧. 這些東西本來就是 pear 裡頭的東西, 一個指令應該就會把缺的都裝上去.
http://pear.php.net/manual/en/

或者直接找有包含這些東西的 linux 發行版本吧. 例如 Debian (UBuntu 應該也有, 反正也可以用 Debian 的套件庫).

commons icon [19] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

感謝Tommy大大
我install pear就可以把OLE及Spreadsheet_Excel_Writerj都安裝起來了
也可以正常運作了,
感謝

commons icon [20] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

Tommy大大,
我是從Spreadsheet_Excel_Writer的那個bug討論的thread裡面找到你這裡來的。我安裝好了Spreadsheet_Excel_Writer以及OLE後按照你的http://www.teatime.com.tw/~tommy/test/excel.phps 裡面的方法生成出來的excel文檔,正文內容看上去都OK,但是下面sheetname裡面包含的中文都亂掉了。請問您有遇見過這種情況么?
謝謝!

commons icon [21] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

名稱的問題請參考另外一篇.
http://blog.teatime.com.tw/1/post/301

commons icon [22] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

太贊了!感謝T大大!

commons icon [23] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

我已經patch 了以上的補丁,但是仍然發生錯誤
Fatal error: Call to undefined method Spreadsheet_Excel_Writer_Worksheet::setBIFF8InputEncoding() in C:\Program Files\EasyPHP 3.0\www\yamao1\Spreadsheet\Excel\Writer\Workbook.php on line 363

commons icon [24] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

有錯.... 表示沒 patch 好吧.

commons icon [25] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

可否email給我一個patch好的workbook.php...
感謝TOMMY大神。

commons icon [26] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

my email: tsang301@yahoo.com.hk

commons icon [27] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

抓 http://www.teatime.com.tw/~tommy/files/Spreadsheet_Excel_Writer-0.9.1_patched.tgz 這個吧.

commons icon [28] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

已經copy 了, 但是excel 內的中文變成問號(?????)
本人的php 程式是先撈數據庫的資料,然後生成excel檔,數據庫的中文資料都變為亂碼了。本人用phpmyadmin,所有數據庫校驗及varchar,text為utf-8 unicode編碼, 是否數據庫編碼的影響?
程式碼如下:

commons icon [29] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

// include class file
include 'Spreadsheet/Excel/Writer.php';
session_start();
$_SESSION["m_computer_code"] = "vch";

$savename = date("YmdHis");

// initialize reader object
$workbook = new Spreadsheet_Excel_Writer("sheets/".$_SESSION["m_computer_code"]."$savename.xls");

$workbook->setVersion(8, 'utf-8');
$worksheet =& $workbook->addWorksheet('International worksheet');
$worksheet->setInputEncoding('UTF-8');
// attempt a connection
try {
$pdo = new PDO("mysql:dbname=phpcart;host=localhost;charset=utf-8", "admin", "Yamao1946");
} catch (PDOException $e) {
die("ERROR: Could not connect: " . $e->getMessage());
}

// read data from database
// convert into spreadsheet
$rowCount = 0;
$sql = "SELECT * FROM `directadd` WHERE `m_computer_code`='". $_SESSION["m_computer_code"]."'";
if ($result = $pdo->query($sql)) {
// get header row
for ($x=0; $xcolumnCount(); $x++) {
$meta = $result->getColumnMeta($x);
$worksheet->write($rowCount, $x, $meta['name']);
}
// get data rows
$rowCount++;
while($row = $result->fetch()) {
foreach ($row as $key => $value) {
$worksheet->write($rowCount, $key, $value);
}
$rowCount++;
}
} else {
echo "ERROR: Could not execute $sql. " . print_r($pdo->errorInfo());
}

// close connection
unset($pdo);

// save file to disk
$workbook->close();

commons icon [30] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

經本人嘗試,如果是static的資料,無論是繁體和簡體都能正常顯示在Excel中。但是經過撈數據庫的步驟後,所生出來的Excel的中文資料都變成問號。

commons icon [31] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

也許你資料庫內抓出來的資料編碼不對吧.
以你上頭的程式來看, 只有使用 utf-8 才會正確的被存到 excel 檔案中.

commons icon [32] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

我的phpmyadmin 所有item的校對都是utf8 unicode 而且default character set 都是uft8,所有的設定都是一致的, 究竟為甚麼生成的excel 中文會變成問號? 救命呀! TOMMY 大神

commons icon [33] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

自己想辦法確認那些字是正確的吧. 畢竟如果是你自己打上去的字可以正確的出來, 表示不是這個模組的問題.

自己把資料庫抓出來的資料寫到檔案上去看看是那一種編碼的字吧.

commons icon [34] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

問題已解決!原來要正確顯示由數據庫中所撈的中文字,需要在連接數據後,查詢語句之前,加上
mysql_query('set names utf8;');由於我使用pdo函式連接數據庫,需要改為$pdo->query('set names utf8;')。加了後,所有繁中,簡中都能夠顯示。總之,感謝TOMMY大神的PATCH。

commons icon [35] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

萬分感謝!!@@

commons icon [36] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

呀.. 多謝大大發表這個excel writer
本人把這個套件install在pear 了
但是使用以下php碼就發生了exception

Warning: Cannot modify header information - headers already sent by (output started at D:\xampplite\htdocs\test\excel.php:2) in D:\xampplite\php\PEAR\Spreadsheet\Excel\Writer.php on line 67

Warning: Cannot modify header information - headers already sent by (output started at D:\xampplite\htdocs\test\excel.php:2) in D:\xampplite\php\PEAR\Spreadsheet\Excel\Writer.php on line 68

Warning: Cannot modify header information - headers already sent by (output started at D:\xampplite\htdocs\test\excel.php:2) in D:\xampplite\php\PEAR\Spreadsheet\Excel\Writer.php on line 69

Warning: Cannot modify header information - headers already sent by (output started at D:\xampplite\htdocs\test\excel.php:2) in D:\xampplite\php\PEAR\Spreadsheet\Excel\Writer.php on line 70

Warning: Cannot modify header information - headers already sent by (output started at D:\xampplite\htdocs\test\excel.php:2) in D:\xampplite\php\PEAR\Spreadsheet\Excel\Writer.php on line 71

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 18 bytes) in D:\xampplite\php\PEAR\Spreadsheet\Excel\Writer\Workbook.php on line 1308

本人是使用xampplite 套件的...是不是預設設定的問題嗎?

commons icon [37] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

1. 應該是 BOM 造成的吧.
2. 把 php 可以使用的記憶體在 php.ini 中加大吧.

commons icon [38] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

:| 多謝大大回覆 原來xampplite 需要預設date_default_timezone_set('Asia/Hong_Kong') ;
加了這句後能夠下載了
不過為什麼活頁簿的名稱是亂碼?

commons icon [39] Re:使用 Spreadsheet_Excel_Writer 產生 UNICODE 的 Excel 檔案 [ 回覆 ]

名稱是亂碼的修正請參考這兒另一篇與 spreadsheet_excel 有關的文吧.

迴響
暱稱:
標題:
個人網頁:
電子郵件:
authimage

迴響

  

Bad Behavior 已經阻擋了 1045 個過去 7 天試圖闖關的垃圾迴響與引用。
Power by LifeType. Template design by JamesHuang. Valid XHTML and CSS