Excel (VBA)

Excel VBAに関するフォーラムです。
  • 掲示板への投稿には会員登録(無料)が必要です。会員登録がまだの方はこちら
  • 掲示板ご利用上のお願い」に反するご記入はご遠慮ください。
  • Q&A掲示板の使い方はこちらをご覧ください
トピックに返信
質問

 
(Windows 10全般 : Excel 2016)
WithとForEachを組み合わせたときのInの後について
投稿日時: 23/08/03 15:45:51
投稿者: ひろと

マクロマスターデータ(wbマスター)で作成した標準モジュールの初版を特定のフォルダに保存し(いちいちエクスポートするのが面倒なので.basは更新しない)、以後必要があればwbマスターの標準モジュールを随時更新し、各ブックに最新のマクロをインポートしようとしています。
この時、以下のコードの赤文字部分のスマートな書き方があれば教えて頂けないでしょうか
 

読込マクロ = Dir(フォルダ & "*.bas")
完了 = False
  Do While 読込マクロ <> ""
   コード = ""
   有無 = False
   With wbマスター.VBProject.VBComponents(fso.GetBaseName(読込マクロ)).CodeModule
    コード = .Lines(1, .CountOfLines)
   End With
   有無 = False

   With ThisWorkbook.VBProject.VBComponents
    For Each 書込マクロ In .Parent.VBComponents
     If 書込マクロ.Name = fso.GetBaseName(読込マクロ) Then
      Exit For
     End If
    Next 書込マクロ
    With .Item(fso.GetBaseName(読込マクロ)).CodeModule
     .DeleteLines 1, .CountOfLines
     .AddFromString コード
    End With
   End With
   読込マクロ = Dir()
  Loop

回答
投稿日時: 23/08/03 17:54:15
投稿者: Suzu

何が スマートではない で、何がスマート なのか・・
 
With で コレクションに対し操作を行っているにも関わらず
 
Parent.コレクション の様に
上位オブジェクトに戻って 参照し、そこから コレクションを参照し直しているのが気に入らない
って事でしょうか?
 
 
With の対象を 初めから 上位オブジェクトにすれば良いのでは?
 
または For Each ではなく
With ThisWorkbook.VBProject.VBComponents
  For i = 1 To .Count
     .Item(i).〜〜
  Next
End With
の様にすれば良いと思います。
 
でも・・
提示されたコード。。
問題にしている部分、必要があると思えません。
別に提示されていない何かがあるのかな??
 
そうだとしても、同じコレクションに対し、何度も名前チェックをするフローの方が気になります。
Dictionary を使うなり やりようはあると思います。

投稿日時: 23/08/03 18:05:11
投稿者: ひろと

Suzuさん
 
コメントありがとうございます。
.VBComponentsが比較的長い単語(?)なのでまとめたかったのですが、出来ないんですね。
他にも応用できると思っていたのですが、甘かったようです。
 
仰る通り、これだけだと該当部分は要らないですね…
実際には、ブックにより「読込マクロ」が無い場合があるため、質問部分付近は
以下のように、無いときは.basを持ってくる処理を入れています。
質問に関係ない部分なので省いていました。
Dictionaryについては使い慣れていないので、これを機に勉強し直そうと思います。
ありがとうございました。
 

    有無 = False
    With ThisWorkbook.VBProject.VBComponents
     For Each 書込マクロ In .Parent.VBComponents
      If 書込マクロ.Name = fso.GetBaseName(読込マクロ) Then
       有無 = True
       Exit For
      End If
     Next 書込マクロ
     If 有無 = False Then
      .Import フォルダ & 読込マクロ
     End If
     With .Item(fso.GetBaseName(読込マクロ)).CodeModule

回答
投稿日時: 23/08/03 18:11:02
投稿者: WinArrow

しようとしていること自体、理解することができませんが、
.bASファイルにエクスポートせずに、
「参照設定」する方法はダメなんですか?

投稿日時: 23/08/03 18:17:19
投稿者: ひろと

WinArrowさん
 
コメントありがとうございます。
 
参照設定だと、自分のパソコンでしか利用できない認識です。
対して、このエクセルはチームメンバーで共有や自PC以外(チーム共通PC)で使うため、せめて自PCで開いたときぐらいは更新してエクセル自体にコードを載せておきたいという思いから、こんな面倒なことをしています。

回答
投稿日時: 23/08/03 21:05:15
投稿者: WinArrow

>参照設定だと、自分のパソコンでしか利用できない認識です。
 
VBAで動的に参照設定可能です。
 
>以後必要があればwbマスターの標準モジュールを随時更新し、各ブックに最新のマクロをインポートしようとしています。
 
インポートするコードの内容が分からないので、
余計な心配かもしれませんが、
ワークシートのレイアウトは、各PCとも整合しているのでしょうか?

回答
投稿日時: 23/08/04 10:20:26
投稿者: Suzu

フラグの判定処理が入っているのですね。それであれば必要でしょう。
 
 

引用:
.VBComponentsが比較的長い単語(?)なのでまとめたかったのですが、出来ないんですね。
他にも応用できると思っていたのですが、甘かったようです。

 
おっしゃっている 意味を理解しかねます。
単語が長いので、タイプ数が増えるので面倒と言う事? オートコレクト機能を使えば気にする話では無いかと。
 
コレクションに
 Items プロパティーが有るコレクション
           無いコレクション
があるので、
 
Items が無い コレクション に対し With を使うと
 For Each の場合、今回の様な書き方
 Item数 の Index を使う 参照
のどちらかになるでしょね。
 
こればかりは仕様なので、諦めです。
 
---------------------------------------------------------------------
ご質問と、直接は関係ありませんが、先にも述べている
ループの中でループ処理を行っていると言いました。
 
気になったのは
 
Dir の ファイル数分、ループ処理を行いますが
 そのループ内で、ThisWowkBook の モジュール名 があるかどうかを
 毎回、TishiWorkBookから、参照しなおし、オブジェトに対しループを行い モジュール名の存在確認
 
 ・だったら、ループの外で、ThisWorkBookの対象に対し参照しましょうよ。
 ・どっちのオブジェクトも、処理の開始から終了の間に別のユーザーの干渉を受けにくい
  であるなら、毎回コレクションを参照する必要ないでしょう? 一度 名称リストを作成すれば良い
 
が気になりました。
 
同じリストに対し何度も一致判定をするのであれば
Dictionary を作り、Exists で判定の方が効率的と思っています。
 
 
また、モジュールのUpDateなのですから削除し、追加するのが良いと思います。
(ユーザーが コードの修正をしているのは、ユーザーに直させる)
 
今回の処理なら、
 
bas ファイル またはの一覧を Dictionary で作成
VBComponent の全数に対しループ処理
    同じ名称 が Dictionary に有ったら
        VBComponent の コードを削除
        インポートし直し
ループ処理
 
で良いと思います。

トピックに返信