配列からの値貼り付けに関する覚書 ② 値と数式の混在は成立しない場合がある(失敗談)
先日体験した失敗談からのご紹介。
例えば、こんなテーブルでのお話。
納期は基本的に、発注日の14日後だ。
ところが、このテーブルの使用者から、こんな要望が寄せられた。
- 果物によっては、納期が変わる場合があって、納期のセルを上書きしたい。
- 上書きの条件は複数様々あり、定まっていない。
- 手入力用の列は設けたくない。
列の内容が数式と手書きで混在するなどやりたくなかったが、要望だから
仕方がない。とここで、閃いた。例えば、こんな方法はどうだろう?
- 納期列に値を張り付けるための配列を準備する。
- もともと設定されていた数式を取得する。
- 各行をループし、上書き条件を満たす場合は値を、
それ以外の場合は数式をセットする。 - 3.を列に貼り付ける。
これは、我ながら中々の名案だと思った。早速試してみよう。今回は試しに、
「みかん」の時だけ納期を発注日の1週間後にしてみた。
Sub Test() Dim Tb As Excel.ListObject Set Tb = ActiveSheet.ListObjects(1) ' 値貼り付け先の範囲を設定。 Dim TargetRange As Range Set TargetRange = Tb.ListColumns("納期").DataBodyRange ' もともと設定されている式を取得。 Dim FormulaText As String Dim r As Range For Each r In TargetRange If r.HasFormula Then FormulaText = r.Formula Exit For End If Next ' 貼り付け用の配列を取得。貼り付け先の範囲を一旦配列に ' 格納することで、配列のサイズ調節を省略。 Dim TargetArray As Variant TargetArray = TargetRange ' 品名が「みかん」のとき、納期を発注日の1週間後に設定。 ' それ以外の品名ならば、もともとの数式を残しておく。 Dim i As Long For i = 1 To Tb.ListRows.Count If Tb.ListRows(i).Range(Tb.ListColumns("品名").Index) = "みかん" Then TargetArray(i, 1) = Tb.ListRows(i).Range(Tb.ListColumns("発注日").Index) + 7 Else TargetArray(i, 1) = FormulaText End If Next ' 配列を値貼り付け。 TargetRange = TargetArray End Sub
さて、実行した結果は・・・何も変わらなかった。どうして?
貼り付け直前の配列の中身を見ると、「みかん」はちゃんと納期の
1週間後になっている。
その後の確認で、「みかん」を「りんご」に、つまり配列の先頭が数式でなく
した場合は、意図した結果になることがわかった。
以上のことから、次のようなルールがあると推測される。
- 配列の先頭が数式であって、且つ貼り付け先がテーブルである場合、
以降の行の値が何であっても、その列は全て先頭の式で満たされる。 - 配列の先頭が値である場合、その列は数式と値が混在しうる。
良い方法を見つけたと思ったのだが・・・失敗です。
参考まで。