Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 7全般 : Excel 2013)
洗練された記述に直したい
投稿日時: 19/04/09 06:44:17
投稿者: beginner001

エクセルの表の中で、右端→下端→左端→上端 とセルの選択が5秒ごとに転位する記述を以下のように作ってみましたが、実に面白くない記述になりました。
この記述を洗練された記述に直したいと思いましたが、全く浮かびません。
どなたかお教えいただければと思い、初めて投稿しました。
よろしくお願いします。
 
 
Sub a3()
    Dim waittime, waittime2, waittime3 As Variant
    waittime = Now + TimeValue("0:0:05")
    waittime2 = Now + TimeValue("0:0:10")
    waittime3 = Now + TimeValue("0:0:15")
        ActiveCell.End(xlToRight).Select
            Application.Wait waittime
        ActiveCell.End(xlDown).Select
            Application.Wait waittime2
        ActiveCell.End(xlToLeft).Select
            Application.Wait waittime3
        ActiveCell.End(xlUp).Select
End Sub

回答
投稿日時: 19/04/09 07:49:41
投稿者: Suzu

なにを、洗練された記述 と言うのによりますが
 
繰り返しの記述を少なく。と言う事で。。
時刻計算を変数で受ける部分は直接 Waitに渡してしまって良いでしょう。
 
End の引数 として、xl 〜 の部分は
xlToRight :-4161
xlDown :-4121
xlToLeft :-4159
xlUp :-4162
 
と、計算等で出すのも面倒そうなので直接書く形。
繰り返す部分を、見やすく縦に並べるために 「:」で2命令を1行に・・
 
 

Sub sumple()
  Dim stTime As Date
  stTime = Now()
  ActiveCell.End(xlToRight).Select: Application.Wait stTime + TimeValue("0:00:05")
  ActiveCell.End(xlDown).Select:    Application.Wait stTime + TimeValue("0:00:10")
  ActiveCell.End(xlToLeft).Select:  Application.Wait stTime + TimeValue("0:00:15")
  ActiveCell.End(xlUp).Select
End Sub

回答
投稿日時: 19/04/09 20:43:16
投稿者: simple

私は、十分に簡素だと思いますし、面白くする必要もないと思います。
簡単なことは簡単にすますのが良いと思います。
 
もしどうしてもということなら、こんな手法もあります。

Sub main()
    Dim direction As Long
    Dim k As Long
    For k = 1 To 4
        direction = Array(xlToRight, xlDown, xlToLeft, xlUp)(k - 1)
        Application.OnTime Now() + TimeSerial(0, 0, 5 * (k - 1)), _
                           "'move " & direction & "'"
    Next
End Sub

Sub move(direction As Long)
    ActiveCell.End(direction).Select
End Sub

 
補足:
(1)Application.Waitは砂時計が出て興ざめなので、普通はWinAPIのSleepを使うことが多い。
(2)上記のようにApplication.OnTimeで将来の実行を予約することもできる。
   この場合は、砂時計は表示されず、時間がきたらプロシージャが実行されます。
(3)Application.OnTimeで指定するマクロは、普通は、引数を持たないことが多いが、
   上記のように引数を持たせることもできます。
 
参考にして下さい。
でも、簡単なことは簡単にしておいたほうがよいです。
# 引数付きマクロの予約実行がどうしても必要な時まで、
# 使わないほうがよいと思います。

回答
投稿日時: 19/04/10 21:10:27
投稿者: mattuwan44

洗練されたコードがどういうものかわかりませんが、
 
「だれが」「いつ」操作しても同じ結果を得たいなら、
ActiveCellという指定では、絶対同じ結果になると、担保されません。
 
ちゃんと、
初期値は、Range("A1")とか指定した方がよりよいかなと思います。
 
ちょっと、面白い書き方をご所望なので、参考までに
僕ならこう書くかなぁというサンプルを書いてみました。
 

Sub test()
    Const cMyCount As Long = 5
    Dim rngTopLeft As Range
    Dim rngTopRight As Range
    Dim rngBottomRight As Range
    Dim rngBottomLeft As Range
    Dim c As Range
    Dim i As Long

    With ActiveSheet.Range("A1").CurrentRegion      '表の範囲の
        Set rngTopLeft = .Cells(1)                  '左上
        Set rngTopRight = .Cells(.Columns.Count)    '右上
        Set rngBottomRight = .Cells(.Cells.Count)   '右下
        Set rngBottomLeft = .Cells(.Rows.Count, 1)  '左下
    End With

    For i = 1 To cMyCount
        For Each c In Union(rngTopLeft, rngTopRight, rngBottomRight, rngBottomLeft)
            c.Select
            Application.Wait Now + TimeValue("0:0:01")
        Next
    Next
End Sub

 
1周して終わりだと面白くないので、5周してみました。
何周か変えたければ、
   Const cMyCount As Long = 5
の部分を直せばよいです。
 
参考になれば。

投稿日時: 19/04/11 07:40:39
投稿者: beginner001

Suzuさん、ありがとうございました。
:を使われていたので、早速調べてみました。新しい知識でした。記述の中にNowを繰り返すのは確かに変ですね。こんなときは変数を作って渡してしまうのですね。勉強になりました。
 
simpleさん、ありがとうございました。
ちょうど今、繰り返しのFor〜bextの構文を勉強中ですので参考になりました。
簡素なことは簡素に表すですね。今の私にとっては難解な部分もありますが、粘り強く取り組んでみます。
 
mattuwan44さん、ありがとうございました。
For〜NextやWith〜End withがは分かったのですが、その他の部分では苦戦しています。粘り強くがんばります。