Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


1392 / 13646 ツリー ←次へ | 前へ→

【74718】セルの書き換え手法2点の違いを教えてください。 化け猫 13/9/3(火) 1:42 質問[未読]
【74719】Re:セルの書き換え手法2点の違いを教えてく... 化け猫 13/9/3(火) 5:20 発言[未読]
【74720】Re:セルの書き換え手法2点の違いを教えてく... ichinose 13/9/3(火) 6:18 発言[未読]
【74726】Re:セルの書き換え手法2点の違いを教えてく... 化け猫 13/9/4(水) 4:51 発言[未読]
【74727】Re:セルの書き換え手法2点の違いを教えてく... ichinose 13/9/4(水) 6:34 発言[未読]
【74728】Re:セルの書き換え手法2点の違いを教えてく... 13/9/4(水) 7:41 回答[未読]
【74731】Re:セルの書き換え手法2点の違いを教えてく... kanabun 13/9/4(水) 10:47 発言[未読]
【74733】Re:セルの書き換え手法2点の違いを教えてく... ichinose@食事中 13/9/4(水) 12:58 発言[未読]
【74747】Re:セルの書き換え手法2点の違いを教えてく... 化け猫 13/9/6(金) 23:32 発言[未読]
【74749】Re:セルの書き換え手法2点の違いを教えてく... ichinose@ 13/9/7(土) 7:51 発言[未読]
【74753】Re:セルの書き換え手法2点の違いを教えてく... 化け猫 13/9/7(土) 11:39 お礼[未読]
【74751】Re:セルの書き換え手法2点の違いを教えてく... kanabun 13/9/7(土) 8:45 発言[未読]

【74718】セルの書き換え手法2点の違いを教えてく...
質問  化け猫  - 13/9/3(火) 1:42 -

引用なし
パスワード
   皆様こんばんわ。
セルの値を書き換える手法として以下2点の違いを教えてください。

1.
  Dim MyRange As Range
   Set MyRange = Range("B4:F8")
  Dim MyV As Variant
   Set MyV = MyRange
  とし

  MyV = .....

  MyRange = MyV で書き換え

2.
  Dim MyV As Variant
   Set MyV = Range("B4:F8")

  MyV = .....  で書き換え

【74719】Re:セルの書き換え手法2点の違いを教えて...
発言  化け猫  - 13/9/3(火) 5:20 -

引用なし
パスワード
   補足します。

前述した絵画部分のコードは、どちらも恒常ループ内に書かれたものです。

前者の方法1で絵画した場合には、恒常ループを抜けた際に絵画は全てクリアされました
後者の方法2では、クリアされませんでした。

私自信は、コードを見る限り後者の動作が妥当のように見え、前者1の結果が理解できません。

【74720】Re:セルの書き換え手法2点の違いを教えて...
発言  ichinose  - 13/9/3(火) 6:18 -

引用なし
パスワード
   おはようございます。

>セルの値を書き換える手法として以下2点の違いを教えてください。
>
>1.
>  Dim MyRange As Range
>   Set MyRange = Range("B4:F8")
>  Dim MyV As Variant
  MyV = MyRange.value
  '↑ここは、こうではないですか?

>
>  MyV = .....
>
  MyRange.value = MyV 'プロパティを記述する習慣を付けた方がよいです

  ’わかりやすいし、まれに付けた時と付けない時とで処理が違う場合があります


  ’このようにセル範囲の値を配列として変数に格納し、編集し、元のセル範囲に
  ’戻す という手法、変数上での値の編集の方が処理速度が速いのでよく使われますよ


>2.
>  Dim MyV As Variant
>   Set MyV = Range("B4:F8")
>
>  MyV = .....  で書き換え

【74726】Re:セルの書き換え手法2点の違いを教えて...
発言  化け猫  - 13/9/4(水) 4:51 -

引用なし
パスワード
   > ichinoseさん

お返事ありがとうございます。

しかし、私の疑問は以下です。
他の方にも教えていただけると助かります。

○ケース1

Dim MyRange As Range
Set MyRange = Range("B4:G4")

Dim MyV As Variant
Set MyV = MyRange

Do

  MyV = .....
  MyRange = MyV

Loop


○ケース2

Dim MyV As Variant
Set MyV = Range("B4:G4")

Do

  MyV = .....

Loop

上記ケースの違いは、ケース1がDo Loopを抜けた際に、B4:G4の出力値をクリアするのに対し、ケース2はクリアされないということです。

ケース1のどこにクリア処理に該当する部分があるのか気になっているのです。

