※本ページには広告・PR が含まれます。

DataGridView:数値・日付・通貨の表示書式を設定する

📋 目次(クリックで展開)

DataGridView に金額を表示したら 1000 とそのまま出てしまう。日付が 2026/08/10 0:00:00 になって時刻が邪魔——。

いずれも DefaultCellStyle.Format に書式指定子を渡すだけで解決します。ただし Format は「効く条件」があり、そこを外すと何も起こりません。また桁区切りを設定すると、編集時に例外が出るという副作用も潜んでいます。

この記事では、書式指定の基本から、Format が無視される原因、CellFormatting との使い分け、実務ではまる落とし穴までを整理します。

結論:DefaultCellStyle.Format の設定例

列単位で DefaultCellStyle.Format を設定します。

// 金額:3桁区切り、小数なし
dataGridView1.Columns["Price"].DefaultCellStyle.Format = "N0";
// 通貨記号付き
dataGridView1.Columns["Amount"].DefaultCellStyle.Format = "C0";
// 日付のみ(時刻を出さない)
dataGridView1.Columns["OrderDate"].DefaultCellStyle.Format = "yyyy/MM/dd";
// パーセント(0.15 → 15%)
dataGridView1.Columns["Rate"].DefaultCellStyle.Format = "P0";

グリッド全体に一括で適用することもできます。

// 全セル共通の既定書式
dataGridView1.DefaultCellStyle.Format = "N0";

これで表示されない場合は、次章の「効く条件」を確認してください。

Format が効く条件

値が IFormattable であること

Format は内部的に value.ToString(format, formatProvider) を呼び出しています。つまり IFormattable を実装した型でなければ何も起こりません

値の型 Format 理由
int / decimal / double 効く IFormattable 実装済み
DateTime / DateTimeOffset 効く 同上
string 効かない IFormattable 未実装
bool 効かない 同上
独自クラス 実装次第 IFormattable を実装すれば効く

N0 を設定したのに桁区切りが出ない」というケースの大半は、値が文字列になっているためです。

ValueType を確認する

まず実際の型を確認してください。

foreach (DataGridViewColumn column in dataGridView1.Columns)
{
Debug.WriteLine($"{column.Name}: {column.ValueType?.Name}");
}

String と出た列は、書式指定の前にデータソース側の型を直す必要があります。

DataTable の場合は列定義で型を指定します。

var table = new DataTable();
table.Columns.Add("Price", typeof(decimal)); // string にしない
table.Columns.Add("OrderDate", typeof(DateTime));

SQL から読み込んだデータで型が崩れる場合は、SELECT 側のキャストか DataTable の再定義で対処します。

クラスをバインドしている場合はプロパティの型がそのまま反映されます。

public class Product
{
public string Name { get; set; }
public decimal Price { get; set; } // string にしない
public DateTime OrderDate { get; set; }
public decimal Rate { get; set; }
}

自動生成列では設定タイミングに注意

AutoGenerateColumnstrue(既定)の場合、列は DataSource を設定した瞬間に生成されます。それより前に Columns["Price"] へアクセスすると例外になります。

// NG:列がまだ存在しない
dataGridView1.Columns["Price"].DefaultCellStyle.Format = "N0";
dataGridView1.DataSource = bindingSource1;
// OK:バインド後に設定する
dataGridView1.DataSource = bindingSource1;
dataGridView1.Columns["Price"].DefaultCellStyle.Format = "N0";

DataBindingComplete イベントで設定する方法もありますが、このイベントは再バインドのたびに発火します。毎回スタイルを作り直さないよう、フラグで初回のみに絞るか、代入前に既存値を確認してください。

書式指定子の一覧

数値

decimalintdouble などに使用します。表示例は ja-JP 環境のものです。

指定子 意味 表示
N0 桁区切り・小数0桁 1234567 1,234,567
N2 桁区切り・小数2桁 1234.5 1,234.50
C0 通貨・小数0桁 1500 ¥1,500
C2 通貨・小数2桁 1500 ¥1,500.00
P0 パーセント 0.15 15%
P1 パーセント・小数1桁 0.155 15.5%
F1 固定小数点 1234.56 1234.6
D5 整数・0埋め 42 00042
X 16進数 255 FF

