Tag Archive เทมเพลต

Byphunsanit

PHPWord: กรอกข้อมูลใส่ template

เพราะว่า word นั้นมีความสามารถปรับแต่งรูปแบบได้ซับซ้อนมากกว่า excel อยู่มาก อย่างน้อยแค่ตำแหน่งของส่วนต่างๆ ในแบบฟอร์มก็มีมากกว่า excel ที่เลือกตำแหน่งได้แค่ว่าจะใส่ column / row ไหน

การใช้ PHP สร้างไฟล์ word ขึ้นมาการสร้างไฟล์แม่แบบขึ้นก่อน โดยการสร้างตัว word template ขึ้นมาก่อนโดยใช้โปรแกรม Microsoft Word สร้างเอกสารไปตามปกติ จึงง่ายกว่า จากนั้นก็แก้เพียงแต่ในส่วนที่่ต้องการจะแทนค่าให้ใส่ ${key name} ลงไป (ระวังเรื่องช่องว่างด้วยนะครับ) หรือส่วนที่ต้องการ repeat ก็เพิ่ม ${key name} … ${/key name} เข้าไปเท่านั้นจะง่ายกว่า ไฟล์ในตัวอย่างนี้สามารถโหลดได้จาก template.docx

จากนั้นก็เขียน code

<?php
ini_set('max_execution_time', 0);
ini_set('memory_limit', '-1');

include '../vendor/autoload.php';

use PhpOffice\PhpWord;

$title = 'Template Render ' . date('Y-m-d H:i:s');

/* load template */
$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('template.docx');

/* fill data */
$templateProcessor->setValue('header', $title);

/* random data */
$scores = [];
for ($a = 0; $a < 10; $a++) {
    $scores[$a + 1] = rand(0, 100);
}

/* clone table row and fill */
$templateProcessor->cloneRow('student_id', count($scores));
foreach ($scores as $key => $value) {
    $templateProcessor->setValue('score#' . $key, htmlspecialchars($value, ENT_COMPAT, 'UTF-8'));
    $templateProcessor->setValue('student_id#' . $key, htmlspecialchars($key, ENT_COMPAT, 'UTF-8'));
}

/* clone all block */
$templateProcessor->cloneBlock('repeater', 5);

header("Content-Description: File Transfer");
header('Content-Disposition: attachment; filename="' . $title . '.docx"');
header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
header('Content-Transfer-Encoding: binary');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Expires: 0');
$templateProcessor->saveAs('php://output');

อธิบาย code

  • การทำงานโดยจะโหลด ตัว PHPWord มาใช้ก่อน จะสังเกตุว่าจะมีการใช้ namespaces แทนที่จะใช้ include เข้ามาเหมือน PHPExcel
  • กำหนดจุดที่จะกรอกข้อมูลโดยใส่ ${key name} ใน word เช่น ${header} จากนั้นใน PHP ก็ส่งค่าตัวแปรไปแทนที่โดยใช้
    $templateProcessor->setValue('header', $title);
  • สามารถ repeat ตารางได้โดยการใส่ ${key name} ใน column ที่ต้องการคัดลอกแถวทั้งแถว เช่น ${student_id} และสั่งให้คัดลอกแถวโดยใช้
    $templateProcessor->cloneRow('student_id', จำนวนครั้ง);

    แถวในตารางที่ใส่ ${student_id} จะเพิ่มขึ้นมาทั้งแถวรวมทั้งคอลัมน์อื่นด้วย

  • สามารถเติิมช้อมูลให้คอลัมน์ที่เพิ่มมาใหม่นี้โดยใช้
    foreach ($scores as $key => $value) {
        $templateProcessor->setValue('score#' . $key, htmlspecialchars($value, ENT_COMPAT, 'UTF-8'));
        $templateProcessor->setValue('student_id#' . $key, htmlspecialchars($key, ENT_COMPAT, 'UTF-8'));
    }

    สังเกตุว่าจะมี

    #' . $key

    เพิ่มขึ้นมาเพิื่อจะแทนที่ลำดับที่เพิ่มขึ้นมานั่นเอง

  • ในรูปแบบตารางที่ซับซ้อนเช่น ตาราง “ใบขออนุญาตสอบซ่อม” ที่ต้องทำซ้ำหลายแถวและหลายคอลัมน์พร้อมๆกัน ทั้งตารางจะไม่สามารถใช้
    $templateProcessor->cloneRow('student_id', จำนวนครั้ง);

    ได้ ต้องเปลี่ยนไปใช้

    $templateProcessor->cloneBlock('repeater', จำนวนครั้ง);

    แทน แต่จะไม่สามารถใส่ตัวแปรลงไปแทนที่ได้ใน version นี้ (PHPWord version 0.13.0)

Byphunsanit

CKEditor template builder

การใส่ content เดี่ยวนี้จะมีรูปแบบที่บังคับเหมือนๆกัน ทั้งที่เป็นเพราะว่า ต้องการให้เนื่อหาออกมาใน format รูปแบบเดียวกันและ พวก framework อย่าง bootstrap ก็ จะมีโครงสร้าง อย่าง tabs ก็จะมีโครงสร้าง

