🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

Excel VBA の CStr・CDate・Val — 文字列を数値・日付へ正しく変換する

|

Excel VBA の CStr・CDate・Val — 文字列を数値・日付へ正しく変換する

検証環境: Excel 365 v2509 · Excel 2021 · Excel 2019 · 最終確認 2026-06-10

要点CStrCDateValCLngCDbl変換関数です。値のを変えます — 文字列を本物の数値へ、文字列を本物の日付へ、数値を文字列へ。これは Format の逆です。Format は値の見た目しか変えません。この違いを掴めば、VBA の静かなデータバグの最大の発生源を止められます。

Sub ConvertDemo()
    Debug.Print CStr(1234.5)            ' "1234.5"        数値    -> 文字列
    Debug.Print CDbl("1234.5") * 2      ' 2469            文字列  -> 数値、そして本物の計算
    Debug.Print CLng("42")              ' 42              文字列  -> Long 整数
    Debug.Print CDate("2026-04-01")     ' 並べ替え・減算できる本物の日付
    Debug.Print Val("12px")             ' 12              数字を読み、最初の非数字で止まる
End Sub

考え方の軸:変換は「値が何であるか」を変える

このクラスターを掃除目線でひと回り:Trim はデータをきれいにし、Format正しく見せC… 関数は正しい型にします。これは別々の 3 つの仕事で、最後の 2 つを取り違えるのが大罪です。

2026-04-01表示されるセルは、本物の日付(並べ替え・減算・月でのフィルターが可能)かもしれないし、そう見えるだけのテキストかもしれません。Format は後者を、CDate は前者を生みます。日付が並ばない、「数値」が合計されない — そういうとき、ほぼ必ず、本物の型付き値が要る場所にテキストが入っています。直し方は変換であって、追加の書式設定ではありません。テキストを「ふりをしている本来のもの」に変えるなら CDate/CDbl/CLng、意図して逆向きに行くなら CStr です。

唯一のルール:CDate は曖昧な日付をマシンの地域設定で読む

これが、チーム内でデータを静かに壊すルールです。

CDate は日付文字列を、実行される PC の地域設定で解釈します。CDate("01/02/2026") は米国のマシンでは 1 月 2 日、ヨーロッパのマシンでは 2 月 1 日。同じブック、同じコード、違うデータ — しかも何もエラーになりません。

警告は出ません。どちらの読み方も有効な日付だからです。バグは、設定の違う同僚にファイルが渡ったとき、あるいは別地域向けに構成されたサーバーで動いたときに初めて表面化します — そのときには、誤った日付が 1 か月分のレポートに焼き付いています。

' ⚠ 危険 — 結果は誰の PC が実行するかに依存する
d = CDate("01/02/2026")          ' 米国では 1 月 2 日、ヨーロッパの多くでは 2 月 1 日

' ✓ 安全 — 部品から日付を組み立てる。地域設定に非依存
d = DateSerial(2026, 2, 1)       ' どのマシンでも常に 2 月 1 日

直し方は、そもそも CDate に曖昧な文字列を渡すのをやめることです。ソースを自分で握っているなら、部品に分けて DateSerial(年, 月, 日) で組み立てる — 3 つの数値を取り、読み違えようがありません。"01/02/2026" を受け取らざるを得ないなら、"/"Split して、順序を地域設定任せにせず自分で決めます。CDate は ISO の "2026-04-01" のような曖昧さのない書式に対してのみ安全とみなしましょう。

第 2 の罠:Val は地域設定に盲目、CDbl はそうでない

どちらも文字列を数値にしますが、小数点の区切りで意見が割れ、その食い違いがコンマ小数のデータを食います。

  • Val常に . を小数点、, を停止文字として扱います。空白を無視し、非数字に当たるまで左から右へ読みます。Val("12px")12Val("1,234.5")1(コンマで止まる)。
  • CDbl地域設定に従います。コンマが小数点の環境(ヨーロッパの多くなど)では CDbl("3,14")3.14

つまり、まったく同じ文字列が、選んだ関数次第で意味を変えます。

' コンマが小数点の環境のユーザーが「3,14」(= 3.14)と入力する
Debug.Print Val("3,14")     ' 3      <- コンマで止まり、",14" は静かに捨てられる
Debug.Print CDbl("3,14")    ' 3.14   <- 地域設定を尊重。ユーザーが意図した値

身を守るルール:自分で握る固定の英語形式の文字列には Val"12px"12 に削る、. 小数で自分が書き出した CSV を読む)。ユーザー入力や地域化されたソース由来のものには CDbl/CLng 混ぜると、地域形式の数値の列が、知らぬ間に小数部を失います。

第 3 の罠:CLng は丸める。しかも期待どおりには丸めない

CLngCInt は切り捨てません — 丸めます。しかも銀行家の丸め(偶数への丸め)です。

Debug.Print CLng(2.5)       ' 2   <- 切り上げでなく、偶数へ丸める
Debug.Print CLng(3.5)       ' 4
Debug.Print Int(2.7)        ' 2   <- Int/Fix は代わりに切り捨てる

