Tag Archive ข้อมูล

PHPExcel: จัดรูปแบบ format ข้อมูล

เมื่อวานเขียน export ข้อมูลออกเป็นไฟล์ excel โดยใช้เวลาไม่นาน เพราะโครงสร้างการทำงานมันเหมือนๆ งานที่เคยทำมา แต่มาตกม้าตายเอาที่การฟอร์เมตของแต่ละ column ให้ตรงกับชนิดข้อมูล เช่น type เป็น date ก็ควรให้เห็นเป็นวันที่ไม่ใช่เลข 1234155 อะไรก็ไม่ทราบ

[code language=”php” title=”PHPExcel/columnsType.php”]<?php

include ‘../vendor/phpoffice/phpexcel/Classes/PHPExcel.php’;

set_time_limit(0);

$objPHPExcel = new PHPExcel();

/* Set default style */
$defaultStyle = $objPHPExcel->getDefaultStyle();

$defaultStyle->getFont()
->setName(‘Arial’)
->setSize(11);

$defaultStyle->getNumberFormat()
->setFormatCode(‘yyyy-mm-dd’);

/* Set document properties */
$title = ‘columnsType_’ . date(‘Y-m-d_H:i’);
$objPHPExcel->getProperties()->setCreator(‘CMS’)
->setCategory(‘Exports Datas’)
->setDescription($title)
->setKeywords(‘Exports Datas ‘ . date(‘Y-m-d’))
->setSubject($title)
->setTitle($title);

/* create new sheet */
$objWorkSheet = $objPHPExcel->getActiveSheet();
$objWorkSheet->setTitle(‘Exports Datas’);

$columns = [
‘row_number’ => [‘title’ => ‘No.’, ‘type’ => ‘row_number’],

‘price’ => [‘title’ => ‘ราคา’, ‘type’ => ‘currency’],

‘dateEnd’ => [‘title’ => ‘เริ่มจำหน่าย’, ‘type’ => ‘date’],
‘dateStart’ => [‘title’ => ‘เริ่มจำหน่าย’, ‘type’ => ‘date’],

‘dateApproved’ => [‘title’ => ‘เวลาอนุมัติ’, ‘type’ => ‘datetime’],

‘height’ => [‘title’ => ‘สูง (เมตร)’, ‘type’ => ‘float’],
‘width’ => [‘title’ => ‘กว้าง (เมตร)’, ‘type’ => ‘float’],

‘calculate’ => [‘title’ => ‘สูตรคํานวณหวย’, ‘type’ => ‘formula’],

‘image’ => [‘title’ => ‘ภาพ’, ‘type’ => ‘image’],

‘items’ => [‘title’ => ‘จำนวน’, ‘type’ => ‘integer’],

‘productName’ => [‘title’ => ‘ชื่อสินค้า’, ‘type’ => ‘string’],

‘timeEnd’ => [‘title’ => ‘เวลาขาย’, ‘type’ => ‘time’],
‘timeStart’ => [‘title’ => ‘เวลาปิดการขาย’, ‘type’ => ‘time’],

‘url’ => [‘title’ => ‘page’, ‘type’ => ‘url’],
];

/* header */
$colNo = -1;
$rowNo = 1;
$colStrings = [];
foreach ($columns as $fieldId => $field) {
$colNo++;
$colStrings[$colNo] = $colString = PHPExcel_Cell::stringFromColumnIndex($colNo);
$objWorkSheet->setCellValue($colString . ‘1’, $field[‘title’]);
$objWorkSheet->setCellValue($colString . ‘2’, ‘type = ‘ . $field[‘type’]);
}
$headerHeight = $rowNo = 2;

$objPHPExcel->getActiveSheet()->freezePane($colString . ($headerHeight + 1));

/* random data */
$datas = [];
for ($a = 0; $a < 10; $a++) {
$temp = [];

$temp[‘calculate’] = ‘=RAND()’;
$temp[‘dateApproved’] = date(DATE_ISO8601, mt_rand(0, 1499291999));
$temp[‘dateEnd’] = date(‘Y-m-d’, mt_rand(0, 1499291999));
$temp[‘dateStart’] = date(‘Y-m-d’, mt_rand(0, 1499291999));
$temp[‘height’] = mt_rand(0, 10) / 10;
$temp[‘image’] = ‘http://lorempixel.com/400/200/sports/?st=’ . mt_rand(1, 500);
$temp[‘items’] = mt_rand(999, 9999999);
$temp[‘price’] = mt_rand(100, 10000);
$temp[‘productName’] = substr(str_shuffle(str_repeat($x = ‘0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ’, ceil(10 / strlen($x)))), 1, 10);
$temp[‘timeEnd’] = date(‘H:i:s’, mt_rand(0, 1499291999));
$temp[‘timeStart’] = date(‘H:i:s’, mt_rand(0, 1499291999));
$temp[‘url’] = ‘https://plusmagi.com/?s=’ . mt_rand(1, 500);
$temp[‘width’] = mt_rand(0, 10) / 10;

array_push($datas, $temp);
}

