Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


8806 / 13644 ツリー ←次へ | 前へ→

【30940】ユーザーフォームのインポート HOSHI 05/11/7(月) 16:22 質問[未読]
【30941】Re:ユーザーフォームのインポート Jaka 05/11/7(月) 16:44 発言[未読]
【30958】Re:ユーザーフォームのインポート ichinose 05/11/7(月) 23:16 発言[未読]
【30959】Re:ユーザーフォームのインポート 訂正 ichinose 05/11/8(火) 7:57 発言[未読]
【30988】Re:ユーザーフォームのインポート 訂正 HOSHI 05/11/8(火) 17:50 質問[未読]
【30991】Re:ユーザーフォームのインポート 訂正 ichinose 05/11/8(火) 20:27 発言[未読]
【31014】Re:ユーザーフォームのインポート 訂正 HOSHI 05/11/9(水) 10:22 お礼[未読]
【31024】Re:ユーザーフォームのインポート 訂正 HOSHI 05/11/9(水) 14:33 お礼[未読]
【31043】Re:ユーザーフォームのインポート 訂正 ichinose 05/11/9(水) 20:55 発言[未読]
【31058】Re:ユーザーフォームのインポート 訂正 HOSHI 05/11/10(木) 11:49 お礼[未読]

【30940】ユーザーフォームのインポート
質問  HOSHI  - 05/11/7(月) 16:22 -

引用なし
パスワード
   古いユーザーフォームを解放して、微調整を加えた新しいユーザーフォームをインポートしたいと考えております。エディターを起動しないで、マクロにて「古いフォームを解放」→「新しいフォームのインポート」を行いたいと思っていますが、可能でしょうか?
可能ならば、どのようにすればよいのでしょうか?
申し訳ありませんが、ご存知の方、ご教授願います。

【30941】Re:ユーザーフォームのインポート
発言  Jaka  - 05/11/7(月) 16:44 -

引用なし
パスワード
   インポートだけですが....。
