14

Chip Pearson のコードを使用して、既存の VBA コード モジュールを別のプロジェクトからのインポートで上書きしようとしています。元のコードはこちら.

私が見ている特定のセクションは次のとおりです。

With ToVBProject.VBComponents
    .Remove .Item(ModuleName)
End With

ただし、このVBComponents.Remove呼び出しが実際に有効になるのは、VBA の実行が停止した場合のみです。つまり、すべてのステートメントが終了するまで、またはコードがブレークポイントに到達してデバッグを停止するまで、削除操作は有効になりません。これは、新しいモジュールをインポートするか、既存のモジュールのコードを新しいモジュールに置き換えるための次のコードが原因で問題になります。

    Set VBComp = Nothing
    Set VBComp = ToVBProject.VBComponents(CompName)

    If VBComp Is Nothing Then
        ToVBProject.VBComponents.import filename:=FName
    Else
        If VBComp.Type = vbext_ct_Document Then
            'delete the module's code,
            'import a temp module,
            'copy over the temp module code,
            'delete the temp module
        End If
    End If

モジュールの削除はまだ有効になっていないためVBCompNothingデバッガーが知る限り有効ではありません。したがって、.importは呼び出されません。

if VBComp.Type = vbext_ct_document thenandをコメントアウトしてend if、新しいモジュールのコードが既存のモジュールを上書きするようVBComp.Typeにしても、コードの実行が終了するとモジュールは削除されてしまい、それを置き換えるインポートは発生しません。

奇妙なことに、これはすべてのモジュールで発生するわけではありません。通話後にリアルタイムで実際に削除されるものもありVBComponents.Removeます。

さまざまなフォーラムでこれに関するいくつかの異なる投稿を見てきましたが、満足のいく解決策はありません。今のところ、.Remove呼び出しを次のように変更する回避策を使用しています。

    With ToVBProject.VBComponents
        .Item(ModuleName).name = ModuleName & "_remove"
        .Remove .Item(ModuleName & "_remove")
    End With

名前を変更ModuleNameすると、 が存在しないように見えるため、.import呼び出しが発生します。もちろん、これは、という名前のモジュールがModuleName & "_remove"実際に存在しないことを前提としています。

より良い解決策はありますか?

4

9 に答える 9

2

どのトリガーが機能するか、または機能しないかを調べるために、コード モジュールの削除/置換に無限の時間を費やしてきました。

別のワークブックのコード モジュールの削除/置換

これは最も問題の少ないアプローチであり、それがCode Module Managementで実装した理由です。そこで、まだ開いていない Workbook をファイル ダイアログで選択できるようにすると、次のように Workbook が開かれます。

Application.EnableEvents = False
....Open "workbook-fullname" ' selected in a file dialog
Application.EnableEvents = False

コード モジュール管理は、VBA コードの実行を妨げていない (これを実現する方法については、こちらを参照) ことにより、対象のワークブックが以前に手動で開いていた (したがって、開いているワークブックのリストとして選択するために表示されている) 場合には機能しません。もちろん、これは Workbook_Open がコードを実行する場合のみの問題です。

私の結論: マクロ (サブプロシージャ、関数など) が実行されると、VBA コードのコピーがメモリに存在します。したがって、コード モジュールを削除する手順が完了するまで、削除は行われません。その結果、インポートはコード モジュールがまだ存在していると見なし、名前を一意にするために数字の接尾辞を付けた同じ名前のコード モジュールをインポートします。もちろん、これは常に当てはまります...

「ThisWorkbook」内のコード モジュールの削除/置換*)

これまでのところ、これを達成する方法は見つかりませんでした。ただし、他のコード モジュールで宣言されていないクラス モジュールを除きます。. したがって、 Removeの前にすべての宣言を一時的にコメントアウトしようとしました。完全成功!削除インポートは正常に機能しました。しかし、以前にコメントアウトされた宣言コード行のコメントを最終的に解除しようとすると、Excel は常にクラッシュしました (どちらの場合も.DeleteLines.InsertLines.ReplaceLine )。私はこれに対する解決策を見つけられなかったので、試してみるのをあきらめました - 少なくとも当分の間。

コード モジュール管理を参照して 、クリーンアップ、削除、転送、エクスポート、インポート、さらには同期をはるかに手間がかからず、保存し、信頼できるものにします。元に戻す機能があるため、転送または削除のために間違った「ターゲット」ワークブックを選択しても問題ありません。

*) ここではActiveWorkbookThisWorkbookの違いが重要です。ThisWorkbookは VBA コードが実行される Workbook であり、ActiveWorkbookは別の Workbook である可能性があります。通常はどちらも同じなので、違いを気にしなくても問題ありません。

于 2015-11-26T15:53:04.560 に答える
2

シートにコードとメソッドの参照がある場合ThisWorkbook、Excel はモジュールにハングアップし、それらを削除しない可能性があります。Application.run("foo")トリックは、のような直接呼び出しの代わりに使用して、Excel からの呼び出しを非表示にすることfoo()です。
これはExcel 2010でうまくいきました

于 2015-03-17T11:30:57.887 に答える