【74727】Re:セルの書き換え手法2点の違いを教えて...
発言  ichinose  - 13/9/4(水) 6:34 -

引用なし
パスワード
   >
>しかし、私の疑問は以下です。
>他の方にも教えていただけると助かります。
>
>○ケース1
>
>Dim MyRange As Range
>Set MyRange = Range("B4:G4")
>
>Dim MyV As Variant
>Set MyV = MyRange
>
>Do
>
>  MyV = .....
>  MyRange = MyV
>
>Loop
この
>  MyV = .....
きちんとコードを記述していただいて、
ループも適当なタイミングで抜けるようにして、
仰りたい現象を誰もが経験できるようにした頂いた方がよいです。

Sub sample1()
 Dim MyRange As Range
 Set MyRange = Range("B4:g4")
 Dim MyV As Variant
 Set MyV = MyRange
 MyV.Value = 123
 MsgBox "ok"
 MyRange = MyV
End Sub

上記で同じような現象が再現できますよね!!

www.excel.studio-kazu.jp/kw/20101203205934.html
www.excel.studio-kazu.jp/kw/20101209011132.html
www2.aqua-r.tepm.jp/~kmado/kcolumn.htm
↑関連サイトです


前回投稿の
>’わかりやすいし、まれに付けた時と付けない時とで処理が違う場合があります

のよい例だと思います。


上記のコードを

Sub sample1()
 Dim MyRange As Range
 Set MyRange = Range("B4:g4")
 Dim MyV As Variant
 Set MyV = MyRange
 MyV.Value = 123
 MsgBox "ok"
 MyRange.value = MyV.Value
End Sub

ちゃんと値がはいります。

【74728】Re:セルの書き換え手法2点の違いを教えて...
回答    - 13/9/4(水) 7:41 -

引用なし
パスワード
   こんにちは。

ケース1は簡略化してこのようにしても、同じ現象になりますね。
  Dim MyRange As Range
  Set MyRange = Range("B4:G4")
  
  MyRange = MyRange


自分自身を代入している(ように見える)のに不思議です。
そこでためしに下記のようにしてみたところ、1〜3では現象が出ず
4で発症します。

1)  Set MyRange = MyRange
2)  MyRange.Value = MyRange.Value
3)  MyRange = MyRange.Value
4)  MyRange.Value = MyRange

3の左辺は代入される側なので、エクセルが.Valueを補ってくれ
るが、4の右辺はそうではないので.Valueを補われず、値代入的
にはカラッポとみなされている、ということのようです。

【74731】Re:セルの書き換え手法2点の違いを教えて...
発言  kanabun  - 13/9/4(水) 10:47 -

引用なし
パスワード
   変数myV の型を Variant で行くか、Rangeで行くかでも
挙動が変わってきますね

--------------------------------------- ケース2
[変数myV はVariant]
Sub Variant_Case2()
 Dim myV As Variant
 Set myV = Range("B4:G4")
 myV = 123      '[B4:G4] 変化なし
End Sub

[変数myV はRange型]
Sub Range_Case2()
 Dim myV As Range
 Set myV = Range("B4:G4")
 myV = 123   '[B4:G4]が123に変わる!

End Sub
Range型にすると、
 Let myV.Value = 123
と解釈されてるようです。

--------------------------------------ケース1
[変数myV はVariant]
Sub Variant_Case1()
 Dim MyRange As Range
 Set MyRange = Range("B4:G4")
 MyRange.Value = Split("あ い う え お か") '初期化
 
 Dim myV As Variant
 Set myV = MyRange
 myV = 123    '[B4:G4] 変化なし
 MyRange = myV  '← ◆ どのセルにも 123 が代入される
End Sub
変数myV は、はじめ
> Set myV = MyRange
として Rangeオブジェクトをセットしていますが、
次のステートメント
> myV = 123
では それとは関係なく 値が代入されているようです。

[変数myV はRange型]
Sub Range_Case1()
 Range("B4:G4").Value = Split("あ い う え お か") '初期化
 
 Dim myV As Range
 Set myV = Range("B4:G4")
 myV = 123   'Range型にすると[B4:G4]が123に変わる!

End Sub

---------------------------------------------------sample1
Sub sample1()
 Dim MyRange As Range
 Set MyRange = Range("B4:G4")
 MyRange.Value = Split("あ い う え お か") '初期化
 
 Dim myV As Variant
 Set myV = MyRange
 myV.Value = 123   '[B4:G4]に123が代入される
 MyRange = myV    '◆MyRangeには Emptyが代入される