P 指定子は値を100倍します。 15 を渡すと 1,500% になります。データベースに 15 で保存している場合は、0.15 に変換するか N0 + CellFormatting% を付与してください。

カスタム数値書式

標準指定子で表現できない場合はカスタム書式を使います。

書式 表示
#,##0 1234 1,234
#,##0.00 1234.5 1,234.50
#,### 0 (空欄)
#,##0 円 1500 1,500 円
#,##0;(#,##0) -500 (500)
#,##0;▲#,##0;- -500 ▲500

セミコロンで区切ると 正数・負数・ゼロ の3パターンを指定できます。会計系の画面で負数を 表示にする、ゼロをハイフンにするといった要件はこれで足ります。

#0 の違いは、値がないときに桁を表示するかどうかです。#,###0 を空欄にし、#,##00 と表示します。

日付・時刻

書式 表示例
yyyy/MM/dd 2026/08/10
yyyy年M月d日 2026年8月10日
yyyy/MM/dd HH:mm 2026/08/10 14:30
MM/dd (ddd) 08/10 (月)
HH:mm:ss 14:30:00
d 2026/08/10(短い日付・カルチャ依存)
D 2026年8月10日(長い日付・カルチャ依存)
t 14:30(短い時刻)

大文字と小文字を混同しないでください。

誤りやすい組み合わせ 正しい意味
MM / mm MM = 月、mm =
HH / hh HH = 24時間制、hh = 12時間制
dd / DD dd = 日、DD は無効

yyyy/mm/dd と書くと 2026/30/10 のような表示になります。分が月の位置に入るためです。

日付の入力側をカレンダーにしたい場合は、書式設定とは別に編集用コントロールの実装が必要です。

スタイルの優先順位

Format を設定したのに反映されない場合、別のスタイルに上書きされている可能性があります。

DataGridView のセルスタイルは6段階で継承され、下にあるものが優先されます。

優先 設定箇所
1(最強) DataGridViewCell.Style
2 DataGridViewRow.DefaultCellStyle
3 DataGridView.AlternatingRowsDefaultCellStyle(奇数行のみ)
4 DataGridView.RowsDefaultCellStyle
5 DataGridViewColumn.DefaultCellStyle
6(最弱) DataGridView.DefaultCellStyle

重要なのは、プロパティ単位で継承される点です。上位でセル背景色だけを設定しても、Format は下位のものが引き継がれます。

// 列で書式を設定
dataGridView1.Columns["Price"].DefaultCellStyle.Format = "N0";
// 行で背景色だけ設定 → Format は列の N0 が維持される
dataGridView1.Rows[0].DefaultCellStyle.BackColor = Color.LightYellow;
// 行で書式も設定 → こちらが勝つ
dataGridView1.Rows[0].DefaultCellStyle.Format = "C0";

実際に適用されている値は InheritedStyle で確認できます。

var applied = dataGridView1.Rows[0].Cells["Price"].InheritedStyle;
Debug.WriteLine($"適用中の Format: {applied.Format}");

デバッグ時にはこれが最も速い切り分け手段です。

null と空欄の扱い

NullValue:表示を差し替える

値が null または DBNull のとき、代わりに表示する内容を指定します。

// 未入力を「未定」と表示する
dataGridView1.Columns["OrderDate"].DefaultCellStyle.NullValue = "未定";
// ハイフンで埋める
dataGridView1.Columns["Price"].DefaultCellStyle.NullValue = "-";

NullValueFormat より優先されます。値が null の時点で書式適用は行われません。

なお DataGridViewImageColumn では NullValue の既定値がエラーアイコンになっており、画像が未設定のセルに × マークが表示されます。

DataSourceNullValue:書き戻す値を決める

ユーザーがセルを空にしたとき、データソースへ何を書き込むかを指定します。既定は DBNull.Value です。

// クラスバインドで null を書き戻す
dataGridView1.Columns["Note"].DefaultCellStyle.DataSourceNullValue = null;
// 空文字を書き戻す
dataGridView1.Columns["Note"].DefaultCellStyle.DataSourceNullValue = string.Empty;

DataTable バインドでは DBNull.Value のままで問題ありませんが、List<T> バインドで string プロパティに DBNull を代入しようとすると例外になります。この場合は null または string.Empty を明示してください。