[#10752]

【30958】Re:ユーザーフォームのインポート
発言  ichinose  - 05/11/7(月) 23:16 -

引用なし
パスワード
   HOSHIさん、Jaka さん、こんばんは。

以下のようにしてみました。
標準モジュールに

'================================================================
Sub main()
  Dim ret As Long
  ret = import_fmcomp(ThisWorkbook, ThisWorkbook.Path & "\frm1.frm")
  If ret = 0 Then
   MsgBox "good"
  Else
   MsgBox Error(ret)
   End If
End Sub
'=========================================================================
Function import_fmcomp(wk As Workbook, imppath As String) As Long
'機能:指定されたブックに指定されたファイルからフォームモジュールをインポートする
'   尚、インポート対象フォームが既に存在する場合は、既存フォームは削除する
'  input : wk --- インポート対象ブック
'      imppath--フォームモジュールのインポートファイルのフルパス
'  Output: 0----正常インポート
'      その他-異常終了
  On Error Resume Next
  Dim fmnm As String
  fmnm = get_formnm(get_forminf_line(imppath))
  On Error Resume Next
  With wk.VBProject
    .VBComponents.Remove .VBComponents(fmnm)
    If Err.Number <> 0 Then MsgBox Err.Description
    Err.Clear
    .VBComponents.Import imppath
    import_fmcomp = Err.Number
    End With
End Function
'============================================================
Function get_formnm(f_str As String)
'機能:指定された文字列から、フォーム名を抽出する
' input:f_str---フォーム名を含んだ 「Begin {***} Frmnm」形式の文字列
' output:get_formnm---フォーム名
  Dim regEx
  Set regEx = CreateObject("VBScript.RegExp")
  regEx.Pattern = "Begin \{.*\} "
  regEx.IgnoreCase = True  ' 大文字と小文字を区別しないように設定します。
  regEx.Global = True  '文字列全体を検索するように設定します。
  get_formnm = Trim(regEx.Replace(f_str, ""))  '置換を実行します。
  Set regEx = Nothing
End Function
'==================================================================
Function get_forminf_line(imppath As String)
'機能:指定されたファイルから、「Begin {***} Frmnm」形式の文字列を取り出す
' input:imppath----インポートファイルのフルパス
' output:get_forminf_line---フォーム名を含んだ 「Begin {***} Frmnm」形式の文字列
  Dim flno As Long
  Dim dat1 As String
  flno = FreeFile()
  Open imppath For Input As #flno
  Line Input #flno, dat1
  Line Input #flno, get_forminf_line
  Close #flno
End Function

但し、Excel2002以上では、「ツール」---「マクロ」----「セキュリティ」の
「信頼のおける発行元」タブの「Visual Basicプロジェクトへのアクセスを信頼する」
にチェックを入れないと実行できません。


確認してみてください。

【30959】Re:ユーザーフォームのインポート 訂正
発言  ichinose  - 05/11/8(火) 7:57 -

引用なし
パスワード
   おはようございます。一箇所訂正です。


>以下のようにしてみました。
>標準モジュールに
>
>'=========================================================================
>Function import_fmcomp(wk As Workbook, imppath As String) As Long
>'機能:指定されたブックに指定されたファイルからフォームモジュールをインポートする
>'   尚、インポート対象フォームが既に存在する場合は、既存フォームは削除する
>'  input : wk --- インポート対象ブック
>'      imppath--フォームモジュールのインポートファイルのフルパス
>'  Output: 0----正常インポート
>'      その他-異常終了
>  On Error Resume Next
>  Dim fmnm As String
>  fmnm = get_formnm(get_forminf_line(imppath))
>  On Error Resume Next
>  With wk.VBProject
>    .VBComponents.Remove .VBComponents(fmnm)
>    If Err.Number <> 0 Then MsgBox Err.Description
'        ↑デバッグ用のステートメントなので削除してください
>    Err.Clear
>    .VBComponents.Import imppath
>    import_fmcomp = Err.Number
>    End With
>End Function
>
>但し、Excel2002以上では、「ツール」---「マクロ」----「セキュリティ」の
>「信頼のおける発行元」タブの「Visual Basicプロジェクトへのアクセスを信頼する」
>にチェックを入れないと実行できません。
>
>
>確認してみてください。

【30988】Re:ユーザーフォームのインポート 訂正
質問  HOSHI  - 05/11/8(火) 17:50 -

引用なし
パスワード
   ichinoseさん、Jakaさん、返信ありがとうございます。

ichinoseさんが記述していただいたコードにて無事に動きました。
ありがとうございます。申し訳ありませんが、もうすこしご教授していただけたら幸いです。

現在のコードは、解放・インポートを行えるのは、ひとつのみとなるのでしょうか?もしそうであるならば、複数のフォームを解放・インポートするには

Sub main()
 Dim ret As Long
 ret = import_fmcomp(ThisWorkbook, ThisWorkbook.Path & "\frm1.frm")

この部分の『"\frm1.frm")』をそれぞれのフォームの名前に変更したマクロを、フォームの個数分だけ作ればいいということになるのでしょうか?
(実際にはこちらの環境にてエクスポートしたフォームの名前は"UserForm1.frm"というものだったので、そこのみ上記場所の記述を変更させています)

それと、フォームを開き、右上の×で閉じた後に、マクロを実行すると、
「読み込み中にエラーが発生しました」となり、ログを見ると、
「行 8: プロパティ OleObjectBlob(UserForm1) のファイル参照が不正です。」
と、なります。
これは、アンロードしていないから、ということになるのでしょうか?(実はよくわかっていません。すいません。)

【30991】Re:ユーザーフォームのインポート 訂正
発言  ichinose  - 05/11/8(火) 20:27 -

引用なし
パスワード
   ▼HOSHI さん:
こんばんは。


>ichinoseさんが記述していただいたコードにて無事に動きました。
>ありがとうございます。申し訳ありませんが、もうすこしご教授していただけたら幸いです。
>
>現在のコードは、解放・インポートを行えるのは、ひとつのみとなるのでしょうか?もしそうであるならば、複数のフォームを解放・インポートするには
>
>Sub main()
> Dim ret As Long
> ret = import_fmcomp(ThisWorkbook, ThisWorkbook.Path & "\frm1.frm")
>
>この部分の『"\frm1.frm")』をそれぞれのフォームの名前に変更したマクロを、フォームの個数分だけ作ればいいということになるのでしょうか?
そういうことです。ループ処理で可能だと思いますよ!!


>それと、フォームを開き、右上の×で閉じた後に、マクロを実行すると、
>「読み込み中にエラーが発生しました」となり、ログを見ると、
>「行 8: プロパティ OleObjectBlob(UserForm1) のファイル参照が不正です。」
>と、なります。
>これは、アンロードしていないから、ということになるのでしょうか?(実はよくわかっていません。すいません。)

