ASP.NET GridViewで支払金額を通貨形式(¥1,234)表示する方法|DataFormatStringとVB.NET実装例

ASP.NET Webフォーム(.aspx+VB.NET)で GridView に金額を表示するとき、「支払金額(Payment)を¥1,234 や $1,234.00 のような通貨形式で見やすくしたい」と悩む場面は多いです。本記事では GridView の列に通貨書式を適用する最短ルートから、通貨記号の固定、カルチャ設定、RowDataBound での柔軟な制御まで、実務で詰まりやすいポイントをまとめて解説します。

目次

GridViewの支払金額列を通貨形式で表示する最短手順(結論)

いちばん簡単なのは、BoundField に DataFormatString を設定する方法です。Payment が数値型(decimal 等)で取得できているなら、これだけで通貨形式になります。

<asp:BoundField 
    DataField="Payment"
    HeaderText="支払金額"
    DataFormatString="{0:C}" />

{0:C} は .NET の「通貨(Currency)」フォーマット指定子です。ページ/アプリのカルチャ設定に合わせて、通貨記号・小数点以下桁数・3桁区切りが自動で決まります。

カルチャ例表示例({0:C})ポイント
en-US$1,234.00小数2桁が一般的
ja-JP¥1,234日本円は小数0桁が一般的

DataFormatStringが効く仕組みを押さえる(「なぜそう表示されるか」)

GridView の BoundField は、データソースから取得した値を内部で String.Format 相当の処理で文字列化して表示します。ここで DataFormatString を設定しておくと、

  • 値(Payment)を数値として扱い
  • 指定した書式({0:C})で文字列に変換し
  • セルの Text として出力

という流れになります。つまり、Payment が数値として取得できていない(文字列型になっている)場合は、期待どおりに書式が当たらないことがあります(この後の「よくある落とし穴」で詳述します)。

カルチャ(Culture/UICulture)で通貨記号や小数桁が決まる

{0:C} の便利さは、カルチャに追随する点です。逆に言うと、通貨記号(¥、$ など)や小数桁は「どのカルチャとしてページが動いているか」に依存します。日本向けサイトで「円マーク&小数なし」を自然に出したいなら、まずカルチャの設定を整えるのが近道です。

ページ単位でカルチャを固定する(簡単・明示的)

.aspx の先頭(Page ディレクティブ)に Culture / UICulture を指定します。

<%@ Page Language="VB" Culture="ja-JP" UICulture="ja-JP" %>

これで {0:C} を使うと、通貨は基本的に「¥」基準になります(サーバー環境やスレッドカルチャが揺れている現場でも、ページ側指定は効きやすいです)。

web.configでアプリ全体のカルチャを決める(運用しやすい)

サイト全体で統一したい場合は web.config の globalization を使います。

<configuration>
  <system.web>
    <globalization culture="ja-JP" uiCulture="ja-JP" />
  </system.web>
</configuration>
設定場所例反映範囲向いているケース
PageディレクティブCulture=”ja-JP”そのページページ単位で表示を確実にしたい
web.configglobalizationアプリ全体サイト全体の表示統一、運用を簡素化したい
コードで設定Thread.CurrentThread…リクエスト単位などユーザーごとに表示言語/通貨を変えたい

BoundFieldで「通貨形式+見やすさ」を仕上げる実装例

通貨形式に加えて、実務では「金額は右寄せ」「NULLは空で表示」「編集モードでも書式を維持」などの仕上げが効きます。GridView の列定義例をまとめておきます。

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
  <Columns>

    <asp:BoundField DataField="CustomerName" HeaderText="顧客" />

    <asp:BoundField 
        DataField="Payment"
        HeaderText="支払金額"
        DataFormatString="{0:C}"
        ApplyFormatInEditMode="true"
        NullDisplayText="">
      <ItemStyle HorizontalAlign="Right" />
      <HeaderStyle HorizontalAlign="Right" />
    </asp:BoundField>

  </Columns>
</asp:GridView>
  • ItemStyle HorizontalAlign=”Right”:金額は右寄せが読みやすい(桁が揃う)
  • NullDisplayText:Payment が NULL のときに「0」や空表示などを制御
  • ApplyFormatInEditMode=”true”:編集行(EditItemTemplate相当)でもフォーマット適用したい場合に有効

小数点以下を消したい場合(C0 / N0 の使い分け)