End Sub
このときは
> Set myV = MyRange
でmyVに Range型 がセットされ、なおかつ
> myV.Value = 123   '[B4:G4]に123が代入される
で 変数myV をセットしたRangeオブジェクトとして使っているので
値(123) が myV.Valueにセットされたのでしょうか?
それで
> MyRange = myV    '◆MyRangeには Emptyが代入される
の行で MyRange.Valueが空白になるのは、
「左辺は配列の値(Value)を要求しているのに右辺はRangeオブジェクトで
配列では無いため、無効なデータとしてEmptyが代入される仕様」
によるものでしょうか?

【74733】Re:セルの書き換え手法2点の違いを教えて...
発言  ichinose@食事中  - 13/9/4(水) 12:58 -

引用なし
パスワード
   こんにちは。

>変数myV の型を Variant で行くか、Rangeで行くかでも
>挙動が変わってきますね

展開によっては、プロパティは、付けておくのがよい という例で
このVariant型の例を投稿するつもりでした。

Variant型なんですから、どんな型でも代入できることから、

> Dim myV As Variant
> Set myV = Range("B4:G4")
> myV = 123      '
  msgbox typename(myv)

で確認すれば Integer と表示されるので、もはや
Range("B4:G4")とは、関係がないからですよね!!


>---------------------------------------------------sample1
>Sub sample1()
> Dim MyRange As Range
> Set MyRange = Range("B4:G4")
> MyRange.Value = Split("あ い う え お か") '初期化
> 
> Dim myV As Variant
> Set myV = MyRange
> myV.Value = 123   '[B4:G4]に123が代入される
> MyRange = myV    '◆MyRangeには Emptyが代入される
>End Sub


>このときは
>> Set myV = MyRange
>でmyVに Range型 がセットされ、なおかつ
>> myV.Value = 123   '[B4:G4]に123が代入される
>で 変数myV をセットしたRangeオブジェクトとして使っているので
>値(123) が myV.Valueにセットされたのでしょうか?
そうだと思います。


>それで
>> MyRange = myV    '◆MyRangeには Emptyが代入される
>の行で MyRange.Valueが空白になるのは、
>「左辺は配列の値(Value)を要求しているのに右辺はRangeオブジェクトで
>配列では無いため、無効なデータとしてEmptyが代入される仕様」
>によるものでしょうか?
たぶん、オブジェクトが渡されると、左辺のValueでは、
右辺のオブジェクトの既定のプロパティまでチェックするんです。
で、既定のプロパティである.Valueが配列だと、Emptyを返します。
単体の値だと正常に値を設定します。

Sub sample2()
 Dim MyRange As Range
 Set MyRange = Range("B4:g4")
 Dim myV As Variant
 Set myV = Range("a1")
 myV.Value = 123
 MsgBox "ok"
 MyRange = myV
End Sub

参考に以下の二つのプロシジャーも実行してみてください。
前回投稿のリンク先でも例にあげていました。

Sub sample3()
Dim MyRange As Range
Set MyRange = Range("B4:g4")
Dim myV As Variant
Set myV = Range("a1,c1:f1")
 myV.Value = 123
MsgBox "ok"
MyRange = myV
End Sub
Sub sample4()
Dim MyRange As Range
Set MyRange = Range("B4:g4")
Dim myV As Variant
Set myV = Range("c1:f1,a1")
 myV.Value = 123
MsgBox "ok"
MyRange = myV
End Sub


自作クラスで既定のプロパティを値、配列、オブジェクトにして試してみると
もっと考察できるかもしれません。

【74747】Re:セルの書き換え手法2点の違いを教えて...
発言  化け猫  - 13/9/6(金) 23:32 -

引用なし
パスワード
   > 皆様

お騒がせしております。
そして、レスが大変遅くなり申し訳ありません。
簡単に状況を再現してみましたので、報告させていただきます。

以下の文をケース1~4とし、各々プログラムに組み込むとします。

ケース1: MyV = MyF
     結果、これでは描画されない。
ケース2: MyV = MyF
     MyRange = MyV
     結果、描画される。
ケース3: MyV(1,1) = MyF(1,1)
     結果、(1,1)の該当セルのみ描画される。
ケース4: MyV(1,1) = MyF(1,1)
     MyRanage = MyV
     結果、描画されるがDo Loopを抜けるとクリアされる。


Option Explicit
Declare Function GetTickCount Lib "kernel32" () As Long
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)