このエラーが再現できるコードを提示してください。
これは、最低限、提示しなければならない情報ですよ!!
本当は、コードだけではなく、再現手順書を記述するんですけど・・・。


私が試した限りでは、上記のエラーは再現できませんでした。

但し、前回提示したプロシジャーmainを以下のように
変更すると、

'================================================================
Sub main()
  Dim ret As Long
  UserForm1.Show
  ret = import_fmcomp(ThisWorkbook, ThisWorkbook.Path & "\userform1.frm")
  If ret = 0 Then
   MsgBox "good"
  Else
   MsgBox Error(ret)
   End If
End Sub

「行 2: フォーム名または MDI フォーム名 UserForm1 は既に使われています。」

なんてエラーログが作成されていました。
結果、Userform1の入れ替えは正常に処理されませんでした。
但し、既存のUserform1は削除まではされていました。


困ったときのOntimeメソッドで、
'=======================================
Sub test()
  UserForm1.Show
  Application.OnTime Now(), "main"
End Sub
'========================================================================
Sub main()
  Dim ret As Long
  ret = import_fmcomp(ThisWorkbook, ThisWorkbook.Path & "\userform1.frm")
  If ret = 0 Then
   MsgBox "good"
  Else
   MsgBox Error(ret)
   End If
End Sub

というようにしてtestを実行すると
正しく入れ替えができました。

これは、確認してください。


ところで・・・・。
私のほうから、気になった点です。
HOSHI さんは、このフォームの入れ替えをどんな目的でなさろうとしているのですか?
私は、VBA開発者用のツールなのかなあと思っていたのですが・・・。

業務用の自動実行処理あるいは、事務処理の簡略化などのプログラムに
この処理を導入しようと考えているのですか?
だとしたら、私は心配です。

その大きな理由は、Excel2002からは、セキュリティの設定を行わないと
Vbprojectの操作が出来ないこと。

もうひとつは、プログラムを作動させながら、当該プロジェクトを操作する
という処理を私もこのサイトは長く見ていますが、これまで殆ど見たことが
ありません。私もそのようなコードは書いたことがないです。
正直、危なっかしくて・・・。

今回のようなエラーは私も初めてです。
つまり、未知数が多いと言うことです。
予期せぬエラーはこれ以外のもあるかもしれませんよ
まっ、それを洗い出すのが目的ならそれはそれで意味はあります。
ここは、VBA研究所ですから・・・。

【31014】Re:ユーザーフォームのインポート 訂正
お礼  HOSHI  - 05/11/9(水) 10:22 -

引用なし
パスワード
   ▼ichinose さん:
おはようございます。丁寧な返信をありがとうございます。

>>それと、フォームを開き、右上の×で閉じた後に、マクロを実行すると、
>>「読み込み中にエラーが発生しました」となり、ログを見ると・・・

>このエラーが再現できるコードを提示してください。
>これは、最低限、提示しなければならない情報ですよ!!

説明が不足しておりました。私が申していたのは、ichinoseさんが記述してくださったコードを実行すると、という意味でした。混乱させてしまって申し訳ありません。

それと、このマクロを作ろうと考えたきっかけは、そんなに対したことではなく、実に単純に自分以外の人間にフォームの更新作業をしてもらう際に、簡単にならないかと考えたからです。(私を含めユーザーフォームという概念を知らない人がほとんどな職場なものですから。)
ichinoseさんのおっしゃるとおり、セキュリティ設定を変更しないとことにはVbprojectの操作は行えないので、正直マクロでのフォーム更新は難しいかなと考え始めています。丁寧に教えてくださったのに、申し訳ありません。しかし個人的には大変勉強になりました。ありがとうございます。

Ontimeメソッドのコードは今から確認してみます。
また確認して、返信いたします。

【31024】Re:ユーザーフォームのインポート 訂正
お礼  HOSHI  - 05/11/9(水) 14:33 -

引用なし
パスワード
   ▼ichinose さん:
こんにちわ。

マクロ「test」をコピペして実行してみました。
一応これまでの流れを書いておきます。

mainのみだった場合
 main実行
  ↓
 「ok」とでて、ユーザーフォームも更新されている。
  ↓
 ユーザーフォームを開いて、×で閉じた後、mainをまた実行してみた
  ↓
 「読み込み中にエラーが発生しました」
  ↓
 もう一度mainを実行してみた
  ↓
 「ok」
