Hàm đọc số bằng chữ bằng Javascript

Khi lập trình có liên quan đến số liệu phải tính toán và yêu cầu phải đọc được số thành chữ như đọc tiền thành chữ. Bạn có thể dùng ngôn ngữ lập trình như C#, VB, hay php để thực hiện, Ở bài này mình sẽ viết hàm đọc số thành chữ bằng javascript

Khi bạn dùng javascript bạn sẽ hạn chế được việt dùng AutoPostback của trang. Và nếu chương trình có yêu cầu chỉ dùng các phím số và phím Enter để tính toán, khi nhập xong ở 1 ô con trỏ sẽ tự động sang ô kế tiếp và đọc tiền bằng chữ cho dữ liệu vừa nhập. Giải pháp tốt nhất là dùng Javascript.

Bài viết sau sẽ mô tả việc ứng dụng của hàm đọc số thành chữ trong javascript
Tương tự bạn hoàn toàn có thể sử dụng thuật toán này để đọc số bằng các ngôn ngữ lập trình khác nhau. Mình cũng đã viết hàm tương ứng bằng C#

Bạn thực hiện hàm như sau:

var ChuSo=new Array(" không "," một "," hai "," ba "," bốn "," năm "," sáu "," bảy "," tám "," chín ");
var Tien=new Array( "", " nghìn", " triệu", " tỷ", " nghìn tỷ", " triệu tỷ");

//1. Hàm đọc số có ba chữ số;
function DocSo3ChuSo(baso)
{
    var tram;
    var chuc;
    var donvi;
    var KetQua="";
    tram=parseInt(baso/100);
    chuc=parseInt((baso%100)/10);
    donvi=baso%10;
    if(tram==0 && chuc==0 && donvi==0) return "";
    if(tram!=0)
    {
        KetQua += ChuSo[tram] + " trăm ";
        if ((chuc == 0) && (donvi != 0)) KetQua += " linh ";
    }
    if ((chuc != 0) && (chuc != 1))
    {
            KetQua += ChuSo[chuc] + " mươi";
            if ((chuc == 0) && (donvi != 0)) KetQua = KetQua + " linh ";
    }
    if (chuc == 1) KetQua += " mười ";
    switch (donvi)
    {
        case 1:
            if ((chuc != 0) && (chuc != 1))
            {
                KetQua += " mốt ";
            }
            else
            {
                KetQua += ChuSo[donvi];
            }
            break;
        case 5:
            if (chuc == 0)
            {
                KetQua += ChuSo[donvi];
            }
            else
            {
                KetQua += " lăm ";
            }
            break;
        default:
            if (donvi != 0)
            {
                KetQua += ChuSo[donvi];
            }
            break;
        }
    return KetQua;
}

//2. Hàm đọc số thành chữ (Sử dụng hàm đọc số có ba chữ số)