バインド先 推奨する DataSourceNullValue
DataTable DBNull.Value(既定のまま)
クラスの参照型プロパティ null
クラスの Nullable<T> プロパティ null
クラスの非 null 値型 空欄を許容しない設計にする

カルチャを指定する

FormatProvider を指定すると、カルチャ依存の表示を制御できます。

// 通貨記号をドルにする
dataGridView1.Columns["UsdPrice"].DefaultCellStyle.Format = "C2";
dataGridView1.Columns["UsdPrice"].DefaultCellStyle.FormatProvider =
CultureInfo.GetCultureInfo("en-US");

未指定の場合は CurrentCulture(実行環境の設定)が使われます。開発機と本番機でロケールが異なると表示が変わるため、通貨や日付を厳密に固定したい画面では明示するのが安全です。

InvariantCulture を使えば環境差をなくせますが、日本語環境では区切り文字が英語圏の形式になります。表示用途では避け、ファイル出力など機械可読なデータに使ってください。

Format は配置を変えない

数値に N0 を設定しても、右寄せにはなりません。配置は別プロパティです。

var style = dataGridView1.Columns["Price"].DefaultCellStyle;
style.Format = "N0";
style.Alignment = DataGridViewContentAlignment.MiddleRight;

数値列が左寄せのままだと桁が揃わず、金額の比較がしづらくなります。書式設定とセットで行うのが実務上の定石です。

まとめて設定するヘルパーを用意しておくと楽になります。

private static void ApplyNumericStyle(
DataGridViewColumn column, string format = "N0")
{
var style = column.DefaultCellStyle;
style.Format = format;
style.Alignment = DataGridViewContentAlignment.MiddleRight;
}

CellFormatting を使うべきケース

Format は「値そのものの書式化」しかできません。次のような要件では CellFormatting イベントを使います。

要件 手段
固定の書式を適用する Format
条件によって書式を変える CellFormatting
他の列の値を参照する CellFormatting
コード値を名称に変換する CellFormatting
値の範囲で色を変える CellFormatting

実装例

private void DataGridView1_CellFormatting(
object sender, DataGridViewCellFormattingEventArgs e)
{
if (dataGridView1.Columns[e.ColumnIndex].Name != "Status")
{
return;
}
// コード値を表示用の名称に変換する
e.Value = e.Value switch
{
0 => "未処理",
1 => "処理中",
2 => "完了",
_ => "不明",
};
// これを忘れると Format が再適用される
e.FormattingApplied = true;
}

e.FormattingApplied = true の設定を忘れないでください。 これを省くと、DataGridView は「まだ書式化されていない」と判断し、セルスタイルの Format を上から適用しようとします。結果として意図しない表示になります。

パフォーマンスに注意

CellFormatting再描画のたびに、表示範囲の全セル分だけ発火します。スクロールすれば何百回も呼ばれます。

ここで DB アクセスや重い計算を行うと、スクロールが目に見えて重くなります。マスタの参照が必要なら、事前に Dictionary へ読み込んでおいてください。

private Dictionary<int, string> _statusNames;
private void LoadMaster()
{
// 起動時に一度だけ読み込む
_statusNames = statusRepository.GetAll()
.ToDictionary(s => s.Code, s => s.Name);
}
private void DataGridView1_CellFormatting(
object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.Value is int code && _statusNames.TryGetValue(code, out var name))
{
e.Value = name;
e.FormattingApplied = true;
}
}

落とし穴

桁区切りを設定すると編集で例外が出る

最もはまりやすい問題です。

Format = "N0" を設定した列を編集モードにすると、テキストボックスには 1,234カンマ付きで表示されます。ユーザーがそのまま確定すると、DataGridView1,234int に変換しようとして失敗します。

System.FormatException: 'DataGridViewComboBoxCell の値が有効ではありません'
または「入力文字列の形式が正しくありません。」

対処は2通りあります。

A. CellParsing で自前解析する

private void DataGridView1_CellParsing(
object sender, DataGridViewCellParsingEventArgs e)
{
if (dataGridView1.Columns[e.ColumnIndex].Name != "Price")
{
return;
}
var text = e.Value as string;
if (string.IsNullOrWhiteSpace(text))
{
e.Value = null;
e.ParsingApplied = true;
return;
}
// カンマを許容して解析する
if (decimal.TryParse(
text,
NumberStyles.Number | NumberStyles.AllowThousands,
CultureInfo.CurrentCulture,
out var value))
{
e.Value = value;
e.ParsingApplied = true;
}
// 解析できなければ ParsingApplied を立てず、既定処理と DataError に委ねる
}

