Categories
Computer Data

วิธีการสร้างไฟล์ Excel ด้วย SheetJS

ปกติเวลาส่งออกไฟล์ Excel ด้วย JavaScript เราจะสร้างไฟล์ CSV ที่มีข้อจำกัดด้าน Worksheet และภาษาไทย ในบทความนี้จะแนะนำไลบรารี SheetJS ที่สร้างไฟล์ Excel ได้สบาย

การส่งออกไฟล์ในรูปแบบ Excel เดิมถ้าจะเอาวิธีแบบง่าย ๆ เลยคือการส่งออกไฟล์ในรูปแบบ CSV ที่เป็นไฟล์ข้อความที่แบ่งข้อมูลระหว่างคอลัมภ์ด้วยการใช้ตัวอักษรคอมมา (,) เพื่อแบ่งข้อมูล โดยการส่งออกไฟล์ในลักษณะนี้เราส่งออกไฟล์ได้ด้วยการพิมพ์คำสั่ง

let csvfile = '< ข้อมูลในไฟล์ csv >';
let blob = new Blob([csvfile], { type: 'text/csv;charset=utf-8;' });
let link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'download.csv';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);

เมื่อส่งออกไฟล์มาแล้ว ไฟล์จะอยู่ในรูปแบบ CSV ที่สามารถเปิดออกมาได้ด้วย Excel อย่างไรก็ดี การส่งออกไฟล์ในกรณีนี้จะมีปัญหากับภาษาไทยเนื่องมาจากตอนส่งออกและเปิดอ่านไฟล์แล้ว ข้อความจะอยู่ในรูปแบบภาษาต่างดาว ซึ่งเราก็ไม่อยากเห็นใช่ไหมครับ

ในบทความนี้ เราจะแนะนำไลบรารีหนึ่งทีสามารถส่งออกไฟล์ Excel ที่เป็นไฟล์ xlsx ที่เปิดอ่านด้วยโปรแกรมนี้ได้สบาย โดยไลบรารีนี้มีชื่อว่า SheetJS

SheetJS

SheetJS

SheetJS เป็นไลบรารีภาษาจาวาสคริปที่อนุญาตให้เราอ่านและเขียนไฟล์ Excel เพื่อนำไปใช้งานต่อได้อย่างสะดวก โดยไลบรารีนี้แบ่งออกเป็น SheetJS Community Edition และ SheetJS Professional Edition ในบทความนี้เราจะกล่าวถึง Community Edition

SheetJS Community Edition เป็นไลบรารีที่อนุญาตให้เราใช้งานได้ฟรี ด้วยลิขสิทธิ์แบบ Apache 2.0 โดยผู้ใช้สามารถดาวน์โหลดมาได้ในเว็บนี้ครับ การติดตั้งไลบรารีนี้ทำได้ไม่ยาก เราสามารถใช้งานบนเว็บเบราวเซอร์ และใช้งานบน Node.js ก็ได้ อย่างไรก็ดี ตัวอย่างนี้เราจะกล่าวถึงบนเว็บเบราวเซอร์

การติดตั้ง

การติดตั้งเพื่อใช้งานบนเว็บเบราวเซอร์เราทำได้โดยสองแบบ แบบแรกเป็นการใช้งานผ่าน <script> ที่ทำได้ตามด้านล่างนี้

<!-- This loads the shim from the CDN -->
<script src="https://cdn.sheetjs.com/xlsx-0.18.10/package/dist/shim.min.js"></script>

<!-- This loads the standalone build from the CDN -->
<script src="https://cdn.sheetjs.com/xlsx-0.18.10/package/dist/xlsx.full.min.js"></script>

ไลบรารีที่เราใช้งานผ่าน <script> นั้น เราจะสังเกตว่า นอกจากการดาวนืโหลดไบรารี SheetJS (xlsx.full.minjs) แล้ว เรายังดาวน์โหลดไบรารี shim ร่วมด้วยเพื่ออนุญาตให้เราใช้งานบนเว็บเบราวเซอร์รุ่นเก่าอย่าง Internet Explorer 11

นอกจากการใช้ <script> เราใช้งานไลบรารีบน React, Angular หรือใช้งานบน VanillaJS ด้วยการนำเข้าไลบรารีด้วยคำสั่ง import ได้โดยการติดตั้งไบรารีผ่านการใช้งานคำสั่ง npm ตามด้านล่างนี้

npm i --save https://cdn.sheetjs.com/xlsx-0.18.10/xlsx-0.18.10.tgz

ส่วน yarn เราสามารถติดตั้งไลบรารีนี้ได้โดย

yarn add https://cdn.sheetjs.com/xlsx-0.18.10/xlsx-0.18.10.tgz

ติดตั้งไบรารีเสร็จแล้ว เรานำเข้าไลบรารีด้วยคำสั่ง import ได้โดย

import * as XLSX from "xlsx";

ส่วนกรณีที่ไม่ได้ใช้ทั้ง npm และ yarn เราสามารถนำเข้าไลบรารีนี้ได้โดย