日本円のように小数が不要な場合は、カルチャが ja-JP なら {0:C} だけで自然に小数なしになりやすいです。それでも「必ず小数なし」を明示したい場合は C0 を使うと確実です。

書式意味例(1234.5 / ja-JP想定)用途
{0:C}通貨(カルチャ依存の小数桁)¥1,235(環境により)ロケールに合わせたい
{0:C0}通貨(小数0桁固定)¥1,235円など小数不要を明示
{0:N0}数値(3桁区切り、小数0桁)1,235通貨記号は自前で付けたい
{0:N2}数値(小数2桁)1,234.50端数を見せたい

通貨記号を固定したい場合はTemplateFieldが強い

「ロケールに応じて $ や ¥ が変わるのは困る。常に円で出したい」のように、通貨記号を固定したいなら TemplateField が分かりやすく、事故が少ないです。

記号+値を単純に出す(最小構成)

<asp:TemplateField HeaderText="支払金額(円)">
  <ItemTemplate>
    ¥<%# Eval("Payment") %>
  </ItemTemplate>
</asp:TemplateField>

ただし、このままだと「3桁区切り」や「小数の扱い」が Payment の型や値に依存しやすいので、実務では次のように書式も合わせることが多いです。

3桁区切り+小数なし(円向けの定番)

<asp:TemplateField HeaderText="支払金額(円)">
  <ItemTemplate>
    ¥<%# Eval("Payment", "{0:N0}") %>
  </ItemTemplate>
</asp:TemplateField>

TemplateField の利点は、必要になったタイミングで「色を変える」「マイナスを赤」「0円はハイフン」「上限超えは警告アイコン」など、表示ルールを段階的に足していけることです。

HTMLや装飾も混ぜたい場合(HtmlEncodeの注意)

例えば金額を太字にしたい、特定条件で色を付けたい、のように HTML を混ぜる場合は、BoundField より TemplateField が安全です(BoundField でも HtmlEncode=”false” で対応できますが、列単位の制御は TemplateField の方が拡張しやすいです)。

<asp:TemplateField HeaderText="支払金額">
  <ItemTemplate>
    <span class="payment-amount">
      <%# Eval("Payment", "{0:C}") %>
    </span>
  </ItemTemplate>
</asp:TemplateField>

CSS 側で右寄せにしたい場合は、GridView のセルにクラスを付ける運用や、ItemStyle を使う運用が定番です。

VB.NET(コードビハインド)で制御したいならRowDataBound

「Payment の値が NULL のときは空」「通貨コード列(JPY/USD)に応じて表示を切り替え」「四捨五入ではなく切り捨て」など、ルールが増えるとマークアップだけでは辛くなります。そんなときは RowDataBound が王道です。

基本形:列インデックスに通貨書式を適用する

Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) _
    Handles GridView1.RowDataBound


If e.Row.RowType = DataControlRowType.DataRow Then

    Dim raw = DataBinder.Eval(e.Row.DataItem, "Payment")

    ' NULL/DBNull対策
    If raw Is Nothing OrElse raw Is DBNull.Value Then
        ' Payment列のセルを空にする(列インデックスは実際の位置に合わせて変更)
        e.Row.Cells(2).Text = ""
        Return
    End If

    Dim value As Decimal = Convert.ToDecimal(raw)

    ' 例:カルチャに沿った通貨表示
    e.Row.Cells(2).Text = String.Format("{0:C}", value)

    ' 見やすさ(右寄せ)をコードで当てることも可能
    e.Row.Cells(2).HorizontalAlign = HorizontalAlign.Right
End If


End Sub 

列インデックス(e.Row.Cells(2))は GridView の列定義順で変わるため、保守性を重視する場合は「TemplateField+Label を配置して FindControl で取得」などにすると、列の追加・並び替えに強くなります。

保守しやすい形:TemplateFieldのLabelに入れる

<asp:TemplateField HeaderText="支払金額">
  <ItemTemplate>
    <asp:Label ID="lblPayment" runat="server" />
  </ItemTemplate>
  <ItemStyle HorizontalAlign="Right" />
