Day: January 15, 2017

  • การสร้างเอกสารด้วย Sphinx

    sphinx คือเครื่องมือที่ช่วยในการสร้างเอกสารที่พัฒนาโดย Georg Brandl เดิมที sphinx ได้รับการพัฒนาเพื่อใช้สร้างเอกสารสำหรับ Python แต่สามารถใช้งานกับภาษาอื่นๆได้เช่นกัน

    sphinx ใช้ reStructuredText (ดูข้อมูลเพิ่มเติมเกี่ยวกับ reStructuredText ได้ที่ บทความ ก่อนหน้า) ในการกำหนดรูปแบบของเอกสาร และชุดเครื่องมือในการ parsing และ translating เอกสารในรูปแบบ  reStructuredText ไปเป็นรูปแบบที่ต้องการเช่น html หรือ pdf เป็นต้น

    ในการติดตั้งใช้งาน sphinx นั้นจำเป็นต้องต้องติดตั้ง Python เนื่องจาก sphinx ได้รับการพัฒนาโดยใช้ Python language ทำให้การใช้งาน sphinx ต้องติดตั้ง Python ด้วย โดย Python ที่ใช้ต้องเป็น Python version 2.7 เป็นอย่างน้อย

    การติดตั้ง Python บน windows  ทำได้โดยเข้าไป download “Python windows installer” ที่ https://www.python.org/ และทำการติดตั้ง หลังจากติดตั้งเรียบร้อย จะต้องทำการกำหนดค่า Python executable directory ใน PATH environment variable เพื่อที่จะสามารถ run Python และ package command เช่น sphinx-build ได้จาก command prompt

    Installing Sphinx with pip

    การติดตั้ง Sphinx ทำได้โดยการใช้ “pip”  ซึ่ง pip เป็นเครื่องมือที่ใช้ในการ download และติดตั้ง 3rd-party libraries สำหรับ Python ซึ่งจะถูกรวมอยู่ใน Python official installation ตั้งแต่ version Python-3.4.0

    การติดตั้ง sphinx โดยใช้คำสั่งดังนี้บน command prompt

    C:\> pip install sphinx
    

    หลังจากติดตั้งเรียบร้อย ให้พิมพ์คำสั่ง sphinx-build -h บน command prompt ถ้าทุกอย่างถูกต้อง จะแสดงข้อมูล Sphinx version number และ list ของ option ต่างๆสำหรับคำสั่งนี้

    Setting up the documentation sources

    การพัฒนาเอกสารด้วย sphinx นั้น เริ่มแรกเราจะต้องกำหนดพื้นที่สำหรับพัฒนาเอกสารและจัดเก็บ config ที่ใช้สำหรับ sphinx ซึ่ง sphinx มีคำสั่ง sphinx-quickstart ซึ่งทำหน้าที่กำหนด source directory และสร้าง default config file “conf.py” ที่จำเป็นให้ โดยใช้คำสั่งดังนี้

    C:\> sphinx-quickstart

    sphinx-quickstart script สร้างโครงสร้าง folder พร้อมทั้ง file เริ่มต้นรวมทั้ง Makefile และ make.bat ซึ่งจะใช้ในการ build (parsing และ translating โดยที่ถ้าพบส่วนที่ไม่ตรงตามข้อกำหนด syntax จะแสดง warning หรือ error พร้อมทั้งรายละเอียดของ line เช่นเดียวกับการ build “code program”)

    หลังได้โครงสร้าง folder สำหรับพัฒนาเอกสารเรียบร้อย ก็สามารถเริ่มต้นเขียนเอกสารโดยใช้ reStructuredText ในการกำหนดรูปแบบการแสดงผลของ text จากนั้นเมื่อต้องการสร้างเอกสารในรูปแบบที่ต้องการเช่น html document ก็จะต้องทำการ build โดยใช้คำสั่ง

    C:\> make html

    ผลลัพธ์ที่ได้จากการใช้คำสั่งนี้คือ HTML document ใน folder ที่กำหนด (ใช้คำสั่ง make โดยไม่ระบุ argument เพื่อแสดงประเภทของเอกสารทั้งหมดที่สามารถสร้างได้)

     

    อ้างอิง : http://www.sphinx-doc.org/en/1.5.1/tutorial.html

  • คู่มือเทคนิคการใช้งาน Function พื้นฐานใน Itextsharp สำหรับมือใหม่ ตอนที่ 2

    บทความนี้ผู้เขียนจะพูดถึงส่วนที่มีการทำงานในลักษณะคล้ายกับ Containner แต่ก่อนจะเริ่มเนื้อหาในส่วนนี้ สำหรับผู้ที่เริ่มต้นใหม่สามารถอ่านบทความ ตอนที่ 1 เพื่อความเข้าใจต่อเนื่องกันนะครับ ส่วนผู้ที่อ่านบทความก่อนหน้านี้ เรามาเริ่มกันเลยดีกว่าครับ

    ก่อนที่ผู้เขียนจะไปพูดถึงส่วนของการเขียนโปรแกรมนั้น ผู้เขียนอยากอธิบายเพื่อทำความเข้าใจให้กับผู้อ่านได้เห็นภาพได้ชัดเจนเกี่ยวลักษณะการทำงานของ Containner แบบต่างๆให้ได้ทราบกัน โดยการทำงานของ Itextsharp นั้น เมื่อเราทำการสร้างเอกสารแล้ว เราไม่สามารถเขียนข้อความหรือใส่ข้อมูลต่างๆลงไปได้ในเอกสารโดยตรง แต่เราจะทำผ่านตัว Containner ครับ โดยตัว Containner ที่ Itextsharp ให้มาก็มีหลายรูปแบบให้เลือกใช้งานกัน วันนี้เราจะมาทราบกันว่ามีรูปแบบอะไรบ้างที่ช่วยให้เราทำงานได้ดีขึ้นครับ

    รูปตัวอย่างแสดงการทำงานของ Containner

    จากรูปตัวอย่างที่ผู้เขียนได้วาดไว้นั้น ผู้เขียนขออธิบายกรอบทั้งด้านซ้ายก่อนนะครับ โดยกรอบแต่ละสี จะเป็น Containner แต่ละที่ Itextsharp มีมาให้เราใช้งาน โดยกรอบสีดำนอกสุดนั้น ก็คือ Document หรือตัวเอกสารที่ได้กล่าวถึงในบทความก่อนหน้านี้ ซึ่งเป็น Containner ใหญ่สุดและเป็นตัวหลัก ใช้สำหรับบรรจุ Containner ตัวอื่นๆลงไปในเอกสาร ต่อมากรอบสีน้ำเงิน ก็คือ Paragraph เรียกง่ายๆว่าย่อหน้า ใน 1 Document นั้นเราสามารถบรรจุ Paragraph กี่อันก็ได้ตามที่ผู้ใช้ต้องการ โดยแต่ละ Paragraph จะเรียงต่อกันลงมาเป็นแนวตั้ง โดย Paragraph ล่าสุดจะอยู่ล่าสุดของเอกสารเสมอ ต่อกันด้วยกรอบสีแดง ก็คือ Phrase เรียกง่ายๆว่า รูปประโยค ใน 1 Paragraph สามารถมี Phrase ได้หลายอัน โดยต่อเรียงจากซ้ายไปขวา เราสามารถเขียนข้อมูลลงใน Phraph ได้ หรือเราใช้เป็น Containner สำหรับบรรจุ Chunk อีกชั้นได้ด้วย แต่ Phraph เหมาะสำหรับใช้เป็น containner มากกว่าใช้ใสข้อมูลโดยตรง เนื่องจากมีเงื่อนไขในการใส่ที่จำกัด และสุดท้ายของกรอบด้านซ้ายและเป็นตัวหลักในการเขียนข้อมูลคือ Chunk นั้นเอง Chunk เป็น Containner ที่มีหน้าที่ในการเก็บข้อมูลที่เราจะใส่ลงไปในเอกสารโดยเฉพาะ โดย Chunk จะต่อเรียงกันไปเลยๆจากซ้ายไปขวาเหมือน Phrase และไม่สามารถบรรจุ Containner อื่นลงไปได้อีก พออ่านมาถึงตรงนี้หลายท่านสงสัยว่า เรามาถึง Containner ตัวเล็กสุดแล้ว แล้วอีก 2 ตัวที่เหลือละ จริงๆผู้เขียนไม่ได้ลืมนะครับ แต่ผู้เขียนพยายามแยกการทำงานของ Containner เป็นชุดๆให้ผู้อ่านได้เข้าใจง่ายๆ เมื่อจบการอธิบายในกรอบด้านซ้ายของรูปตัวอย่างแล้ว เรามาเริ่ม กรอบทางด้านขวากันเลยดีกว่า เมื่อเราดูรูปกรอบด้านขวาจะพบว่ามี Containner บ้างตัวหายไป ทั้งที่มีการใช้งานทางด้านซ้าย ก็คือเจ้า Paragraph นั้นเอง เพราะผู้เขียนคิดว่าการทำงานของ Paragraph นั้นจะซ้ำซ้อนกับ PdfPCell นั้นเอง แต่ก่อนจะพูดถึง PdfPCell สิ่งที่ลืมไปไม่ได้เลยคือ PdfPtable นั้นเอง สำหรับผู้พัฒนาโปรแกรม คงเข้าใจได้ง่ายๆว่า ถ้าเราจะสร้างCell เราจะขาด Table ไปไม่ได้ เพราะ Cell เป็นส่วนนึงของ Tableนั้นเอง โดย PdfpTable จะทำหน้าที่ในการบรรจุ Containner PdfPCell ไว้นั้นเอง เมื่อเราทำการใส่ PdfPCell ลงใน PdfPTable แล้ว PdfPCell จะเรียงต่อกันจากซ้ายไปขวา เรื่อยๆ แล้วหลายคนสงสัย แล้วไม่มี PdfPRow ให้ใช้งานหรอ มีครับแต่ไม่ค่อยได้รับความนิยมในการใช้งานมากนัก เพราะตัว PdfPTable นั้นสามารถเพิ่ม PdfPCell ได้โดยตรงไม่ต้องเพิ่ม PdfPRow แต่อย่างใด ผู้เขียนจึงขอตัดออกไปก่อน แต่จะมีตัวอย่างการใช้งานให้ดูตอนท้ายครับ แล้วถามว่าเราสามารถเอา PdfPTable ไปใส่ใน Paragraph ได้ไหม ได้ครับ เราสามารถเอา PdfPTable ใน Paragraph และเช่นเดียวกันเราสามารถเอา Paragraph ใส่ใน PdfPTable รู้สึกผู้เขียนจะร่ายยาวไปแล้ว คนอ่านคงเบื่อ เรามาเข้าสู่ช่วงของการเขียนโปรแกรมกันเลยดีกว่า โดยเริ่มจากตัว Containner ตัวเล็กสุดคือ Chunk

    Chunk chk1 = new Chunk("Howdy",fnt);//1
    
    Chunk chk2 = new Chunk();//2
    chk2.Append("Howdy");
    chk2.Font = fnt;
    
    Phrase P = new Phrase(new Chunk("Howdy", fnt));//3
    

    จากตัวอย่างด้านบนจะเป็นรูปแบบการใช้งาน Chunk ในรูปแบบต่างๆกันขึ้นอยู่กับความเหมาะสมหรือความถนัดของผู้ใช้งาน แบบที่ 1 จะเป็นการประกาศใช้งานพร้อมทั้งกำหนดค่าข้อมูลและรูปแบบของ font ลงไปในขั้นตอนเดียว ส่วนแบบที่ 2 จะแตกต่างตรงที่ประกาศการใช้งาน Chunk ขึ้นมาก่อนแล้วค่อยไปกำหนดค่าข้อมูลและรูปแบบ Font ภายหลัง หรือแบบที่ 3 เป็นการสร้าง Chunk ลงไปใน Containner ตัวอื่นโดยตรง แบบนี้ไม่สามารถแก้ไขข้อมูลได้แล้วครับ Containner ตัวต่อมาคือ Phrase มาดูตัวอย่าง Code กัน

    Chunk ck1 = new Chunk("Howdy ",fnt);
    Chunk ck2 = new Chunk("You",fnt);
    
    Phrase P1 = new Phrase(new Chunk("Howdy You", fnt));//1
    
    Phrase P2 = new Phrase("Howdy You",fnt);//2
    Phrase P3 = new Phrase();//3
    P3.Add("Howdy ");
    P3.Add("You");
    
    Phrase P4 = new Phrase();//4
    P4.Add(ck1);
    P4.Add(ck2);
    
    Paragraph PR1 = new Paragraph(new Phrase("Howdy You",fnt));//5
    

    จากตัวอย่างทั้งหมด ผลลัพธ์ที่ได้คือ Howdy You เหมือนกันหมดครับต่างกันแค่วิธีการเขียนเท่านั้นเอง ในตัวอย่างที่ 1 เป็นการใช้งานแบบประกาศ Phrase ขึ้นมาพร้อมกับสร้าง Chunk ขึ้นมาพร้อมกำหนดค่าข้อมูลเพิ่มมาด้วยในชุดคำสั่งเดียว ซึ่งในตัวอย่างที่ 2 มีการเขียนเหมือนกันต่างตรงที่ เขียนข้อมูลและรูปแบบตรงๆ ไม่ผ่านทาง Chunk นั้นเอง ส่วนตัวอย่างที่ 3 และ 4 จะมีการประกาศใช้งาน Phrase ในชื่อ P3 และ P4 ต่างกันตรงที่ P3 จะทำการเพิ่มข้อมูลตรงในรูปแบบของ String แต่ P4 จะนำ Chunk ที่ได้สร้างไว้ก่อนมาใช้งาน ถ้าสังเกตุดีๆจะพบว่า แบบตัวอย่างที่ 3 นั้นไม่สามารถกำหนดรูปแบบของข้อความได้ ต่างจากตัวอย่างที่ 4 ที่มีการกำหนดรูปแบบมาแล้วใน Chunk ซึ่งแบบนี้จะทำงานได้ง่ายกว่าและยืดหยุ่นมากว่าด้วยครับ และสุดท้ายตัวอย่างที่ 5 เป็นการสร้าง Phrase ซ้อนอยู่ในการประกาศ Paragarph นั้นเอง ทำให้เราไม่สามารถแก้ไขข้อมูลใน Phraseได้แล้วครับ Containner ตัวต่อมาที่จะพูดถึงคือ Paragarph มาดูตัวอย่าง Code กัน

    Paragraph PR1 = new Paragraph(new Phrase("Howdy You",fnt));//1
    
    Paragraph PR2 = new Paragraph(new Phrase(new Chunk("Howdy You", fnt)));//2
    
    Paragraph PR3 = new Paragraph();//3
    PR3.Add("Howdy You");
    
    Paragraph PR4 = new Paragraph();//4
    PR4.Add(new Chunk("Howdy You", fnt));
    
    Paragraph PR5 = new Paragraph();//5
    PR5.Add(new Phrase(new Chunk("Howdy You", fnt)));
    
    Paragraph PR6 = new Paragraph();//6
    PR6.Add(P1);
    
    Paragraph PR7 = new Paragraph();//7
    PR7.Add(ck1);
    PR7.Add(ck2);
    
    pdfDoc.Add(new Paragraph("Howdy You"));//8
    

    จากตัวอย่างรูปแบบที่ 1 และ 2 เป็นการเขียนในลักษณะที่คล้ายกันคือทำการประกาศ Paragraph พร้อมทั้งประกาศ Containner ตัวที่เล็กกว่าใส่ลงไปด้วยและทำการเขียนข้อมูล ต่างกันเพียง แบบที่ 2 จะประกาศซ้อนลงไปอีกชั้นนึงในส่วนของ Chunk นั้นเอง ส่วนตัวอย่างแบบที่ 4 5 6 และ 7 ใช้การประกาศ Containner ที่เหมือนกัน ต่างกันตรงการเพิ่มข้อมูลลง Paragraph นั้นๆ และสุดท้ายตัวอย่างที่ 8 คือการประกาศ Paragraph ลงไปใน Document เลยนั้นเอง แล้วเราก็มาถึง 2 ตัวสุดท้ายของบทความนี้แล้วครับ นั้นก็คือ PdfPtable และ PdfPcell นั้นเอง นั้นส่วนของ 2 ตัวนี้จะยกตัวอย่างแบบพื้นฐานให้ดูก่อนนะครับ จะไม่ได้ดูรายละเอียดเยอะมาก เดี๋ยวจะยาวเกินไปครับ เรามาดูตัวอย่างกันเลยดีกว่า

    //-------------- 1 -------------//
    PdfPTable PdfTable = new PdfPTable(4);
    float[] tbwidths = { 10f, 10f, 10f, 10f };
    PdfTable.SetWidths(tbwidths);
    
    //-------------- 2 -------------//
    PdfPCell PdfCell = new PdfPCell(new Phrase("Howdy You",fnt));
    PdfPCell PdfCell2 = new PdfPCell(new Phrase(new Chunk("Howdy You", fnt)));
    PdfPCell PdfCell3 = new PdfPCell();
    PdfCell3.AddElement(P1);
    
    //-------------- 3 -------------//
    PdfTable.AddCell(PdfCell);
    PdfTable.AddCell(PdfCell2);
    PdfTable.AddCell(PdfCell3);
    PdfTable.AddCell(new PdfPCell(new Phrase("Howdy You",fnt)));
    

    จากตัวอย่างผู้เขียนได้แบ่งcode ออกเป็น 3 ส่วนดังนี้ ส่วนที่ 1 จะเป็นส่วนของการประกาศและสร้าง Table ขึ้นมาครับ โดยผู้เขียนได้สร้าง Table ชื่อ PdfTable ซึ่ง Table นี้มีขนาด 4 Colunm บบรทัดต่อมาจะเป็นส่วนของการจัดความกว้างของ Colunm ส่วนนี้ต้องระวังนิดนึงคือ จำนวนต้องมีเท่ากับจำนวน Colunm ของ Table นะครับ ส่วนเรื่องขนาดความกว้าง อันนี้แล้วแต่ตามความเหมาะสมในการใช้งาน ตัวโปรแกรม Itextsharp ช่วยเราเรื่องการขยายขนาดให้พอดีครับ อันนี้ต้องลองเล่นๆดูจะเข้าใจมากขึ้น บรรทัดต่อมาเป็นการนำค่าความกว้างที่ตั้งไว้กำหนดให้ Table ของเรา ก็จะจบการสร้างtableแบบพื้นฐานแล้ว เรามาต่อกันส่วนที่ 2 ในส่วนนี้จะเป็นส่วนของการประกาศและสร้าง PdfPCell ในรูปแบบต่างๆ ซึ่งรูปแบบจะคล้ายๆกับการสร้าง containner ตัวอื่นๆที่ผ่านมา และส่วนที่ 3 เป็นส่วนที่นำเอาส่วนที่ 2 หรือก็คือ PdfPCell ของเรานั้นเอง ใส่ลงไปยัง PdfPTable ที่ได้สร้างไว้ในส่วนที่ 1 แค่นี้ก็ถือว่าเสร็จสิ้นการสร้าง Table แล้วครับ แล้วลืมไม่ได้เลยคือตัวอย่างการใช้งาน PdfPRow ที่ได้สัญญาเอาไว้ในตอนแรก

    //-------------- 1 -------------//
    PdfPTable PdfTable = new PdfPTable(4);
    float[] tbwidths = { 10f, 10f, 10f, 10f };
    PdfTable.SetWidths(tbwidths);
    
    //-------------- 2 -------------//
    PdfPCell PdfCell = new PdfPCell(new Phrase("Howdy You",fnt));
    PdfPCell[] cells = new PdfPCell[] { new PdfPCell(), new PdfPCell(), new PdfPCell(), new PdfPCell()};
    
    cells[0].AddElement(new Phrase("Howdy You", fnt));
    cells[1].AddElement(new Phrase(new Chunk("Howdy You", fnt)));
    cells[2].AddElement(PR1);
    cells[3] = PdfCell;
    
    //-------------- 3 -------------//
    PdfPRow row = new PdfPRow(cells);
    PdfTable.Rows.Add(row);
    

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