NumberStyles.AllowThousands が要点です。これを指定しない decimal.Parse はカンマを受け付けません。

B. 編集時だけ書式を外す

private void DataGridView1_CellBeginEdit(
object sender, DataGridViewCellCancelEventArgs e)
{
if (dataGridView1.Columns[e.ColumnIndex].Name == "Price")
{
dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex]
.Style.Format = string.Empty;
}
}
private void DataGridView1_CellEndEdit(
object sender, DataGridViewCellEventArgs e)
{
if (dataGridView1.Columns[e.ColumnIndex].Name == "Price")
{
// セル個別のスタイルを解除して列の設定に戻す
dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex]
.Style.Format = null;
}
}

編集中は生の数値、確定後は書式付きという挙動になります。入力しやすさを優先するならこちらです。

ただしセル単位でスタイルを生成するため、大量行を編集する画面ではメモリ消費が増えます。行数が多い場合はAを選んでください。

ソートは元の値で行われる

Format は表示だけを変えるため、並べ替えは書式化前の値を基準に行われます。これは正しい挙動です。

1,000900 を文字列比較すれば 1,000 が先に来ますが、数値比較なので 900 が先になります。書式に惑わされず期待どおりに並びます。

一方で CellFormatting でコード値を名称に変換した列は、名称ではなくコード順に並びます。ユーザーから見ると「あいうえお順になっていない」と映るため、名称順が必要ならデータソース側に表示名の列を持たせてください。

クリップボードには書式後の値が載る

Ctrl + C でコピーされるのは書式適用後の文字列です。N0 を設定した列は 1,234 としてコピーされます。

Excel に貼り付ける際は問題になりませんが、貼り付け先で再解析する場合はカンマの扱いに注意が必要です。

列幅の自動調整は書式後の幅で計算される

AutoSizeMode による自動調整は、書式適用後の表示文字列を基準にします。N0 で桁区切りを付けると文字数が増えるため、書式設定の後に列幅を調整してください。

dataGridView1.Columns["Price"].DefaultCellStyle.Format = "N0";
dataGridView1.Columns["Price"].AutoSizeMode =
DataGridViewAutoSizeColumnMode.AllCells;

指定方法の比較

方法 適用範囲 メモリ 向いているケース
DataGridView.DefaultCellStyle 全セル グリッド共通の既定値
Column.DefaultCellStyle 列全体 通常はこれ
Row.DefaultCellStyle 行全体 合計行など特定行
Cell.Style 単一セル 例外的なセルのみ
CellFormatting 条件次第 動的な変換が必要な場合

列単位が基本です。セル単位のスタイルは行数に比例してオブジェクトが増えるため、ループで一括設定するのは避けてください。

// NG:行数ぶんスタイルオブジェクトが生成される
foreach (DataGridViewRow row in dataGridView1.Rows)
{
row.Cells["Price"].Style.Format = "N0";
}
// OK:列に一度だけ設定する
dataGridView1.Columns["Price"].DefaultCellStyle.Format = "N0";

まとめ

  • 書式は DefaultCellStyle.Format に指定子を渡すだけ。列単位での設定が基本
  • FormatIFormattable な型にしか効かない。反映されないときは ValueTypeString になっていないか確認する
  • 自動生成列では DataSource 設定後に書式を指定する
  • P 指定子は値を100倍する。15 ではなく 0.15 を渡す
  • 日付の MM は月、mm は分。HH は24時間制、hh は12時間制
  • スタイルは6段階で継承され、プロパティ単位で上書きされる。InheritedStyle で実際の適用値を確認できる
  • NullValue は表示の差し替え、DataSourceNullValue は書き戻す値。役割が異なる
  • Format は配置を変えない。数値列は Alignment で右寄せする
  • 桁区切りを設定すると編集時の再変換で失敗するCellParsing か編集時の書式解除で対処する
  • 条件付きの変換は CellFormattinge.FormattingApplied = true を忘れない

関連記事


💬 コメント