</asp:TemplateField>
Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) _
    Handles GridView1.RowDataBound

    If e.Row.RowType <> DataControlRowType.DataRow Then Return

    Dim lbl = TryCast(e.Row.FindControl("lblPayment"), Label)
    If lbl Is Nothing Then Return

    Dim raw = DataBinder.Eval(e.Row.DataItem, "Payment")
    If raw Is Nothing OrElse raw Is DBNull.Value Then
        lbl.Text = ""
        Return
    End If

    Dim value As Decimal = Convert.ToDecimal(raw)
    lbl.Text = value.ToString("C") ' {0:C}と同等
End Sub

この形なら「Payment列が何番目か」を意識せずに済むため、運用中に列が増減する管理画面でも崩れにくいです。

「通貨記号を固定」+「書式は数値側で整える」例

固定通貨(例:常に円)で、小数なし・3桁区切りなら、N0 で数値を整形してから記号を付けるのが読みやすいです。

Dim value As Decimal = Convert.ToDecimal(raw)
lbl.Text = "¥" & value.ToString("N0")

このやり方のメリットは、「円は小数なし」「ドルは小数2桁」といったカルチャ依存の揺れから切り離して、表示仕様を固定できる点です。

複数通貨(JPY/USD/EURなど)を行ごとに切り替える例

EC管理画面や請求一覧で「通貨コード列」がある場合、行ごとに表示を変えたいことがあります。例えばデータに CurrencyCode(JPY, USD…)があり、Payment を同じ列で表示したいケースです。

Imports System.Globalization

Private Shared ReadOnly CurrencySymbolMap As New Dictionary(Of String, String)(StringComparer.OrdinalIgnoreCase) From {
    {"JPY", "¥"},
    {"USD", "$"},
    {"EUR", "€"},
    {"GBP", "£"}
}

Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) _
    Handles GridView1.RowDataBound

    If e.Row.RowType <> DataControlRowType.DataRow Then Return

    Dim lbl = TryCast(e.Row.FindControl("lblPayment"), Label)
    If lbl Is Nothing Then Return

    Dim rawValue = DataBinder.Eval(e.Row.DataItem, "Payment")
    If rawValue Is Nothing OrElse rawValue Is DBNull.Value Then
        lbl.Text = ""
        Return
    End If

    Dim value As Decimal = Convert.ToDecimal(rawValue)

    Dim codeObj = DataBinder.Eval(e.Row.DataItem, "CurrencyCode")
    Dim code As String = If(codeObj Is Nothing OrElse codeObj Is DBNull.Value, "", codeObj.ToString())

    Dim symbol As String = If(CurrencySymbolMap.ContainsKey(code), CurrencySymbolMap(code), "")

    ' 通貨ごとに小数桁のルールを変える例(USD/EURは2桁、JPYは0桁)
    Dim format As String = If(code.Equals("JPY", StringComparison.OrdinalIgnoreCase), "N0", "N2")

    lbl.Text = symbol & value.ToString(format)
End Sub

ポイントは、通貨コード=カルチャではないことです。ISO通貨コード(JPY)から CultureInfo を直接引ける仕組みは単純ではないため、要件が「記号と桁数の表示」程度なら、上のように 必要な通貨だけ辞書で管理する運用が実装も保守も安定します。

よくある落とし穴(「設定したのに効かない」を潰すチェックリスト)

Payment列が文字列になっている

DataFormatString は数値として扱える値に対して効きます。SQL 側で Payment を文字列として返していたり、DataTable に詰める過程で string になっていると、{0:C} が期待どおりに動かないことがあります。

  • SQL の列型が DECIMAL / MONEY などの数値型になっているか
  • SELECT で文字列連結していないか(例:’¥’ + CAST(…))
  • DataTable / DataSet 側で列型が Decimal になっているか

NULL(DBNull)の扱いで例外や表示崩れが出る

支払未確定などで Payment が NULL になる設計は珍しくありません。RowDataBound で Convert.ToDecimal を直接呼ぶと例外になるため、DBNull.Value のガードは必須です。BoundField の場合は NullDisplayText で吸収するのが手軽です。

編集モードで書式が外れる

GridView の編集(Edit)を使っている場合、「表示時は通貨なのに編集行では普通の数値になる」ことがあります。BoundField を使うなら ApplyFormatInEditMode=”true” を検討してください。編集 UI を別途整えたいなら TemplateField+EditItemTemplate の方が自由度が高いです。

3桁区切りは出たが、円なのに小数が付く/ドルなのに小数がない

