Month: May 2021

  • ซ่อน/แสดง คอลัมน์ใน ASP.NET GridView ด้วย jQuery

    การแสดงผลข้อมูลใน Gridviews ในบางสถานการณ์เราต้องการซ่อนข้อมูลบางคอลัมน์ออกไปก่อนตามเงื่อนไขใดๆ และเมื่อเงื่อนไขเปลี่ยนเราก็จะแสดงข้อมูลในคอลัมน์ที่ถูกซ่อนนั้นออกมา

    ในบทความนี้ผู้เขียนจะแสดงตัวอย่างการ ซ่อน/แสดง คอลัมน์ใน ASP.NET GridView ด้วยชุดคำสั่ง jQuery โดยมีขั้นตอนดังต่อไปนี้

    1. เพิ่มโค้ด HTML ดังตัวอย่างด้างล่าง ซึ่งเป็นโค้ดที่แสดง Checkbox เพื่อใช้เลือกแสดงคอลัมน์ CallNo และ ASP.NET GridView ที่มีข้อมูล 5 คอลัมน์

    <asp:CheckBox ID="chkCallNo" Text=" Show CallNo" runat="server" Checked="true" />
    
    <hr />
    <asp:GridView ID="gvBib" runat="server" AutoGenerateColumns="False" >
    	<Columns>
    		<asp:BoundField DataField="BIB_NO" HeaderText="Bib#" />
    		<asp:BoundField DataField="TITLE" HeaderText="Title" />
    		<asp:BoundField DataField="Author" HeaderText="Author" />
    		<asp:BoundField DataField="CALL_NO" HeaderText="CallNo" />
    		<asp:BoundField DataField="ISBN" HeaderText="ISBN" />
    	</Columns>
    </asp:GridView>

    2. เพิ่มโค้ดใน event Page_Load ในหน้า code behind เพื่อจำลองข้อมูลที่จะใช้แสดงใน GridView

    protected void Page_Load(object sender, EventArgs e)
    {
        if(!IsPostBack)
        {
            DataTable dt = new DataTable();
            dt.Columns.AddRange(new DataColumn[5] { new DataColumn("BIB_NO"), 
                                                    new DataColumn("TITLE"), 
                                                    new DataColumn("AUTHOR"),
                                                    new DataColumn("CALL_NO"),
                                                    new DataColumn("ISBN")});
            dt.Rows.Add(1, "1 ทศวรรษ ดัชนีสุขภาพคนไทย", "สำนักงานคณะกรรมการสุขภาพแห่งชาติ (สช.)", "WA13 ห159 2556", "");
            dt.Rows.Add(2, "ความลับในร่างกายมนุษย์ที่เราไม่เคยรู้", "ฟรานซิส, เกวิน", "QS4 ฟ133a 2560", "9786168022887");
            dt.Rows.Add(3, "The best ICU", "ดุสิต สถาวร", "WX218 B561 2560", "9786168122020");
            dt.Rows.Add(4, "COVID-19 โรคระบาดแห่งศตวรรษ", "นำชัย ชีววิวรรธน์", "QW168.5.C8 น515c 2563", "9789740217060");
            dt.Rows.Add(5, "Good health & smart life ในวัย 40+", "ไวต์, จอห์น", "WT104 ว967g 2560", "9786160827237");
            gvBib.DataSource = dt;
            gvBib.DataBind();
        }
        
    }

    เนื่องจากโค้ดตัวอย่างมีการใช้งาน class DataTable และ DataColumn ซึ่งอยู่ใน namespace System.Data เพราะฉะนั้นจะต้อง Import namespace นี้ด้วย

    using System.Data;

    3. เพิ่มโค้ด jQuery เพื่อควบคุมการแสดง/ซ่อน คอลัมน์ เมื่อมีการคลิก เลือก/ยกเลิก เช็คบ๊อก (โดยในบทความนี้ผู้เขียนขออนุญาตข้ามขั้นตอนการติดตั้ง jQuery ออกไป)

    $(function () {
    
        //bind event click ให้กับ checkbox
        $("[id*=chkCallNo]").click(function () {
    		
    	//เก็บสถานะของ checkbox ว่าเลือกอยู่หรือไม่
            var isChecked = $(this).is(":checked");
    		
    	//เก็บ element ของหัวคอลัมน์ CallNo
            var th = $("[id*=gvBib] th:contains('CallNo')");
    	
            //ถ้า checkbox ถูกเลือก จะแสดงคอลัมน์ CallNo และถ้าไม่ ก็จะซ่อนคอลัมน์
            th.css("display", isChecked ? "" : "none");
    	
            //วนลูปเรคอร์ดที่เหลือทั้งหมด
            $("[id*=gvBib] tr").each(function () {
    	    
                //ใช้ลำดับของหัวคอลัมน์ CallNo (th.index) มาหาคอลัมน์ CallNo ที่อยู่ record ข้อมูล 
                //และกำหนดให้ซ่อนหรือแสดงตามการเลือก checkbox
                $(this).find("td").eq(th.index()).css("display", isChecked ? "" : "none");
            });
        });
    
    });

    ทดสอบ run ก็จะได้ผลลัพธ์ดังรูปด้านล่าง

    และเมื่อคลิกเช็คบ๊อก Show CallNo ออก คอลัมน์ CallNo ใน Gridview ก็จะหายไป

    จากตัวอย่างโค้ดในบทความนี้ จะเห็นว่าการซ่อนหรือแสดงคอลัมน์ด้วย jQuery ไม่ได้มีความยุ่งยาก สามารถนำไปประยุกต์ใช้กับงานของท่านได้

    ซึ่งผู้เขียนหวังเป็นอย่างยิ่งว่าบทความนี้น่าจะมีประโยชน์กับท่านผู้อ่านไม่มากก็น้อย สวัสดีครับ


    แหล่งข้อมูลอ้างอิง

  • กำหนด Lexer สำหรับ Full Text Search บน ฐานข้อมูล Oracle เพื่อค้นหาภาษาไทยให้ถูกต้อง

    เนื่องจากระบบสืบค้นที่ดูแลอยู่เจอปัญหาค้นหาเลขไทย “๑ ๒ ๓ …” ไม่เจอ หลังจากตรวจสอบจนแน่ใจแล้วว่าก่อนจะส่งคำสั่ง Query ไปยังฐานข้อมูลไม่ได้เผลอตัดเลขไทยออกที่ขั้นตอนไหน จึงทำการตรวจสอบคำสั่งที่ใช้ในการค้นหา พบว่าใช้ฟังก์ชัน

    SELECT * FROM THAI_LIBRARY WHERE CONTAINS(BOOK_NAME, '๑๐๐ ปีชาติไทย', 1) > 0;

    จากคำสั่ง (ที่สมมุติขึ้น) ด้านบนจะเห็นได้ว่าใช้ CONTAINS ซึ่งเป็นฟังก์ชันที่อยู่ในกลุ่ม Oracle Text ซึ่งฟังก์ชันนี้จะค้นหาคำใกล้เคียงจาก Index แล้วคืนค่า Score มาให้เราเพื่อใช้เป็นเงื่อนไขพิจารณาว่าจะใช้ข้อมูลรายการนั้นหรือไม่

    ที่มาภาพ

    ภาพด้านบนแสดงขั้นตอนการสร้าง Oracle Text Index เนื่องจากระบบจัดเก็บข้อมูลเป็น Text อยู่แล้วจึงไม่มีการกำหนด Fillter, Sectioner ทำให้จุดที่ต้องตรวจสอบว่า เลขไทยเราหายไปจาก Index ได้ยังไงเหลืออยู่คือ Lexer ที่จะเป็นตัวกำหนด Wordlist, Stoplist ในการทำ Index ต่อไป ไปดูว่ามี Lexer อะไรบ้าง

    จากตารางด้านบน เนื่องจากฐานข้อมูลของระบบที่ดูแลอยู่ประกอบไปด้วย ภาษาไทย ภาษาอังกฤษ เป็นหลัก และอาจจะมีภาษาอื่นๆปนอยู่ด้วย Lexer ที่น่าจะใช้ได้คือ AUTO_LEXER, MULTI_LEXER, WORLD_LEXER หลังจากได้ทดสอบกำหนดค่า Lexer ให้กับฐานข้อมูล และทดสอบค้นหาด้วย เลขไทย พบว่าจะต้องใช้ WORLD_LEXER จึงจะสามารถรองรับกรณีนี้ได้ โดยใช้คำสั่งดังนี้

    EXEC CTX_DDL.CREATE_PREFERENCE('WorldLex', 'world_lexer');

    DROP INDEX USER01.IDXFT_THAI_LIBRARY_BOOKNAME;
    CREATE INDEX USER01.IDXFT_THAI_LIBRARY_BOOKNAME ON USER01.THAI_LIBRARY(BOOK_NAME)
    INDEXTYPE IS CTXSYS.CONTEXT
    PARAMETERS('LEXER WorldLex STOPLIST CTXSYS.EMPTY_STOPLIST SYNC(ON COMMIT)')
    NOPARALLEL;

    USER01 คือ User ของฐานข้อมูล Oracle

    THAI_LIBRARY คือ ชื่อตาราง

    BOOK_NAME คือ ชื่อคอลัมภ์ ที่ต้องการทำ Index

    IDXFT_THAI_LIBRARY_BOOKNAME ชื่อ ตาราง index

    ผลพลอยได้ จากการปรับในครั้งนี้พบว่าเดิมต้องทำการตัดคำให้เรียบร้อย (เนื่องจากค่า Default คือ Basic Lexer ที่แบ่งคำด้วยช่องว่างเท่านั้น) เพื่อค้นหา แต่เมื่อปรับ Lexer ให้ถูกต้องสามารถส่งคำค้นเป็นประโยคยาวๆ ไปค้นหาได้เลย หวังว่าบทความนี้จะเป็นประโยชน์กับท่านที่ใช้งาน Full Text Search ของ Oracle และประสบปัญหาคล้ายๆกันนี้ครับ

  • Bootstrap Modal Full Screen

    หลายๆ ท่านที่เคยใช้งาน Bootstrap เป็น Frontend Framework น่าจะเคยใช้ modal กันมาบ้าง ซึ่ง modal เป็นจาวาสคลิปต์ปลั๊กอิน มีไว้สำหรับการแสดงผลข้อมูล ทั้งรูปภาพ ข้อความ หรือแบบฟอร์มรับข้อมูล ( html input form ) ในลักษณะป๊อปอัพ ซึ่ง modal ของ bootstrap สามารถแสดงผลได้หลายขนาด ทั้งแบบปกติ แบบเล็ก และแบบใหญ่ ขึ้นอยู่กับ class ที่เราสามารถระบุเพิ่มเข้าไปว่าต้องการให้แสดงผลเป็นแบบไหน

    ตัวอย่างโค้ด modal dialog และปุ่มสำหรับเปิด modal

    <!-- Button trigger modal -->
    <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal">Modal</button>
    
    <!-- Modal -->
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    	<div class="modal-dialog" role="document">
    		<div class="modal-content">
    			<div class="modal-header">
    				<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
    				<h4 class="modal-title" id="myModalLabel">Modal title</h4>
    			</div>
    			<div class="modal-body">
    				...
    			</div>
    
    		</div>
    	</div>
    </div>
    

    จะได้ผลลัพธ์ดังรูป

    ถ้าต้องการให้ modal แสดงผลใหญ่ขึ้นหรือเล็กลง ให้ระบุ modal-lg modal-sm หลัง modal-dialog ดังตัวอย่าง

    <div class="modal-dialog modal-lg" role="document">
    <div class="modal-dialog modal-sm" role="document">
    

    ถ้าเราต้องการให้ modal สามารถแสดงผลแบบเต็มจอ (full screen) จะไม่สามารถทำได้ (อ้างอิงจากเวอร์ชัน 3.3 ที่ผู้เขียนใช้งาน แต่จากการตรวจสอบล่าสุดพบว่าเวอร์ชัน 5.0 สามารถทำได้แล้ว)

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

    <style>
    .fullscreen {
    	margin: 0;
    	top: 0;
    	left: 0;
    	width: 100% !important;
    	height: 100% !important;
    }
    </style>
    

    ระบุ class fullscreen ไว้ด้านหลัง modal-dialog

    <div class="modal-dialog fullscreen" role="document">

    modal จะได้แสดงผลเต็มจอดังรูป

    และเพื่อให้การแสดงผล modal มีความยืดหยุ่นและมีการทำงานใกล้เคียงกับ dialog ของ Windows ทั่วไป คือสามารถขยายให้เป็น full screen และย่อให้กลับมาขนาดเท่าเดิม โดยสิ่งที่เราต้องทำเพิ่มคือ

    1. เพิ่มปุ่ม fullscreen
      • เมื่อ modal แสดงผลอยู่ในสภาพปกติ
      • เมื่อคลิกปุ่ม fullscreen จะเปลี่ยนการแสดงผล modal ให้เป็นแบบ fullscreen
      • ซ่อนปุ่ม fullscreen และแสดงผลปุ่ม restore แทน
    2. เพิ่มปุ่ม restore
      • เมื่อ modal แสดงผลในรูปแบบ fullscreen
      • เมื่อคลิกปุ่ม restore จะเปลี่ยนการแสดงผล modal กลับไปเป็นสภาพปกติ
      • ซ่อนปุ่ม restore และแสดงผลปุ่ม fullscreen แทน

    โดยมีขั้นตอนดังต่อไปนี้

    1. เพิ่มปุ่ม fullscreen และปุ่ม restore ใน div class=”modal header”

    <div class="modal-header">
            //ปุ่ม Close
    	<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
    
            //ปุ่ม restore
    	<button type="button" class="close restore-diloag" title="restore" style="display: none; vertical-align: middle" tabindex="-1"><i class='fa fa-clone' style="font-size: 16px; font-weight: bolder"></i>&nbsp;</button>
    
            //ปุ่ม fullscreen
    	<button type="button" class="close fullscreen-dialog" title="maximize" style="vertical-align: middle" tabindex="-1"><i class='fa fa-window-maximize' style="font-size: 16px"></i>&nbsp;</button>
    	<h4 class="modal-title" id="myModalLabel">Modal title</h4>
    </div>
    

    จะเห็นว่าปุ่มที่เพิ่มขึ้นมาจะมีการระบุชื่อ class “restore-dialog” และ “fullscreen-dialog” ซึ่งจะใช้ในการอ้างถึงในโค้ด jQuery ที่ใช้ควบคุมการทำงานเมื่อมีการคลิกปุ่มนั้นๆ

    2. เนื่องจากผู้เขียนใช้ icon ที่อยู่ใน font awesome ดังนั้นจะต้องเพิ่ม link style sheet เพื่ออ้างไปถึงไฟล์ css ของ font awesome ภายนอกไซต์ที่กำลังพัฒนา (CDN) โดยไปเพิ่มไว้ใน tag <head></head>

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />

    3. เพิ่มชุดคำสั่ง jQuery

    <script>
    	$(function () {
    
    		//เมื่อคลิกปุ่ม fullscreen
    		$(document).on('click', '.fullscreen-dialog', function (e) {
    
    			//เพิ่ม class fullscreen เพื่อให้แสดงผลแบบเต็มจอ
    			$('div.modal-dialog').addClass("fullscreen");
    
                            //แสดงปุ่ม restore
    			$('div.modal-dialog').find('.restore-diloag').show();
    
                            //ซ่อนปุ่ม fullscreen
    			$('div.modal-dialog').find('.fullscreen-dialog').hide();
    		});
    
    		//เมื่อคลิกปุ่ม restore
    		$(document).on('click', '.restore-diloag', function (e) {
    
                            //ลบ class fullscreen เพื่อให้กลับไปแสดงผลเหมือนเดิม
    			$('div.modal-dialog').removeClass("fullscreen");
    
                            //ซ่อนปุ่ม restore
    			$('div.modal-dialog').find('.restore-diloag').hide();
    
                            //แสดงปุ่ม fullscreen
    			$('div.modal-dialog').find('.fullscreen-dialog').show();
    		});
    	});
    </script>

    4. ทดสอบ ก็จะได้ผลลัพธ์ดังภาพ

    จะเห็นว่ามีปุ่ม fullscreen แสดงอยู่ เมื่อกด modal จะแสดงผลเป็น fullscreen ดังภาพ

    และเมื่อกดปุ่ม restore หน้าจอ modal ก็จะแสดงผลกลับไปเป็นเหมือนเดิม

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

    สวัสดีครับ


    แหล่งข้อมูลอ้างอิง

  • จะทำอย่างไรให้สามารถดึงข้อมูลมาแสดงผลด้วย Progress bar โดยใช้ .Net (C#)

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

    แบบแถบละสี

    1. ดึงข้อมูลจากฐานข้อมูล และจัดเตรียม Tag Html ที่จะใช้ในการแสดงผล
        private void getData()
        {
            ////////////////////เป็นการสมมุติการดึงข้อมูลมาใส่ Datatable ที่ชื่อว่า dtProgress ซึ่งเป็นจำนวนของผลไม้แต่ละชนิด
    
            StringBuilder strProgress = new StringBuilder();
            DataTable dtProgress = new DataTable();
            dtProgress.Columns.AddRange(new DataColumn[2] { 
                             new DataColumn("Percent", typeof(int)),
                            new DataColumn("Name",typeof(string))});
    
            dtProgress.Rows.Add(25, "Orange");
            dtProgress.Rows.Add(56, "Grape");
            dtProgress.Rows.Add(45, "Mango");
            dtProgress.Rows.Add(100, "Banana");
          
          ////////////////////เป็นการวนลูปค่าเพื่อสร้างแท็ก html ในการแสดงผลแถบ Progress bar
             int i = 0;
             for ( i = 0; i <= dtProgress.Rows.Count -1; i++) 
             {
             
         ////////////////////เป็นการแสดงชื่อผลไม้แต่ละชนิดบนแถบ Progress bar
                strProgress.Append("<h3 class=\"progress-title\">" + dtProgress.Rows[i]["Name"] + "</h3>");
                strProgress.Append("<div class=\"progress-outer\">");
                strProgress.Append("<div class=\"progress\">");
    
         ////////////////////เป็นการแสดงกำหนดขนาดให้กับแถบสี Progress bar ตามข้อมูล % ในแถวที่วน และมีการ ดึงค่าสไตล์ชีทจากการเรียกใช้ฟังก์ชั่น getCss()
    
    ตามเงื่อนไขของจำนวน % ด้วย
                strProgress.Append("<div class=\"progress-bar progress-bar-striped " + getCss(int.Parse(dtProgress.Rows[i]["Percent"].ToString())) + " \" style=\"width:" + dtProgress.Rows[i]["Percent"] + "%;\"></div>");
    
    
         ////////////////////แสดงจำนวน % ของแต่ละแถบ Progress bar
    
                strProgress.Append("<div class=\"progress-value\"><span>" + dtProgress.Rows[i]["Percent"] + "</span>%</div>");
                strProgress.Append("</div></div>");
             }
    
         ////////////////////นำค่า Tag Html ที่เตรียมไว้ มาแสดงผลด้วย Literal
    
             ltrProgressBar.Text = strProgress.ToString();
    
        }

    2. เมธอดในการแปลงค่าสไตล์ชีทเพื่อปรับสีตามจำนวนที่ส่งมาเป็นพารามิเตอร์

    private string getCss(int Percent)
        {
            string ReturnResult = "";
    
            if (Percent >= 0 && Percent <= 25) 
            {
                ReturnResult = "progress-bar-danger";
            }
            else if (Percent > 25&& Percent <= 50) 
            {
                ReturnResult = "progress-bar-warning"; 
            }
            else if (Percent > 50 && Percent <= 75)
            {
                ReturnResult = "progress-bar-info";
            }
            else if (Percent > 75 && Percent <= 100)
            {
                ReturnResult = "progress-bar-success";
            }
            return ReturnResult;
        }

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

    • สีแดง ช่วงตั้งแต่ 0 – 25 %
    • สีส้ม ช่วงตั้งแต่ 26 – 50 %
    • สีฟ้า ช่วงตั้งแต่ 51 – 75 %
    • สีเขียว ช่วงตั้งแต่ 76 – 100 %

    ตัวอย่างการเรียกใช้งาน

        protected void Page_Load(object sender, EventArgs e)
        {
            getData();
        }

    ผลลัพธ์

    แบบหลายสีในแถบเดียวกัน(แบบที่ 1)

              โดยในตัวอย่างนี้ จะเป็นการแสดงข้อมูลจำนวนผลไม้เป็น % รวมในแถบ Progress bar เดียวกัน ซึ่งจะแยกตามสี และมีบอกจำนวนรวมถึงชื่อผลไม้ให้ทราบ อีกทั้งยังแสดงจำนวนรวมของผลไม้ทุกชนิดด้วย โดยมีวิธีการทำ ดังนี้ค่ะ

    1. ดึงข้อมูลจากฐานข้อมูล และจัดเตรียม Tag Html ที่จะใช้ในการแสดงผล
        private void getMultiFruitColorData()
        {
            StringBuilder strProgress = new StringBuilder();
            DataTable dtProgress = new DataTable();
            dtProgress.Columns.AddRange(new DataColumn[2] { 
                             new DataColumn("Percent", typeof(int)),
                            new DataColumn("Name",typeof(string))});
            dtProgress.Rows.Add(25, "Orange");
            dtProgress.Rows.Add(12, "Grape");
            dtProgress.Rows.Add(7, "Mango");
            dtProgress.Rows.Add(25, "Banana");
    
            int i = 0;
            int percent = 0;
            string CssStr = "";
            int Total = 0;
            
                strProgress.Append("<h3 class=\"progress-title\">Multiple-fruits</h3>");
                strProgress.Append("<div class=\"progress-outer\">");
                strProgress.Append("<div class=\"progress\">");
            for (i = 0; i <= dtProgress.Rows.Count - 1; i++)
            {
                percent = int.Parse(dtProgress.Rows[i]["Percent"].ToString());
    
    
    ////////////////////คำนวณผลรวม % ของผลไม้ทุกชนิดตามการวนรอบที่จะแสดงในแถบ Progress bar
    
                Total += percent;
                switch (i) 
                {
                    case 0: CssStr = "progress-bar-danger"; break;
                    case 1: CssStr = "progress-bar-warning"; break;
                    case 2: CssStr = "progress-bar-info"; break;
                    case 3: CssStr = "progress-bar-success"; break;
                }
    
    ////////////////////เป็นการแสงค่า % ของผลไม้แต่ละชนิดในแถบ Progress bar เดียวกัน โดยแสดงชื่อผลไม้ และจำนวน % ของผลไม้แต่ละชนิดด้วย
    
                strProgress.Append("<div class=\"progress-bar progress-bar-striped " + CssStr + "\" style=\"width:" + percent + "%;\">" + dtProgress.Rows[i]["Name"] + "(" + percent + "%)</div>");
               
            }  
    
     ////////////////////เป็นการแสงผลรวม % ของผลไม้ทุกชนิดในแถบ Progress bar
    
            strProgress.Append("<div class=\"progress-value\"><span>" + Total + "</span>%</div></div>");
            strProgress.Append("</div></div>");
    
            ltrProgressBar.Text = strProgress.ToString();
    
        }
    

              จากโค้ดตัวอย่างข้างต้น จะเห็นว่าการสร้างแท็ก Html จะแตกต่างจากแบบแรก คือจะมีการสร้างใน <div class=\”progress\”> เดียวกัน ซึ่งมีหลักการคล้ายกับการสร้าง Progress bar อย่างง่ายหลายสีในแถบเดียวกันที่เคยกล่าวไว้แล้วในบทความก่อนหน้านั่นเอง

    ผลลัพธ์

    แบบหลายสีในแถบเดียวกันและแสดงหลายแถบ Progress Bar(แบบที่ 2)

              ในตัวอย่างนี้ เป็นการแสดงผลแถบสีแยกตามช่วงของข้อมูลบน Progress bar แต่ละแถบ โดยการแสดงผลจะแบ่งสีตามปริมาณข้อมูลในแต่ละช่วง ดังนี้

    สีแดง ช่วงตั้งแต่ 0 – 25 % สีส้ม ช่วงตั้งแต่ 26 – 50 % สีฟ้า ช่วงตั้งแต่ 51 – 75 % สีเขียว ช่วงตั้งแต่ 76 – 100 %

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

    1. ดึงข้อมูลจากฐานข้อมูล และจัดเตรียม Tag Html ที่จะใช้ในการแสดงผล
        private void getMultiColorData()
        {
            StringBuilder strProgress = new StringBuilder();
            DataTable dtProgress = new DataTable();
            dtProgress.Columns.AddRange(new DataColumn[2] { 
                             new DataColumn("Percent", typeof(int)),
                            new DataColumn("Name",typeof(string))});
    
            dtProgress.Rows.Add(25, "Orange");
            dtProgress.Rows.Add(56, "Grape");
            dtProgress.Rows.Add(45, "Mango");
            dtProgress.Rows.Add(100, "Banana");
    
            int i = 0;
            int j = 0;
            int maxRange = 0;
            int percent = 0;
            for (i = 0; i <= dtProgress.Rows.Count - 1; i++)
            {
                percent= int.Parse(dtProgress.Rows[i]["Percent"].ToString());
    
    
    ////////////////////วนเพื่อสร้าง Progress bar ใหม่ในผลไม้แต่ละชนิด
    
                strProgress.Append("<h3 class=\"progress-title\">" + dtProgress.Rows[i]["Name"] + "</h3>");
                strProgress.Append("<div class=\"progress-outer\">");
                strProgress.Append("<div class=\"progress\">");
                maxRange = 0;
    
    ////////////////////คำนวณหาว่าค่าของ % ตกอยู่ในช่วงใด 1-4(เนื่องจากแบ่งออกเป็นช่วงละ 25 % และรวมเป็น 100%)
    
    
                if (percent >= 0 && percent <= 25)
                {
                    maxRange = 1;
                }
                else if (percent > 25 && percent <= 50)
                {
                    maxRange = 2;
                }
                else if (percent > 50 && percent <= 75)
                {
                    maxRange = 3;
                }
                else if (percent > 75 && percent <= 100)
                {
                    maxRange = 4;
                }
    
    ////////////////////วนลูปเพื่อแสดงผลสีในแต่ละช่วงบน Progress bar โดยมีการเรียกใช้งานเมธอด getCssRange()
    
                for (j = 1; j <= maxRange; j++)
                {
                    strProgress.Append(getCssRange(percent, j, maxRange));
                 }
                strProgress.Append("<div class=\"progress-value\"><span>" + dtProgress.Rows[i]["Percent"] + "</span>%</div></div>");
                strProgress.Append("</div></div>");
            }
    
            ltrProgressBar.Text = strProgress.ToString();
    
        }

    2. สร้างเมธอดที่ใช้ในการสร้างแท็ก Html ในการแสดงผลแถบสี ซึ่งในส่วนของกระบวนการคำนวณแถบสีจะไม่ขอลงในรายละเอียด แต่แสดงไว้ให้เห็นภาพการทำงานหลักๆเท่านั้น ดังนี้ค่ะ

        private string getCssRange(int Percent,int Range,int MaxRange)
        {
            string ReturnResult = "";
    
            switch (Range)
            {
                case 1:
                    if (MaxRange > Range)
                        ReturnResult = "<div class=\"progress-bar progress-bar-striped progress-bar-danger\" style=\"width:25%;\"></div>";
    
                    else 
                    {
                        Percent = Percent >= 25 ? 25 : Percent - (25 * (Range - 1));
                    ReturnResult = "<div class=\"progress-bar progress-bar-striped progress-bar-danger\" style=\"width:" + Percent + "%;\"></div>";
                    }
                    break;
                case 2:
                    if (MaxRange > Range)
                        ReturnResult = "<div class=\"progress-bar progress-bar-striped progress-bar-warning\" style=\"width:25%;\"></div>";
    
                    else
                    {
                        Percent = Percent >= 50 ? 50 : Percent - (25 * (Range - 1));
                        ReturnResult = "<div class=\"progress-bar progress-bar-striped progress-bar-warning\" style=\"width:" + Percent + "%;\"></div>";
                    }
                   
                    break;
    
                case 3:
                    if (MaxRange > Range)
                        ReturnResult = "<div class=\"progress-bar progress-bar-striped progress-bar-info\" style=\"width:25%;\"></div>";
    
                    else
                    {
                        Percent = Percent >= 75 ? 75 : Percent- (25* (Range-1));
                        ReturnResult = "<div class=\"progress-bar progress-bar-striped progress-bar-info\" style=\"width:" + Percent + "%;\"></div>";
                    }
                     break;
    
                case 4:
    
                     if (Percent==100)
                         ReturnResult = "<div class=\"progress-bar progress-bar-striped progress-bar-success\" style=\"width:25%;\"></div>";
                     else
                     {
                         Percent =   Percent - (25 * (Range - 1));
                         ReturnResult = "<div class=\"progress-bar progress-bar-striped progress-bar-success \" style=\"width:" + Percent + "%;\"></div>";
                     }
                      break;
    
            }
             return ReturnResult;
        }
    

    ผลลัพธ์

    หมายเหตุ : จากตัวอย่างข้างต้น เป็นเพียงการยกตัวอย่างเพื่อให้ผู้อ่านเข้าใจการประยุกต์ใช้งาน และการทำงานร่วมกับ Progress bar เพิ่มมากขึ้นเท่านั้น ซึ่งผู้อ่านสามารถดัดแปลง และมีวิธีการรวมถึงเทคนิคที่แตกต่างออกไปที่จะนำมาใช้ในการพัฒนาเพื่อแสดงผลข้อมูล ขึ้นกับอัลกอริธึมของแต่ละท่าน

              จากบทความนี้จะเห็นได้ว่า วิธีการดึงข้อมูลมาแสดงผลด้วย Progress bar แบบนี้ จะมีความยืดหยุ่นกว่าแบบที่มีการกำหนดค่าตายตัวในบทความก่อนหน้า อีกทั้งยังสามารถแสดงจำนวนแถบ Progress bar และสีได้ไม่จำกัด ขึ้นอยู่กับข้อมูล การกำหนดเงื่อนไขในการแสดงผล และความต้องการของผู้พัฒนาที่จะดึงข้อมูลมาแสดงผลนั่นเอง และผู้เขียนหวังเป็นอย่างยิ่งว่า บทความนี้ จะพอเป็นแนวทางในการนำไปใช้งานจริงให้กับทุกท่านได้นะคะ ขอบคุณค่ะ ^^

    แหล่งข้อมูลอ้างอิง :

    https://bestjquery.com/tutorial/progress-bar/demo78/

    https://www.jquery-az.com/boots/demo.php?ex=51.0_5

  • มาทำความรู้จักและเรียนรู้การใช้งาน Progress bar ในเบื้องต้นกันเถอะ

              โดยปกติแล้วในการพัฒนาเว็บไซต์ของเรา คงมีบางเวลาที่เราอาจจะอยากแสดงผลข้อมูลของเราในรูปแบบของ Progress bar ซึ่งเป็นแถบของข้อมูล เพื่อเพิ่มมุมมองให้กับการแสดงผลให้ไม่น่าเบื่อจำเจแทนที่จะเป็นเพียงการแสดงผลตัวเลขเฉยๆ โดยเจ้า Progress bar นี้จะทำให้เราเห็นภาพได้ว่า ข้อมูลของเราได้ดำเนินการใกล้ถึงเป้าหมายแล้วหรือยัง ซึ่งขึ้นอยู่กับวัตถุประสงค์ในการนำไปใช้ ดังนั้นในบทความนี้ ผู้เขียนจึงขอแนะนำวิธีการใช้งาน Progress bar แบบเบื้องต้น โดยจะมีขั้นตอนง่ายๆ 3 ขั้นตอน ดังนี้

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

    ไฟล์ Progress.css

      .progress-title {
        font-size: 18px;
        font-weight: 700;
        color: #000;
        margin: 0 0 10px;
      }
    
    .progress-outer {
        background: #fff;
        padding: 5px 60px 5px 5px;
        border: 5px solid #bebfbf;
        border-radius: 45px;
        margin-bottom: 20px;
        position: relative;
    }
    
    .progress {
        background: #bebfbf;
        border-radius: 20px;
        margin: 0;
    }
    
        .progress .progress-bar {
            border-radius: 20px;
            box-shadow: none;
            animation: animate-positive 2s;
        }
    
        .progress .progress-value {
            font-size: 20px;
            font-weight: 700;
            color: #6b7880;
            position: absolute;
            top: 3px;
            right: 10px;
        }
    
        .progress-bar.active{
        animation: reverse progress-bar-stripes 0.40s linear infinite, animate-positive 2s;
        }
       @-webkit-keyframes animate-positive{
        0% { width: 0%; }
        }
       @keyframes animate-positive {
        0% { width: 0%; }
        }
    
       .progress-bar-striped {
        background-image: linear-gradient(
    45deg
    ,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);
        background-size: 1rem 1rem;
      }
      .progress-bar {
        display: -ms-flexbox;
        display: flex;
        -ms-flex-direction: column;
        flex-direction: column;
        -ms-flex-pack: center;
        justify-content: center;
        overflow: hidden;
        color: #fff;
        text-align: center;
        white-space: nowrap;
         transition: width .6s ease;
       }
       .progress {
        display: -ms-flexbox;
        display: flex;
        height: 1rem;
        overflow: hidden;
        font-size: .75rem;
        background-color: #e9ecef;
        border-radius: .25rem;
        box-shadow: inset 0 0.1rem 0.1rem rgb(0 0 0 / 10%);
        }
     

    เพิ่มเติม : การอ้างอิงไฟล์สไตล์ชีทจากภายนอก โดยที่อยู่ของไฟล์ก็ขึ้นกับการระบุของแต่ละท่าน

    <link href="dist/css/Progress.css" rel="stylesheet">

    2. การกำหนดพื้นที่ในการแสดงผล Progress bar ในส่วนของแท็ก body ในไฟล์ html

    <div class="container">
        <div class="row">
            <div class="col-md-6">
    
             <!-- progress bar-->
                <h3 class="progress-title">Basic Progress</h3>  <!-- progress bar Title-->
                <div class="progress-outer">
                    <div class="progress">
                        <!-- กำหนดสไตล์ชีทเพื่อแสดงแถบสี และขนาดของ progress bar -->
                        <div class="progress-bar progress-bar-striped progress-bar-info" style="width:85%;"></div>
                       <div class="progress-value"><span>85</span>%</div> <!-- แสดงข้อความจำนวน % บน progress bar -->
                    </div>
                </div>
            <!-- End progress bar-->
          
            </div>
        </div>
    </div>

    คำอธิบาย : จากตัวอย่าง จะเห็นว่าเราสามารถปรับแต่งและใส่ข้อมูลให้กับ Progress bar 3 ส่วนคือ

    • ข้อความบนแถบ Progress bar ได้ในส่วนของ Progress-title คือ <h3 class=”progress-title”>Basic Progress</h3>
    • กำหนดความกว้างของ Progress bar ได้ผ่านทาง style-inline คือ style=”width:85%;
    • แสดงข้อความจำนวนของข้อมูลบนแถบ Progress bar คือ <div class=”progress-value“><span>85</span>%</div> นั่นเอง

    3. การเรียกใช้งาน jQuery เพื่อการแสดงผล Progress bar ของเราให้มีการเพิ่มขึ้นของจำนวนเลขที่แสดงตั้งแต่ 0 จนถึงจำนวนเลขนั้น เช่น หากเลขที่ต้องการแสดงคือ 60% ตัวเลขแสดงจำนวนดังกล่าวจะค่อยๆเปลี่ยนแปลงเพิ่มขึ้นโดยเริ่มจาก 0 จนถึง 60 นั่นเอง

    <script type="text/javascript" src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
     <script>
    $(document).ready(function(){
        $('.progress-value > span').each(function(){
            $(this).prop('Counter',0).animate({
                Counter: $(this).text()
            },{
                duration: 1500,
                easing: 'swing',
                step: function (now){
                    $(this).text(Math.ceil(now));
                }
            });
        });
    });
     </script>

    ผลลัพธ์

    เพิ่มเติม
              จากตัวอย่างข้างต้น จะเป็นการแสดงผล Progress bar แบบพื้นฐานอย่างง่าย เพียงเท่านี้ท่านก็จะสร้าง Progress bar ได้ด้วยตนเองแล้ว แต่หากท่านใดที่อยากเพิ่มสีสันและความสวยงามให้กับ Progress bar ของท่าน ก็สามารถทำได้ดังตัวอย่างนี้ค่ะ
    1. ปรับแก้เพิ่มเติมในส่วนของการกำหนดพื้นที่ในการแสดงผล

    <div class="container">
        <div class="row">
            <div class="col-md-6">
    
             <!-- progress bar-->
                <h3 class="progress-title">Progress1</h3>  <!-- progress bar Title-->
                <div class="progress-outer">
                    <div class="progress">
                        <!-- กำหนดสไตล์ชีทเพื่อแสดงแถบสี และขนาดของ progress bar -->
                        <div class="progress-bar progress-bar-striped progress-bar-danger" style="width:25%;"></div>
                       <div class="progress-value"><span>25</span>%</div> <!-- แสดงข้อความจำนวน % บน progress bar -->
                    </div>
                </div>
    
            <!-- End progress bar-->
                <h3 class="progress-title">Progress2</h3>
                <div class="progress-outer">
                    <div class="progress">
                        <div class="progress-bar progress-bar-striped progress-bar-warning" style="width:50%;"></div>
                        <div class="progress-value"><span>50</span>%</div>
                    </div>
                </div>
                <h3 class="progress-title">Progress3</h3>
                <div class="progress-outer">
                    <div class="progress">
                        <div class="progress-bar progress-bar-striped progress-bar-info" style="width:75%;"></div>
                        <div class="progress-value"><span>75</span>%</div>
                    </div>
                </div>
                <h3 class="progress-title">Progress4</h3>
                 <div class="progress-outer">
                    <div class="progress">
                        <div class="progress-bar progress-bar-striped progress-bar-success" style="width:90%;"></div>
                        <div class="progress-value"><span>90</span>%</div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    2. เพิ่มสไตล์ชีทที่ใช้สำหรับเพิ่มสีสันให้กับ Progress bar ของเรา

    .progress-bar-danger {
        background-color: #d9534f;
    }
    .progress-bar-warning {
        background-color: #f0ad4e;
    }
    .progress-bar-success {
        background-color: #5cb85c;
    }
    .progress-bar-info {
        background-color: #5bc0de;
    }

    ผลลัพธ์

              จากตัวอย่างข้างต้น จะเป็นวิธีการสร้าง Progress bar ที่มีการใส่สีสันให้กับแต่ละแถบเส้น แต่ลูกเล่นของการแสดงผล Progress bar ยังสามารถทำได้หลายแบบ ซึ่งผู้เขียนจะขอแนะนำอีกวิธี ซึ่งเป็นการสร้าง Progress bar แบบหลายสีในแถบเดียวกันโดยมีวิธีการเพิ่มเติม ดังนี้ค่ะ

    การกำหนดพื้นที่ในการแสดงผล Progress bar ในส่วนของแท็ก body ในไฟล์ html

    <div class="container">
        <div class="row">
            <div class="col-md-6">
    
                  <h3 class="progress-title">Multiple-color Progress</h3>
                    <div class="progress-outer">
                <!-- การกำหนดแถบสีใน 1 แถบ progress bar-->
                        <div class="progress">
    
                            <!-- แถบสีแดงใน progress bar ขนาด 25%-->
                            <div class="progress-bar progress-bar-danger progress-bar-striped" style="width: 25%">25%
                            </div>
                              <!-- แถบสีส้มใน progress bar ขนาด 25%-->
                            <div class="progress-bar progress-bar-warning progress-bar-striped" style="width: 25%">50%
                            </div>
                             <!-- แถบสีฟ้าใน progress bar ขนาด 25%-->
                            <div class="progress-bar progress-bar-info progress-bar-striped " style="width: 25%">75%
                            </div>
                             <!-- แถบสีเขียวใน progress bar ขนาด 25%-->
                            <div class="progress-bar progress-bar-success progress-bar-striped active" style="width: 10%">10%
                            </div>
                            <div class="progress-value">
                                <span>85</span>%</div>
                        </div>
                    </div>
          
            </div>
        </div>
    </div>

              จากโค้ดตัวอย่างข้างต้น จะสังเกตเห็นว่าการกำหนดค่าต่างๆจะมีลักษณะกับหลักการที่กล่าวไว้แล้วข้างต้น แต่จะแตกต่างกันตรงที่การแสดงผลหลายแถบสีในแถบเดียวกันจะมีการกำหนด progress bar ภายใต้แท็ก <div class=”progress”> เดียวกัน และหากต้องการกำหนดให้มีกี่แถบสีก็สามารถเพิ่มสี และกำหนดขนาดของแต่ละแถบสีได้ตามต้องการ

    ผลลัพธ์

              โดยบทความนี้ก็ถือเป็นเพียงส่วนหนึ่งของการแนะนำการใช้งาน รวมถึงลูกเล่นของ Progress bar ในเบื้องต้นเท่านั้น เนื่องจากรูปแบบและการใช้งานของ Progress bar ยังมีให้เลือกใช้ เลือกลองกันอีกมากมายหลายแบบเลยนะคะ ผู้เขียนหวังว่าความรู้จากบทความนี้จะเป็นพื้นฐานและตัวช่วยให้กับนักพัฒนาสามารถนำไปประยุกต์ใช้ในงานของตนได้ไม่มากก็น้อยค่ะ ^^

    แหล่งข้อมูลอ้างอิง :

    https://bestjquery.com/tutorial/progress-bar/demo78/

    https://www.jquery-az.com/boots/demo.php?ex=51.0_5

  • ว่าด้วยการนับแถวข้อมูลใน ORACLE

                  การนับแถวข้อมูล (Row Count) ในตารางข้อมูล (Table) บน ORACLE จะใช้คำสั่ง SQL พื้นฐานคือ

                                SELECT COUNT(*) FROM table_name;

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

    ภาพการสร้างตารางข้อมูล table1 และเพิ่มข้อมูล 7 แถว

                  จากภาพเป็นการเพิ่มตารางข้อมูล และเพิ่มข้อมูลในลักษณะที่แตกต่างกันคือ เพิ่มข้อมูลที่ไม่ซ้ำกัน เพิ่มข้อมูลซ้ำกัน เพิ่มข้อมูลที่เป็น NULL ทั้งสิ้น 7 rows

                  เมื่อใช้คำสั่งเรียกดูข้อมูลและนับจำนวนข้อมูลพบว่าข้อมูลถูกแสดงถูกต้อง และสามารถนับได้ 7 rows ถูกต้อง

    ภาพการแสดงข้อมูลและการนับจำนวนแถวข้อมูลแบบพื้นฐาน

                  เมื่อใช้พารามิเตอร์ ALL ในคำสั่ง COUNT จะพบว่าสามารถนับได้ 5 แถว ซึ่งจะหมายถึงการนับเฉพาะแถวที่มีค่าข้อมูล (ยกเว้นแถวที่มี F1 เป็น NULL)

                  การทำงานโดยใช้คำสั่ง SELECT COUNT( ALL f1) FROM table1; จะให้ผลการทำงานเหมือนกับการนับโดยระบุเงื่อนไข SELECT COUNT(*) WHERE f1 IS NOT NULL; ดังรูป

    ภาพการแสดงข้อมูล และการนับข้อมูลโดยใช้พารามิเตอร์ ALL และการระบุเงื่อนไข WHERE …. IS NOT NULL

                  เมื่อใช้พารามิเตอร์ DISTINCT ภายในคำสั่ง COUNT จะพบว่าผลการนับจะแสดงค่าที่ไม่ซ้ำเท่ากับ 4 (ค่าที่นับได้คือ 1,2,3,4) ค่า NULL ใน Row=5,7 ไม่ถูกนับเนื่องจาก NULL ไม่มีค่า

    ภาพแสดงการนับข้อมูลและการนับข้อมูลโดยระบุพารามิเตอร์ DISTINCT

                  สรุปในเบื้องต้นการนับจำนวนแถวใน ORACLE โดยใช้คำสั่ง COUNT นอกจากจะนับจำนวนแบบง่ายด้วยคำสั่ง COUNT(*) แล้ว เราสามารถระบุพารามิเตอร์ให้มีค่าเป็น ALL หรือ DISTINCT ก็จะให้ผลลัพธ์ของการทำงานที่แตกต่างกันได้

  • การใช้งานหน่วยเวลาใน ORACLE ระดับมิลลิวินาที

                  การใช้งานประเภทเวลาใน ORACLE ที่เราใช้งานปกติคือข้อมูลประเภท Date (Data Type=Date) ซึ่งจะเก็บข้อมูลที่มีหน่วยเล็กที่สุดคือ วินาที (second)

                  การใช้งานระบบที่มีผู้ใช้จำนวนมากพร้อมๆกัน ในบางครั้งหน่วยวินาทีอาจไม่ละเอียดพอ จำเป็นต้องใช้หน่วยเวลาที่เล็กกว่าวินาทีคือมิลลิวินาที (1000 มิลลิวินาที = 1 วินาที) ซึ่งใน ORACLE ได้จัดเตรียมข้อมูลประเภทนี้ไว้ให้คือ Timestamp ซึ่งสามารถใช้งานได้ทั้งการสร้างเป็นคอลัมน์ในตารางข้อมูลหรือเป็นตัวแปรใน PL/SQL ดังตัวอย่าง

    การใช้งาน Timestamp ใน SQL

    รูปแสดงการสร้างตาราง

                  จากรูปจะสร้างฟิลด์ประเภท NUMBER, DATE และ TIMESTAMP (ที่ระดับความละเอียด 6 digits) โดยฟิลด์ DATE กำหนด Default Value = SYSDATE และ TIMESTAMP กำหนด Default = SYSTIMESTAMP

                  เมื่อเพิ่มข้อมูลโดยระบุค่าในฟิลด์ ID ค่าในฟิลด์ Date1, Date2 จะถูกป้อนค่าอัตโนมัติดังรูป โดยจะเห็นค่าความละเอียดของหน่วยเวลาที่แตกต่างกันของทั้งสองฟิลด์ดังรูป

    รูปเมื่อเพิ่มข้อมูลรายการใหม่ และสืบค้นข้อมูล

                  จากรูปจะพบว่าค่าในฟิลด์ Date1 มีค่าเวลาหน่วยวินาทีเท่ากับ 38 ส่วน Date2 มีค่าเวลาหน่วยวินาทีเป็น 38.779

                  ทดสอบการเพิ่มข้อมูลเพื่อดูค่าเวลาในฟิลด์ Timestamp โดยเพิ่มข้อมูลและหยุด 100 มิลลิวินาที ก่อนเพิ่มรายการถัดไป

    คำสั่งเพิ่มข้อมูล และพัก 0.1 วินาทีก่อนเพิ่มข้อมูลรายการถัดไป
    การสืบค้นข้อมูลเพื่อดูค่า Timestamp ที่รายการ ID = 2 และ 3

                  จากรูปจะพบว่าค่า Date1 ของรายการ 2,3 มีค่าเท่ากันในขณะที่ Date2 (Timestamp) มีค่าต่างกัน

    การใช้งานตัวแปรประเภท Timestamp ใน PL/SQL

                  นอกจาก Timestamp สามารถใช้งานในคำสั่ง SQL แล้ว ยังสามารถใช้งานได้ใน PL/SQL ได้อีกด้วยดังรูป

    รูปแสดงการใช้งานตัวแปรประเภท Timestamp

                  จากรูปเป็นการสร้างตัวแปรประเภท Timestamp และนำค่าข้อมูลในฟิลด์ข้อมูลมาจัดเก็บและแสดง

                  จากบทความนี้สามารถสรุปได้ว่า สามารถใช้งาน Data Type ประเภท Timestamp บน ORACLE เพื่อจัดการกับข้อมูลที่มีผู้ใช้งานระบบหลายคนพร้อมๆกัน ซึ่งจำเป็นต้องใช้หน่วยเวลาที่มีความละเอียดกว่าวินาที

  • Migrate จากฐานข้อมูล MySql มายัง Oracle ด้วย Sql Developer

    เนื่องจากงานที่รับผิดชอบ จะต้องมีการโอนย้ายข้อมูลจากฐานข้อมูลอื่นๆมายัง Oracle เป็นประจำ พบว่าการย้าย MySql มายัง Oracle นั้นสามารถทำได้ง่ายมาก (อาจเพราะเจ้าของเดียวกัน) โดยมีวิธีดังนี้

    1. ดาวส์โหลดและติดตั้ง Oracle SQL Developer

    2. ทำการเชื่อมต่อไปยังฐานข้อมูล Oracle ด้วย User system

    3. สร้าง Oracle User สำหรับเก็บข้อมูลจาก MySql และกำหนดสิทธิให้เรียบร้อย

    4. ดาวส์โหลดไฟล์ Third Party JDBC Driver สำหรับ My Sql

    5. เปิดการใช้งาน Third Party JDBC Driver โดยไปที่ Tools > Preferences > Database > Third Party JDBC Drivers

    6. ทำการ Restart โปรแกรม Sql Developer เมื่อทำการ New Connection จะมีตัวเลือกเพื่อเชื่อมต่อไปยัง My Sql

    7. ทำการเชื่อมต่อไปยัง My Sql  หากต้องการเพียง Data, Schema สามารถคลิกขวาตารางที่ต้องการเลือก Copy To Oracle ได้เลย

    เพียงเท่านี้ ข้อมูล Table, Field ก็จะถูกโอนย้ายและ Map Data Type ให้อัตโนมัติสามารถ Query จาก Oracle ได้เลย

    แต่สำหรับงานที่ต้องการ Constraint, Trigger, ฯลฯ ด้วย จะมีขั้นตอนเพิ่มเติมดังนี้

    1. ไปที่  Tools > Migration > Migrate กำหนด User ที่จะใช้เป็น Migrate Repository (เก็บข้อมูลต่างๆขณะดำเนินการ Migrate)

    2. กำหนดโฟลเดอร์จัดเก็บ Script, Log file

    3. เลือก Connection My Sql ที่ต้องการ Migrate

    4. เลือก My Sql User ที่ต้องการ Migrate

    5. การ Map Data Type สามารถใช้ค่า Default ได้

    6. เลือก Sql Object ที่ต้องการ

    7. เลือก Connection ของ DB User ที่ใช้เก็บโครงสร้าง และคำสั่งต่างๆ ที่ระบบใช้ในการ Migrate

    8. กำหนด User เป้าหมายที่จะนำข้อมูลเข้า จากนั้นเลือก Finish

    เพียงเท่านี้ก็เรียบร้อยครับ ข้อควรระวังคือการเลือก Repository User ควรสร้างขึ้นมาใหม่ เนื่องจากจะมีการสร้าง Table ขึ้นมาระหว่างการ Migrate และการกำหนดสิทธิให้กับ User ต่างๆให้ครบถ้วน แบบที่สองดูเหมือนหลายขั้นตอน แต่ก็เป็นแบบ Wizard ที่ใช้งานได้ไม่ยาก หวังว่าบทความนี้จะเป็นประโยชน์ครับ

  • [บันทึกกันลืม] วิธีย้ายทั้ง Folder จาก Google Drive ไปยัง Shared Drives ขององค์กร

    จากที่ Google Apps for Education หรือ Google Workspace for Education ปัจจุบัน ซึ่งจากเดิม ชูนโยบาย Unlimited Storage มาเป็น 100 GB ต่อ คน และ 100 TB ต่อ องค์กร — เพียงพอ ต่อการใช้งานเพื่อการศึกษาจริง ๆ ถ้าจัดการให้ดี

    เหตุแห่งการเปลี่ยนแปลง

    ผมว่า ก็เรา ๆ นี่แหล่ะ ใช้พื้นที่เค้าแบบไม่ใช่เพื่อการศึกษา ต้องยอมรับก่อน แล้วเรามาแก้ไขกัน

    • มีบางคนในองค์กร เอาไปเก็บไฟล์หนัง ไม่เกี่ยวกับการศึกษา จริงหรือไม่ รู้อยู่แก่ใจ, เรื่องนี้ Super Admin ขององค์กรตรวจสอบได้ ด้วย Google Vault จัดการให้เด็ดขาด (Super Admin รายงานได้ ผู้มีอำนาจต้องตัดสินใจ … กล้าไม๊ ค่อยมาดูกัน)
    • บางองค์กรไม่มีมาตรการควบคุมบัญชี สร้างมากเกินความจำเป็น แล้วบางคนเอาบัญชีไปขายใน Lazada, Shopee จริงไม่จริง รู้อยู่แก่ใจ
    • บางคน เอาแต่ประโยชน์ส่วนตน ได้สิทธิ์ แต่เอาพื้นที่ Shared Drives ไปปล่อยให้ เว็บโป๊ เว็บหนังซีรี่ ใช้พื้นที่ซะงั้น

    ก็เป็นธรรมดา Google ลงทุนทรัพยากร แต่ไม่ได้ใช้ให้ถูกตามวัตถุประสงค์ ก็ต้องมีการควบคุม งานส่วนตัว ใช้ My Drive, งานของหน่วยงาน ใช้ Shared Drives จบ

    (บางคนบอกว่า ย้ายไป Microsoft OneDrive ก็ได้วะ 5TB … ทำเหมือนเดิม เดี๋ยวก็จะได้ผลเหมือนเดิม)

    ผมได้เล่าไว้บ้างแล้ว เกี่ยวกับการใช้พื้นที่ของ Shared Drives

    มาดูวิธีแก้ปัญหากันดีกว่า

    • จากเดิม คนในสำนักงานก็จะชอบใช้ My Drive แล้ว Share ให้คนในหน่วยงานใช้กัน ก็เข้าใจได้ เพราะตอนแรกไม่มี Shared Drives เคยทำอย่างไรก็จะทำอย่างนั้น ไม่ชอบเปลี่ยนแปลง ถึงเวลาต้องเปลี่ยนแล้ว คือ งานส่วนรวม เอาไปเก็บใน Shared Drive
    • เอาหล่ะ สมมุติว่า เราเคยใช้ Folder หนึ่ง เก็บสารพัดสิ่งที่เกี่ยวกับงานจริง ๆ แต่มันอยู่ใน My Drive (พื้นที่ส่วนตัว) สมมุติใช้ Folder ชื่อ parent ในนั้นมี Sub folder ย่อย และมีไฟล์ย่อย ๆ ซ้อน ๆ ลงไปจำนวนมาก
    parent folder ซึ่งเป็นงานจริง ๆ และมีไฟล์ และ folder ย่อย ๆ ลงไปจำนวนมาก
    • แนะนำว่า แต่ละหน่วยงาน เช่น ระดับภาควิชา หรือ ระดับหน่วยงาน ไปสร้างพื้นที่ไว้บน Shared Drives

    ปัญหาคือ … การย้ายไฟล์จาก​ Google Drives ไปยัง Shared Drives นั้น ทำได้ในระดับไฟล์ ไม่สามารถย้ายทั้ง Folder ได้

    ใครใคร่ย้าย ก็เลือกไฟล์ แล้วคลิกขวา Move to ไป

    แต่กรณี ของผมมีไฟล์ ที่สร้างจากอุปกรณ์ ขนาด 400-800 kb จำนวน …. 60 GB คิดคร่าว ๆ 2 ไฟล์ เป็น 1 MB ก็ราว ๆ 60 x 1024 x 2 = 122,880 ไฟล์

    กรณีย้ายไฟล์จำนวนมากใน Folder เดียวกัน ไปไว้บน​ Shared Drives

    ผมสร้าง Google Apps Script ไว้ที่ https://gist.github.com/nagarindkx/70f254a21c5cad7f964e762ab8b2e733

    function moveFilesFromDriveToShareDrive() {
      /*
      Created by: Kanakorn Horsiritham
      Digital Innovation and Data Analytics (DIDA)
      Faculty of Medicine
      Prince of Songkla University
      Hatyai, Songkhla
      THAILAND
      */
      sourceFS=DriveApp.getFolderById('GoogleDrive-Folder-ID').getFiles()
      destinationFS=DriveApp.getFolderById('SharedDrives-Folder-ID')
      
      while(sourceFS.hasNext()){
        f=sourceFS.next()
        f.moveTo(destinationFS) 
      }
    }

    สิ่งที่ท่านต้องทำคือ

    1. เปิด Google Drive ต้นทางบน Web Browser แล้วดูที่ URL แล้ว Copy เฉพาะ GoogleDrive-Folder-ID เช่น

      https://drive.google.com/drive/folders/GoogleDrive-Folder-ID

      เก็บไว้ก่อน

    2. เปิด Shared Drives ปลายทาง แล้วทำเหมือนกัน

    3. จากนั้น สร้าง Google Apps Script ใน​ Google Drives

    4. ตั้งชื่อ Project ว่า movefile1

    5. copy code ข้างต้นมาใส่ จากนั้นแก้ไข GoogleDrive-Folder-ID และ SharedDrives-Folder-ID จากข้อ 1,2 แล้วกดปุ่ม Save

    6. ถ้าไฟล์ไม่มากนัก ก็ เลือก moveFilesFromDriveToShareDrive กดปุ่ม Run

    ถ้าทำครั้งแรก ระบบอาจจะถามอย่างนี้ ก็ให้เลือก Review Permissions แล้ว Next Next เลือก Account ไป (ขั้นนี้แล้ว ไม่อธิบายรายละเอียดแล้วนะครับ)

    จากนั้นก็รอไป Script จะทำงานต่อเนื่อง ยาวนานไม่เกิน 1800 วินาที หรือ 30 นาที ผลที่ได้คือ เฉพาะ Files เท่านั้น ที่จะย้ายไปอยู่ใน Shared Drives แต่ใจเย็น ๆ มีวิธีพาไปทั้งยวง รอแป๊บ

    7. แต่ถ้ามีไฟล์จำนวนมาก จนครบ 30 นาทีแล้ว ก็ยังไม่หมด ก็ต้องอาศัย Trigger เพื่อสั่งให้ทำทุก ๆ 1 ชั่วโมง ดังนี้
    เลื่อน Cursor ไปทางซ้ายมือ คลิกที่ Triggers

    คลิกปุ่ม Add Trigger

    เลือกตามนี้ แล้ว Save

    จากนั้นก็รอไป ระบบจะทำจนหมดเวลา 30 นาที รออีก 1 ชั่วโมง แล้วก็ทำต่อไปเรื่อย ๆ

    อันนี้ ของผม

    ยังอีกยาวนาน

    กรณีย้ายทั้ง Folder ไปไว้บน​ Shared Drives

    UPDATE!!!!

    เลือก Folder ต้นทาง และ ปลายทาง จากนั้น copy/move ได้เลย โดย ที่จะสร้างโครงสร้าง Folders และ Files ที่ Shared Drives ตามเดิมจากต้นทาง

    ผมทำ Script ไว้ที่ https://gist.github.com/nagarindkx/e2897455b2ede2ae168f8cd5ccf16982

    function copyFilesFromDriveToShareDrive() {
      /*
      Created by: Kanakorn Horsiritham
      Digital Innovation and Data Analytics (DIDA)
      Faculty of Medicine
      Prince of Songkla University
      Hatyai, Songkhla
      THAILAND
      */
      
      sourceID='GoogleDrive-Folder-ID'
      destinationID='SharedDrives-Folder-ID' 
       
      copyFolder(sourceID, destinationID)
      //moveFolder(sourceID, destinationID)
    
    }
    
    function copyFolder(sourceID, destinationID){
      sFD = DriveApp.getFolderById(sourceID)
      dFD = DriveApp.getFolderById(destinationID)
      
      files = sFD.getFiles()
      while(files.hasNext()) {
        f=files.next()
        if (! dFD.getFilesByName(f.getName()).hasNext()) {
          f.makeCopy(f.getName(), dFD)
          console.log('copy file: ' + f.getName())
        } else {
          Logger.log( "file: " + f.getName() + ' exist')
        }
        
      }
    
      folders=sFD.getFolders()
      nextlevel=[]
      while(folders.hasNext()) {
        fd = folders.next()
        tmpDestinationFolder = dFD.getFoldersByName(fd.getName())
        if (! tmpDestinationFolder.hasNext()) {
          new_folder = dFD.createFolder(fd.getName())
          Logger.log( "create folder: " + fd.getName())
        } else {
          new_folder = tmpDestinationFolder.next()
          Logger.log( "folder: " + fd.getName() + ' exist')
        }
        
        nextlevel.push([fd.getId(), new_folder.getId()])
      }
      nextlevel.forEach(function(r){
        copyFolder(r[0], r[1])
      })
    }
    
    
    function moveFolder(sourceID, destinationID){
      sFD = DriveApp.getFolderById(sourceID)
      dFD = DriveApp.getFolderById(destinationID)
      
      files = sFD.getFiles()
      while(files.hasNext()) {
        f=files.next()
        if (! dFD.getFilesByName(f.getName()).hasNext()) {
          console.log('file: ' + f.getName())
          f.moveTo( dFD)
          console.log('move file: ' + f.getName())
        } else {
          Logger.log( "file: " + f.getName() + ' exist')
        }
      }
    
      folders=sFD.getFolders()
      nextlevel=[]
      c=0
    
      if (folders.hasNext()) {
        while(folders.hasNext()) {
          fd = folders.next()
          tmpDestinationFolder = dFD.getFoldersByName(fd.getName())
          if (! tmpDestinationFolder.hasNext()) {
            new_folder = dFD.createFolder(fd.getName())
          } else {
            new_folder = tmpDestinationFolder.next()
            Logger.log( "folder: " + fd.getName() + ' exist')
          }
          nextlevel.push([fd.getId(), new_folder.getId()])
          c=c+1
        }
        nextlevel.forEach(function(r){
          moveFolder(r[0], r[1])
        })
      } else {
        sFD.setTrashed(true)
      }
      
    }