首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 金額大小寫轉換:阿拉伯數字轉中文大寫金額 (壹貳叁肆伍陸柒捌玖) 完整函數

     編輯:Delphi

前言

財務系統、發票列印、支票列印常需將阿拉伯數字金額轉為中文大寫 (「壹佰貳拾叁元整」)。本文提供完整的 DecimalToChineseCurrency 函數,支援整數、小數 (角/分)、大數值 (萬/億/兆)、零值壓縮 (「零零」→「零」)、單位重疊修正 (「零億」→「億」)。

核心轉換函數

function DecimalToChineseCurrency(const Decimal: string): string;
var
  NumMap, UnitMap: TStringList;
  I, DotPos, UnitIdx: Integer;
  CleanStr: string;
  HasDecimal: Boolean;
begin
  Result := Decimal; // 預設回傳原值 (格式錯誤時)
  HasDecimal := False;
  DotPos := 0;
  
  // 1. 輸入驗證:僅允許數字與單一小數點
  for I := 1 to Length(Decimal) do
  begin
    if Decimal[I] = '.' then
    begin
      if HasDecimal then Exit; // 多個小數點
      HasDecimal := True;
      DotPos := I;
    end
    else if not (Decimal[I] in ['0'..'9']) then
      Exit; // 非法字元
  end;
  
  // 2. 統一處理:補齊小數點位置
  CleanStr := Decimal;
  if not HasDecimal then
  begin
    CleanStr := CleanStr + '.';
    DotPos := Length(CleanStr);
  end;
  
  // 移除小數點,純數字字串
  CleanStr := StringReplace(CleanStr, '.', '', [rfReplaceAll]);
  
  // 3. 數字與單位映射表
  NumMap := TStringList.Create;
  UnitMap := TStringList.Create;
  try
    NumMap.Delimiter := ',';
    UnitMap.Delimiter := ',';
    
    // 數字映射:0=零, 1=壹, 2=貳, 3=叁, 4=肆, 5=伍, 6=陸, 7=柒, 8=捌, 9=玖
    NumMap.CommaText := '0=零,1=壹,2=貳,3=叁,4=肆,5=伍,6=陸,7=柒,8=捌,9=玖';
    
    // 單位映射:從個位開始 (索引對應位數)
    // -1=分, 0=角, 1=元, 2=拾, 3=佰, 4=仟, 5=萬, 6=拾, 7=佰, 8=仟, 9=億, 10=拾, 11=佰, 12=仟, 13=兆...
    UnitMap.CommaText := 
      '-1=分,0=角,1=元,2=拾,3=佰,4=仟,5=萬,6=拾,7=佰,8=仟,9=億,10=拾,11=佰,12=仟,13=兆,14=拾,15=佰,16=仟';
    
    // 4. 從低位向高位處理 (個位索引 1 對應 CleanStr 最後一字元)
    Result := '';
    for I := 1 to Length(CleanStr) do
    begin
      var Digit := CleanStr[Length(CleanStr) - I + 1]; // 取對應數字字元
      UnitIdx := I - DotPos; // 單位索引:個位=1, 十位=2... 小數點左側為正
      
      if Digit = '0' then
      begin
        // 零處理:四捨五入單位 (萬/億/兆/元) 保留單位,其他省略
        if (UnitIdx mod 4 = 1) then // 元、萬、億、兆 位
          Result := UnitMap.Values[IntToStr(UnitIdx)] + Result
        else
          Result := NumMap.Values['0'] + Result; // 普通零
      end
      else
      begin
        // 非零:數字 + 單位
        Result := NumMap.Values[Digit] + UnitMap.Values[IntToStr(UnitIdx)] + Result;
      end;
    end;
    
    // 5. 後處理:零值壓縮與單位修正
    // 連續零合併
    while Pos('零零', Result) > 0 do
      Result := StringReplace(Result, '零零', '零', [rfReplaceAll]);
    
    // 高階單位前的零移除
    Result := StringReplace(Result, '零兆', '兆', [rfReplaceAll]);
    Result := StringReplace(Result, '零億', '億', [rfReplaceAll]);
    Result := StringReplace(Result, '零萬', '萬', [rfReplaceAll]);
    Result := StringReplace(Result, '零元', '元', [rfReplaceAll]);
    
    // 單位重疊修正 (如 萬億 → 億)
    Result := StringReplace(Result, '兆億', '兆', [rfReplaceAll]);
    Result := StringReplace(Result, '億萬', '億', [rfReplaceAll]);
    Result := StringReplace(Result, '兆萬', '兆', [rfReplaceAll]);
    
    // 結尾處理
    if Result.EndsWith('零') then
      Result := Result.Substring(0, Result.Length - 1); // 移除末尾零
    if Result.EndsWith('分') or Result.EndsWith('角') then
      Result := Result + '零'; // 如 "壹角" → "壹角零" (習慣寫法)
      
  finally
    NumMap.Free;
    UnitMap.Free;
  end;