<ul class="nav nav-tabs">
  <li class="active"><a data-toggle="tab" href="#home">Home</a></li>
  <li><a data-toggle="tab" href="#menu1">Menu 1</a></li>
  <li><a data-toggle="tab" href="#menu2">Menu 2</a></li>
</ul>

<div class="tab-content">
  <div id="home" class="tab-pane fade in active">
    <h3>HOME</h3>
    <p>Some content.</p>
  </div>
  <div id="menu1" class="tab-pane fade">
    <h3>Menu 1</h3>
    <p>Some content in menu 1.</p>
  </div>
  <div id="menu2" class="tab-pane fade">
    <h3>Menu 2</h3>
    <p>Some content in menu 2.</p>
  </div>
</div>

ถ้าจะต้อง copy จาก template snipted ก็ไม่สดวก ไหนๆ ก็ใช้ WYSIWYG ตอนที่กรอกข้อมูลอยู่แล้วก็ทำให้มันใส่ เทมเพลต template ในเนื้อหาให้แล้วมาแก้ทีหลัง จะดีกว่า

เริ่มกันเลย

  1. โหลด CKEditor
  2. โหลด plugin Content Templates แตกไฟล์โพลเดอร์ ออกมา ในโฟลเดอร์ ckeditor\plugins\templates เป็น \ckeditor\plugins\templates
  3. เขียน code ประมาณ
    <!doctype html>
    <html lang="th-TH">
    <head>
    <meta charset="utf-8">
    <title>CKEditor: Content Templates</title>
    </head>
    
    <body>
    <textarea name="editor" id="editor1" rows="10" cols="80">
    This is my textarea to be replaced with CKEditor.
    </textarea>
    <script src="ckeditor.js"></script>
    <script>
    CKEDITOR.replace( 'editor', {
    	"extraPlugins": "templates",
    });
    </script>
    </body>
    </html>
    
  4. สร้างเทมเพลตเพิ่มโดยเปิดไฟล์ \ckeditor\plugins\templates\templates\default.js
    	templates: [
    ...
    {
    		title: 'Bootstrap Tabs',
    		image: 'bootstrapTabs.gif',
    		description: 'add bootstrap tabs to content.',
    		html: '<ul class="nav nav-tabs">' +
    '<li class="active"><a data-toggle="tab" href="#home">Home</a></li>' +
    '<li><a data-toggle="tab" href="#menu1">Menu 1</a></li>' +
    '<li><a data-toggle="tab" href="#menu2">Menu 2</a></li>' +
    '</ul>' +
    '<div class="tab-content">' +
    '<div id="home" class="tab-pane fade in active">' +
    '<h3>HOME</h3>' +
    '<p>Some content.</p>' +
    '</div>'+
    '<div id="menu1" class="tab-pane fade">' +
    '<h3>Menu 1</h3>' +
    '<p>Some content in menu 1.</p>' +
    '</div>' +
    '<div id="menu2" class="tab-pane fade">' +
    '<h3>Menu 2</h3>' +
    '<p>Some content in menu 2.</p>' +
    '</div>' +
    '</div>'
    	},
    ...
     ]
    } );
    

    ใส่ภาพตัวอย่างที่ \ckeditor\plugins\templates\templates\images

  5. ทดลองใช้งานดู ตัว icons จะอยู่ที่ เมนูชุดแรกหลังปุ่มพิมย์ ถ้าไม่เห็นเทมเพลตที่สร้างลอง clear cache ดูก่อน

เสียเวลาเขียนระบบเพิ่ม แต่อำนวยความสดวกให้ทำ content ง่ายขึ้นเยอะเลย

Byphunsanit

PHP เทมเพลต

วิธีติดต่อ user ดีที่สุดคือการส่งจดหมายข่าวบอกไปว่าเว็บเราอัพเดต มีอะไรน่าสนใจบ้าง แต่จะให้ส่งข้อความไปเหมือนๆ กันทุกๆ คน คงจะดูไม่น่าสนใจเท่าไหร ถ้ามีบางส่วนที่พิเศษไปสำหรับแต่ละคน เช่น แสดงชื่อของลูกค้า จะดูน่าสนใจขึ้นใช้ไหมครับ
ก่อนอื่นก็สร้างไฟล์ที่เป็นต้นแบบของจดหมายมาก่อนชื่อ templates.tmp.html

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>#title#</title>
</head>
<body bgcolor="#c00000">
#contents#
</body>
</html>

จากนั้นจะทดลองเปลี่ยนเนื้อหาจากต้นฉบับดู สร้างไฟล์ templates.php ตามตัวอย่าง

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>PHP template By Pitt Phunsanit</title>
</head>
<body>
<?php
$output = file_get_contents('templates.tmp.html');
$patternSearch = array('#title#', '#contents#');
$patternReplace = array('ทดลองเทมเพลต', 'แสดงเนื้อหาแล้วนะ');
$output = str_replace($patternSearch, $patternReplace, $output);
echo'<textarea cols="200" rows="40">',$output,'</textarea>';
?>
</body>
</html>

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