「常に切り上げ」や「小数を切り落とす」が欲しいなら、CLng は道具ちがいです — IntFixWorksheetFunction.Round を使いましょう。そして CInt は 32,767 を超えるとオーバーフローします。実務の件数になりうるものには CLng を。

テキスト側でもう 1 つ:CStr(123)"123" ですが、古い Str(123) は符号用に先頭の空白を予約して " 123" を返し、地域に関係なく常に . を使います。きれいな数値→テキストには、CStr(特定の見た目が欲しいときは Format)が Str に毎回勝ちます。

どれをいつ使うか

持っているもの 使うもの 理由
テキストにしたい数値 CStr(n) きれい、地域対応、先頭空白なし
テキスト → 数値(ユーザー/地域化ソース) CDbl / CLng 地域の小数点区切りを尊重
テキスト → 数値(自分が握る固定の英語形式) Val(s) 常に . 小数、非数字で停止
テキスト → 本物の日付(曖昧さなし、ISO) CDate("2026-04-01") 明確な書式を安全に解釈
曖昧な部品からの日付 DateSerial(年, 月, 日) 地域非依存、読み違え不可
表示用文字列だけ、値は不変 Format 化粧のみ — 型は変えない

意見:データの解釈を地域設定に委ねるな

一線はこれです:暗黙の変換と、曖昧な文字列への CDate は、便利機能ではなく時限爆弾。 someDate = rng.ValueCDate(textCell) をして自分のマシンで「ちゃんと動く」コードは、サーバーで 1 月の代わりに 2 月を静かに生むのと同じコードです。自分の PC で走らせる限り、あらゆるテストを通ります。

だから、意図的に、曖昧さなく変換しましょう。日付は DateSerial で組む。ユーザーの数値は CDbl、固定文字列は Val で解釈し、どちらを握っているか分かっていること。列まるごとが「テキストとして保存された数値」で届いたら、本当の直し方は書式設定のひと回しではなく — 取り込み境界で一度、地域設定を釘付けにした変換です。やけどするチームは暗黙の読みを信じたチーム。そうでないチームは、自分で書式を決めたチームです。

よくある変換のミス(と直し方)

症状 原因 直し方
別の PC で日付が 1 か月ずれる CDate が曖昧な dd/mmmm/dd を読んだ DateSerial(年, 月, 日) で組む
コンマ小数がコンマ以降を全部失う Val, を停止文字扱いした 地域化入力には CDbl を使う
CDate/CDbl で「型が一致しません」 文字列が有効な日付/数値でなかった 先に IsDate(s) / IsNumeric(s) を判定
丸めが予想外の値になる CLng/CInt が銀行家の丸めを使う Int/FixWorksheetFunction.Round
大きな件数の変換で オーバーフロー CInt は 32,767 で頭打ち CLng を使う
数値→テキストに先頭空白がつく 符号枠を予約する Str() を使った CStr() を使う

変換が積み上がってきたら — 欲しい「データ」を伝える

あなたは CDateDateSerial の見学をしたかったわけではありません。「日付が dd/mm、金額がコンマ区切りのこのエクスポートを読んで、モデルに正しく取り込みたい」だけだった。IsDate でガードし、地域設定を釘付けにし、Val でなく CDbl を選び、曖昧な日付を組み直す頃には、変換の配管がマクロそのものになっています。ExcelMaster Agent なら、代わりにデータを説明できます — 「A 列の日付は日が先、B 列の金額はコンマ小数。本物の日付と数値に変換して」 — するとそれらを曖昧さなく解釈する Python を、ブックを先にバックアップしたうえで書き出します。無料で試す →

関連ガイド

よくある質問

VBA で文字列を数値に変換するには? ユーザー入力や地域化されたソースからの入力には CDblCLng を使います。地域の小数点区切りを尊重するからです:コンマ小数の環境では CDbl("3,14")3.14Val は自分が握る固定の英語形式の文字列にだけ使いましょう。Val は常に . を小数点として扱い、最初の非数字で止まるからです。

VBA の CStr と Str の違いは? CStr は数値をきれいにテキスト化し、地域設定に従います。Str は符号用に先頭空白を予約し(Str(123)" 123")、地域に関係なく常に . を小数点に使います。数値→テキストには CStr を選びましょう。

VBA の CDate が間違った日付を返すのはなぜ? CDate"01/02/2026" のような曖昧な文字列をマシンの地域設定で解釈するからです — 米国では 1 月 2 日、ヨーロッパの多くでは 2 月 1 日。DateSerial(2026, 2, 1) で部品から組んで地域非依存にし、CDate は ISO "2026-04-01" のような曖昧さのない書式に限って使いましょう。

VBA の CLng は丸める? 切り捨てる? CLng(と CInt)は丸めます。銀行家の丸めで、CLng(2.5)2CLng(3.5)4。代わりに小数を切り捨てるなら IntFix、切り上げ丸めなら WorksheetFunction.Round。なお CInt は 32,767 を超えるとオーバーフローするので、大きな値には CLng を使います。

VBA の変換で「型が一致しません」を避けるには? 先に入力を判定します:If IsNumeric(s) Then n = CDbl(s)If IsDate(s) Then d = CDate(s)。このガードが、紛れ込んだ非数値や無効な日付文字列がループの途中で実行時エラーを起こすのを防ぎます。