import * as XLSX from https://cdn.sheetjs.com/xlsx-0.18.10/package/xlsx.mjs

การส่งออกไฟล์ในรูปแบบ Excel

หลังจากที่ติดตั้งแล้ว เราสามารถส่งออกข้อมูลในรูปแบบ Excel ได้ครับ ขั้นตอนการทำงานของไลบรารีนี้สำหรับการส่งออกไฟล์แบ่งออกเป็นสี่ขั้นตอนได้แก่

สร้างไฟล์ Workbook

เราสามารถสร้างไฟล์ Workbook ได้โดยการพิมพ์คำสั่งตามด้านล่างนี้

let wb = XLSX.utils.book_new();

แปลงข้อมูลให้อยู่ในรูปแบบที่เหมาะสมต่อการสร้าง Worksheet

เราสามารถฃ แปลงข้อมูลให้อยู่ในรูปแบบที่เหมาะสมต่อการสร้าง Worksheet ได้ โดยข้อมูลที่สามารถแปลงได้ ได้แก่

  • JSON (JavaScript Object Notation)
  • อาเรย์ซ้อนอาเรย์ (Array of array)
  • ข้อมูลที่อยู่ในตารางของ HTML (HTML Table)

ตัวอย่างแรกเป็น JSON โดยเราสามารถสร้างข้อมูลได้ตามด้านล่างนี้ โดยให้เป็นอาเรย์ของตัวแปรประเภท Object

let json = [];
for(let index = 0; index < 100; index++) {
  let data = {
    "index": index,
    "multiplier": 2,
    "result": 2 * index
  }
    
  json.push(data);
}

เมื่อสร้างข้อมูลเสร็จแล้ว เรานำข้อมูลนี้แปลงอยู่ในรูปแบบที่พร้อมสำหรับการสร้าง Worksheet ได้โดย

let ws = XLSX.utils.json_to_sheet(json);

วิธีต่อมา เป็นวิธีที่ใช้งานกับอาเรย์ซ้อนอาเรย์ (Array of array) วิธีนี้เราสร้างข้อมูลขึ้นมาก่อนได้ตามด้านล่างนี้

let aoa = [['index', 'multiplier', 'result']];
for(let index = 0; index < 100; index++) {
  let data = [index, 2, 2*index]
  aoa.push(data);
}

เมื่อสร้างข้อมูลเสร็จแล้ว เรานำข้อมูลนี้แปลงอยู่ในรูปแบบที่พร้อมสำหรับการสร้าง Worksheet ได้โดย

let ws = XLSX.utils.aoa_to_sheet(aoa);

วิธีที่สาม เป็นการนำข้อมูลที่อยู่ในตารางของ HTML (HTML Table) มาอยู่ในรูปแบบที่เหมาะกับสร้าง Worksheet จุดนี้เราเขียนโค้ดได้โดย

let table = document.createElement('table');
let tr = document.createElement('tr');
let header = ['index', 'multiplier', 'result'];
header.forEach((name) => {
  let th = document.createElement('td');
  th.innerText = name;
  tr.appendChild(th);
});

table.appendChild(tr);

for(let index = 0; index < 100; index++) {
  let tr = document.createElement('tr');
  let data = [index, 2, 2*index];
  data.forEach((data_each) => {
    let td = document.createElement('td');
    td.innerText = data_each;
    tr.appendChild(td);
  });

  table.appendChild(tr);
}

หรือกรณีที่เรามีตารางอยู่แล้ว เราสามารถใช้งานผ่านคำสั่ง document.getElementById, document.querySelector ได้เลยครับ

ต่อมา เราแปลงให้อยู่ในรูปแบบที่พร้อมสำหรับการสร้าง Worksheet ได้โดยพิมพ์โค้ดตามด้านล่างนี้

let ws = XLSX.utils.table_to_sheet(table);

สร้าง Worksheet

เราสามารถสร้าง Worksheet โดยนำข้อมูลที่ผ่านการแปลงให้อยู่ในรูปแบบที่เหมาะสมตามขั้นตอนที่สองได้โดยการพิมพ์โค้ดตามด้านล่างนี้

XLSX.utils.book_append_sheet(< workbook >, < worksheet >, < ชื่อของ worksheet >);

ในตัวอย่างจะใช้ตัวแปร wb สำหรับ Workbook กับ ws สำหรับ Worksheet เราสามารถพิมพ์โค้ดได้ตามด้านล่างนี้ครับ

XLSX.utils.book_append_sheet(wb, ws, `Multiply by 2`);

หมายเหตุ: การสร้าง Worksheet นั้น เราสามารถสร้างได้มากกว่า 1 Worksheet โดยเราทำตามขั้นตอนที่สอง และสามได้ครับ

ส่งออกไฟล์ในรูปแบบ Excel

เราสามารถส่งออกไฟล์ Excel ได้สามวิธีได้แก่

  • XLSX.write
  • XLSX.writeFile
  • XLSX.writeFileAsync