結果的にはできるのですが、なぜ途中、一度フォームを開いて×で閉じると、エラーになるのかが、理論的にわからなかったので、お聞きした次第です。ちなみに一度mainで更新した後、フォームを一度も開かずにmainを再度実行してみたところ、エラーにはなりませんでした。

testも試してみましたが、こちらの環境ではエラーになりました。「読み込み中にエラーが発生しました」とでて、ログには「行 2: フォーム名または MDI フォーム名 UserForm1 は既に使われています。」となっています。

書くのが遅くなりましたが、(これも最低限提示するべき情報でした!すいません!)osはxp2のExle2002です。


正直、話の趣向がずれてきていますが、報告のみさせていただきました。
説明の足りない質問に丁寧に付き合ってくださりありがとうございます。

【31043】Re:ユーザーフォームのインポート 訂正
発言  ichinose  - 05/11/9(水) 20:55 -

引用なし
パスワード
   ▼HOSHI さん:
こんばんは。

>
>マクロ「test」をコピペして実行してみました。
>一応これまでの流れを書いておきます。
>
>mainのみだった場合
> main実行
>  ↓
> 「ok」とでて、ユーザーフォームも更新されている。
>  ↓
> ユーザーフォームを開いて、×で閉じた後、mainをまた実行してみた
>  ↓
> 「読み込み中にエラーが発生しました」
>  ↓
> もう一度mainを実行してみた
>  ↓
> 「ok」
>結果的にはできるのですが、なぜ途中、一度フォームを開いて×で閉じると、エラーになるのかが、理論的にわからなかったので、お聞きした次第です。ちなみに一度mainで更新した後、フォームを一度も開かずにmainを再度実行してみたところ、エラーにはなりませんでした。
>
>testも試してみましたが、こちらの環境ではエラーになりました。「読み込み中にエラーが発生しました」とでて、ログには「行 2: フォーム名または MDI フォーム名 UserForm1 は既に使われています。」となっています。
>
>書くのが遅くなりましたが、(これも最低限提示するべき情報でした!すいません!)osはxp2のExle2002です。
現象確認しました。
私は、Win2000&Excel2002SP3で確認しました。
testが正常に作動したのは、ある条件下のみでした。失礼しました。

で、結局はこのような使い方は止めた方がよいです、ということなんですが、
それとは別にこれを動かす方法があるのか、模索してみました。

考え方としては、フォームを入れ替えるブックと入れ替えを行うコードを含むブックに
分けてみたらどうかと思いました。

例えば、
仮にフォームの入れ替えを行うブックをtextbk.xlsとします。
入れ替えるユーザーフォームは、Userform1
このブックの標準モジュールには、

'=================================================
Sub test()
  UserForm1.Show
  Application.OnTime Now(), "importbk.xls!main"
End Sub

次に入れ替えを実行するコードを含んだブックを
importbk.xlsとします。
このimportbk.xlsの標準モジュールに
'===============================================================
Sub main()
  Dim ret As Long
  ret = import_fmcomp(Workbooks("testbk.xls"), ThisWorkbook.Path & "\userform1.frm")
  If ret = 0 Then
   MsgBox "good"
  Else
   MsgBox Error(ret)
   End If
End Sub
'========================================
import_fmcomp、 get_formnm、及び、get_forminf_lineは、
同じ内容でこのブックの標準モジュールに記述します。

尚、testbk.xls、importbk.xls、インポートするUserform1.frmは、
同じフォルダ上にあるとします。

testbk.xls、importbk.xlsが共に開いた状態で

testbk.xlsのプロシジャーtestを実行してみてください。

私が確認した限り正常に作動しています。

【31058】Re:ユーザーフォームのインポート 訂正
お礼  HOSHI  - 05/11/10(木) 11:49 -

引用なし
パスワード
   ▼ichinose さん:
こんにちわ。

>仮にフォームの入れ替えを行うブックをtextbk.xlsとします。
となっておりましたが、コードには「test.xls」となっておりましたので、その部分を統一させた上で確認しました。

結果・・・無事成功しました!
すごいです。初心者の私でも色々と応用をきかせられそうです。「importbk.xls」はフォームのアップデートパッチといったところですね。

丁寧にご教授くださり、ありがとうございました。
大変勉強になりました。

8806 / 13644 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free