こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

エクセル上のVBA

当方、VBAまるっきり初心者です(触りはじめて3日くらい)。
エクセルはある程度理解しているつもりですが…
バージョンはエクセル2000です。

他シートのセルのひとつに入力すれば、
別シートのセルがそれを参照したうえで
値として表示出来るようにならないでしょうか。


 今のところ、以下のような状況です。

step01 sheet1のセルA1に任意の数値(整数限定です)を入力。

step02 sheet2のセルA1に、sheet1のセルA1の数値を用いて
    MOD関数で余りを出す。

step03 sheet2のセルB2に以下のVBAによって
    step02の余りを値として表示。

     Private Sub Worksheet_Change(ByVal Target As Range)
       Range("b2").Value = Range("a1")
     End Sub


 これだとsheet1の数字を変えても、
sheetの切替後sheet2のセルB2に
表示される値が変わってくれません。

 最初の入力(step01の入力)をおこなえば
sheet2のセルB2まで値が変わってくれるような方法を
教えていただけないでしょうか。

 拙い説明で申し訳ありませんが、よろしくお願いします。

投稿日時 - 2009-05-06 23:06:12

QNo.4937377

困ってます

質問者が選んだベストアンサー

答えは非常に簡単です。
>step03 sheet2のセルB2に以下のVBAによってstep02の余りを値として表示。
>Private Sub Worksheet_Change(ByVal Target As Range)
> Range("b2").Value = Range("a1")
>End Sub
とありますが、これはSheet2のコードにこのマクロを書き込んでいますよね?
その場合はWorksheet_Changeイベントの意味は「Sheet2がChangeされた時」になるのです。ですので、Sheet1のA1を変更してもSheet2は何も起こらないわけです。ためしに現状のマクロですとSheet2のどこかを変更してみると値が反映されるはずです。
これを解決するには、Sheet2のコードにではなく、Sheet1のコードのWorkSheet_Changeに書き込んであげるとよいです。そうすると「Sheet1がChangeされた時」になるのでSheet1のA1を変更するとそのマクロは動作するようになるのです。

答えのみですとそれだけですが、ちょこっとアドバイス。蛇足でしたらすみません。
Changeイベントにマクロを書き込むとどこか遠くの意図しないセルをいじってもこのマクロは実行されてしまいます。それを防ぐために
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = Range([目的のセル]).Address Then
'  (目的の動作のマクロをここへ記入)
End If
End Sub
とするといいですよ。
さらに、Sheet1のマクロの中でSheet2のセルの指定の仕方は、Sheet1のA1の値をSheet2のA1にコピーするのでしたらこうなります。
Sheet2.Range("A1").Value = Sheet1.Range("A1").Value
あと、マクロを使用する場合は、他のシートが参照するのではなく、参照しているように見える場所へマクロで書き込みをするという考え方のほうがいいですね。ですので、こうなります
Step1:Sheet1のA1の値が変わる
Step2-1:Sheet1のChangeイベントが発生する(入力などによって変更されたときのみChangeイベントが発生し、再計算による値の変化はChangeイベントは発生しません。たぶんこの部分を勘違いして詰まってるのかな?と思います)
Step2-2:Changeイベント内のマクロによりSheet1のA1の値を使ってSheet2のA1に余りを書き込む。(マクロの場合はAをBで割った余りは「余り = A Mod B」で求められます)
Step3:Sheet2のA1の内容をSheet2のB2に書き込む。
・・・なのですが、この手法の場合はStep2-2の時点で値として貼り付けできているので、Step2-2の結果の書き込み先をB2にしちゃってStep3は無くしてもいいかもしれませんね。
以上、長文になりましたががんばってください。

投稿日時 - 2009-05-07 01:18:00

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

こんにちは。

マクロを始めて数日で、イベント・ドリブン型のマクロに手を付けるというのは、早すぎるように思います。

簡単だと思う人もいるようですが、私は、本来、教える側ではなく作る側の人ですから、その質問内容では作ることができません。いろんな例が思い浮かんで、ひとつに絞り込むことはできません。

たぶん、掲示板に質問を出すということは、ある程度の目的があって、そういうものを作られているのかと思います。VBAの練習なら、いきなりイベント・ドリブン型はやめたほうが良いです。理由は、基本的な構文を知ってからのほうがよいからです。イベントの場合は、引数は、Applicationから渡されるものですから、そいう仕組みが多少でも分かってからのほうがよいです。Target はなぜあるのか、とか、いきなりというのは難しいです。