Sub kakunin()

  Dim MyRange As Range
  Set MyRange = Range("B4:G4")
  
  Dim MyV As Variant
  Set MyV = MyRange
  
  Dim MyF As Variant
  Set MyF = Worksheets("確認").Range("B5:G5")
  
  Dim StartTime As Long
  Dim WaitTime As Long
    
  StartTime = GetTickCount
  WaitTime = Range("B3")
  
  Do
      
    "ケース1~4"
    
    If (GetTickCount - StartTime) > WaitTime Then
      
      Exit Do
      
    End If
    
    DoEvents
    
  Loop
    
End Sub

どういう理屈なのか今一度考えてみようと思います。
解説いただける方がいれば、よろしくお願いいたします。

【74749】Re:セルの書き換え手法2点の違いを教えて...
発言  ichinose@  - 13/9/7(土) 7:51 -

引用なし
パスワード
   この現象にループは関係ないので、
ループは外した方が例としては、簡素化されてよいと思います。

でも、このように例題コードを記述されること自体すごいですねえ!!

結論は、繰り返しになりますが、オブジェクトのプロパティは、記述するに
尽きるのですが。
現象のポイントは、

1 MyVという変数は、Variant型なので、色んな型の値がはいることができます。  書式の記述の仕方次第でRange型変数から、違う型の変数に変化すること

2 Rangeオブジェクトの代入式(MyRanage = MyV)において、右辺(MyV)に
  プロパティを記述しないと左辺側で既定のプロパティをチェックし、Valueプロパティが配列だとEmptyに設定する


「2」については、既投稿をよく読んでください

 MyVというVariant型変数が どの型の変数に代わっていくのかを
 追ってみるとよいです
ケース1の場合

Declare Function GetTickCount Lib "kernel32" () As Long
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub test1()
  Dim MyRange As Range
  Set MyRange = Range("B4:G4")
  Dim MyV As Variant
  Set MyV = MyRange
  Dim MyF As Variant
  Set MyF = Range("B5:G5")
  Dim StartTime As Long
  Dim WaitTime As Long
  StartTime = GetTickCount
  WaitTime = Range("B3")
  MsgBox TypeName(MyV)
  Do
     MyV = MyF
     MsgBox TypeName(MyV)
     If (GetTickCount - StartTime) > WaitTime Then
      Exit Do
     End If
     DoEvents
  Loop
End Sub

ループに入る直前の確認では、確かにMyVという変数は、Range型と表示されます。
が、
     MyV = MyF
     ↑これの実行直後の
     MsgBox TypeName(MyV)

は、Variant() と表示されます。
つまり、MyVという変数は、ただの配列が格納されているのです。
セル範囲Range("B4:G4")とは、無関係になっています。
よって、見た目には何の変化も起こりません。

MyV = MyF

MyV.Value=MyF.Value

と代えるだけでMyVをRange型変数だと解釈し、値が入ります。


ケース2の場合

Sub test2()
  Dim MyRange As Range
  Set MyRange = Range("B4:G4")
  Dim MyV As Variant
  Set MyV = MyRange
  Dim MyF As Variant
  Set MyF = Range("B5:G5")
  Dim StartTime As Long
  Dim WaitTime As Long
  StartTime = GetTickCount
  WaitTime = Range("B3")
  MsgBox TypeName(MyV)
  Do
     MyV = MyF
     MsgBox TypeName(MyV)
     MyRange = MyV
     If (GetTickCount - StartTime) > WaitTime Then
      Exit Do
     End If
     DoEvents
  Loop
End Sub

test1と同様、MyVという変数は、ループ内で Variant()と表示されています。

MyRange = MyV 
配列変数をRange型の変数のValueプロパティ(既定のプロパティ)への代入は、
よく使われる手法ですから、Myrangeで規定されたセル範囲に値が設定されます。


ケース3

Sub test3()
  Dim MyRange As Range
  Set MyRange = Range("B4:G4")
  Dim MyV As Variant
  Set MyV = MyRange
  Dim MyF As Variant
  Set MyF = Range("B5:G5")
  Dim StartTime As Long
  Dim WaitTime As Long
  StartTime = GetTickCount
  WaitTime = Range("B3")
  MsgBox TypeName(MyV)
  Do
     MyV(1, 1) = MyF(1, 1)
     MsgBox TypeName(MyV(1, 1))
     If (GetTickCount - StartTime) > WaitTime Then
      Exit Do
     End If
     DoEvents
  Loop
End Sub

MsgBox TypeName(MyV(1, 1))は、Range と表示されます。

MyV(1, 1)は、正確には、 MyV.item(1,1)です。

