เนื้อหาตอนต่อไปนี้ เราจะมาดูในเรื่องของการจัดการกับรูปแบบ
การแสดงข้อมูลใน Excel เช่น การจัดตำแหน่ง การกำหนดเส้นขอบ การสร้าง
เส้นขอบ การจัดหน้ากระดาษ เหล่านี้เป็นต้น
ดังนั้น เพื่อให้เนื้อหา เฉพาะเจาะจงไปแค่รูปแบบหรือ style ในที่นี้เราจึงไม่สนใจใน
รายละเอียดของข้อมูลเท่าไหร่นัก
เราจะใช้ข้อมูลจังหวัดในประเทศไทย จากตารางข้อมูลในฐานข้อมูลทดสอบ ที่ http://niik.in/que_2398_6277
ไฟล์ demo.php
<?php // โค้ดไฟล์ dbconnect.php ดูได้ที่ http://niik.in/que_2398_5642 require_once("dbconnect.php"); // include composer autoload require 'vendor/autoload.php'; // import the PhpSpreadsheet Class use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; // Set value binder //\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\DefaultValueBinder() ); \PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() ); $spreadsheet = new Spreadsheet(); // สร้าง speadsheet object $sheet = $spreadsheet->getActiveSheet(); // กำหนดการทำงานที่่แผ่นงานปัจจุบัน // แสดงข้อมูลทั้งหมดของตาราง tbl_excel1 $sql = " SELECT province_id,province_name,province_name_eng FROM tbl_provinces "; $result = $mysqli->query($sql); if($result && $result->num_rows>0){ // คิวรี่ข้อมูลสำเร็จหรือไม่ และมีรายการข้อมูลหรือไม่ $arrayData = $result->fetch_all(); $totalRow = count($arrayData); // จำนวนแถวข้อมูลทั้งหมด $result->free(); // สามารถใช้ $result->close() หรือ $result->free_result() แทนได้ } // กำหนดค่าให้กับพิกัด Cell ในรูปแบบข้อมูล array // กำหนดหัวข้อคอลัมน์ $columnName = ['ID','Name','Name Eng']; $sheet->fromArray($columnName) // array ข้อมูลหัวข้อคอลัมน์ ->fromArray( $arrayData, // ตัวแปร array ข้อมูล NULL, // ค่าข้อมูลที่ตรงตามค่านี้ จะไม่ถูกำหนด 'A2' // จุดพิกัดเริ่มต้น ที่ใช้งานข้อมูล เริ่มทึ่มุมบนซ้าย หากไม่กำหนดจะเป็น "A1" ค่าเริ่มต้น ); /// ส่วนของการจัดรูปแบบการแสดง กำหนดต่อจากบรรทัดนี้ // ส่วนของการสร้างไฟล์ excel $writer = new Xlsx($spreadsheet); $output_file = "hello_world.xlsx"; // กำหนดชื่อไฟล์ excel ที่ต้องการ $writer->save($output_file); // สร้าง excel if(file_exists($output_file)){ // ตรวจสอบว่ามีไฟล์ หรือมีการสร้างไฟล์ แล้วหรือไม่ echo '<a href="'.$output_file.'" target="_blank">Download</a>'; }
ตัวอย่างผลลัพธ์บางส่วน
จัดรูปแบบการแสดงใน Excel
การกำหนดความกว้างของคอลัมน์
ใน PhpSpreadsheet การกำหนดเกี่ยวกับขนาดต่างๆ ไม่ได้เหมือนหรือได้ผลลัพธ์ตามรูปแบบของ Excel ตรงๆ แต่ก็พอจะเป็นค่าประมาณ
ที่เราสามารถปรับแต่งให้เหมาะสมได้ หน่วยที่ใช้จะเรียกว่า char unit โดยขนาดความกว้างแบบเต็ม รวม padding แล้ว จะเท่ากับ 64 pixels
หรือประมาณ 9.140625 char (character units)
รูปแบบคำสั่ง กำหนดความกว้างให้กับคอลัมน์ที่ต้องการ คือ
$sheet->getColumnDimension('A')->setWidth(12); // $sheet->getColumnDimension('A')->setWidth(9.140625); // เท่ากับ 64 pixels หรือ 1 char = 7.001709401709402 pixels
เรากำหนดคอลัมน์ที่ต้องการกำหนดขนาดความกว้างด้วยตัวอักษรภาษาอังกฤษ เช่น A ตามตัวอย่างด้านบน ส่วนค่าที่กำหนดอย่าง
12 และ หรือ 9.140625 คือค่าในหน่วย char units เราสามารถใช้ค่า 7.001709401709402 pixel ไปหาค่าที่ต้องการกำหนดเป็น char unit
ได้เช่น เราอยากได้ความกว้างสักประมาณ 100 px จะต้องกำหนด char เท่าไหร่ ก็สามารถหาได้จาก
100 / 7.001709401709402 = 14.2822265625
ลองทดสอบค่าดู ด้วยคำสั่ง
$sheet->getColumnDimension('A')->setWidth(14.2822265625);
ผลลัพธ์ที่ได้
เราสามารถกำหนดความกว้างพร้อมกันหลายคอลัมน์ โดยใช้การวนลูป array ดังนี้
foreach(['A','C'] as $column) { // หากต้องการกำหนดคอลัมน์ใดๆ ก็เพิ่มเข้าไปใน array $sheet->getColumnDimension($column)->setWidth(14.2822265625); }
หรือกรณีเป็นคอลัมน์ติดๆ กันต่อเนื่อง ก็อาจจะใช้เป็น
foreach(range('A','C') as $column) { // เป็นการสร้าง array จะได้ค่า ['A','B','C'] แล้ววนลูปกำหนดค่า $sheet->getColumnDimension($column)->setWidth(14.2822265625); }
นอกจากนี้ เรายังสามารถกำหนดให้ขนาดของคอลัมน์ขยายอัตโนมัติ โดยยึดจากความกว้างสูงสุดในคอลัมน์นั้นในการใช้งาน
โดยสามารถทำได้ด้วยการใช้คำสั่ง
$sheet->getColumnDimension('A')->setAutoSize(true);
เช่นกัน เราสามารถใช้การวนลูปเพื่อกำหนดให้กับหลายคอลัมน์พร้อมๆ กันได้ ดังนี้
foreach(range('A','C') as $column) { $sheet->getColumnDimension($column)->setAutoSize(true); }
ผลลัพธ์ที่ได้
หรือถ้าเราต้องการให้บางคอลัมน์ กว้างแบบกำหนดเอง ส่วนบางคอลัมน์กว้างอัตโนมัติ ก็อาจจะใช้รูปแบบดังนี้ได้
foreach(range('A','C') as $column) { if($column=='A'){ $sheet->getColumnDimension($column)->setWidth(9.140625); }else{ $sheet->getColumnDimension($column)->setAutoSize(true); } }
นอกจากเราสามารถเลือกที่จะกำหนดความกว้างเฉพาะคอลัมน์ที่เราต้องการแล้ว เรายังสามารถเลือกกำหนดความกว้างค่าเริ่มต้นให้กับ
คอลัมน์ทั้งหมด ได้ดังนี้
$sheet->getDefaultColumnDimension()->setWidth(14.2822265625);
คำสั่งข้างต้น จะเป็นการกำหนดทุกคอลัมน์ใน excel มีความกว้างประมาณ 100 px เท่ากันหมด คำสั่งนี้ เราไม่จำเป็นต้องกำหนดหรือระบุชื่อคอลัมน์
จะเหมาะสำหรับกรณีตารางข้อมูลที่เราต้องการให้แสดงทุกคอลัมน์มีขนาดเท่ากัน
หรือเราจะใช้งานร่วมกับ เช่นให้ทกคอลัมน์เท่ากันหมดที่ 100 px แต่ให้คอลัมน์ A เท่ากับ 64 px เราก็สามารถประยุกต์ร่วมกันได้ดังนี้
$sheet->getDefaultColumnDimension()->setWidth(14.2822265625); // ประมาณ 100 px $sheet->getColumnDimension('A')->setWidth(9.140625); // ประมาณ 64 px
การกำหนดความสูงของแถวรายการ
สำหรับความสูงของแถวรายการ excel จะใช้หน่วย point (pt) โดยค่าเริ่มต้น จะอยู่ 12.75 pt หรือเท่ากับ 17 pixels ค่าที่สามารถกำหนดความ
สูงของแถวรายการจะอยู่ที่ 0 - 409 pt (0 - 545.333333 pixels) ซึ่งถ้าเรากำหนดเป็น 0 นั่นหมายถึงเป็นการซ่อนแถวนั้นๆ ไป
เราสามารถประมาณค่าในหน่วย pixel โดยใช้สัดส่วน 1 point = 1.333333 pixel โดยสมมติว่าเราต้องการความสูงที่ประมาณ 50 px
ก็จะใช้การคำนวณเป็นดังนี้
50 / 1.333333 = 37.50000937500234
ลองมาดูคำสั่งการกำหนดความสูงของแถว โดยเราจะลองกำหนดให้กับห้วข้อรายการ เป็นดังนี้
$sheet->getRowDimension('1')->setRowHeight(37.50000937500234); // ประมาณ 50 px
ผลลัพธ์ที่ได้
เช่นเดียวกันกับรูปแบบการกำหนดคอลัมน์ เราสามารถที่กำหนดหลายๆ แถวพร้อมกัน ในรูปแบบดังนี้
foreach([1,3,5] as $row) { // หากต้องการกำหนดแถวใดๆ ก็เพิ่มเข้าไปใน array $sheet->getRowDimension($row)->setRowHeight(37.50000937500234); // ประมาณ 50 px }
หรือกรณีเป็นหลายแถวติดๆ กันต่อเนื่อง ก็อาจจะใช้เป็น
foreach(range(1,5) as $row) { // เป็นการสร้าง array จะได้ค่า [1,2,3,4,5] แล้ววนลูปกำหนดค่า $sheet->getRowDimension($row)->setRowHeight(37.50000937500234); // ประมาณ 50 px }
เราสามารถกำหนดค่าเริ่มความสูงของทุกๆ แถวรายการด้วยคำสั่ง
$sheet->getDefaultRowDimension()->setRowHeight(15);
การซ่อนหรือแสดง แถว - คอลัมน์
เราสามารถใช้คำสั่ง setVisible() สำหรับซ่อนหรือแสดง แถว - คอลัมน์ โดยกำหนดค่า false ถ้าต้องการซ่อน และกำหนด true หลังจาก
ซ่อนด้วยคำสั่ง setVisible(false) เพื่อแสดง โดยรูปแบบการใช้งานจะคล้ายกันสำหรับแถว และคอลัมน์ เพียงแค่อ้างอิงการใช้งานตามประเภท
ของรายการนั้น
// กรณีคอลัมน์ $sheet->getColumnDimension('C')->setVisible(true); $sheet->getColumnDimension('D')->setVisible(false); // กรณีแถวรายการ $sheet->getRowDimension('10')->setVisible(true); $sheet->getRowDimension('11')->setVisible(false);
การรวมและยกเลิกรวม cell
เราสามารถรวม cell และ ยกเลิกการรวม cell โดยใช้คำสั่ง mergeCells() และ unmergeCells() ตามลำดับ มาดูตัวอย่าง สมมติเราต้องการ
แสดงจำนวนจังหวัดทั้งในแถวต่อจากแถวข้อมูลสุดท้าย ในที่นี้ ก็คือ ตำแหน่ง C79
ตำแหน่ง C79 มาจาก จำนวนแถวหัวข้อ(1) + จำนวนรายการ(77) + แถวลำดับถัดไป(1) = 79
ดูตัวอย่างคำสั่ง
$rowSumNo = $totalRow+2; // แถวที่เราจะจัดการ $sheet ->setCellValue('A'.$rowSumNo, 'จำนวน'); $sheet ->setCellValue('B'.$rowSumNo, 'ทั้งหมด'); $sheet ->mergeCells('A'.$rowSumNo.':B'.$rowSumNo); // รวม cel A79:B79 $sheet ->setCellValue('C'.$rowSumNo, '=MAX(A2:A78)'); // ใช้สูตรหาค่าสูงสุด ซึ่งก็คือ 77
ผลลัพธ์ที่ได้
จะเห็นว่าข้อความคำว่า "ทั้งหมด" จะไม่แสดง แต่จะใช้ค่าจาก พิกัด cell แรกทั้งหมด ดังนั้น ถ้าเราต้องการข้อความว่า "จำนวนทั้งหมด"
ใน cell ที่มีการรวมกัน เราต้องกำหนดค่าไว้ใน พิกัดแรก (ในที่นี้ก็คือ A79) ดังนี้
$rowSumNo = $totalRow+2; // แถวที่เราจะจัดการ $sheet ->setCellValue('A'.$rowSumNo, 'จำนวนทั้งหมด'); $sheet ->mergeCells('A'.$rowSumNo.':B'.$rowSumNo); // รวม cel A79:B79 $sheet ->setCellValue('C'.$rowSumNo, '=MAX(A2:A78)'); // ใช้สูตรหาค่าสูงสุด ซึ่งก็คือ 77
จะได้เป็น
เรามาลองกรณีสมมติ ว่าในคอลัมน์ A79 และ B79 มีข้อมูลอยู่แล้ว และเราต้องการเอาค่าจากพิกัดทั้งสอง มาใส่ในพิกัดข้อมูลที่รวม cell แล้ว
แนวทางจะเป็นดังนี้
$rowSumNo = $totalRow+2; // แถวที่เราจะจัดการ // สมมติมีข้อมูลอยู่แล้ว $sheet ->setCellValue('A'.$rowSumNo, 'จำนวน'); $sheet ->setCellValue('B'.$rowSumNo, 'ทั้งหมด'); // ดึงค่ามาใช้ $cellA79_value = $sheet->getCell('A'.$rowSumNo)->getValue(); $cellB79_value = $sheet->getCell('B'.$rowSumNo)->getValue(); $mergeValue = $cellA79_value.$cellB79_value; // กำหนดค่าให้กับพิกัดแรก ที่มีการรวม cell $sheet ->setCellValue('A'.$rowSumNo, $mergeValue); $sheet ->mergeCells('A'.$rowSumNo.':B'.$rowSumNo); // รวม cel A79:B79 $sheet ->setCellValue('C'.$rowSumNo, '=MAX(A2:A78)'); // ใช้สูตรหาค่าสูงสุด ซึ่งก็คือ 77
ผลลัพธ์ที่ได้ จะคล้ายกับตัวก่อนหน้า ที่ต่างไปคือเราเพิ่มช่องว่างระหว่างค่าข้อมูล เพื่อให้เห็นความแตกต่าง
วิธีนี้เหมาะสำหรับรวมพิกัด cell ที่มีค่าเดิมอยู่แล้ว ให้อยู่ด้วยกัน เช่น สมมติ มีคอลัมน์ชื่อ และคอลัมน์นามสกุล แต่เราต้องการรวมชื่อและนามสกุล
ให้อยู่ในคอลัมน์เดียวกัน ก็สามารถใช้วิธ๊นี้ได้
$lastRow = $totalRow +1; for($i=1; $i<=$lastRow; $i++){ $coorCellB = 'B'.$i; $coorCellC = 'C'.$i; // ดึงค่ามาใช้ $columnB_value = $sheet->getCell($coorCellB)->getValue(); $columnC_value = $sheet->getCell($coorCellC)->getValue(); $mergeValue = $columnB_value.' - '.$columnC_value; $sheet ->setCellValue('B'.$i, $mergeValue); $sheet ->mergeCells('B'.$i.':C'.$i); // รวม cel }
ผลลัพธ์ที่ได้
และอีกเทคนิคหนึ่งก็คือ ใช้สูตรรวมข้อมูลไว้ในคอลัมน์ใหม่ แล้วใช้การซ่อนคอลัมน์เดิมไป ดังนี้
$lastRow = $totalRow +1; for($i=1; $i<=$lastRow; $i++){ $coorCellB = 'B'.$i; $coorCellC = 'C'.$i; // ใช้สูตรรวมข้อความไว้ใน คอลัมน์ D $sheet ->setCellValue('D'.$i, '=CONCATENATE('.$coorCellB.'," - ",'.$coorCellC.')'); } // จากนั้นซ่อนคอลัมน์ที่ไม่ใช้งานไป $sheet->getColumnDimension('B')->setVisible(false); $sheet->getColumnDimension('C')->setVisible(false);
ผลลัพธ์ที่ได้
เราจะมาดูกันต่อในตอนหน้า เกี่ยวกับการกำหนด style ให้กับพิกัด cell