[リストへもどる]   [VBレスキュー(花ちゃん)]
一括表示

投稿時間:2006/06/01(Thu) 11:33
投稿者名:ダンボ
URL :
タイトル:
VBAマクロを入れ替えるマクロ
EXCEL2000のVBAです。
マクロ入りのブックを関係者に配布していますが、割と頻繁にマクロの更新が発生しています。
各ブックのシートデータは関係者毎に異なるので、今ある各ブックに対してマクロだけを誤りなく
入れ替えたいのです。具体的には標準モジュールのCommon.basだけを入れ替えます。

現在は私が各ブックを集めて、「Common.basの解放」→「Common.basのインポート」を
注意深くやっていますが、手間やミスが心配です。
ワンタッチで、各ブックのCommon.basだけを入れ替えるミニシステムのヒントを下さい。
(方式案1)各ブックに隠しボタンを入れておき、クリックすると「Common.basの解放」→
  「Common.basのインポート」を実行する。
 (問題点:ユーザがクリックするとまずい。)
 (疑問点:そのマクロはCommon.basに作るが、実行中の自分自身のモジュールを解放追加できるのか)
(方式案2)独立したツールをVBまたはVBAで作成し、各ブックの「Common.bas」モジュールを解放・追
加する。
 (疑問点:ブックの共通モジュールを解放・追加するコードが分からない)

方式案2が妥当かな?

投稿時間:2006/06/01(Thu) 11:48
投稿者名:Blue
Eメール:
URL :
タイトル:
Re: VBAマクロを入れ替えるマクロ
マクロでマクロを操作するには、VBProjectを使います。

私がよくみるExcel VBA専用の掲示板
hhttp://park7.wakwak.com/~efc21/cgi-bin/wwwlng.cgi
の過去ログの「VBProject」で検索してみて、該当のものがあるか探してみてください。
(おそらく、VBComponentのImportあたり)

投稿時間:2006/06/01(Thu) 19:30
投稿者名:ダンボ
Eメール:
URL :
タイトル:
Re^2: VBAマクロを入れ替えるマクロ
Blueさん、いつもありがとうございます。

基本的には下記コードで他のブックのCommon.basを入れ替えられそうです。
With WB.VBProject.VBComponents
    .Remove .Item("Common")
    .Import FNAME
End With

デバッグ中ですが.Remove .Item("Common")を発行しただけではWBのCommon.basが解放されていない。
次の.Import FNAMEではCommon1.basができてしまう。
ところがExcelに戻ってVBのデザインモードにした瞬間にCommon.basが解放されるように見えます。
対象ブックをデザインモードにする...てなコードは...無い...よね...

投稿時間:2006/06/02(Fri) 09:06
投稿者名:YK
Eメール:
URL :
タイトル:
Re^3: VBAマクロを入れ替えるマクロ
こんにちは。

> 基本的には下記コードで他のブックのCommon.basを入れ替えられそうです。
> With WB.VBProject.VBComponents
>     .Remove .Item("Common")
    此処で一旦閉じる
    開き直して
>     .Import FNAME
> End With

 でどうでしょう、検証はしていません。

>
> 次の.Import FNAMEではCommon1.basができてしまう。
はシートでも一旦閉じないと同じですね。

投稿時間:2006/06/02(Fri) 09:20
投稿者名:YK
Eメール:
URL :
タイトル:
Re^4: VBAマクロを入れ替えるマクロ
追伸です。

後はDeleteLinesで消して
InsertLinesで追加と言う方法もあります。

投稿時間:2006/06/02(Fri) 11:40
投稿者名:ダンボ
Eメール:
URL :
タイトル:
新たな問題(解決不能?)
YK さん、どうも有り難うございます。

Rmove-ImportにするかDeleteLines-InsertLinesにするか瞬時検討後、後者にしました。
理由:本来の目的を考えるとワークブックの開き直しはなんだか美しくない。
小問題点:Common.basの先頭にはAttribute文が付いている。そのまま読み込むとNG
対策:最後にDeleteLines 1をしても良いが、折角だからCommon.basの先頭行は配布日を記したコメント
行に置き換えておく。

Private Function MacroRewite(WB As Workbook, TS As Object)
    With WB.VBProject.VBComponents("Common").CodeModule
        .DeleteLines 1, .CountOfLines
        .InsertLines 1, TS.ReadAll
    End With
End Function

ところがですよ。解決不能な問題がありました。
配布したブックには他人にマクロを触られないようにVBProjectに保護を掛けてあるのです。
これを外さないとWith文のところでエラーになります。
ではVBProjectの保護を一時的に外すコーディングは...と考えてみると「あるのだろうけれどMSは教えな
い」
「それを許したら他人のマクロも上手に改竄できるから」

考えすぎですかね?>All

#いや、パスワードは何のためにあるのか。パスワードを指定すればVBProjectの保護を一時的に外す
メソッドがあるのではないか? 見あたりません...

投稿時間:2006/06/02(Fri) 12:16
投稿者名:ダンボ
Eメール:
URL :
タイトル:
Re: 新たな問題(解決不能?)
> #いや、パスワードは何のためにあるのか。パスワードを指定すればVBProjectの保護を一時的に外す
> メソッドがあるのではないか? 見あたりません...


「プロジェクト保護 解除」でググってみると、こんなのはある。う、美しくない。
しかも対象ブックをActiveにして表示しておかないと駄目なんだろう。

「解除の場合」
SendKeys "%{F11}", True
SendKeys "%T"
SendKeys "E"
SendKeys "password"

投稿時間:2006/06/02(Fri) 17:04
投稿者名:YK
Eメール:
URL :
タイトル:
Re^2: 新たな問題(解決不能?)
こんにちは。