หนึ่ง ส่งออกไฟล์ผ่านคำสั่ง XLSX.write คำสั่งนี้เป็นคำสั่งที่ให้เราส่งออกไฟล์ได้ โดยเราสามารถส่งออกได้ผ่านการพิมพ์คำสั่งตามด้านล่างนี้

let ret = XLSX.write(wb, { type: "file" });

โดยตัวแปรที่เขียนด้วย { type: “file” } ในส่วนนี้เป็นการตั้งค่าการส่งออกของไฟล์ครับให้อยู่ในรูปที่อยู่ไฟล์ blob (ในรูปแบบ URL) ที่พร้อมสำหรับการดาวน์โหลดไฟล์

นอกจากการพิมพ์ { type: “file” } แล้ว ผู้ใช้สามารถกำหนดชนิดของข้อมูลที่ส่งออกได้ตามด้านล่างครับ

typeoutput
“base64”string: ข้อความที่เข้ารหัสในรูปแบบ Base64
“binary”string: ข้อความที่อยู่ในรูปแบบ Binary
“string”string: ก็เป็น string ที่เข้ารหัส UTF8
“buffer”Node.js Buffer
“array”ArrayBuffer
“file”ที่อยู่ของไฟล์ที่เราสร้างขึ้น (ปกติจะใช้ใน Node.js)

ส่วนรายละเอียดการตั้งค่าเพิ่มเติม ผู้ใช้สามารถอ่านได้ที่ตารางด้านล่างข้อความ “The write functions accept an options argument:” ในหน้า Writing Files

เมื่อเราใช้งานคำสั่งนี้ตามตัวอย่าง ไฟล์จะยังไม่ได้ดาวน์โหลดทันที เราสามารถดาวน์โหลดไฟล์ได้โดยการพิมพ์คำสั่ง

let a = document.createElement('a');
a.href = ret;
a.download = 'download.xlsx';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);

แล้วเว็บเบราวเซอร์จะดาวน์โหลดไฟล์ให้เอง

สอง เขียนผ่านการใช้คำสั่ง XLSX.writeFile คำสั่งนี้จะเป็นการส่งออกไฟล์ Excel เช่นกัน โดยผู้ใช้สามารถใช้งานผ่านการพิมพ์ตามด้านล่างนี้

let ret = XLSX.writeFile(wb, 'multiply.xlsx', { type: "file" });

โดยการตั้งค่าใน { type: “file” } ผู้ใช้สามารถอ่านได้ในวิธีแรกที่ส่งออกไฟล์โดยการใช้คำสั่ง XLSX.write

เมื่อใช้คำสั่งนี้แล้ว ตัวเว็บพยายามดาวน์โหลดไฟล์ลงเครื่องของผู้ใช้ได้เลย ทำให้เราไม่จำเป็นต้องสร้างลิ้งค์เพื่อกดแล้วให้ดาวน์โหลดอีกที

อีกวิธีหนึ่งคือ writeFileAsync อันนี้ก็เขียนไฟล์เช่นกัน แต่ฟังก์ชันนี้จะใช้งานได้บน Node.js เท่านั้น โดยผู้ใช้สามารถใช้งานได้โดยการพิมพ์คำสั่งตามด้านล่างนี้ครับ

XLSX.writeFileAsync(< ชื่อไฟล์ที่ต้องการส่งออก >, < ตัวแปร workbook >, < การตั้งค่า อันนี้ดูได้ที่วิธีที่ 1 ตรงส่วนการใช้งานคำสั่ง XSLX.write >, < ฟังก์ชัน callback ในภาษาจาวาสคริป >)

ผลจากการใช้คำสั่งนี้

เมื่อใช้งานคำสั่งนี้แล้ว พบว่าการใช้งานผ่าน SheetJS ดีกว่าการส่งออกไฟล์ในรูปแบบ CSV ได้แก่

  • ส่งออกได้หลาย Worksheet ผิดกับไฟล์ CSV ที่มีข้อจำกัดที่สามารถส่งออกได้ 1 Worksheet เท่านั้น
  • เราสามารถส่งออกไฟล์ Excel ที่มีข้อความเป็นภาษาไทย แล้วเปิดในโปรแกรม Excel แล้วข้อความไม่กลายเป็นภาษาต่างดาวแบบที่เปิดบน CSV

สำหรับผู้อ่านแล้ว เราแนะนำไลบรารีนี้ครับ ส่วนรายละเอียดเพิ่มเติม ผู้อ่านสามารถอ่านได้ในเว็บของผู้ผลิตไลบรารีนี้

By Kittisak Chotikkakamthorn

อดีตนักศึกษาฝึกงานทางด้าน AI ที่ภาควิชาวิศวกรรมไฟฟ้า มหาวิทยาลัย National Chung Cheng ที่ไต้หวัน ที่กำลังหางานทางด้าน Data Engineer ที่มีความสนใจทางด้าน Data, Coding และ Blogging / ติดต่อได้ที่: contact [at] nickuntitled.com