function DocTienBangChu(SoTien)
{
    var lan=0;
    var i=0;
    var so=0;
    var KetQua="";
    var tmp="";
    var ViTri = new Array();
    if(SoTien<0) return "Số tiền âm !";
    if(SoTien==0) return "Không đồng !";
    if(SoTien>0)
    {
        so=SoTien;
    }
    else
    {
        so = -SoTien;
    }
    if (SoTien > 8999999999999999)
    {
        //SoTien = 0;
        return "Số quá lớn!";
    }
    ViTri[5] = Math.floor(so / 1000000000000000);
    if(isNaN(ViTri[5]))
        ViTri[5] = "0";
    so = so - parseFloat(ViTri[5].toString()) * 1000000000000000;
    ViTri[4] = Math.floor(so / 1000000000000);
     if(isNaN(ViTri[4]))
        ViTri[4] = "0";
    so = so - parseFloat(ViTri[4].toString()) * 1000000000000;
    ViTri[3] = Math.floor(so / 1000000000);
     if(isNaN(ViTri[3]))
        ViTri[3] = "0";
    so = so - parseFloat(ViTri[3].toString()) * 1000000000;
    ViTri[2] = parseInt(so / 1000000);
     if(isNaN(ViTri[2]))
        ViTri[2] = "0";
    ViTri[1] = parseInt((so % 1000000) / 1000);
     if(isNaN(ViTri[1]))
        ViTri[1] = "0";
    ViTri[0] = parseInt(so % 1000);
  if(isNaN(ViTri[0]))
        ViTri[0] = "0";
    if (ViTri[5] > 0)
    {
        lan = 5;
    }
    else if (ViTri[4] > 0)
    {
        lan = 4;
    }
    else if (ViTri[3] > 0)
    {
        lan = 3;
    }
    else if (ViTri[2] > 0)
    {
        lan = 2;
    }
    else if (ViTri[1] > 0)
    {
        lan = 1;
    }
    else
    {
        lan = 0;
    }
    for (i = lan; i >= 0; i--)
    {
       tmp = DocSo3ChuSo(ViTri[i]);
       KetQua += tmp;
       if (ViTri[i] > 0) KetQua += Tien[i];
       if ((i > 0) && (tmp.length > 0)) KetQua += ',';//&& (!string.IsNullOrEmpty(tmp))
    }
   if (KetQua.substring(KetQua.length - 1) == ',')
   {
        KetQua = KetQua.substring(0, KetQua.length - 1);
   }
   KetQua = KetQua.substring(1,2).toUpperCase()+ KetQua.substring(2);
   return KetQua;//.substring(0, 1);//.toUpperCase();// + KetQua.substring(1);
}

 

Lập trình với SQL ::Tính tổng

Bài này mình hướng dẫn bạn lập trình bằng SQL sử dụng vòng lặp. Mô tả bằng việc tính tổng của n số nguyên

Mình đã đọc trên các diễn đàn và có nhiều bạn chưa biết dùng vòng lặp trong SQL. Ở đây mình sử dụng SQL dùng vòng lặp để tính tổng của n số nguyên.
Nếu bạn đã từng học lập trình chắc bạn đã làm bài tập tính tổng của n số bằng ngôn ngữ cơ bản như Pascal, C, ... Giải thuật của bài này thì không có gì để bàn vì nó dễ.
Cách  thực hiện trong SQL như sau:

-- =============================================
-- Author:        webmaster@hmweb.com.vn
-- Description:   <Tínt tổng>
-- =============================================

 CREATE FUNCTION [dbo].[fuTinhTong]
(
      @n int
)
RETURNS bigint
AS
BEGIN
      DECLARE @i int
      SET @i=0
      DECLARE @Tong bigint
      SET @Tong=0
        -- Dùng vòng lặp
      WHILE @i<=@n
      BEGIN
            SET @Tong = @Tong+@i 
            SET @i=@i+1
      END
      RETURN  @Tong
END
Bạn chạy thử hàm trên như sau:
SELECT dbo.fuTinhTong(20) AS Tong20 -->210
SELECT dbo.fuTinhTong(10) AS Tong20 -->55
Áp dụng bài này: Trong bài viết trước mình đã viết hàm Tính số ngày trong tháng; Khi bạn cần tính số liệu thống kê theo tháng bạn có thể thực hiện như mô tả dưới đây
DECLARE @DayOfMonth int
SET @DayOfMonth = dbo.DaysInMonth(@Thang,@nam)
IF @DayOfMonth IS NULL SET @DayOfMonth=0
DECLARE @i int
SET @i=1
WHILE @i<=@DayOfMonth
BEGIN
      -- {Khối lệnh cần tính toán}
      SET @i=@i+1
END

Lập trình với SQL : Phương trình bậc 2

Bài này mình hướng dẫn bạn lập trình bằng SQL; mô tả bằng việc giải phương trình bậc 2 trong SQL. Đây không phải là bài toán khó nhưng cái mình muốn giới thiệu đó là cách dùng ngôn ngữ SQL để lập trình.

Bạn đã quen với phương trình bậc 2  ax2+bx+c=0 với thuật giải:

Nếu a=0
    Không phải bậc 2