/* add data */
$row_number = 0;
foreach ($datas as $item) {
$colNo = -1;
$row_number++;
$rowNo++;
foreach ($columns as $fieldId => $field) {
$colNo++;

$coordinate = $colStrings[$colNo] . $rowNo;

switch ($field[‘type’]) {
case ‘date’:
case ‘datetime’:
case ‘time’:{
$ts = strtotime($item[$fieldId]);
$value = PHPExcel_Shared_Date::PHPToExcel($ts);
}break;

case ‘image’:{
$value = $item[$fieldId];

$gdImage = imagecreatefromjpeg($value);
$objDrawing = new PHPExcel_Worksheet_MemoryDrawing(); /*create object for Worksheet drawing*/

$objDrawing->setCoordinates($coordinate); /*set image to cell*/
$objDrawing->setDescription(‘Customer Signature’); /*set description to image*/
$objDrawing->setHeight(50);
$objDrawing->setImageResource($gdImage);
$objDrawing->setName(‘Customer Signature’); /*set name to image*/
$objDrawing->setOffsetX(25); /*setOffsetX works properly*/
$objDrawing->setOffsetY(10); /*setOffsetY works properly*/
$objDrawing->setWidth(100); /*set width, height*/

$objDrawing->setWorksheet($objWorkSheet); /*save*/

$objWorkSheet->getRowDimension($rowNo)->setRowHeight(60); /* set row height*/
}break;

case ‘row_number’:{
$value = $row_number;
}break;

case ‘url’:{
$value = str_replace(‘http://’, ”, $item[$fieldId]);
$objWorkSheet->getCell($coordinate)
->getHyperlink()
->setTooltip(‘Click here to access page’)
->setUrl($item[$fieldId]);
}break;

default:{
$value = $item[$fieldId];
}break;
}

$objWorkSheet->setCellValue($coordinate, $value);
}
}

/* auto width column */
$cellIterator = $objWorkSheet->getRowIterator()->current()->getCellIterator();
$cellIterator->setIterateOnlyExistingCells(true);
foreach ($cellIterator as $cell) {
$objWorkSheet->getColumnDimension($cell->getColumn())->setAutoSize(true);
}

/* format for columns */
$colNo = -1;
foreach ($columns as $fieldId => $field) {
$colNo++;

$coordinate = $colStrings[$colNo] . ($headerHeight + 1) . ‘:’ . $colStrings[$colNo] . $rowNo;

switch ($field[‘type’]) {

case ‘currency’:{
$objWorkSheet->getStyle($coordinate)
->getNumberFormat()
->setFormatCode(‘#,##0.00’);
/*->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_NUMBER);*/
}break;

case ‘date’:{
$objWorkSheet->getStyle($coordinate)
->getNumberFormat()
->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_DATE_DMYSLASH);
}break;

case ‘datetime’:{
$objWorkSheet->getStyle($coordinate)
->getNumberFormat()
->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_DATE_DATETIME);
/*->setFormatCode(‘Y-m-d H:i:s’);*/
}break;

case ‘float’:{
$objWorkSheet->getStyle($coordinate)
->getNumberFormat()
->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1);
}break;

case ‘integer’:
case ‘row_number’:{
$objWorkSheet->getStyle($coordinate)
->getNumberFormat()
->setFormatCode(‘#,##’);
}break;

case ‘time’:{
$objWorkSheet->getStyle($coordinate)
->getNumberFormat()
->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4);
/*->setFormatCode(‘Y-m-d H:i:s’);*/
}break;

default:{
$objWorkSheet->getStyle($coordinate)
->getNumberFormat()
->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_GENERAL);
}break;
}

}

