ExcelでINDIRECT関数を使って取得した数値が、VBAで数式を値へ変換した後に意図しない別の数値へ変化することがあります。特に「8」が「-118」のような値になる場合、Excel内部の日付シリアル値変換が関係している可能性があります。この記事では、INDIRECT関数の結果がVBA処理後に変化する原因と、数値を正しく保持するためのVBA記述方法について解説します。
INDIRECT関数の結果がVBA処理後に変わる原因
Excelのセルに表示されている値と、VBAが取得している値は必ずしも同じ扱いではありません。Excel内部では、数値・日付・文字列などを状況に応じて自動判定しています。
特にVBAで「c.Value = c.Value」のような処理を行うと、セルの数式を評価した結果を一度取得し、その値を再度セルへ書き戻します。このタイミングでExcelが値の型を再判定することがあります。
例えば、数式の結果が「8」という数字だった場合でも、Excelが日付として解釈できる状況では、内部的なシリアル値として扱われ、別の数値に変換される場合があります。
Excelの日付シリアル値による自動変換とは
Excelでは日付を内部的に連続した番号で管理しています。例えば、1900年1月1日を基準にして日付を数値として保存しています。
そのため、セルに入力された値が日付として扱われると、本来は単なる数字だったものが日付シリアル値へ変換されることがあります。
質問のように「8」が「-118」になるケースでは、VBAが値を書き戻す際に、Excelが日付型として解釈した結果、別形式のシリアル値として保存している可能性があります。
c.Value = c.Valueで発生しやすい問題
数式を値へ変換する目的でよく使われる「c.Value = c.Value」ですが、この方法は便利な反面、Excelの自動型変換の影響を受けます。
特に外部参照、INDIRECT関数、TEXT関数、日付関連のデータが混在する場合、Excelが値の種類を推測してしまうことがあります。
例えば、数式結果を文字列として保持したい場合でも、ValueプロパティではExcelが適切な型へ変換するため、意図しない結果になる場合があります。
値変換時に日付扱いを防ぐVBAの対処方法
数式結果をそのまま値として保存したい場合は、ValueではなくValue2を利用する方法が有効です。
VBAでは以下のように記述します。
Range(“V28”).Value2 = Range(“V28”).Value2
Value2は日付や通貨型への自動変換を行わず、Excel内部の値をそのまま扱います。そのため、日付シリアル値への誤変換を防ぎやすくなります。
通常の数値や文字列を扱う場合でも、特別な理由がなければValue2を利用することで予期しない型変換を避けられます。
文字列として固定したい場合の方法
取得した値を絶対に文字列として保持したい場合は、セルの表示形式を文字列に変更してから書き込む方法があります。
例えば、以下のような処理を行います。
Range(“V28”).NumberFormat = “@”
Range(“V28”).Value = Range(“V28”).Text
ただし、Textプロパティはセルの表示内容を取得するため、列幅や表示形式の影響を受けます。そのため、単純な値保持ならValue2のほうが安全です。
INDIRECT関数や外部参照を使う場合の注意点
INDIRECT関数は文字列から参照先を作成する便利な関数ですが、外部ブック参照ではファイルの状態やリンク状況によって結果の型が変わることがあります。
例えば、外部ファイルから取得した値が日付形式になっている場合、数式では正しく表示されていても、VBA処理時に日付型として認識されることがあります。
VBAで大量のセルを処理する場合は、値の取得方法や書き込み方法を意識することで、このような予期しない変換を防ぐことができます。
数式を値へ変換するときの推奨コード
複数セルを対象に数式を値へ変換する場合も、Value2を使用する方法がおすすめです。
例として以下のように記述できます。
Dim c As Range
For Each c In Selection
c.Value2 = c.Value2
Next c
この方法では、Excelの日付や通貨形式への自動変換を避けながら、数式結果を値として固定できます。
まとめ
INDIRECT関数で取得した「8」がVBA処理後に「-118」へ変化する場合、Excelの自動型変換、特に日付シリアル値への変換が原因になっている可能性があります。
「c.Value = c.Value」は簡単な数式固定方法ですが、値の種類によっては意図しない変換が発生します。数値をそのまま保持したい場合は「Value2」を使用することで、多くのケースで問題を回避できます。
Excel VBAでは表示上の値だけでなく、内部でどのデータ型として扱われているかを意識することが、予期しない変換トラブルを防ぐポイントになります。


コメント