MyV(1, 1) この書式で記述した時点でMyvという変数をRange型の変数だと
解釈してくれているということです。

よって、セルB4にだけ 値が設定されます。

ケース4

Sub test4()
  Dim MyRange As Range
  Set MyRange = Range("B4:G4")
  Dim MyV As Variant
  Set MyV = MyRange
  Dim MyF As Variant
  Set MyF = Range("B5:G5")
  Dim StartTime As Long
  Dim WaitTime As Long
  StartTime = GetTickCount
  WaitTime = Range("B3")
  MsgBox TypeName(MyV)
  Do
     MyV(1, 1) = MyF(1, 1)
     MsgBox TypeName(MyV)
     MyRange = MyV
     If (GetTickCount - StartTime) > WaitTime Then
      Exit Do
     End If
     DoEvents
  Loop
End Sub

上記では、MyRangeもMyVもRange型変数です。

MyRange = MyV
これには前述のポイント2が関係してきます。

>Rangeオブジェクトの代入式(MyRanage = MyV)において、右辺(MyV)に
  プロパティを記述しないと左辺側で既定のプロパティをチェックし、Valueプロパティが配列だとEmptyに設定する

以上です。Rangeオブジェクトの規定のプロパティValueをオブジェクト内にある
ただの変数という解釈だと中々理解できませんよ!!
Valueと命名されたプログラムだと解釈してください。

それと、ご自分でオブジェクトを作成してみると、何となく理解できてくると
思います。

【74751】Re:セルの書き換え手法2点の違いを教えて...
発言  kanabun  - 13/9/7(土) 8:45 -

引用なし
パスワード
   ▼化け猫 さん:

私からも再度...

>  Dim MyV As Variant
>  Set MyV = MyRange

Rangeオブジェクトをセットするんなら、変数 MyV は
Dim MyV As Range
と宣言してください。そこを なぜか? MyV As Variant で宣言するから
混乱に拍車がかかるんだと思います。
そして、Rangeオブジェクトの「値を」代入するなら MyV.Value のように
.Value プロパティを省略しない!

この2点に気をつけて、異なる結果になることがあるのは何故?
と、問題点を絞っていってください。

●Range型オブジェクトは As Variant でなく As Range で宣言する
●Rangeの「値」を使うなら .Value (または .Value2)プロパティを省略しない


>> 皆様
>
>お騒がせしております。
>そして、レスが大変遅くなり申し訳ありません。
>簡単に状況を再現してみましたので、報告させていただきます。
>
>以下の文をケース1~4とし、各々プログラムに組み込むとします。
>
>ケース1: MyV = MyF
>     結果、これでは描画されない。
>ケース2: MyV = MyF
>     MyRange = MyV
>     結果、描画される。
>ケース3: MyV(1,1) = MyF(1,1)
>     結果、(1,1)の該当セルのみ描画される。
>ケース4: MyV(1,1) = MyF(1,1)
>     MyRanage = MyV
>     結果、描画されるがDo Loopを抜けるとクリアされる。
>
>
>Option Explicit
>Declare Function GetTickCount Lib "kernel32" () As Long
>Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
>
>
>Sub kakunin()
>
>  Dim MyRange As Range
>  Set MyRange = Range("B4:G4")
>  
>  Dim MyV As Variant
>  Set MyV = MyRange
>  
>  Dim MyF As Variant
>  Set MyF = Worksheets("確認").Range("B5:G5")
>  
>  Dim StartTime As Long
>  Dim WaitTime As Long
>    
>  StartTime = GetTickCount
>  WaitTime = Range("B3")
>  
>  Do
>      
>    "ケース1~4"
>    
>    If (GetTickCount - StartTime) > WaitTime Then
>      
>      Exit Do
>      
>    End If
>    
>    DoEvents
>    
>  Loop
>    
>End Sub
>
>どういう理屈なのか今一度考えてみようと思います。
>解説いただける方がいれば、よろしくお願いいたします。

【74753】Re:セルの書き換え手法2点の違いを教えて...
お礼  化け猫  - 13/9/7(土) 11:39 -

引用なし
パスワード
   > ichinoseさん

早いレスありがとうございます。(^<^)
さすがですね!
なんとなーくですがわかったような気がします。
もう少し、頭の中で吟味してみます。

あとTypeName()は知りませんでした...
色々試してみます。

> kanabunさん

レスありがとうございます。(^<^)
kanabunさんの言うとおりですね。
今回私は、実際になにが起きているのかが気になり、
理解を深めたかったのです。

色々とアドバイスくださりありがとうございます。

1392 / 13646 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free