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.config | globalization | アプリ全体 | サイト全体の表示統一、運用を簡素化したい |
| コードで設定 | 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で安全に制御する
- 表示揺れの原因はだいたいカルチャ設定と型(数値か文字列か)にある

コメント