これはほぼカルチャの問題です。サーバーの既定カルチャや、アプリの globalization 設定が意図と違う可能性があります。

  • 日本向けで円表示なら:Culture/UICulture を ja-JP に固定する
  • ユーザーごとに切替なら:リクエスト単位でカルチャを設定する(後述)
  • 「必ずこの桁数」という要件なら:C ではなく C0 / N0 / N2 を使って固定する

「¥」が文字化けする/環境により見え方が違う

円マークは環境(フォント、文字コード、OSの表示)で見え方が揺れることがあります。最終手段としては ¥ を使う手もありますが、表示結果はフォント依存です。管理画面用途なら「記号より通貨コード(JPY)を併記する」など、誤認を避ける工夫も効果的です。

SQL側で通貨形式にして返すのはおすすめしにくい理由

「SQL の SELECT で文字列に整形して返せば簡単」と考えがちですが、運用で困りやすいので、基本は DBは数値、表示は.NET側をおすすめします。

  • 並び替え(Sort)や集計が崩れる:文字列化すると数値としての大小比較ができなくなる
  • ロケール対応が難しい:同じ値でもユーザー言語で表示を変えたいときに詰む
  • 表示仕様の変更に弱い:小数桁や記号変更でSQL改修が必要になりがち
  • パフォーマンス:SQL Server の FORMAT は便利ですが、負荷が上がりやすいケースがある

GridView 側で DataFormatString / TemplateField / RowDataBound を使えば、数値のまま保持しつつ UI で最適表示できるため、保守が楽になります。

ユーザーごとに通貨表示を変えたい場合(多言語・海外向けサイト)

海外向けの管理画面や、ユーザーの地域設定で表示を変えたい場合は、「アプリ全体固定」ではなく「リクエスト単位でカルチャを決める」設計が必要になります。代表的には次の2パターンです。

Accept-Languageに追随(ブラウザ言語)

ブラウザが送る言語設定に追随すると、ユーザーの期待に近い表示になりやすい反面、「通貨は必ずUSDにしたい」などの業務要件とはズレることがあります。業務要件が強い場合は、次の「ユーザー設定(DB)」方式が確実です。

ユーザー設定(DB)に追随(実務向け)

会員テーブルに Locale(例:en-US、ja-JP)や通貨コード(JPY/USD)を持たせ、ログインユーザーに合わせて表示を切り替えます。RowDataBound 内で CultureInfo を切り替える設計もできますが、画面全体の統一感を出すなら、ページ開始時点でカルチャを設定する方が自然です。

Imports System.Globalization
Imports System.Threading

Protected Overrides Sub InitializeCulture()
    ' 例:ログインユーザーのカルチャを取得("ja-JP" / "en-US" など)
    Dim userCultureName As String = "ja-JP" ' 実際はDBやプロフィールから取得

    Dim ci As CultureInfo = CultureInfo.GetCultureInfo(userCultureName)
    Thread.CurrentThread.CurrentCulture = ci
    Thread.CurrentThread.CurrentUICulture = ci

    MyBase.InitializeCulture()
End Sub

この設定をしておくと、BoundField の {0:C} でも TemplateField の {0:C} でも、ページ全体が同じカルチャで統一されるため、金額以外(日時や数値)も自然に整います。

用途別のおすすめ(迷ったらここを選ぶ)

要件おすすめ理由実装の手間
ロケールに合わせて通貨表示したいBoundField + DataFormatString=”{0:C}”最短で実装、カルチャに追随低
必ず「¥」など記号を固定したいTemplateField + 記号 + Eval(“{0:N0}”)表示仕様を固定できる中
NULL対応や条件分岐が多いRowDataBound(TemplateField併用)柔軟に制御でき、拡張しやすい中〜高
行ごとに通貨が変わる(JPY/USD混在)RowDataBound + 通貨コード列で分岐要件に合わせた表示が可能高

まとめ(支払金額の表示品質で管理画面の使いやすさが変わる)

  • GridView の Payment を通貨形式にする最短手段は、BoundField の DataFormatString=”{0:C}”
  • 「¥固定」など仕様を固定したいなら、TemplateField+Eval(“{0:N0}”)が扱いやすい
  • NULL処理や複雑な表示要件があるなら、RowDataBoundで安全に制御する
  • 表示揺れの原因はだいたいカルチャ設定と型(数値か文字列か)にある

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次