それから、

>step01 sheet1のセルA1に任意の数値(整数限定です)を入力。

これは問題ないと思います。

>step02 sheet2のセルA1に、sheet1のセルA1の数値を用いてMOD関数で余りを出す。
>step03 sheet2のセルB2に以下のVBAによってstep02の余りを値として表示。

ワークシートのMOD関数と、VBAのMOD演算子とは、その性質が違います。MOD関数はワークシートにあるのでしょうか。そこはどうしたらよいのでしょうか。文面からすると、シート2のA1に商、シート2のB2に余りのようですが。

投稿日時 - 2009-05-07 13:15:18

ANo.3

>sheetの切替後sheet2のセルB2に表示される値が変わってくれません。
プログラムとかの経験がまだ無いからこういう質問が出てしまうのだが、下記でも読んで、この件の奥が深いことを感じてもらえたらと思う。(エクセルの知識なんてコンピュタの勉強の極く一部の上澄みでしかない)
VBAでの答えは簡単なんだが、そこにいたる学習過程として、高度な考え方が顔を出す。
それは関係するセルの値が変わったら、再計算を自動的にするというのは、「セルのデータが変わったということを捉えて」
「どこが変わったかも含め」
「自分では常時監視できないので、通知をくれて」
「再処理実行をしてくれる仕組み」です。
自分(ユーザー側で)でたくさん有るセルの値が、毎時刻々に変わったか監視(例えば素人的にIF文で聞く)のはとてもじゃないが出来ない。その時間だけでコンピュター処理を占められて、自分のしたいことが出来ない。だからもっと基礎的、高い(深い)レベルでそういうことをしてくれる仕組みを作らないとならない。
こういう考えはコンピュターが始まって30年間ぐらいは、普通には(通信関連・オンラインシステムなどを除いて、大規模システム以外は)出来なかった。そのほかに入出力関係で、割り込み処理と言うのが必要で、そこまでは早くからOSが処理していた。
だから変更データは1日分とか集めて、区切り(例えば業務が終わる夜)の時刻に、変更に伴う関連箇所の変更をまとめてやっていた。オフラインバッチ処理と言う。
身近になったのは、パソコンが画面と対話する処理(ソフト)を普及させ、コンピュターの速度が格段に早くなり、Win系のOSがでてVBが身近になってからだ。
こういうのをイベントと言います。エクセルに限らず、色んなところでイベントの考えは必要で、その体系化が必要になるがOSレベルで考えられている。
エクセルVBAではシートのChangeイベントであり、沢山あるイベントの1つで、どのセルの値が変わったか、判る(Target引数)ようになっている。
ーー
関数はその点では、エクセルの仕組みの中に、再計算が組み込まれていて、計算に使っている(引数にしている)セルの値が変わったら再計算している。それは処理的には大変なことだと思う。しかし今のパソコンの処理能力が向上したおかげで、何万百万のセルの再計算をしても辛抱しきれないほどの時間はかかっていない(エクセルの公称許容限度内でも、実際は使い物になら無いぐらい遅くなってしまう、式を入れているセルの数、式の引数の多さの程度はある。)
表計算ソフトにとって再計算は第1か2の大切な機能です。それが出来ないソフトが有るとすると、誰も見向きもしない。
A1セルが変更されたとき、一般にはコンピュターは、果たして他のセルでA1の値を使っているのか、どのセルの式で使っているのか、割り出すのは大変なはず。しかし世界の叡智が動員されて、内部的な処理技術が確立されているから、エクセルが使い物になっている。

投稿日時 - 2009-05-07 09:57:46

ANo.1

VBAは詳しくないのですが
>sheetの切替後
なら Sheet2のコードは次からはじめると思います
Private Sub Worksheet_Activate()

>最初の入力(step01の入力)をおこなえば
はこんなんかあなぁ Sheet1のコードに
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Range("a1"), Target) Is Nothing Then
Exit Sub
Else: Worksheets("sheet2").Range("b2").Value _
= Worksheets("sheet2").Range("a1")
End If
End Sub
参考まで

投稿日時 - 2009-05-06 23:52:12

あなたにオススメの質問