Excel (VBA)

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

 
(指定なし : 指定なし)
『forEach文』の重さ&『VBAコードかエクセル条件付書式か』
投稿日時: 24/08/21 00:38:13
投稿者: けけちゃま

初心者となります。
まずはイメージエクセル表を説明します。
(イメージエクセルの画像が添付できず伝わりにくいかもしれませんがどうぞよろしくお願いいたします。)
 
A1値="月日"
B1値="時間"
C1値="メモ"
D1値="確認"
と入力しております(つまりエクセルの1行目は項目名となります)
 
A列にはmm/ddの月日がはいります。(その都度、エクセルに手入力です)
B列にはhh:mmの時間がはいります。(その都度、エクセルに手入力です)
C列は任意でメモをいれる予定です。(今回のコードには関与しません)
D列は、プルダウンで"済"を選択できるようにします。(つまり、"空欄"or"済" の2種類しか入力できないことになっております。
 
 
 
その表の横こにオートシェイプでボタンを設け、下記「Test」マクロを登録します。
「Test」マクロの作業は、D列が空欄である行を対象にし、A列とB列に登録した日時が、システム日時より24時間以上過去になる場合は、D列を赤色にするものです。
 
 

Public Sub Test()

      Dim testRange As Range
      Dim Table As Range

      Set Table = Range("A1").CurrentRegion
      Set Table = Table.Offset(1)
      Set Table = Table.Resize(Table.Rows.Count - 1)


          For Each testRange In Table.Rows

'@条件 Table範囲のうち「D列が空欄」かつ「A列に値がある」かつ「B列に値がある」とき下記の作業をする

       If testRange.Cells(1,4).Value = "" And testRange.Cells(1,1).Value <> "" And testRange.Cells(1,2).Value <> "" Then

'作業@日時がシステム日より2日以上前であればD列赤色にする

         If testRange.Cells(1,1) <= Date -2 Then

                        testRange.Cells(1,4).Interior.ColorIndex = 3

'作業A日時がシステム日の前日であり、時間がシステム時間より小さいときはD列を赤色にする(つまり24時間経過している)

         ElseIf testRange.Cells(1,1) = Date -1 And testRange.Cells(1,2) <= Time Then

                        testRange.Cells(1,4).Interior.ColorIndex = 3

                  End If


       End If

          Next

End Sub

 
 
(すみません、本命のコードを書いているパソコンが会社用であり、いま使っている私用パソコンにコピーができず手打ちになっております)
 
これで問題なく稼働はしたのですが、下記疑問が沸いております。
 
【疑問1】 行数がたとえ1000行になっても速度は遅くならないのか?
 
【疑問2】 VBA言語を使わなくても、エクセルの条件付き書式を使ったほうがファイルは軽いのか?
 
【疑問3】 仮にエクセルの条件付き書式に書き込めたとしても、行いたい作業(Test)は、ファイルを開いた時に1回するだけであり、定期的(1時間ごと)に確認するにはその都度ファイルを開き直さないといけないということか?(もしそれであれば今回のようにマクロを使ったほうが使いやすいのかな・・)
 
【+α】もっといいコードがあれば参考に教え頂けると嬉しいです。
 
以上となります。
本当基本的な関数くらいしかわからないですが、精進いたします。。。(苦手分野はファンクションプロシージャです)
お分かりになるかたがおられましたら、ご教示いただければ幸いです。

回答
投稿日時: 24/08/21 06:20:55
投稿者: simple

引用:
【疑問1】行数がたとえ1000行になっても速度は遅くならないのか?

 速い遅いは判断基準に依ります。ご自身で確認されたらどうですか?
 プロシージャの最初で Timerの値を変数に保持、終了した時点のTimerとの差が実行時間です。
引用:
【疑問2】VBA言語を使わなくても、エクセルの条件付き書式を使ったほうがファイルは軽いのか?

 一般的に、ワークシートに備わっているネイティブな機能はできるだけ使ったほうがよいと思われます。実行効率も高いはずです。
 この場合の判定は、 = A2 + B2 <= NOW()-1 ということになるでしょう。(値の空白条件は除いています)
 ただし、NOW()という揮発性関数を使うことにより、変更されたセルの位置にかかわらず、再計算のつど 実行されることに注意が必要です。影響度合いは確認してください。
引用:
【疑問3】仮にエクセルの条件付き書式に書き込めたとしても、行いたい作業(Test)は、
 ファイルを開いた時に1回するだけであり、定期的(1時間ごと)に確認するには
 その都度ファイルを開き直さないといけないということか?
 (もしそれであれば今回のようにマクロを使ったほうが使いやすいのかな・・)

  開いたときに自動実行されるわけではないと思いますが。
  比較する相手を特定セルとする内容( = A2 + B2 <= $G$1 - 1 )の条件付き書式を使うことにして、マクロでG1セルをNOW()の値に更新すればいいでしょう。(開き直す必要はありませんね。)
 それこそボタンに登録してポチが実際的でしょう。
 また、Application.OnTimeメソッドを使って、そのマクロを定期的に繰り返すこともできますが、
 個人的にはオーバースペックな気がします。(必要性がこちらには不明なので)
 (例えば、こちらのサイトの即効テクニック集に参考になりそうなコードがあります。必要ならトライしてみてください。
 https://www.moug.net/tech/exvba/0130009.html

 なお、そのマクロには条件を満たさないときの処理も必要な気がします。

回答
投稿日時: 24/08/21 10:56:07
投稿者: WinArrow

細かいことですが、
24時間経過判断個所で「Time」関数を「使っているが、
Time取得時点を、プロシジャ―開始時にした方がよいと思います。(分単位にしましょう)
 
 

回答
投稿日時: 24/08/21 11:37:09
投稿者: mattuwan44

>【疑問1】
1000行が多いか少ないか、処理が重くなるのかならないのか、
やってみないと分からないかと思います。
(それぞれ使っているパソコンの能力もありますし。)
 
>【疑問2】
昔のエクセルだと、個々に書式設定するとファイルが肥大化し重くなりました。
最近のエクセルだと改善されているかもです。
 
>【疑問3】
定期的にマクロを実行することは可能です。
参考URL>>
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q10233897815
 
>【+α】もっといいコードがあれば参考に教え頂けると嬉しいです。
データの日時は順に入力されるのか?あるいは、バラバラなのか?
そして、昇順または降順に並び替えてもよいのか?
あと、作業列を追加してもよいのか?
例えば、日付と時間を分けてセルに入力する仕様のようですが、
計算に使うには一つにまとめる必要があります。
時間の差も一つ列を設ければ、条件付き書式設定等の数式も簡単になるかと
思います。(作業列がなくても出来ますが、長く複雑な数式は読みにくいので)
入力は、ユーザーフォームを使うと、誤入力の防止やデータの表示が制御しやすいかと思いました。
 

投稿日時: 24/08/21 14:35:44
投稿者: けけちゃま

simple様
 
ありがとうございます。
 
【疑問1】
Timer関数は初めてしりました。
そして20列で計算してみたら0.015秒でしたので、100倍(2000列)だと1秒ほどと思えば、そこまでストレスはないのかなと思いました。
 
【疑問2】
そうですよね・・
エクセルの機能でできてしまうなら、そっちで作業をしたほうがいいですよね。
無駄にファイルを複雑化している気がしました。(私が)
(とはいってもエクセル関数については、さらに初心者なのでsimple様の式を参考にしながら、入れ子?を使って作ってみたいと思います。)
 
【疑問3】
なるほどですね(変な日本語ですみません)!。
G1にNOWをボタンポチでその都度更新し、そのG1の値に基づいて常に計算式をエクセルで組むということですかね。(リンクいただいた簡易時計も一応つかってみました。確かにオーバースペックかもしれませんが、なんか豪華がエクセルになりそうなので実用するかどうかは検討したいと思います。

投稿日時: 24/08/21 14:44:40
投稿者: けけちゃま

WinArrow 様
 
ありがとうございます。
全然細かくて大丈夫です(1個ずつ不完全な部分は潰していきたいのです)。
 
ElseIf testRange.Cells(1,1) = Date -1 And testRange.Cells(1,2) <= Time Then
 
のことですかね。
 

引用:
Time取得時点を、プロシジャ―開始時にした方がよいと思います。(分単位にしましょう)

 
ただ・・すみません、私の理解がおいつかず・・・どいうことでしょうか…泣

投稿日時: 24/08/21 15:05:01
投稿者: けけちゃま

mattuwan44 様
 
ありがとうございます。
 
【疑問1】
【疑問2】
そうですよね、一旦Timer関数を使って時間計算したる、エクセル関数版を作って実験してみます。
  
【疑問3】
リンクありがとうございます。
これも1分毎で条件書式発動でよいかと思うので参考にしたいと思います。
  
【+α】
イメージとしては、シェアポイントにエクセルを格納させて、会社のスタッフが毎日、各自入力していくとものなのです。
 
そのため日付は基本てきにはバラバラでなく、昇順になると思います。
ただし、8/19が30件 8/20が10件 8/21が15件と、同じ日時が数個はいることになります。
それぞれ時間は各スタッフがいつその仕事を渡されたを入力する時間なので、バラバラになります。
並び替えをすると、共有ファイルなので他のユーザーに迷惑をかけてしまうため、「並び替えはできない」想定でございます。
(だから、24時間こえたら、わかりやすいように赤色になるようにしてくれと言われたのです)
 

引用:
あと、作業列を追加してもよいのか?
例えば、日付と時間を分けてセルに入力する仕様のようですが、
計算に使うには一つにまとめる必要があります。
時間の差も一つ列を設ければ、条件付き書式設定等の数式も簡単になるかと
思います。(作業列がなくても出来ますが、長く複雑な数式は読みにくいので)

 
それであれば、B列のとなり(C列)にNOW()に設定して、そこからエクセル式で計算とかもよさそうですね。
個人的にVBAはユーザーフォームのときに成果大発揮と思っていて、こんかいエクセル関数を使うべきか、VBAコードを書くべきか沼ってしまいました。
ユーザーフォームで、4つの数字を入れると、0:00〜23:59の時間表記にするやり方がわからなくて汗(これは、同様の質問がないか探してみます。日付はISDATE判定でようやく作り慣れたのですが、次は時間判定をユーザーフォームづくりに挑戦してみましょうかね・・汗)。

回答
投稿日時: 24/08/21 16:02:32
投稿者: WinArrow

引用:
ただ・・すみません、私の理解がおいつかず・・・どいうことでしょうか…泣

 
Timeは、プロシジャ開始時点で取得し(変数に格納)、
セル毎の判断は変数を使うということです。
 
Time案数は秒単位で取得されます。
これを個々のセルと比較すると、同じ値のセルでも違った判断になります。
 

Dim hhmm As Date
    hhmm = Format(Time, "hh:mm")
 
蛇足
ユーザーフォームのテキストボックスの数字4桁を、Date変数に格納するコード
Dim hhmm As Date
    With Me.TextBox1
        hhmm = TimeValue(Format(.Text, "00:00"))
   End With
 
数字3桁でも対応しています。
数字が、時刻として使えるかのチェックは、ご自分で考えてください。

回答
投稿日時: 24/08/21 16:27:07
投稿者: mattuwan44

>これも1分毎で条件書式発動でよいかと思う
 
条件付き書式設定なら、リアルタイムで更新されるのではないでしょうか?
 
>並び替えをすると、共有ファイルなので他のユーザーに迷惑をかけてしまうため、
>「並び替えはできない」想定でございます。
>(だから、24時間こえたら、わかりやすいように赤色になるようにしてくれと言われたのです)
 
並び替えが出来ない理由がよくわかりませんし、入力順が重要なら、
マクロで順番を記録しておけば、すぐに復帰はできるかなぁ。。。
簡易データベースとして使用するシートと見せるシートと分けるのもありかも?
なんならオートフィルターやらピボットテーブルやらで、
見たいものだけ表示させたほうがいいかも?
1000件2000件とデータが増えたら、かなり見難いことになるかも。

回答
投稿日時: 24/08/21 17:07:55
投稿者: WinArrow

揮発性関数を使っていた場合、
単純な件数倍という計算は当てはまらないのでは?

投稿日時: 24/08/21 21:23:37
投稿者: けけちゃま

WinArrow 様
 
ありがとうございます。
TIME関数の盲点(?)でした。
分単位の意味がわかりました。
また補足もありがとうございます。
 
はい、時刻として使えるかのチェックについては自分でまずは考えてみます!
 

投稿日時: 24/08/21 21:33:31
投稿者: けけちゃま

mattuwan44 様
 
ありがとうございます。
確かに並び替えしたほうが見やすいですし、そのほうが24時間経過条件ももっとシンプルにできそうな気がしてきました…。
根本的なことになるかもしれませんが、その点をもう一度検討したいとおもいました(汗
 
また、色んな案もいただきありがとうございます!いずれも一度持ち帰って自分で整理したいと思います。
 
 
 
 
 

投稿日時: 24/08/21 21:39:05
投稿者: けけちゃま

皆様
 
この度はご教示、および色んなご意見をいただきありがとうございます。
 
今回は、一旦エクセル関数を挑戦しつつ、簡易時計マクロをおくか、別途現在時間セルを作ってみようと思います。
 
また計算の重さについても、
 

引用:
揮発性関数を使っていた場合、単純な件数倍という計算は当てはまらないのでは?

 
ともあるので、やはり地道に実験をしてみたいと思いました。
 
【疑問1】〜【疑問3】については、一旦解決をさせていただきます!
 
本当にありがとうございました!こんな早くにアドバイスをいただき大変たすかりました。