Nếu a>0
    Tình delta=b2-4*a*c
    Nếu delta>0
        Phương trình có 2 nghiệm, x1,x2
    Nếu delta=0
        Phương trình có nghiệm kép x=...
    Nếu delta<0
        Phương trình vô nghiệm

Thuật toán thì dễ nhưng có thể có nhiều bạn chưa biết lập trình trong SQL.

-- =============================================
-- Author:        webmaster@hmweb.com.vn
-- Description:   <Giải PT bậc 2>
-- =============================================

CREATE FUNCTION fuPhuongTrinhBac2
(
      @a decimal(18,2),
      @b decimal(18,2),
      @c decimal(18,2)
)
RETURNS nvarchar(2000)
AS
BEGIN
      DECLARE @delta decimal(18,2)
      SET @delta=0.00
      DECLARE @Result nvarchar(2000)
      SET @Result=''
      IF @a=0
            SET @Result=N'Phương trình không phải bậc 2'
      ELSE
      BEGIN
           SET @delta=@b*@b-4*@a*@c
           IF @delta>0
           BEGIN
                SET @Result=@Result+ N'Phương trình có 2 nghiệm:
                x1='+ Cast(((-@b)+SQRT(@delta))/(2*@a) AS nvarchar(300))+';'
                SET @Result=@Result+ N'
                x2='+ Cast(((-@b)-SQRT(@delta))/(2*@a) AS nvarchar(300))+''
           END
           IF @delta=0
           BEGIN
                SET @Result=@Result+ N'Phương trình có nghiệm kép
                x ='+ Cast( ((-@b)/(2*@a)) AS nvarchar(300))+';'
           END
           IF @delta<0
               SET @Result=@Result+ N'Phương trình vô nghiệm'
            END
      RETURN @Result
END
Bạn chạy thử hàm trên với lệnh:
SELECT dbo.fuPhuongTrinhBac2 (1,4,-3) AS PTB2  
--Phương trình có 2 nghiệm: x1=0.645751; x2=-4.64575
SELECT dbo.fuPhuongTrinhBac2 (1,2,-3) AS PTB2  
-- Phương trình có 2 nghiệm: x1=1; x2=-3
SELECT dbo.fuPhuongTrinhBac2 (1,4,0) AS PTB2   
-- Phương trình có 2 nghiệm: x1=0; x2=-4

Select dữ liệu từ database ra SiteMapNode

Trong bài viết Xây dựng Menu đa cấp với Multi Sitemap mình có hướng dẫn cách tạo menu đa cấp với MultiSitemap với dữ liệu từ file.sitemap có sẵn. Bài này mình sẽ viết hàm trong SQL để lấy dữ liệu từ database dưới dạng SiteMapNode để sử dụng tạo menu đa cấp