パスワードの解除に関してはセキュリティ上詳しいことは控えます。
でも、SendKeysを使用しての方法が一般的だと思います。

投稿時間:2006/06/05(Mon) 10:50
投稿者名:ダンボ
Eメール:
URL :
タイトル:
SendKeysで苦戦
YK さん、皆さんどうも有り難うございます。

このマクロ配布ミニシステムは私一人しか使いません。作業手間とミスを防ぐのが目的なので
コードや動作が美しくなくてもいいです。なのでSendKeysでゴリゴリ行きます。

内部設計:
・被置換ワークブックを開く
・コードエディターを呼び出す
・プロジェクトペインにカーソルを移す
・被置換ワークブックはプロジェクトペインの一番下にある(確認済)のでそこまでカーソルを下ろす
・右矢印入力("%TE"の方が良いか?)でパスワードダイアログを開く
・パスワード記入+Enter

で下記コーディングとなりデバッグ中です。物が物だけにステップモードでの確認がしづらく
一気に実行すると、パスワードダイアログが開きません。当然保護が解除できずに後段で保護エラー
になります。どこら辺がおかしいでしょうかね?

Private Function CodeProtect(WB As Workbook) As Boolean
      WB.Activate
      MsgBox "確認"               '被置換ワークブックが最前画面にあることを確認
      SendKeys "%{F11}", True     'VBA Editorを呼ぶ
      SendKeys "^R", True         'Project Exlorerにカーソルを移す
'      SendKeys "{TAB}", True
      SendKeys "{DOWN}", True     'Project Exlorerの一番下に被置換モジュールがある
           :
      SendKeys "{DOWN}", True     'カーソルが一番下まで来た(あふれた下矢印は無視される)
      SendKeys "{RIGHT}", True    'パスワードダイアログを呼び出す
'      SendKeys "%TE", True       '        ("%TE"も試した)
      SendKeys "****", True       'パスワードを記入する(****は実際はパスワード文字列)
      SendKeys "{ENTER}", True   'パスワード入力完了して続行
End Function

投稿時間:2006/06/05(Mon) 16:13
投稿者名:YK
Eメール:
URL :
タイトル:
Re: SendKeysで苦戦
こんにちは。

こんな風でいけると思います。

If WB.VBProject.Protection Then
    CodeProtect WB
End If

Private Function CodeProtect(WB As Workbook) As Boolean
    WB.VBProject.VBE.Windows(1).SetFocus
    DoEvents
    SendKeys "%(TE)"
    Application.Wait Now + TimeValue("00:00:01")
    SendKeys "passward~"
    Application.Wait Now + TimeValue("00:00:01")
    SendKeys "~"
End Function

投稿時間:2006/06/08(Thu) 17:34
投稿者名:ダンボ
Eメール:
URL :
タイトル:
Re^2: SendKeys苦戦中
YK さん、コードご提示ありがとうございます。なかなか良い結果が報告できないので心苦しいです。
まず、いただいたコードをそのまま実行すると画面には何のダイアログも出ずに、
CodeProtect関数を通過して、後段で保護エラーになります(呼出元のWith句のところで)

Private Function CodeProtect(WB As Workbook) As Boolean
    WB.VBProject.VBE.Windows(1).SetFocus
    DoEvents
    SendKeys "%(TE)"
    Application.Wait Now + TimeValue("00:00:01")
    SendKeys "****~"    '****にはパスワード
    Application.Wait Now + TimeValue("00:00:01")
    SendKeys "~"
End Function

そこで下記のように直すと、
Private Function CodeProtect(WB As Workbook) As Boolean
    On Error GoTo 0
    MsgBox "CodeProtect確認"
    WB.VBProject.VBE.Windows(1).SetFocus
    DoEvents
    Application.Wait Now + TimeValue("00:00:01")
    SendKeys "****"
    SendKeys "{ENTER}", True    'パスワード入力完了して続行
    DoEvents
    Application.Wait Now + TimeValue("00:00:01")
    MsgBox "pause"
End Function

パスワード入力ダイアログは出るようになった。が、1分以上待っても****は表示されない。
そこで手でパスワードを入力してEnterを押すと"pause"のメッセージが出て続行するのですが、
後段のどこかで、「メモリーが"read"になることはできませんでした」となりアボートします。

投稿時間:2006/06/09(Fri) 08:48
投稿者名:YK
Eメール:
URL :
タイトル:
Re^3: SendKeys苦戦中
こんにちは。

先に提示したコードはエクセルのモジュールでテストしたものでした。
失礼しました。
VBでは

WB.VBProject.VBE.Windows(1).SetFocus
SendKeys "{ENTER}"
DoEvents
SendKeys "%(TE)"
DoEvents
SendKeys "passward" & "{ENTER 2}"
DoEvents

で良いと思われます。

投稿時間:2006/07/04(Tue) 12:40
投稿者名:ダンボ
Eメール:
URL :
タイトル:
[敗北宣言]SendKeys苦戦中
YKさん、長らく報告せずに済みませんでした。

最後にご提示いただいたコードも、実行するとすっぽ抜けて、後段で保護エラーに
なります。なんとか自力解決をと思っているうちに月日は流れて。。。
状況が変わり、マクロの更新作業が殆ど無くなりました。今回は私の負けということで
SendKeysによるパスワード解除はひとまずあきらめます。

ただ、YKさんの教え
・DoEventsを入れてみる。
・Waitを入れてみる。
・プロジェクトペインにTabで移動ではなくWindowsインデックスでアクセスする。
等々についてはしかと承りましたので次の次の戦いで活用します。

#次はね、トロイの木馬方式でやってみたいのです。
Public Function で固定場所の固定ファイルから読み込む関数を定義しておく。
マクロ更新時には、その関数を呼び出し、次で読み込まれたコードを実行する。