$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, ‘Excel2007’);
header(‘Content-Type: application/vnd.ms-excel’);
header(‘Content-Disposition: attachment;filename="’ . $title . ‘.xlsx"’);
header(‘Cache-Control: max-age=0’);
header(‘Cache-Control: no-store, no-cache, must-revalidate, max-age=0’);
header(‘Cache-Control: post-check=0, pre-check=0’, false);
header(‘Pragma: no-cache’);
$objWriter->save(‘php://output’);[/code]

หลักการต้องทำงานคู่กัน 2 ส่วนคือ

  1. ส่วนใส่ข้อมูล บางชนิดต้องแปลงข้อมูลก่อน เช่น date, datetime, timestamp และ time ต้องเปลี่ยนเป็น unix timestamp ก่อน
  2. ส่วนกำหนด cell format (ในตัวอย่างให้วิธีกำหนดทั้ง column ไปเลย) ต้องเลือกรูปแบบที่เหมาะสมโดยจะกำหนดเอง[code language=”php” title=”custom format”]->setFormatCode(‘Y-m-d H:i:s’);[/code] หรือจะใช้ตามมาตราฐานก้ได้ Class PHPExcel_Style_NumberFormat ก็ได้

jQuery: upload แบบ ajax

ตัวอย่างการใช้ jQuery upload ไฟล์แบบ ajax[code language=”html” title=”ajax.form.upload.html”]<!doctype html>
<html>

<head>
<meta charset="utf-8">
<title>jQuery: form > send file</title>
<link href="../vendor/twbs/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css">
<style>
.progressbar {
background: #c00000;
clear: both;
height: 10px;
width: 0;
}

.progressLoaded {
width: 50px;
}

.progressLoaded::after {
content: " bytes";
}

.progressPercent {
width: 50px;
}

.progressPercent::after {
content: " %";
}

.progressTotal {
float: left;
width: 50px;
}

.progressTotal::after {
content: " bytes";
}

.progressTotal::before {
content: " of ";
}
</style>
</head>

<body>
<h1>upload file with ajax</h1>
<form action="values.php" class="form-horizontal" enctype="multipart/form-data" id="formA" method="post">
<div class="form-group">
<label class="col-sm-2 control-label" for="socialidI">หมายเลขบัตรประชาชน</label>
<div class="col-sm-10">
<input class="form-control" id="socialidI" maxlength="13" name="socialid" placeholder="หมายเลขบัตรประชาชน" type="number">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="photoI">ภาพถ่าย</label>
<div class="col-sm-10">
<input class="form-control" id="photoI" name="photo" placeholder="upload file" type="file">
</div>
</div>
<div class="form-group">
<div class="col-sm-10 text-right">
<button type="submit" class="btn btn-success">ส่งข้อมูล</button>
</div>
</div>
</form>
<div class="col-sm-12">
<h4>Progress</h4>
<div class="progressLoaded"></div>
<div class="progressTotal"></div>
<div class="progressPercent"></div>
<div class="progressbar"></div>
</div>
<div class="col-sm-12" id="resultA"></div>
<script src="../vendor/components/jquery/jquery.min.js"></script>
<script>
function xhrProgress(xhr) {
if (xhr.upload) {
// For handling the progress of the upload
xhr.upload.addEventListener(‘progress’, function (e) {
if (e.lengthComputable) {
$(‘.progressTotal’).html(e.total);
$(‘.progressLoaded’).html(e.loaded);

percentComplete = parseInt((e.loaded / e.total * 100), 10);
$(‘.progressPercent’).html(percentComplete);
$(‘.progressbar’).css("width", percentComplete + ‘%’);
}
}, false);
}
return xhr;
}

$(function () {

var formA = $(‘#formA’);

formA.submit(function (event) {
event.preventDefault();

$.ajax({
"beforeSend": function (jqXHR, settings) {
/* แยกตัวแปรไว้ตรวจสอบข้อมูล */
var params = settings.data;

if (settings.data.get(‘socialid’) == ”) {

jqXHR.abort();
alert(‘กรุณากรอกหมายเลขบัตรประชาชน’);

return false;
}

if (settings.data.get(‘photo’).name == ”) {

jqXHR.abort();
alert(‘กรุณาอัพโหลดรูปภาพ’);

return false;
}

},
"contentType": false,
"data": new FormData(formA[0]),
"method": "POST",
"processData": false,
"success": function (data, textStatus, jqXHR) {
$(‘#resultA’).html(data);
},
"url": "values.php",
"xhr": function () {
return xhrProgress($.ajaxSettings.xhr());
},

});

});

});
</script>
</body>

</html>[/code]ไฟล์ที่รอรับข้อมูล[code language=”php” title=”values.php”]<?php
echo ‘FILE<pre>’, print_r($_FILES, true), ‘</pre>’;
echo ‘GET<pre>’, print_r($_GET, true), ‘</pre>’;
echo ‘POST<pre>’, print_r($_POST, true), ‘</pre>’;
[/code]

วิธีนี้ใช้ความสามารถใหม่ FormData ที่ใช้กับ browser เก่าแก่กว่า Internet Explorer 10 หรือ Edge ไม่ได้ ดูเพิ่มเติม

jQuery: ส่ง form แบบ ajax ชั้นสูง

ก่อนที่จะใช้ jQuery ส่งข้อมูลแบบ ajax ออกไป อาจจะใช้ javascript ทำงานเบื้องต้นก่อนได้เช่น การตรวจสอบข้อมูล (validation) ว่า user ได้ทำการกรอกข้อมูลตามที่จำเป็นครบรึเปล่า หรือนำข้อมูลออกไปจากแบบฟอร์ม โดยที่ไม่ต้องไปทำในฝั่ง server

ใน jQuery Ajax สามารถทำได้โดยการระบุ “beforeSend” ตาม code ตัวอย่าง[code language=”javascript” title=”jQuery: advance process before send data”]$.ajax({
"beforeSend": function(jqXHR, settings) {

/* ใส่ตัวแปรเข้าไปเพิ่ม */
settings.data += ‘&ajax=true’;

/* แยกตัวแปรไว้ตรวจสอบข้อมูล */
var params = new URLSearchParams(settings.data);

/* บังคับกรอกข้อมูล */
if (params.get(‘way’) == ‘socialid’ && params.get(‘socialid’) == ”) {

jqXHR.abort();
alert(‘กรุณากรอกหมายเลขบัตรประชาชน’);

return false;
} else if (params.get(‘way’) == ‘phone’ && params.get(‘phone’) == ”) {

jqXHR.abort();
alert(‘กรุณากรอกหมายเลขโทรศัพท์’);

return false;
}

if (params.get(‘amount’) == ”) {

jqXHR.abort();
alert(‘กรุณากรอกจำนวนเงิน’);

return false;
}

/* เอาข้อมูลที่ไม่ต้องการส่งออก */
settings.data = RemoveParameterFromUrl(settings.data, ‘way’);
settings.data = RemoveParameterFromUrl(settings.data, ‘way’);
if (params.get(‘way’) == ‘socialid’) {
settings.data = RemoveParameterFromUrl(settings.data, ‘phone’);
} else {
settings.data = RemoveParameterFromUrl(settings.data, ‘socialid’);
}

},
"data": formA.serialize(),
"method": "POST",
"success": function(data, textStatus, jqXHR) {
$(‘#resultA’).html(data);
},
"url": "values.php",
});[/code]เราจะดูข้อมูลที่รวบรวมมาได้ใน object settings.data และสามารถต่อ string เพิ่มเข้าไปได้เหมือนการต่อ string[code language=”javascript” title=”add new data”]settings.data += ‘&ajax=true’;[/code]การที่จะแยกข้อมูลออกมาสามารถใช้[code language=”javascript” title=”get value from query string”]var params = new URLSearchParams(settings.data);[/code]แบ่งข้อมูลออกมาเป็น array เพื่อใช้ตรวจสอบข้อมูลหรือจะนำไปใช้ในการเปลี่ยนแปลงข้อมูล เช่นเดียวกันก็สามารถ delete ลบข้อมูลที่ไม่ได้การออกไปได้โดยใช้ function[code language=”javascript” title=”delete data from url”]function RemoveParameterFromUrl(url, parameter) {
return url.replace(new RegExp(‘^([^#]*\?)(([^#]*)&)?’ + parameter + ‘(\=[^&#]*)?(&|#|$)’), ‘$1$3$5’).replace(/^([^#]*)((\?)&|\?(#|$))/, ‘$1$3$4’);
}[/code]

ตัวอย่าง form เขียนโดยยกกรณีโอนเงินโดยใช้ พร้อมเพย์ (PromptPay) ที่ user จะเลือกได้ว่าจะโอนเงินโดยใช้ บัตรประชาชน หรือหมายเลขโทรศัพท์ของผู้รับแทนที่จะใช้หมายเลขบัญชี

[code language=”html” title=”ajax.form.advance.html”]<!doctype html>
<html>

<head>
<meta charset="utf-8">
<title>jQuery: Advance Form Send</title>
<link href="../vendor/twbs/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css">
</head>

<body>
<h1>พร้อมเพย์ (PromptPay)</h1>
<form action="values.php" class="form-horizontal" id="formA" method="post">
<div class="form-group">
<label class="col-sm-2 control-label">โอนเงินด้วย</label>
<div class="col-sm-10">
<div class="radio">
<label>
<input checked name="way" type="radio" value="socialid"> หมายเลขบัตรประชาชน
</label>
</div>
<div class="radio">
<label>
<input name="way" type="radio" value="phone"> หมายเลขโทรศัพท์
</label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="socialidI">หมายเลขบัตรประชาชน</label>
<div class="col-sm-10">
<input class="form-control" id="socialidI" maxlength="13" name="socialid" placeholder="หมายเลขบัตรประชาชน" type="number">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="phoneI">หมายเลขโทรศัพท์</label>
<div class="col-sm-10">
<input class="form-control" id="phoneI" maxlength="11" name="phone" placeholder="หมายเลขโทรศัพท์" type="tel">
</div>
</div>
<div class="form-group">
<label for="amount" class="col-sm-2 control-label">จำนวนเงิน</label>
<div class="col-sm-10">
<div class="input-group">
<input class="form-control" id="amount" max="5000" min="0" name="amount" placeholder="จำนวนเงิน" type="number">
<div class="input-group-addon">&#3647;</div>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-10 text-right">
<button type="submit" class="btn btn-success">โอนเงิน</button>
</div>
</div>
</form>
<div class="col-sm-12" id="resultA"></div>
<script src="../vendor/components/jquery/jquery.min.js"></script>
<script>
function RemoveParameterFromUrl(url, parameter) {
return url.replace(new RegExp(‘^([^#]*\?)(([^#]*)&)?’ + parameter + ‘(\=[^&#]*)?(&|#|$)’), ‘$1$3$5’).replace(/^([^#]*)((\?)&|\?(#|$))/, ‘$1$3$4’);
}

$(function () {
var formA = $(‘#formA’);

formA.submit(function (event) {
event.preventDefault();

$.ajax({
"beforeSend": function (jqXHR, settings) {

/* ใส่ตัวแปรเข้าไปเพิ่ม */
settings.data += ‘&ajax=true’;

/* แยกตัวแปรไว้ตรวจสอบข้อมูล */
var params = new URLSearchParams(settings.data);

/* บังคับกรอกข้อมูล */
if (params.get(‘way’) == ‘socialid’ && params.get(‘socialid’) == ”) {

jqXHR.abort();
alert(‘กรุณากรอกหมายเลขบัตรประชาชน’);

return false;
} else if (params.get(‘way’) == ‘phone’ && params.get(‘phone’) == ”) {

jqXHR.abort();
alert(‘กรุณากรอกหมายเลขโทรศัพท์’);

return false;
}

if (params.get(‘amount’) == ”) {

jqXHR.abort();
alert(‘กรุณากรอกจำนวนเงิน’);

return false;
}

/* เอาข้อมูลที่ไม่ต้องการส่งออก */
settings.data = RemoveParameterFromUrl(settings.data, ‘way’);
settings.data = RemoveParameterFromUrl(settings.data, ‘way’);
if (params.get(‘way’) == ‘socialid’) {
settings.data = RemoveParameterFromUrl(settings.data, ‘phone’);
} else {
settings.data = RemoveParameterFromUrl(settings.data, ‘socialid’);
}

},
"data": formA.serialize(),
"method": "POST",
"success": function (data, textStatus, jqXHR) {
$(‘#resultA’).html(data);
},
"url": "values.php",
});
});
});
</script>
</body>

</html>[/code]และฝั่ง server side ที่ควรจะมีการ validation ตรวจสอบข้อมูลซ้ำอีกครั้งเพื่อความมั่นใจ แต่ตัวอย่างนี้จะแสดงข้อมูลที่ทางฝั่ง server ได้รับเท่านั้น เพื่อให้เห็นการ edit แก้ข้อมูลที่ส่งไป[code language=”php” title=”values.php”]<?php
echo ‘GET<pre>’, print_r($_GET, true), ‘</pre>’;
echo ‘POST<pre>’, print_r($_POST, true), ‘</pre>’;[/code]

สร้างไฟล์ csv จาก phpexcel

phpexcel สร้างไฟล์ excel ได้สะดวกมาก แต่ไม่ใช่ทุกระบบจะสามารถ import ข้อมูลจากไฟล์แบบเอ็กเซลได้ การส่งออกไฟล์แบบตัวอักษรล้วนๆ และใช้เครื่องหมายคั่นแบบไฟล์ csv จึงยังจำเป็นอยู่

ที่สำคัญคือสามารถแก้หรือเพิ่มเงื่อนไขจาก code ส่งออกข้อมูลเป็น excel โดย phpexcel ที่มีอยู่เดิม โดยดัดแปลงเล็กน้อยในส่วน header และการ write data[code language=”php” title=”PHPExcel_writer_csv.php”]<?php

/* PHPExcel_IOFactory – Reader */
include ‘PHPOffice/PHPExcel/Classes/PHPExcel.php’;

$objPHPExcel = new PHPExcel();

/* Set default style */
$defaultStyle = $objPHPExcel->getDefaultStyle();

$defaultStyle->getFont()
->setName(‘Arial’)
->setSize(11);

$defaultStyle->getNumberFormat()
->setFormatCode(‘yyyy-mm-dd’);

/* Set document properties */
$title = ‘Exports_Datas_’ . date(‘Y-m-d_H:i’);
$objPHPExcel->getProperties()->setCreator(‘Pitt Phunsanit’)
->setCategory(‘Exports Datas’)
->setDescription($title)
->setKeywords(‘Exports Datas ‘ . date(‘Y-m-d’))
->setSubject($title)
->setTitle($title);

/* rename sheet */
$objWorkSheet = $objPHPExcel->getActiveSheet();
$objWorkSheet->setTitle(‘Exports Datas’);

for ($rowNo = 1; $rowNo < 10; $rowNo++) {
for ($colNo = 0; $colNo < 5; $colNo++) {

$insert = rand(0, 1);
if($insert == 1) {

$colString = PHPExcel_Cell::stringFromColumnIndex($colNo);

$coordinate = $colString . $rowNo;

$objWorkSheet->setCellValue($coordinate, ‘ส่งออกข้อมูล -> ‘.$coordinate);
}
}
}

header(‘Cache-Control: max-age=0’);
header(‘Content-Encoding: UTF-8’);
header(‘Content-Description: File Transfer’);
header(‘Content-Type: application/octet-stream’);
header(‘Content-type: text/csv; charset=UTF-8’);
header(‘Content-Disposition: attachment;filename="’.$title.’.csv"’);
echo "\xEF\xBB\xBF"; /* UTF-8 BOM */

$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, ‘CSV’);

/* set Delimiter, (defaults ,) */
//$objWriter->setDelimiter(‘|’);
//$objWriter->setEnclosure(”);
/* Set line ending (defaults PHP_EOL) */
//$objWriter->setLineEnding(‘0x0d0a’);

$objWriter->save(‘php://output’);[/code]

ถ้าสังเกตุจะมี $insert = rand(0, 1); และ if($insert == 1) { ทำให้บาง cell ไม่มีข้อมูล เพื่อที่จะแสดงให้เห็นว่าการใช้ phpexcel จะดีกว่าการใช้ echo ส่งออกข้อมูลแบบที่ง่ายที่สุด (CSV) ในกรณีที่บางคอลัมข้อมูลไม่มี เราไม่จำเป็นต้อง echo ค่าว่าง หรือมานับ , ว่าครบมั๋ย phpexcel จะจัดการให้เอง

ถ้าเปลี่ยนรูปแบบอื่นเช่น

  • ต้องการใช้เครื่องหมายอื่นเช่น pipe | ก็สามารถกำหนดโดยใช่ setDelimiter
  • ต้องการ wrap ข้อมูลก็ใช้ setEnclosure จะปิดหัว ปิดท้ายข้อมูลแต่ละ cell ให้
  • ต้องการใช้เครื่องมายอื่นในการแบ่งข้อมูลออกเป็นชุดๆ ก็ setLineEnding

เขียนครั้งเดียวส่งออกข้อมูลได้ 2 รูปแบบ ส่วนคำสั่งที่ไม่ได้ใช้ในรูปแบบ csv เช่น setTitle ก็ไม่ทำให้มี error ดีจริงๆ phpexcel

ส่งออกข้อมูลแบบที่ง่ายที่สุด (CSV)

วิธีที่ส่งออกข้อมูลที่ง่ายที่สุด และอิมพอร์ตเข้าโปรแกรมต่างๆได้มากที่สุดคือ comma-separated values (CSV) แปลง่ายๆว่า ไฟล์ตารางที่คั่นด้วยคอมม่า แปลบ้านๆไปอีกคือ text file ที่ข้อมูลถูกแบ่งโดย , หรือเครื่องหมายอื่นเช่น pipe | โดยข้อมูลต่ละ record จะแบ่งโดยการขึ้นบรรทัดใหม่ (ใน php คือ \n)

เขียนง่ายๆ แค่มีการเพิ่ม header เข้าไปว่ามันเป็น csv นะและ echo ธรรมดาๆ[code language=”php”]<?php

$filename = ‘Exports_Datas_’ . date(‘Y-m-d_H:i’);

header(‘Cache-Control: max-age=0’);
header(‘Content-Encoding: UTF-8’);
header(‘Content-Description: File Transfer’);
header(‘Content-Type: application/octet-stream’);
header(‘Content-type: text/csv; charset=UTF-8’);
header(‘Content-Disposition: attachment;filename="’.$filename.’.csv"’);
echo "\xEF\xBB\xBF"; /* UTF-8 BOM */

/* random add datas */
for($a = 0; $a < 10; $a++) {
$datas = [];
for($b = 0; $b < 5; $b++) {
$datas[$b] = ‘ส่งออกข้อมูล ‘.rand(1, 100);
}
echo implode(‘,’, $datas)."\n";
}[/code]

หลังจากเรียกไฟล์ php ก็จะเห็นว่ามีการให้ download ขึ้นมาให้ save ลองคลิกเปิดดูถ้าเครื่องมี excel อยู่ก็จะเปิดอ่านข้อมูลได้ทันที หรือจะใช้ text editor เปิดขึ้นมาดูก็ได้ ทดลองเปลี่ยนเป็นให้ดึงข้อมูลจาก database ดูครับ

หาและลบข้อมูลซ้ำในตาราง

การย้ายระบบจากระบบเก่ามาระบบใหม่ เป็นธรรมดาที่จะเจอปัญหาความผิดพลาดจากการที่ระบบเดิมออกแบบมาไม่ดี ทำให้มีข้อมูลซ้ำซ้อน เช่น ระบบรับสมัครสมาชิกไม่ได้กรองข้อมูลว่า ผู้ที่ลงทะเบียนสมัครไว้แล้วหรือยัง แต่ในระบบใหม่มีความจำเป็นที่จะต้องควบคุมให้ หนึ่งคน มีได้หนึ่งยูเซอร์เท่านั้น เราสามารถกรองออกได้โดยข้อมูล อีเมล์ หมายเลขบัตรประชาชน อาจจะเป็นต้องใช้ ชื่อและนามสกุลด้วย โดยใช้ query ง่ายๆ[sourcecode language=”sql”]SELECT email, count (*) AS duplicate
FROM `users`
GROUP BY email
HAVING duplicate > 1;[/sourcecode]ก็จะได้อีเมล์ที่ซ้ำกันออกมาออกมา แต่เจอผู้ที่สมัครหลายยูเซอร์จำนวนมาก จะมาลบที่ละคนก็ไม่ไหว อาศัยกฎของทางเว็บที่ห้ามสมัครเกินกว่าหนึ่งยูเซอร์ มาเป็นเหตุผลในการลบรายการที่ซ้ำออกไป อัตโนมัติ
โดยเราไม่จำเป็นต้องเขียนคำสั่งใน PHP มาวนลบข้อมูล เพราะสามารถใช้วิธีสร้างตารางชั่วคราวมาเก็บข้อมูลที่ไม่ซ้ำ[sourcecode language=”sql”]
INSERT INTO `users_temp`
SELECT *, count (*) AS duplicate
FROM `users`
GROUP BY email
HAVING duplicate > 1;[/sourcecode]อธิบายง่ายๆ คือเลือกข้อมูลโดยกรุ๊บข้อมูลที่ซ้ำไปแทรกในตารางใหม่ ครั้งต่อไปก็ดัดแปลงเป็นเลขบัตรประชาชน ชื่อและนามสกุล พอสมควรแล้วก็ลบตารางเดิม เปลี่ยนชื่อตารางใหม่ไปแทนของเดิม