Month: May 2021

  • การใช้งาน touchpad ใน windows 10

    การใช้งาน touchpad ใน windows 10 มีดังนี้

    1. ใช้ 1 นิ้วกดที่ touchpad  การทำงานจะเหมือนกด mouse ด้านซ้าย

    ถ้ากด 1 ครั้ง จะเป็นการเลือกไฟล์หรือกดปุ่มคำสั่งที่ cursor ชี้อยู่เวลานั้น

    ถ้ากด 2 ครั้ง จะเป็นการเปิดไฟล์หรือเปิดโปรแกรม

    2. ใช้ 1 นิ้วกดที่ touchpad  2 ครั้งค้างไว้แล้วลาก  การทำงานจะเหมือนกด mouse ด้านซ้ายค้างไว้แล้วเลื่อน mouse

    เป็นการเลื่อนไฟล์ที่เลือกไปตำแหน่งอื่น หรือ เป็นการเลือกไฟล์แบบคลุม หรือใช้เลื่อน scroll bar

    3. ใช้ 2 นิ้วกดที่ touchpad  1 ครั้ง การทำงานจะเหมือนกด mouse ด้านขวา

    เป็นการแสดงคำสั่งอื่นๆ

    4. ใช้ 2 นิ้วกดที่ touchpad  1 ครั้งค้างแล้วกางออกหรือหุบเข้า

    เป็นการทำ Zoom in , Zoom out

    5. ใช้ 2 นิ้วกดที่ touchpad  1 ครั้งค้างแล้วเลื่อนขึ้นลง

    เป็นการเลื่อนหน้าจอขึ้นลง

    6. ใช้ 3 นิ้วกดที่ touchpad  1 ครั้ง

    เป็นการเปิดปุ่ม search

    7. ใช้ 3 นิ้วกดที่ touchpad  1 ครั้งค้างแล้วลากขึ้น

    เป็นการเปิด task view

    8. ใช้ 3 นิ้วกดที่ touchpad  1 ครั้งค้างแล้วลากลง

    เป็นการแสดงหน้า desktop

    9. ใช้ 3 นิ้วกดที่ touchpad  1 ครั้งค้างแล้วลากไปทางซ้ายหรือขวา

    เป็นการสลับโปรแกรมที่เปิดใช้งานอยู่

    10. ใช้ 4 นิ้วกดที่ touchpad  1 ครั้ง

    เป็นการเปิด Action Center

    11. ใช้ 4 นิ้วกดที่ touchpad  1 ครั้งค้างแล้วลากไปทางซ้ายหรือขวา

    เป็นการเลือกหน้า Desktop ที่เปิดอยู่

    ถ้าต้องการปิดการใช้งาน touchpad ขณะเสียบ mouse ให้ทำดังนี้

    1. เปิด windows setting แล้วเลือก Devices

    2. เลือก Touchpad แล้วเอาเครื่องหมายถูกหน้าข้อความ “Leave touchpad on when a mouse is connected” ออก

  • ลบภาพบนเอกสาร Word ทั้งหมดได้ง่าย ๆ ภายในพริบตา

    หลายท่านคงเคยมีปัญหาในการนำข้อความจาก word  อาจจะต้องนำไป Copy ไว้ที่ไหนสักที่ หรือ นำไปเขียน blog บนเว็บ แต่ไฟล์ที่เรามีอยู่ในมือ ดูแล้วมีรูปภาพเต็มไปหมด ไอ้เราก็ต้องการเฉพาะแค่ข้อความเท่านั้น ทำไงล่ะทีนี้ จะต้องมานั่งลบรูปทีละรูปอย่างนั้นเหรอ ?? เสียเวลาชะมัด เห้อ …..  แต่เดี๋ยวก่อนค่ะ มันไม่เสียเวลาขนาดนั้น มันก็มีวิธีอยู่นะคะ ที่เราจะไม่ต้องมานั่งคลิกลบทีละรูป เอาล่ะมาดูวิธีกันดีกว่า

    1. เปิดไฟล์ที่เราต้องการลบรูปทั้งหมดขึ้นมา จะเห็นว่าในไฟล์มีรูปภาพหลายรูปเลยล่ะค่ะ


    2. คลิกที่ปุ่ม Replace


    3. ในช่อง Find What  ให้พิมพ์ ^g   ส่วนตรง Replace With ไม่ต้องกรอกอะไรลงไปค่ะ ปล่อยว่างไว้เลย  จากนั้นให้กดปุ่ม Replace All


    4. ปรากฏข้อความแจ้งดำเนินการเสร็จสิ้น กดปุ่ม OK เพื่อปิดข้อความ


    5. กดปุ่ม Close เพื่อปิดหน้าจอการ Replace


    6. จะเห็นว่ารูปทั้งหมดหายวับไปกับตา เหลือเพียงแค่ข้อความที่เราต้องการ


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

  • การจัดหมวดหมู่แถวของข้อมูลบน GridView ด้วย C#

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

    ขั้นตอนในการพัฒนา

    1. เตรียมข้อมูลในการแสดงผล โดยจากตัวอย่างนี้ จะทำการสมมุติข้อมูลของดอกไม้ ผลไม้ และต้นไม้ และมีข้อมูลเพื่อใช้ในการแยกประเภทไว้ด้วย เพื่อให้เห็นภาพมากขึ้นค่ะ
    //// ประกาศตัวแปร GroupData
     เป็น ViewState เพื่อใช้ในงานข้อมูลในส่วนการแทรกแถวประเภทกลุ่มใน Event อื่นด้วย 
    
    public DataTable  GroupData
    
            {
                get
                {
                    if (ViewState["GroupData"] == null)
                    {
                        ViewState["GroupData"] = new DataTable();
                    }
                    return (DataTable)ViewState["GroupData"];
                }
                set { ViewState["GroupData"] = value; }
            }
    
    //// ผู้อ่านสามารถเรียกใช้ฟังก์ชั่น Getdata() การดึงข้อมูลนี้ในตอน Page_Load เพื่อดูเป็นตัวอย่างได้ค่ะ
    protected void Getdata() 
            {
                
                GroupData.Columns.AddRange(new DataColumn[5] {
                             new DataColumn("CategoryName", typeof(string)),
                             new DataColumn("Name", typeof(string)),
                             new DataColumn("ID", typeof(string)),
                              new DataColumn("Amt", typeof(int)),
                            new DataColumn("CategoryID",typeof(string))});
    
                GroupData.Rows.Add("Flower", "Rose", "1",2500, "01");
                GroupData.Rows.Add("Flower", "Lotus", "3",150, "01");
                GroupData.Rows.Add("Fruit", "Grape", "2",350, "02");
                GroupData.Rows.Add("Fruit", "Mango", "4",1750, "02");
                GroupData.Rows.Add("Fruit", "Orange", "5",2240, "02");
                GroupData.Rows.Add("Tree", "Cactus", "6",370, "03");
                GroupData.Rows.Add("Tree", "Hazelnut Tree", "6",2250, "03");
                ////นำข้อมูลใน Datatable ชื่อ GroupData แสดงผลใน GridView
                GroupGv.DataSource = GroupData;
                GroupGv.DataBind();
            }
    

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

    2. เตรียม GridView ที่จะใช้ในการแสดงผล โดยจะขอยกตัวอย่างให้ดูการแสดงผล GridView แบบทั่วไปก่อนมีการจัดกลุ่ม เพื่อให้เห็นความแตกต่าง ดังนี้ค่ะ

        <asp:GridView ID="GroupGv" runat="server" AutoGenerateColumns="False"
            DataKeyNames="ID"  CssClass="table table-sm table-hover Blue" Width="100%">
            <AlternatingRowStyle CssClass="Blue" />
            <EmptyDataRowStyle CssClass="Blue" />
            <EmptyDataTemplate>
                <br />
                <div style="text-align: center">
                    <i class="fas fa-exclamation-circle"></i>&nbsp;&nbsp; ไม่พบข้อมูล<br />
                    &nbsp;
                </div>
    
            </EmptyDataTemplate>
            <EmptyDataRowStyle HorizontalAlign="Center" />
            <HeaderStyle CssClass="Blue" />
    
            <Columns>
                <asp:TemplateField HeaderText="Name">
                    <ItemTemplate>
                        <asp:HiddenField ID="hdCatID" runat="server" Value='<%# Eval("CategoryID") %>' />
                        <asp:HiddenField ID="hdID" runat="server" Value='<%# Eval("ID") %>' />
                        <asp:HiddenField ID="HidCatName" runat="server" Value='<%# Eval("CategoryName") %>' />
                        <asp:Label ID="lblName" runat="server" Text='<%# Eval("Name") %>'></asp:Label>
                    </ItemTemplate>
                     <ItemStyle  Width="50%"  />
                </asp:TemplateField> <asp:BoundField HeaderText="Category Name" DataField="CategoryName">
                <ItemStyle  Width="30%"/>
                 </asp:BoundField>
                  <asp:BoundField HeaderText="Amount" DataField="Amt"  DataFormatString="{0:#,##0}" >
                <ItemStyle HorizontalAlign="Right"  Width="20%"/>
                 </asp:BoundField>
               
            </Columns>
        </asp:GridView>
    

    เพิ่มเติม : ข้อมูลจำนวนเป็นข้อมูลที่เป็นตัวเลข จึงได้ทำการจัด Format รูปแบบของข้อมูลให้แสดงผลแบบตัวเลข ด้วยการระบุ DataFormatString=”{0:#,##0}” เช่น หากข้อมูล 2500 จะแสดง 2,500 ให้อัตโนมัติ

    ผลลัพธ์(ก่อนทำการจัดกลุ่ม)

    3. เพิ่ม Event ที่ชื่อว่า OnDataBound=”GroupGv_DataBound” ให้กับ GridView เพื่อแสดงผลข้อมูลแบบกลุ่ม และตัดคอลัมน์ประเภท(Category Name)ออกไป เนื่องจากเราจะนำไปใช้แสดงผลในการจัดกลุ่ม

        <asp:GridView ID="GroupGv" runat="server" AutoGenerateColumns="False"
            DataKeyNames="ID"  CssClass="table table-sm table-hover Blue" Width="100%" OnDataBound="GroupGv_DataBound">
            <AlternatingRowStyle CssClass="Blue"  />
            <EmptyDataRowStyle CssClass="Blue" />
            <EmptyDataTemplate>
                <br />
                <div style="text-align: center">
                    <i class="fas fa-exclamation-circle"></i>&nbsp;&nbsp; ไม่พบข้อมูล<br />
                    &nbsp;
                </div>
    
            </EmptyDataTemplate>
            <EmptyDataRowStyle HorizontalAlign="Center" />
            <HeaderStyle CssClass="Blue" />
    
            <Columns>
                <asp:TemplateField HeaderText="Name">
                    <ItemTemplate>
                         <%--นำค่าไปใช้ตอนแทรกแถวหมวดหมู่ที่ต้องการจัดกลุ่ม--%>
                        <asp:HiddenField ID="hdCatID" runat="server" Value='<%# Eval("CategoryID") %>' />
                        <asp:HiddenField ID="hdID" runat="server" Value='<%# Eval("ID") %>' />
                        <asp:HiddenField ID="HidCatName" runat="server" Value='<%# Eval("CategoryName") %>' />
                        <asp:Label ID="lblName" runat="server" Text='<%# Eval("Name") %>'></asp:Label>
                    </ItemTemplate>
                     <ItemStyle  Width="70%"  />
                </asp:TemplateField> 
                  <asp:BoundField HeaderText="Amount" DataField="Amt"  DataFormatString="{0:#,##0}">
                <ItemStyle HorizontalAlign="Right"  Width="30%"/>
                 </asp:BoundField>
               
            </Columns>
        </asp:GridView>
    

    4. เพิ่มโค้ดในส่วนของฝั่งเซิร์ฟเวอร์(C#) ให้กับ Event ของ GridView ที่เราเพิ่มในข้อ 3. เพื่อจัดกลุ่ม ดังนี้ค่ะ

            string lastCatName = "";
            string AllName = "";
    
            protected void GroupGv_DataBound(object sender, EventArgs e)
            {
                lastCatName = "";
                Table table = (Table)GroupGv.Controls[0];
    
               ////////วนเพื่อแทรกแถวชื่อแต่ละประเภทของข้อมูล เช่น ดอกไม้ ต้นไม้ หรือผลไม้ 
                foreach (GridViewRow row in GroupGv.Rows)
                {
                  
                  
                    HiddenField HidCatName = (HiddenField)row.FindControl("HidCatName");
                    HiddenField HidCatID = (HiddenField)row.FindControl("hdCatID");
                    HiddenField HidID = (HiddenField)row.FindControl("hdID");
                    
            
               ////////หากพบว่าเป็นประเภทใหม่จะทำการสร้างแถวและเพิ่มแทรกเข้าไป โดยมีการกำหนดค่าต่างๆ เช่น ข้อความที่จะแสดง สีพื้นหลัง สีตัวอักษร และค่า ColumnSpan เป็นต้น
    
     
                    if (HidCatName.Value != lastCatName)
                    {
                       
                        int realIndex = table.Rows.GetRowIndex(row);
                        string text = HidCatName.Value;
                        GridViewRow newHeaderRow = new GridViewRow(realIndex, 0, DataControlRowType.Header, DataControlRowState.Normal);
    
    
                        /////สร้าง TableCell และระบุค่าต่างๆ ก่อนนำไปเพิ่มในแถว newHeaderRow ที่เพิ่งสร้าง
                       TableCell newCell = new TableCell();
                        newHeaderRow.Cells.AddAt(0, newCell);
    
                        ///กำหนด ColumnSpan เท่ากับจำนวนคอลัมน์ทั้งหมดใน GridView (GroupGv.Columns.Count)เพื่อให้คอลัมน์ที่ต้องการเพิ่มยาวครอบคลุมทั้งแถว
                        newCell.ColumnSpan = GroupGv.Columns.Count;
                        newCell.BackColor = System.Drawing.Color.FromName("#399ea9"); ;
                        newCell.ForeColor = System.Drawing.Color.White;
                        newCell.Font.Bold = true;
                        newCell.Text = string.Format(HidCatName.Value, "&nbsp;{0}", text);
    
                        ////เพิ่มแถวที่ต้องการแทรกเข้าไปในตารางหรือ GridView ที่เรากำลังจัดการอยู่นั่นเอง
                        table.Controls.AddAt(realIndex, newHeaderRow);
                       
                    }
                    lastCatName = HidCatName.Value;
                }
            }         
    

    ผลลัพธ์ (หลังมีการจัดกลุ่ม)

    เพิ่มเติม : จากตัวอย่างข้างต้น เนื่องด้วยข้อมูลเป็นการจัดกลุ่มและมีข้อมูลเชิงตัวเลข ผู้เขียนจึงขอแนะนำเพิ่มเติมในส่วนของการแสดงจำนวนรวมแยกในแต่ละกลุ่มไว้ด้วย โดยเพิ่มเติมโค้ดในส่วนของ GroupGv_DataBound ดังนี้ค่ะ

     protected void GroupGv_DataBound(object sender, EventArgs e)
            {
                lastCatName = "";
                Table table = (Table)GroupGv.Controls[0];
    
                foreach (GridViewRow row in GroupGv.Rows)
                {
                  
                    HiddenField HidCatName = (HiddenField)row.FindControl("HidCatName");
                    HiddenField HidCatID = (HiddenField)row.FindControl("hdCatID");
                    HiddenField HidID = (HiddenField)row.FindControl("hdID");
    
    
                    if (HidCatName.Value != lastCatName)
                    {
    
                       //// เป็นการหาผลรวมค่าของฟิลด์ Amt ซึ่งหมายถึงจำนวน โดยเป็นการรวมค่าฟิลด์แยกตามแต่ละ CategoryID นั่นเอง
    
                        var sumOfValuesInCategory = GroupData.AsEnumerable().Where(x => x.Field<string>("CategoryID") == HidCatID.Value).Sum(x => x.Field<int>("Amt")).ToString();
                       
    
                        int realIndex = table.Rows.GetRowIndex(row);
                        string text = HidCatName.Value;
                        GridViewRow newHeaderRow = new GridViewRow(realIndex, 0, DataControlRowType.Header, DataControlRowState.Normal);
                        TableCell newCell = new TableCell();
                        newHeaderRow.Cells.AddAt(0, newCell);
    
                       /////ปรับแก้การระบุค่า ColumnSpan จากเดิมที่รวมกันทุกคอลัมน์(GroupGv.Columns.Count) 
                       //// แต่กรณีนี้ต้องเว้นคอลัมน์ไว้แสดงผลจำนวนรวมแต่ละประเภทด้วย
    
                        newCell.ColumnSpan =1;
                        newCell.BackColor = System.Drawing.Color.FromName("#399ea9"); ;
                        newCell.ForeColor = System.Drawing.Color.White;
                        newCell.Font.Bold = true;
                        newCell.Text = string.Format(HidCatName.Value, "&nbsp;{0}", text);
    
                        ///สร้าง TableCell หรือคอลัมน์ใหม่ เพื่อแสดงผลข้อมูลจำนวนรวมของแต่ละประเภท 
    
                        TableCell newCellTotal = new TableCell();
    
    
                        /////เพิ่ม TableCell ในแถวที่กำลังสร้างและระบุค่าต่างๆ
                        newHeaderRow.Cells.AddAt(1, newCellTotal);
                        newCellTotal.ColumnSpan = 1;
                        newCellTotal.BackColor = System.Drawing.Color.FromName("#399ea9"); ;
                        newCellTotal.ForeColor = System.Drawing.Color.White;
                        newCellTotal.Font.Bold = true;
                        newCellTotal.HorizontalAlign = HorizontalAlign.Right;
    
    
                        ////นำค่าผลรวมในตัวแปร sumOfValuesInCategory ที่คำนวณได้ข้างต้นมาจัดรูปแบบก่อนแสดงผลใน TableCell สร้าง
    
                        newCellTotal.Text = string.Format("{0:#,##0}",int.Parse(sumOfValuesInCategory));
                       
                        table.Controls.AddAt(realIndex, newHeaderRow);
                    
                    }
                    lastCatName = HidCatName.Value;
                }
            }

    ผลลัพธ์

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

    แหล่งอ้างอิง
    https://stackoverflow.com/questions/61773421/sum-column-where-condition-with-datatable

  • Crystal Report : Report หลายตัวหัวท้ายต่าง แต่ตรงกลาง Code เหมือนกัน จัดการอย่างไร (WinApp)

    หลาย ๆ ครั้งที่ท่านมีรายงานมากกว่า 1 ฉบับที่มีรูปร่างหน้าตาส่วนหัวกระดาษหรือท้ายกระดาษที่ต่างกัน แต่ส่วนของ Detail นั้นเหมือนกันอย่างกับแกะ และเจ้าส่วน Detail นี้ ดั๊นนนน เป็นเจ้า Detail ที่มีเงื่อนไขเยอะแยะ ยุบยับซับซ้อนซ่อนเงื่อน ถ้าจะให้สร้าง File เพื่อวาง Report Viewer เป็น 2 File หรือตามจำนวนรายงานก็ใช่ที่

    จากการที่ประสบพบเจอมากับตัว ส่วนหัว ส่วนท้าย ดั๊นนน ไม่คล้ายไม่เหมือนเลย แต่ข้อมูลตรงกลางนั้น ต้องใช้ข้อมูลชุดเดียวกัน เหมือนกัน ทีนี้ถึงกับกุมขมับเลยว่าจะทำยังไงดี ได้คำปรึกษาแนะนำจากพี่ชายที่แสนดี @wachirawit-j มาช่วยชี้แจงแถลงไข ถึงต้องรีบจัดการเก็บข้อมูลไว้ เผื่อครั้งหน้าเจออีกแล้วลืมจะได้กลับมาอ่านซ้ำ ไปดูกันเล้ยยยยยย

    ReportClass cr = new ReportClass();

    ตัวแปร cr ที่ประกาศนี้ จะเป็นตัวแปรที่ไว้ใช้ในอนาคตทั้งไฟล์ เป็นตัวแปรที่เป็นตัวเก็บค่าว่า จะเป็น Crystal Report File ตัวไหนและใช้สำหรับกำหนดค่า FormulaField เพื่อใช้กับ Report File นั้น ๆ ตัวอย่าง

    cr.DataDefinition.FormulaFields["ffType"].Text = "'Normal'";

    Code ข้างต้นเป็นการกำหนดค่าให้กับ Formula Field ที่ชื่อว่า ffType ในฝั่ง Crystal Report โดยกำหนดให้มีค่าเท่ากับข้อความว่า “Normal” ซึ่งจะเห็นว่ามีการใช้ตัวแปร cr ในการดำเนินการ

    Code ส่วนอื่น ๆ ที่มีการกำหนดค่าก็จะมีการเรียกตัวแปร cr นี้เหมือนกัน ซึ่ง cr จะเป็นตัวที่บอกว่าคือ Crystal Report File ไหน

    private class CRModel
    {
       public RptNormal crNormal {get; set;}
       public RptSpecial crSpecial {get; set;}
    }

    Code ข้างต้นเป็นการสร้าง Class ชื่อว่า CRModel มีสมาชิกภายใน Class 2 Report นั่นคือ RptNormal.rpt กำหนดให้ใช้ตัวแปร crNormal และ RptSpecial.rpt กำหนดให้ใช้ตัวแปร crSpecial

    จากนั้นในส่วนของการตรวจสอบว่าจะใช้ Report ตัวไหนหรือการกำหนด report ให้กับ Reportsource เป็นดังนี้

    if(rptType == "normal") //ตรวจสอบว่าเป็นรายงานประเภทปกติ?
    {
       crModel.crNormal = new RptNormal(); //กำหนด crNormal ให้เป็นรายงาน RptNormal
       SetValue(crModel, rptType); //เรียก Method กำหนดค่าต่าง ๆ ในรายงาน
       crystalReportViewer1.ReportSource = crModel.crNormal; //กำหนด Reportsource ให้มีค่าเป็น crNormal
    }
    else
    {
       crModel.crSpecial = new RptSpecial(); //กำหนด crNormal ให้เป็นรายงาน RptSpecial
       SetValue(crModel, rptType); //เรียก Method กำหนดค่าต่าง ๆ ในรายงาน
       crystalReportViewer1.ReportSource = crModel.crSpecial; //กำหนด Reportsource ให้มีค่าเป็น crSpecial
    }
    private void SetValue(CRModel objCR, string rptType)
    {
       if(rptType == "normal")
       {
          cr = objCR.crNormal
       }
       else
       {
          cr = objCR.crSpecial
       }
    
       #Region Code ส่วนกำหนดค่าให้กับ cr 
    
          cr.DataDefinition.FormulaFields["ff1"].Text = "'123'";
          cr.DataDefinition.FormulaFields["ff2"].Text = "'456'";
    
       #endRegion
    }

    เพียงเท่านี้ก็จะสามารถจัดการ Code ที่ File เดียวได้แล้ว เย้!

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

  • Crystal Report : รูปที่ใส่ไป ทำไม size ถึงกลับไป(ใหญ่)เท่าเดิม

    เคยหรือไม่ ที่ใส่รูปลงไปในรายงาน จากนั้นหากต้องการ Config ค่าของรูปนั้น เมื่อจัดการเสร็จ กด OK ออกมา รูปที่ท่านใส่ไปนั้น กลับขยายกลายร่างกลับสู่ขนาดจริง

    ซึ่งบางครั้งหากท่านไม่ได้มีการย่อขนาดรูปให้ตรงตามที่ต้องการก่อนแต่ใช้วิธี Config ในส่วนของ Object Picture แทน ท่านอาจจะเจอปัญหานี้กันบ้าง

    วิธีแก้ไขง่ายมากๆๆๆๆๆๆๆ หลาย ๆ ท่านอาจจะคาดไม่ถึง หรือหลาย ๆ ท่านอาจจะรู้แล้ว แต่ผู้เขียนเพิ่งได้กลับมาจับ Crystal Report อีกครั้ง ได้เจอปัญหานี้เข้า เลยอยากมาแชร์ และเป็นการบันทึกไว้อ่านเองด้วย มาดูกันเลยค่ะว่า วิธีจัดการมีขั้นตอนอย่างไร ท่านผู้อ่านอย่าเพิ่งตกใจกับความง่ายยยยยยย นี้นะคะ ไปกันเล้ยยยยย ^^

    เมื่อท่านลาก Object Picture มาแล้ว ให้เลือก Menu Format Object ที่ ๆ ท่านเข้าไป Config รูปปกติค่ะ

    จากนั้นที่ Tab Picture เมื่อท่านตั้งค่าทุกอย่างเสร็จแล้วอย่าเพิ่งกดปุ่ม OK นะคะ เบรกก๊อนนน ><

    ให้สลับกลับไปที่ Tab Common ก่อนค่ะ

    สังเกตดี ๆ นะคะ ที่วงไว้สีแดง ๆ หนา ๆ ตัวนี้เลยค่ะ Can Grow เจ้าปัญหา ให้กลับมาดูก่อนนะคะ ว่ามีเครื่องหมายถูกอยู่ข้างหน้ารึเปล่า ถ้าไม่มี ไม่เป็นไรค่ะ นั่นคือสิ่งที่ถูกต้องแล้ว ให้กด OK ออกได้เล้ยยย แต่ถ้ามีเครื่องหมายถูกอยู่ เอาออกด่วน ๆๆๆๆ เลยค่ะ ไม่งั้น รูปที่ท่านใส่ไว้ ก็จะ Grow กลับสู่ขนาดดั้งเดิม ซึ่งหากท่านใส่ไว้แบบไม่ปรับขนาดมาก่อน แล้วมีขนาดใหญ่มาก ก็จะเป็นปัญหาได้ค่ะ

    หวังว่าจะเป็นประโยชน์ต่อผู้อ่านไม่มากก็น้อยนะคะ 🙂

  • Crystal Report : Term & Condition หรือ Privacy Policy ที่ต้องมีต่อท้ายรายงาน ทำได้อย่างไร

    หลาย ๆ ครั้งที่เราพิมพ์เอกสาร แล้วจำเป็นต้องมีเอกสารแนบท้ายกระดาษเป็นพวก Term & Condition หรือ Privacy Policy

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

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

    อ่ะ เรามาเริ่มกันเลย อันดับแรก เริ่มจากสร้างรายงานที่เป็นไฟล์เอกสารแนบท้าย สร้างและจัดรูปแบบให้เรียบร้อย เพราะต่อไปนี้ ไฟล์เอกสารแนบท้ายเหล่านี้ จะกลายไปเป็น Subreport ของรายงานหลัก โดยไปที่ส่วนของ Report Footer คลิกขวา เลือก Insert -> Subreport

    ระบบจะมีหน้าต่าง Subreport มาให้ระบุไฟล์ Crystal Report ที่ต้องการให้เป็น Subreport ซึ่งให้เลือกไฟล์ที่เราสร้างไว้

    จากนั้นจะได้ Subreport วางไว้ในส่วนของ Section Report Footer เรียบร้อย

    ขั้นตอนต่อไปเป็นการ Config ให้สามารถแสดง Subreport เป็นหน้าสุดท้ายโดย คลิกขวาที่แถบ Section เลือก Section Export ไปที่ Report Footer -> Tab Paging ให้ ทำเครื่องหมาย / หน้า New Page Before

    แต่เนื่องจากเราวาง Subreport ไว้ที่ Section Report Footer ทำให้เมื่อลอง Preview จะพบว่า หัวกระดาษและท้ายกระดาษส่วนอื่นแสดงด้วย ดังนั้นเราต้องมาจัดการในส่วนอื่น ๆ โดยเขียน Formula ใน Section อื่น ๆ ที่แสดงทุกหน้า เช่น Section Report Header, Section Page Header เป็นต้น ในที่นี้จะจัดการส่วน Section Page Header a จากนั้นทางขวา ในส่วนของ Suppress คลิกที่ x-2 เพื่อทำการเขียน Formula

    จะพบหน้าต่าง Formula จากนั้น เขียนคำสั่งดังภาพด้านล่าง ซึ่งเป็นคำสั่งตรวจสอบว่า ถ้าหน้าปัจจุบัน คือหน้าสุดท้าย ให้ทำการซ่อน Section Page Header จากนั้นกด Save and close เพื่อปิด และเขียนคำสั่งเดียวกันนี้ใน Section ส่วนอื่น ๆ ที่ต้องการซ่อนในหน้าสุดท้ายจนครบ

    จากนั้นทดลอง Run ดูจะพบว่า หน้าสุดท้ายที่ต้องการให้แสดง Term & Condition หรือ Privacy Policy จะไม่มี Section ส่วนอื่นมากวนใจ

    หวังว่าบทความนี้จะมีประโยชน์ต่อผู้อ่านไม่มากก็น้อยนะคะ 🙂

  • บันทึกหน้าจอคอมพิวเตอร์ด้วย Xbox Game Bar Hidden Feature บน Windows10

    ใครที่เครื่องคอมพิวเตอร์ของคุณใช้ Windows 10 และกำลังมองหาโปรแกรมที่จะบันทึกหน้าจอเป็นคลิป โดยที่ไม่อยากจะต้องหาโปรแกรมเสริมจากที่อื่น ซึ่งอาจจะต้องเสียเงิน หรือกินพื้นที่ของเครื่องแล้วละก็
    ใน Windows 10 มี Hidden Feature ที่ช่วยบันทึกหน้าจอคอมพิวเตอร์ของคุณขณะใช้งานได้ทันทีโดยไม่ต้องติดตั้งเพิ่มเติม ด้วย Xbox Game Bar

    Xbox Game Bar สร้างขึ้นใน Windows 10 เพื่อใช้จับภาพวิดีโอและภาพหน้าจอขณะเล่นเกมพีซีได้ แม้ว่าชื่อจะเหมือนทำมาเฉพาะสำหรับเกม แต่จริงๆแล้ว สามารถบันทึกได้หน้าจอคอมพิวเตอร์ของคุณเหมือนโปรแกรมบันทึกภาพทั่วไปเลย

    วิธีการบันทึก
    • กดปุ่ม Windows + G เพื่อเริ่มใช้งาน ซึ่งจะปรากฏแถบเครื่องมือต่าง ๆ ให้เลือกใช้งาน (สามารถกดจับภาพหน้าจอ, กดบันทึกวิดีโอหน้าจอ, กดเปิด-ปิดไมค์ และอื่นๆ ได้จากส่วนนี้)



    – Capture เอาไว้ใช้ในการกดบันทึกต่าง ๆ เช่น ถ่ายภาพ, บันทึกหน้าจอหรือปิดไมค์



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


    – Performance แสดงสถานะการใช้ทรัพยากรในเครื่องของคุณ


    สามารถกดบันทึกวิดีโอหรือจับภาพหน้าจอได้ที่แถบ Game Bar หรือกดคีย์ลัด ดังนี้
    • เริ่มต้น/หยุด การบันทึก (Start/stop recording)
    กดปุ่ม : Windows+Alt+R


    • จับภาพหน้าจอ (Take screenshot)
    กดปุ่ม Windows +Alt+Prtscn


    เปิด/ปิด ไมโครโฟน (Microphone on/off)
    กดปุ่ม Windows+Alt+M



    สำหรับไฟล์ที่บันทึกโดยปกติจะถูกเก็บไว้ที่ : C:\Users\USER\Videos\Captures

    คุณสามารถตรวจสอบเครื่องคอมพิวเตอร์ของคุณว่าได้เปิดใช้งานฟังก์ชัน Xbox Game Bar แล้วหรือไม่ โดยพิมพ์ Settings ตรงช่องค้นหาด้านซ้ายของหน้าจอ แล้วเลือกเมนู Settings และเลือก Gaming


    จะปรากฎหน้า Xbox Game Bar ให้ตรวจสอบว่า On ไว้หรือไม่ หากต้องการปิดการใช้งาน ก็สามารถ Off ไว้ได้
    หรือต้องการเปลี่ยน Key board Shortcut สำหรับการใช้งานฟังก์ชันนี้ ก็สามารถกำหนดเองได้จากหน้านี้เช่นกัน



    เมนู Captures ทางซ้าย ในส่วนนี้จะเป็นการกำหนดโฟลเดอร์ที่ต้องการจัดเก็บไฟล์วิดีโอที่อัดไว้


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

    ขอขอบคุณ : YouTube : Win G



  • ขยับแถว (row) ขึ้น/ลง ใน ASP.NET Gridview ด้วย Code Behind

    เช่นเคยครับ จากบล็อก ขยับแถว (row) ขึ้น/ลง ใน ASP.NET Gridview ด้วย jQuery เป็นการเพิ่มฟีเจอร์ให้กับ ASP.NET Gridview ด้วยการประยุกต์ใช้ jQuery บทความต่อมา ก็จะเป็นการเพิ่มฟีเจอร์เดียวกัน แต่จะเป็นการพัฒนาด้วยโค้ดฝั่ง code behind

    เนื่องจากการทำงานฝั่ง code behind จะไม่สามารถเคลื่อนย้ายเร็คคอร์ดของ gridview ได้โดยตรง ดังนั้นเราจะทำทางอ้อม ด้วยการใช้ฟิลด์ในตารางฟิลด์หนึ่งมาเป็นข้อมูลสำหรับเรียงใน Gridview เมื่อต้องการย้ายเร็คคอร์ด เราก็จะเปลี่ยนตัวเลขในฟิลด์นี้ แล้วทำการเรียงข้อมูลใหม่ และแสดงผลข้อมูลใน Gridview อีกครั้ง ไปดูขั้นตอนต่างๆ กันเลยครับ

    1. ในส่วนของโค้ด HTML จะมีการปรับปรุงเพิ่มเล็กน้อยเฉพาะในส่วนของปุ่ม UP/DOWN ซึ่งเราจะเปลี่ยนไปใช้ปุ่มที่เป็นคอนโทรลของ ASP.NET เพื่อให้สามารถเขียนโปรแกรมควบคุมจากฝั่ง code behind ได้

    <asp:GridView ID="gvBib" runat="server" AutoGenerateColumns="False" OnRowCommand="gvBib_RowCommand" >
        <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" />
            <asp:TemplateField>
                <ItemTemplate>
                    <asp:Button ID="btnUp" runat="server" Text="UP" CommandName="up" CommandArgument="<%# ((GridViewRow) Container).RowIndex %>"></asp:Button>
                    <asp:Button ID="btnDown" runat="server" Text="DOWN" CommandName="down" CommandArgument="<%# ((GridViewRow) Container).RowIndex %>"></asp:Button>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

    โดย

    • CommndName ใช้สำหรับตรวจสอบว่าเป็นการเลือก up หรือ down
    • CommandArgument ใช้สำหรับระบุแถวที่คลิกเลือก

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

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

    3. เพิ่มโค้ดในส่วนของ gvBib_RowCommand ซึ่งเป็น event ที่จะเกิดเมื่อมีการคลิกปุ่ม UP หรือ DOWN

    protected void gvBib_RowCommand(object sender, GridViewCommandEventArgs e)
    {
    	DataTable dt = (DataTable)ViewState["dtBook"];
    
            //เก็บแถวที่คลิกเลือก
    	int curIdx = Convert.ToInt32(e.CommandArgument);
    
    	if(e.CommandName == "up")   //ถ้ากดปุ่ม UP
    	{
    		//กำหนดลำดับใหม่ให้กับแถวก่อนหน้ากับแถวปัจจุบันให้สลับกัน
    		dt.Rows[curIdx - 1]["SEQ"] = curIdx;
    		dt.Rows[curIdx]["SEQ"] = curIdx - 1;
    	}
    	else if (e.CommandName == "down")   //ถ้ากดปุ่ม DOWN
    	{
    		//กำหนดลำดับใหม่ให้กับแถวถัดไปกับแถวปัจจุบันให้สลับกัน
    		dt.Rows[curIdx + 1]["SEQ"] = curIdx;
    		dt.Rows[curIdx]["SEQ"] = curIdx + 1;
    	}
    	dt.AcceptChanges();
    
    	//กำหนดให้ข้อมูลเรียงตามฟิลด์ SEQ
    	dt.DefaultView.Sort = "SEQ";
    
    	//เซ็ตข้อมูลที่มีการเรียงลำกับแล้วกลับไปให้ DataTable
    	dt = dt.DefaultView.ToTable();
    
    	//กำหนดข้อมูลที่เรียงลำดับใหม่แล้วให้กับ Gridview และแสดผล
    	gvBib.DataSource = dt;
    	gvBib.DataBind();
    
    	//เก็บข้อมูลกลับเข้า ViewState
    	ViewState["dtBook"] = dt;
    }

    เมื่อทดลองรัน จะปรากฏผลลัพธ์ดังรูปด้านล่าง

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

    และ
    ซึ่งเกิดจากการเลื่อนไปยังตำแหน่งที่ไม่มีในข้อมูล จึงจะต้องปรับแก้โค้ดอีกเล็กน้อยดังนี้
    //เก็บแถวที่คลิกเลือก
    int curIdx = Convert.ToInt32(e.CommandArgument);
    
    if(e.CommandName == "up")   //ถ้ากดปุ่ม UP
    {
        //ตรวจสอบว่าไม่ใช่แถวแรกหรือไม่
        if (curIdx != 0)
        {
            //กำหนดลำดับใหม่ให้กับแถวก่อนหน้ากับแถวปัจจุบันให้สลับกัน
            dt.Rows[curIdx - 1]["SEQ"] = curIdx;
            dt.Rows[curIdx]["SEQ"] = curIdx - 1;
        }
    }
    else if (e.CommandName == "down")   //ถ้ากดปุ่ม DOWN
    {
        //ตรวจสอบว่าไม่ใช่แถวสุดท้ายหรือไม่
        if (curIdx != dt.Rows.Count - 1)
        {
            //กำหนดลำดับใหม่ให้กับแถวถัดไปกับแถวปัจจุบันให้สลับกัน
            dt.Rows[curIdx + 1]["SEQ"] = curIdx;
            dt.Rows[curIdx]["SEQ"] = curIdx + 1;
        }
    }

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

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

    จนกว่าจะพบกันใหม่ สวัสดีครับ


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

  • สร้างไฟล์ PDF จาก HTML + CSS ด้วย iText7.pdfhtml (C#)

    การพัฒนา Web Application หลายครั้งที่จะมีความต้องการจาก User ให้พัฒนาระบบที่สามารถนำข้อมูลจากฐานข้อมูลมาออกรายงาน หรือบันทึกในรูปแบบ PDF ได้ ระบบที่กำลังพัฒนาอยู่ขณะนี้ก็เช่นเดียวกัน มีความต้องการให้สร้าง E-Form บันทึกข้อมูลในฐานข้อมูล และสร้างไฟล์ PDF ที่มีการจัดรูปแบบเป็นหนังสือราชการ ได้แก่ บันทึกข้อความ ประกาศ ระเบียบ คำสั่ง เป็นต้น จากนั้นจึงนำไฟล์ PDF ที่ได้ไปใช้ลงนามด้วย Digital Signature และดำเนินการอื่นๆ ต่อได้

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

    จากการศึกษาและลองผิดลองถูกก็ได้แนวทางในการพัฒนาดังนี้

    1. สร้างไฟล์ HTML และจัดรูปแบบแสดงผลข้อมูลด้วย CSS ให้เหมือนกระดาษ
    2. ใช้ Add-on ของ iText7 ชื่อ iText7.pdfhtml ช่วยแปลงจาก HTML เป็น PDF
    3. บันทึกไฟล์ PDF บนเซิร์ฟเวอร์ หรือแสดงผลผ่าน Browser

    ตัวอย่างการพัฒนาด้วย Blazor Server Application

    1. เปิด Visual Studio 2019 และสร้าง Project ใหม่ เลือก Blazor Server App คลิก Next ระบุโฟลเดอร์บันทึก Project จากนั้น ระบุ Target Framework เป็น .NET 5.0 คลิก Create
    1. ติดตั้ง Add-on ชื่อ itext7.pdfhtml จาก NuGet โดยไปที่เมนู Project -> Manage NuGet Packages
    2. คลิก Browse และค้นหา itext7.pdfhtml เลือกเวอร์ชั่นล่าสุด (3.0.4) และคลิก Install
    1. สร้างไฟล์ HTML จัดรูปแบบข้อมูลด้วย CSS เก็บไว้ในโฟลเดอร์ wwwroot ในที่นี้สร้างไฟล์ชื่อ doc1.html และระบุ style sheet ไว้ในโฟลเดอร์ css
    1. เปิดไฟล์ Pages/Index.razor เขียนโค้ดดังนี้
      5.1 @using iText.Html2pdf
      เพื่อให้สามารถเรียกใช้งาน Ad-on ได้
      5.2 @using System.IO
      เพื่อให้สามารถเขียนไฟล์ได้
      5.3 กำหนด onclick event ของปุ่ม ให้ทำฟังก์ชั่น CreatePDF
      5.4 public static string SRC = $”{BASEURI}doc1.html”;
      ระบุไฟล์ HTML ต้นทางที่ต้องการแปลงเป็น PDF
      5.5 public static string DEST = $”{TARGET}doc1.pdf”;
      ระบุไฟล์ pdf บันทึกผลลัพธ์ของการแปลงไฟล์
      5.6 HtmlConverter.ConvertToPdf(new FileInfo(SRC), new FileInfo(DEST), properties);
      แปลงไฟล์ HTML เป็น PDF
    1. คลิก รัน หรือกด F5 จะได้หน้าจอดังรูป
    1. คลิก Create PDF ระบบจะสร้างไฟล์ชื่อ doc1.pdf ดังรูป

    เพียงเท่านี้ก็จะได้ผลลัพธ์ไฟล์ PDF แล้ว แต่จากการใช้งานพบว่า ยังมีข้อจำกัดในส่วนของการจัดรูปแบบข้อความภาษาไทยแบบ Justify ยังไม่สวยงามเท่าที่ควร