end;

反向轉換:中文大寫轉阿拉伯數字

function ChineseCurrencyToDecimal(const ChineseCurrency: string): string;
var
  Map: TStringList;
  I, PairCount: Integer;
  Pair: string;
begin
  Map := TStringList.Create;
  try
    Map.Delimiter := ',';
    Map.CommaText := '元=.,零=0,壹=1,貳=2,叁=3,肆=4,伍=5,陸=6,柒=7,捌=8,玖=9';
    
    Result := '';
    PairCount := Length(ChineseCurrency) div 2; // 假設格式為 "數字單位" 成對
    
    for I := PairCount downto 1 do
    begin
      Pair := ChineseCurrency[(I-1)*2 + 1] + ChineseCurrency[I*2]; // 取一對
      if Map.Values[Pair] <> '' then
        Result := Map.Values[Pair] + Result;
    end;
    
    // 簡易處理:將中文單位轉為小數點位置
    // 完整實作需解析單位位權,此處略
  finally
    Map.Free;
  end;
end;

測試用例

procedure TestCurrencyConversion;
var
  Tests: array of record
    Input, Expected: string;
  end;
  I: Integer;
begin
  Tests := [
    ('0', '零元'),
    ('1', '壹元'),
    ('10', '壹拾元'),
    ('100', '壹佰元'),
    ('1000', '壹仟元'),
    ('10000', '壹萬元'),
    ('100000000', '壹億元'),
    ('123.45', '壹佰貳拾叁元肆角伍分'),
    ('1001.00', '壹仟零壹元'),
    ('1000100', '壹佰萬零壹佰元'),
    ('0.01', '壹分'),
    ('0.10', '壹角'),
    ('1000000000000', '壹兆元')
  ];
  
  for I := 0 to High(Tests) do
  begin
    var Res := DecimalToChineseCurrency(Tests[I].Input);
    WriteLn(Format('%s → %s  %s', [Tests[I].Input, Res, 
      IfThen(Res = Tests[I].Expected, '✓', '✗ Exp: ' + Tests[I].Expected)]));
  end;
end;

關鍵處理邏輯說明

階段處理內容關鍵點
輸入驗證僅數字 + 單一小數點拒絕科學記號、貨幣符號、多小數點
小數點歸一化補齊 . 位置,移除小數點得純數字串DotPos 記錄小數點原始位置,用於計算單位索引
低位優先處理從個位向高位迴圈UnitIdx = 位置 - DotPos,對應 UnitMap 索引
零值策略四捨五入單位保留單位字UnitIdx mod 4 = 1 (元/萬/億/兆) 保留單位
後處理規則7 條替換規則順序重要:先合併連續零,再處理高階單位前的零

擴展建議

  • 支援負數:前綴「負」字,處理絕對值
  • 支援更大單位:京、垓、秭、穰... 擴展 UnitMap
  • 貨幣符號:前綴「人民幣」、「NT$」等
  • 正式格式:結尾加「整」或「正」 (如「壹佰元整」)
  • 地區差異:港台慣用「圓」而非「元」,「拾/佰/仟」字形差異

結語

中文大寫金額轉換看似簡單,實則包含「零值壓縮」、「單位位權計算」、「四捨五入單位保留」等細節邏輯。本函數以 TStringList 映射表驅動核心轉換,後處理規則鏈修正格式,邏輯清晰、易擴展、可直接用於發票、支票、財務報表列印模組。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved