Quantcast
Channel: WFU BLOG
Viewing all articles
Browse latest Browse all 784

網頁資料存成 CSV 需要解決的問題整理﹍亂碼 + JS 技巧 + Bootstrap 表格

$
0
0
最近客戶需要在網頁上顯示大量的會員資料後,製作一個「匯出」按鈕,將表格所有資料匯出存成 CSV 檔,再用 EXCEL 之類的試算表軟體開啟。

整個流程要用的的技術其實沒有太高深,但是陷阱卻是很多,因此整理成一篇備存。

(圖片出處: pexels.com)


一、需要解決的難題


1. JS 如何儲存 CSV

一開始需要瞭解如何將資料存成 CSV 檔,概念可參考這個討論串「How to export JavaScript array info to csv (on client side)?」:

  • 在頁面製作一個超連結,而網址連結的字串可以設定成 CSV 這樣的型態
  • 把所有資料格式整理好,用逗點分隔開,塞進 href 的值即可
  • 使用者點擊連結後,就能存成 CSV 檔


2. 解決 UNICODE 亂碼問題

可惜這樣的 CSV 檔,用 EXCEL 開啟後,只要內容有中文(UNICODE)就會產生亂碼,原因可參考這篇「【Javascript】匯出 csv」。

利用這篇的技巧,在 CSV 檔開頭前幾個字元,塞入特定的編碼字串,可讓 CSV 檔成功在 EXCEL 顯示中文。


3. 資料太多時會被截斷

看完前面第一點的概念後,就知道存成 CSV 檔是靠網址傳值的概念。但客戶的會員資料起碼有幾萬筆,很快就超出瀏覽器網址字串限制的長度,所以無法成功儲存所有的會員資料為 CSV 檔。

這個討論串「Export HTML table to csv in google chrome browser」使用了不同的作法:

  • 原本的作法藉著網址傳遞字串資料,會受到網址字串的長度限制。
  • 新的作法將字串轉換為二進位資料(BLOB),依然用網址傳遞,但資料型態不同,就不會受到字串的長度限制。
  • BLOB 格式的資料大小依然會有上限,但存成 CSV 檔的資料型態,要超出限制是極度困難的事情,所以除非資料多到像影片檔那麼大,那麼可不必擔心此事。


4. 依然是 UNICODE 亂碼問題

解決資料長度問題,改用 BLOB 格式後,又要再度面臨亂碼問題。

找到這篇「使用 JavaScript 导出 CSV 文件」,一樣在資料開始處加入特殊編碼字串,終於一切都正常了。



二、表格範例 + 匯出按鈕



匯出 WFU BLOG 會員資料

權限序號暱稱性別註冊日期
加值會員W00001Wayne Fu男生2014/9/12
一般會員W00002Che女生2014/9/17
一般會員W00003Ken男生2014/9/17
一般會員W00004Sun男生2014/9/17
一般會員W00005Liu男生2014/9/17
一般會員W00006Don男生2014/9/18
一般會員W00007Cha女生2014/9/18
一般會員W00008Tun女生2014/9/18
一般會員W00009男生2014/9/18
一般會員W00010HY男生2014/9/18
一般會員W00011女生2014/9/18
一般會員W00012Kat女生2014/9/19
一般會員W00013Mar男生2014/9/19
一般會員W00014Wan男生2014/9/20
一般會員W00015Bas女生2014/9/20
一般會員W00016男生2014/9/23
一般會員W00017女生2014/9/23
一般會員W00018Li男生2014/10/2
一般會員W00019女生2014/10/2
一般會員W00020男生2014/10/3




三、範例程式碼


以上效果的範例程式碼如下:

<script src='//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js'></script>
<link href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css' rel='stylesheet'></link>

<a id="exportBtn" class="btn btn-success" target="_blank" download="WFUBLOG-會員資料.csv">匯出 WFU BLOG 會員資料</a>
<br/><br/>
<style>
#member_list {white-space: nowrap;}
#member_list thead{background: #5893c8;color:#fff;}
</style>
<div id="member_list" class="table-responsive">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>權限</th>
<th>序號</th>
<th>暱稱</th>
<th>性別</th>
<th>註冊日期</th>
</tr>
</thead>
<tbody>
<tr>
<td>加值會員</td>
<td>W00001</td>
<td>Wayne Fu</td>
<td>男生</td>
<td>2014/9/12</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00002</td>
<td>Che</td>
<td>女生</td>
<td>2014/9/17</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00003</td>
<td>Ken</td>
<td>男生</td>
<td>2014/9/17</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00004</td>
<td>Sun</td>
<td>男生</td>
<td>2014/9/17</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00005</td>
<td>Liu</td>
<td>男生</td>
<td>2014/9/17</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00006</td>
<td>Don</td>
<td>男生</td>
<td>2014/9/18</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00007</td>
<td>Cha</td>
<td>女生</td>
<td>2014/9/18</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00008</td>
<td>Tun</td>
<td>女生</td>
<td>2014/9/18</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00009</td>
<td>陳</td>
<td>男生</td>
<td>2014/9/18</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00010</td>
<td>HY</td>
<td>男生</td>
<td>2014/9/18</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00011</td>
<td>美</td>
<td>女生</td>
<td>2014/9/18</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00012</td>
<td>Kat</td>
<td>女生</td>
<td>2014/9/19</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00013</td>
<td>Mar</td>
<td>男生</td>
<td>2014/9/19</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00014</td>
<td>Wan</td>
<td>男生</td>
<td>2014/9/20</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00015</td>
<td>Bas</td>
<td>女生</td>
<td>2014/9/20</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00016</td>
<td>莊</td>
<td>男生</td>
<td>2014/9/23</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00017</td>
<td>詹</td>
<td>女生</td>
<td>2014/9/23</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00018</td>
<td>Li</td>
<td>男生</td>
<td>2014/10/2</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00019</td>
<td>陳</td>
<td>女生</td>
<td>2014/10/2</td>
</tr>
<tr>
<td>一般會員</td>
<td>W00020</td>
<td>淵</td>
<td>男生</td>
<td>2014/10/3</td>
</tr>
</tbody>
</table>
</div>
<script>
// 點擊匯出
$("#exportBtn").click(function() {
var csvList = [],
titleList = [],
memberContent = "",
csvContent;

// 取得標題
$("#member_list th").each(function() {
titleList.push(this.innerHTML);
});
csvList.push(titleList);

// 取得所有資料
$("#member_list tbody > tr").each(function() {
var regList = [];
$(this).children("td").each(function() {
regList.push(this.innerHTML);
});
csvList.push(regList);
});

// 產生 csv 內容
csvList.forEach(function(rowArray) {
var row = rowArray.join(",");
memberContent += row + "\r\n";
});

// 產生 csv Blob
csvContent = URL.createObjectURL(new Blob(["\uFEFF" + memberContent], {
type: 'text/csv;charset=utf-8;'
}));

// 產生 csv 連結
this.href = csvContent;
});
</script>


  • 前 2 行綠字可參考「引用 jQuery 的注意事項」,檢查範本是否已安裝過 jQuery、Bootstrap,如果已經安裝過請刪除,以免重複安裝。
  • 藍字可修改下載的檔名
  • 如果熟悉 JS,可參考註釋內容自行修改


更多「網頁技巧」相關文章:

Viewing all articles
Browse latest Browse all 784

Trending Articles