Thường việc này bạn có thể dùng code asp.net (C# hay VB) để thực hiện bằng vòng lặp hoặc sử dụng System.Xml - XmlTextWriter để thực hiện. Nhưng bạn cũng có thể sử dụng vòng lặp trong SQL để thực hiện việc này. Ở đây mình viết hàm trong SQL kết quả trả về là nội dung của file MenuTop.sitemap. Hàm này lấy đến menu cấp 3. nếu dự án của bạn có nhiều hơn 3 cấp bạn hãy sửa lại hàm cho phù hợp

Bạn chạy hàm sau trong SQL

-- =============================================
-- Author:        webmaster@hmweb.com.vn
-- Description:   <Get Sitemap content>
-- =============================================
ALTER   FUNCTION [dbo].[fuGetTreeNodeMap]
(
)
RETURNS NVarChar(4000)
AS 
BEGIN
DECLARE @SQL nvarchar(4000)
SET @SQL=''
-- Khai báo mở sitemap
SET @SQL=@SQL+N'<?xml version="1.0" encoding="utf-8" ?>
<siteMap>'
-- Duyệt cây cấp 1 (Có Decen=0)
DECLARE @CateID int, @CateName nvarchar(200), @Link nvarchar(200)
Declare CursorCategory Cursor For SELECT CateID, CateName, Link FROM TBCategory WHERE Decen=0
Open CursorCategory
Fetch next from CursorCategory INTO @CateID, @CateName , @Link
while @@FetchStatus =0
BEGIN
-- Nếu cây cấp 1 không có con thì đóng luôn TreeNode
IF dbo.fuCountSubMenu(@CateID)=0
BEGIN
      SET @SQL=@SQL+ '
      <siteMapNode url="'+dbo.ufDomainName() + @Link + '" title="' + @CateName + '" />'
END
-- Nếu cây cấp 1 có con thì mở TreeNote và tiếp tục duyệt cây cấp 2
      ELSE
      BEGIN
            SET @SQL=@SQL+ '
            <siteMapNode url="'+dbo.ufDomainName() + @Link + '" title="' + @CateName + '" >'
            -- Duyệt cây cấp 2
                  DECLARE @CateID2 int, @CateName2 nvarchar(200), @Link2 nvarchar(200)
                  Declare CursorCategory2 Cursor For SELECT CateID, CateName, Link FROM TBCategory WHERE Decen=1 AND  ParentID=@CateID
                  Open CursorCategory2
                  Fetch next from CursorCategory2 INTO @CateID2, @CateName2 , @Link2
                  WHILE @@FETCHSTATUS=0
                  BEGIN
                        -- Nếu cây cấp 2 không có con thì đóng luôn TreeNode
                        IF dbo.fuCountSubMenu(@CateID2)=0
                              BEGIN
                                    SET @SQL=@SQL+ '<siteMapNode url="'+dbo.ufDomainName() + @Link2 + '" title="' + @CateName2 + '" />'
                              END
                        -- Nếu cây cấp 2 có con thì mở TreeNode và tiếp tục duyệt cây cấp 3
                        ELSE
                              BEGIN
                              SET @SQL=@SQL+ '
                                    <siteMapNode url="'+dbo.ufDomainName() + @Link2 + '" title="' + @CateName2 + '" >'
                                    -- Duyệt cây cấp 3
                                    DECLARE @CateID3 int, @CateName3 nvarchar(200), @Link3 nvarchar(200)
                                    Declare CursorCategory3 Cursor For SELECT CateID, CateName, Link FROM TBCategory WHERE Decen=2 AND ParentID=@CateID2
                                    Open CursorCategory3
                                    Fetch next from CursorCategory3 INTO @CateID3, @CateName3 , @Link3
                                    WHILE @@FETCHSTATUS=0
                                          BEGIN
                                                SET @SQL=@SQL+ '
                                                <siteMapNode url="'+dbo.ufDomainName() + @Link3 + '" title="' + @CateName3 + '" />'
                                          FETCH NEXT FROM CursorCategory3 INTO @CateID3, @CateName3 , @Link3
                                          END
                                    Close CursorCategory3
                                    DEALLOCATE CursorCategory3
                                    SET @SQL=@SQL+ '</siteMapNode>'
                              END
                        FETCH NEXT FROM CursorCategory2 INTO @CateID2, @CateName2 , @Link2
                  END
                  Close CursorCategory2
                  DEALLOCATE CursorCategory2
                  SET @SQL=@SQL+ '</siteMapNode>'
            END
FETCH NEXT FROM CursorCategory INTO @CateID, @CateName , @Link
END
Close CursorCategory
DEALLOCATE CursorCategory
--Đóng sitemap
SET @SQL=@SQL+'
</siteMap>'
-- Print @SQL
RETURN  @SQL
END

Nếu bảng TBCategory của bạn có nhiều bản ghi thì độ dài chuỗi @SQL có thể quá 4000. Khi đó bạn cần phân tách và ghép chuỗi lại

Kết quả hàm trên (hoặc bạn thử bằng lệnh Print @SQL) như sau (Bạn có thể copy vào visual studio để xem đúng cấu trúc)

<?xml version="1.0" encoding="utf-8" ?>
<siteMap>
  <siteMapNode url="http://www.hmweb.com.vn" title="Thể thao" >
    <siteMapNode url="http://www.hmweb.com.vn" title="Pháp luật" />
    <siteMapNode url="http://www.hmweb.com.vn" title="Môi trường" />
  </siteMapNode>
  <siteMapNode url="http://www.hmweb.com.vn" title="Thể thao" >
    <siteMapNode url="http://www.hmweb.com.vn" title="Bóng đá" >
      <siteMapNode url="http://www.hmweb.com.vn" title="Bóng đá trong nước" />
      <siteMapNode url="http://www.hmweb.com.vn" title="Bóng đá Anh" />
      <siteMapNode url="http://www.hmweb.com.vn" title="Bóng đá TBN" />
      <siteMapNode url="http://www.hmweb.com.vn" title="Bóng đá Ý" />
    </siteMapNode>
    <siteMapNode url="http://www.hmweb.com.vn" title="Quần vợt" />
  </siteMapNode>
  <siteMapNode url="http://www.hmweb.com.vn" title="Sức khỏe" />
  <siteMapNode url="http://www.hmweb.com.vn" title="Kinh doanh" >
    <siteMapNode url="http://www.hmweb.com.vn" title="Chứng khoán" />
    <siteMapNode url="http://www.hmweb.com.vn" title="Thị trường" />
    <siteMapNode url="http://www.hmweb.com.vn" title="Doanh nghiệp" />
  </siteMapNode>
  <siteMapNode url="http://www.hmweb.com.vn" title="Giải trí" />
</siteMap>

Khi đã có dữ liệu hàm trên rồi bạn có thể chạy thử bằng câu lệnh SELECT dbo.fuGetTreeNode_Map() để xem kết quả.
Từ kết quả trên để đưa ra file.sitemap bạn chỉ cần viết 1 hàm (C#) write ra file với phát biểu Select là xong.

Có thời gian mình sẽ hướng dẫn dùng asp.net để bind dữ liệu thàng sitemap

Chúc các bạn thành công

Xây dựng Menu đa cấp với Multi Sitemap

Để tránh việc trình duyệt phải quay lại server và lấy dữ liệu từ database quá nhiều chúng ta có thể xây dựng menu đa cấp bằng cách dùng asp:Menu  sử dụng Site Map file. Bạn hãy xây dựng cho mình 1 control để sử dụng được nhiều Site map trong website của bạn. Mình sẽ hướng dẫn các bạn xây dựng để có thể sử dụng Menu đa cấp với MultiSitemap
1. Xây dựng Control menu
Bạn hãy tạo một thư mục Controls (Bạn có thể không cần tạo thư mục nhưng theo mình thì bạn nên tạo vì trong dự án của mình có thể có nhiều controls) sau đó nhấn phải chuột vào thư mục này, Chon Add New Item… tiếp theo chọn Web User Control đặt tên cho Control của bạn (ucMenuMultiSitemap.ascx)

Nội dung trong file Control (ucMenuMultiSitemap.ascx) như sau:

<asp:Menu 
    id="mnMainMeNu" 
    runat="server" 
    StaticEnableDefaultPopOutImage="False" 
    Orientation="Horizontal" 
    Height="20px"
    EnableTheming="True"
    DynamicVerticalOffset="0" 
    DynamicHorizontalOffset="0">
    <StaticMenuStyle 
        BorderStyle="Outset" 
        BorderWidth="0px" 
        CssClass="IE8Fix" 
        Height="23px"  />
    <StaticMenuItemStyle 
        CssClass="IE8Fix" 
        ForeColor="Black" 
        Height="20px"
        HorizontalPadding="7px"  />
    <DynamicMenuStyle 
        BorderStyle="Outset" 
        BorderWidth="1px" 
        CssClass="IE8Fix"  />
    <DynamicMenuItemStyle 
        CssClass="IE8Fix" 
        ForeColor="Black"
        Height="21px" 
        HorizontalPadding="7px" 
        Width="150px"  />
    <DynamicHoverStyle 
        BackColor="SteelBlue" 
        CssClass="IE8Fix" 
        ForeColor="White" 
        Height="20px"  />
    <StaticHoverStyle 
        BackColor="SteelBlue" 
        CssClass="IE8Fix" 
        ForeColor="White"  />
    <DataBindings> 
        <asp:MenuItemBinding
            DataMember="siteMapNode" 
            TextField="title"  
            NavigateUrlField="url"  /> 
    </DataBindings>
</asp:Menu>

Trong file code C# (ucMenuMultiSitemap.ascx.cs) bạn viết như sau.

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class Controls_ucMenuMultiSitemap : System.Web.UI.UserControl
{
    /// <summary>
    /// Định nghĩa các loại menu
    /// </summary>
    public enum MenuSitemap
    {
        TopMenu, BottomMenu, NotSet, LeftMenu, RightMenu
    }
    MenuSitemap eMenuToLoad = MenuSitemap.NotSet;
    public MenuSitemap MenuToLoad
    {
        get { return eMenuToLoad; }
        set { eMenuToLoad = value; }
    }
    protected void Page_Load(object sender, EventArgs e)
    {
        mnMainMeNu.DataSource = GetMenuDataSource(eMenuToLoad, Server.MapPath("~"));
        mnMainMeNu.DataBind();
    }
    /// <summary>
    /// Lấy menu theo tùy chọn menu và tên file sitemap
    /// </summary>
    XmlDataSource GetMenuDataSource(MenuSitemap menu, string serverMapPath)
    {
        XmlDataSource objData = new XmlDataSource();
        objData.XPath = "siteMap/siteMapNode";
        switch (menu)
        {
            case MenuSitemap.TopMenu:
                objData.DataFile = serverMapPath + @"\App_Data\MenuTop.sitemap";
                break;
            case MenuSitemap.BottomMenu:
                objData.DataFile = serverMapPath + @"\App_Data\MenuBottom.sitemap";
                break;
            case MenuSitemap.LeftMenu:
                objData.DataFile = serverMapPath + @"\App_Data\MenuLeft.sitemap";
                break;
            case MenuSitemap.RightMenu:
                objData.DataFile = serverMapPath + @"\App_Data\MenuRight.sitemap";
                break;
            default:
                break;
        }
        objData.DataBind();
        return objData;
    }
}

Vậy là xong phần xây dựng Control menu

2. Sử dụng Control menu

Để sử dụng Control này trước tiên bạn cần khai báo như sau (Đặt trên thẻ <!DOCTYPE)

<%@ Register TagPrefix="hmwebmenu" TagName="MyMenu" Src="~/Controls/ucMenuMultiSitemap.ascx" %>

Sau đó trong nội dung nơi mà bạn muốn đặt menu của bạn, bạn chỉ cần sử dụng thẻ menu như sau:

<hmwebmenu:MyMenu ID="MyMenu1" runat="server" MenuToLoad="BottomMenu" />
<%--Trong thẻ trên bạn chọn MenuToload=”BottomMenu” là để menu của bạn đọc nội dung từ file MenuBottom.sitemap được khai báo trong hàm GetMenuDataSource, Nếu không muốn khai báo trong trang aspx, bạn có thể dùng codebehind để thực hiện --%>

Kết quả khi chạy như sau:

Bạn cần chú ý trong thẻ <style> bạn cần có IE8Fix để sử dụng trong menu nếu không với trình duyệt IE8 sẽ không chạy được với asp:menu.

<style>
.IE8Fix
{
    z-index: 1000;
}
</style>

Bạn có thể download source về và chạy thử. 

MultiSitemapMenu.rar (4,18 kb)

Bạn có thể thắc mắc khi lấy nội dung từ database để tạo menu đa cấp. Việc đó cũng không khó khăn. ở bài sau mình sẽ hướng dẫn cách bind dữ liệu từ database ra file.sitemap. Bạn xem hàm viết bằng SQL

Mở rộng bài này bạn có thể thực hiện việc phân quền cho ứng dụng. Ví dụ ứng dụng của bạn có 2 mức quyền là admin và User khi đó bạn cần tạo 2 file admin.sitemap và user.sitemap, còn việc phân quyền đề khi nào thì gọi các file tương ứng thì cũng không có gì khó khăn

Chúc các bạn thành công!