[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『VBAでのファイルを更新(閉じる)したい』(はせぴぃ)
VBAにて「Book1.xls」のユーザフォーム内のコマンドボタン(かマクロ)にて 自分もVBA初心者なのでよくわかっていないのですが、
“book2.xls”を開く → “book1.xls”を(保存しないで)閉じる
事をしたいのですが、
ThisWorkbook.Close False
でできるのはわかるのですが、
book2.xlsの起動時にユーザフォームを開くように設定していると
うまくできません。
よい方法がございましたらお教え願いませんか? お願い致します。
ユーザーフォームが登録してあるブックを閉じたら、 エラーは当然ですね。 閉じないと都合が悪いのですか? みやほりん
>book2.xlsの起動時にユーザフォームを開くように設定しているとうまくできません。 これだけでの記述ではどんなコードなのかわかりません。 再現できるBook1.XlsとBook2.Xlsの構成とコードを提示して下さい。 今、抱えている問題のあるコードを全部掲載するのではなく、 この掲示板用に簡単に再現できる構成とコードの掲載が必要です。
それと出来るなら、このような処理をしたい背景も・・・。
問題自体は、Ontimeメソッドあたりを工夫すれば、できるかもしれません・・・。 が、プログラムの構造的に難しい構造(他者にとって理解しづらい)になってしまいそうです。 これって、フェーズチェンジみたいな事がしたいということですもんね!!
Book1.Xlsを閉じるのではなく、非表示状態にしておくのではいけませんか?
ichinose
また、ファイルの共有もしていきたいので閉じてしまいたいです。
(私自身も素人な解答ですいませんm(_ _)m)
コードは
book1内のユーザフォーム1内ボタン1は
Private Sub CommandButton1_Click()
'
Unload UserForm1 ' Dim path As String path = ThisWorkbook.path Workbooks.Open Filename:=path & "book2.xls" Range("A1").Select ' With Workbooks("book2.xls") .Close End With ' ( UserForm2.Show ) ' End Sub
book2内のオブジェクト内のthisworkbook内に
Private Sub Workbook_Open()
'
Sheets("sheet1").Select UserForm2.Show ' End Sub
(はせぴぃ)
Book1でBook1に対するCloseメソッドを書き、Book2のUserForm2をLoad →UserForm2を閉じないとBook1が閉じない Book2でBook1に対するCloseメソッドを書き、Book2のUserForm2をLoad →Book1を閉じると、それ以降のコードが実行されない。 Book2を開く、Book1を閉じる、までの処理として、 Userform2をLoadするのはWorkbook_Openで実行せずに、ボタンクリックなどの 別処理で行ってはいかがですか? >パソコン素人の方々の操作を想定 私の経験では、便利にしてあげればあげるほど、素人のままでいてくれます。 (みやほりん)(-_∂)b
>非表示状態だと不都合が生じそうな気がします。 どんな不都合でしょうかねえ?? Book2.Xlsのユーザーフォームを閉じたら、Book1のフォームを再び 表示されるような仕様でいけないのですか?
>ファイルの共有もしていきたいので閉じてしまいたいです これも仕様によりますが、やりようはあると思いますけどねえ・・・・。
一応、こんなコードにすると、 >VBAにて「Book1.xls」のユーザフォーム内のコマンドボタン(かマクロ)にて >"book2.xls”を開く → “book1.xls”を(保存しないで)閉じる
という仕様は実現できます。
Book1.xls 、book2.xlsは、いずれも新規ブックで試してください。
Book1.Xlsでは、
ユーザーフォームをひとつ作成してください(UserForm1) このUserForm1には、コマンドボタンをひとつ配置してください(CommandButton1)
標準モジュールに
'========================================================================= Option Explicit Sub test() UserForm1.Show ThisWorkbook.Close False End Sub
UserForm1のモジュールに
'======================================================================== Option Explicit Private Sub CommandButton1_Click() Application.OnTime Now(), "'" & ThisWorkbook.Path & "\[book2.xls]'!スケジュール" Unload Me End Sub
book2.xlsにもユーザーフォームをひとつ作成してください(UserForm2)。 このUserForm1には、テキストボックスをひとつ配置してください(TextBox1)。 これは、book1.xlsのUserform1と区別しやすくするためにコントロールを変えました。
標準モジュールに
'=========================================================================== Option Explicit Sub スケジュール() Application.OnTime Now(), "auto_open" End Sub '============================================================================ Sub auto_open() UserForm2.Show End Sub
以上です。book1.xls及び、book2.xlsは、同じフォルダに保存してください。
Excelのマクロセキュリティを「低」に設定(または、デジタル署名して「中」)してbook1.xlsの testを実行してみてください。
Userform1が表示され、コマンドボタンのクリックでbook2.xlsのUserform2が表示され、 book1.xlsは、閉じます。
試してみてください。 私なら、仕様を変えてでも、このようなプログラム構造にはしないと思いますけど・・・。
ichinose 誤字訂正
ichinoseさん、ありがとうございます。 テストしてみたら、出来ました。
さらに甘えたいのですが、
book1 ←┬→book2
├→book3 └→book4
のようにbook1とbook2、3、4を相互コントロールさせたいのですが
出来ますでしょうか?
(book2、3、4はbook1と同じ階層内のフォルダにまとめてある)
−┬−book1
└−folder1−┬−book2
├−book3
└−book4
>私なら、仕様を変えてでも、このようなプログラム構造にはしないと思いますけど・・・
とはなぜなのか、お聞かせ下さい。
今後の糧にしたいです。
(はせぴぃ)
前回投稿の
>UserForm1のモジュールに >'======================================================================== >Option Explicit >Private Sub CommandButton1_Click() > Application.OnTime Now(), "'" & ThisWorkbook.Path & "\[book2.xls]'!スケジュール" > Unload Me >End Sub
を Private Sub CommandButton1_Click() With Workbooks.Open(ThisWorkbook.Path & "\book2.xls") Application.Run .Name & "!スケジュール" End With Unload Me End Sub
こっちに変えてください。そうすると、デジタル署名なしのセキュリティ「中」でよいです。
>このようなプログラム構造にはしないと思いますけど・・・とはなぜなのか ちょっと、大げさでしたね!!でも・・・・。
プログラム構造の基本って、前にもどこかで記述しましたが、
前処理 ------> 1回以上のループ処理 ------>終了処理
という形だと思います。このループ処理が複雑になると他のプロシジャーを呼び出したり、他のプロセスを 呼び出したりしますが、プログラムの流れは、上記の終了処理にてプログラムが終了する、 いえ、そのようなプログラム構造にすることが構造化プログラミングです!!
今回のプログラム構造のようにBook1のプログラムは、終了し、別のブックのプログラムがそのまま起動する という構造は、特殊な構造といえます。
特殊な構造にするなら、それなりの理由が必要だと思うのです。
例えば、Book1というプログラムの容量があまりにも大きくなりすぎているので、そのままExcel内においてお く状態でBook2のプログラムを実行させるより、リソースを開放した方がよい という判断で投稿したような プログラム構造にする。 昔、メモリ容量が少なかった時代に大きいプログラムを開発する手法として、使われていました。
>非表示状態だと不都合が生じそうな気がします。
>ファイルの共有もしていきたいので閉じてしまいたいです
この二つのことが投稿したような構造にしないと本当に実現できないのか もう少し検討した方が良いのではないかということです。 検討した結果、どうしても というなら、仕方ないですが・・・。
> book1 ←┬→book2 > > ├→book3 > └→book4 >のようにbook1とbook2、3、4を相互コントロールさせたいのですが
こんな投稿を拝見すると、Book1がメニュー画面でBook2,Book3,Book4でそれぞれ独立した機能を持った (VBAプログラムを持った)ブックのプログラムを実行する という仕様が想像されてなりません。 ならば、Book2,Book3,Book4のぞれぞれの処理が終了後、再びBook1のメニューにもどり、 終了するなら、このBOOK1のメニュー内のボタンによって終了する仕様ではいけませんか?
ということです。こういう仕様なら、トップダウンのわかりやすいプログラム構造になります。
それでも現状仕様がよいというなら、投稿したようなOnTimeメソッドを相互に使えば可能だとは 思います。例題コードは提示しました(Book1.Xlsを閉じて、Book2.Xlsを起動する方法)。 相互コントロールというのが、book2.xlsを閉じて、Book1.Xlsを起動する方法なら、逆をやるだけですよね!!
ichinose
ichinoseさん、詳しい解説ありがとうございます。
お話いただいたコードは、まだ試しておりませんが、 元を返すようですが、読ませていただいたところ、 最初におっしゃられた通り"非表示"扱いにしたほうが よさそうなのですね?
自分もVBA初心者なのでよくわかっていないのですが、 ネットなどの解説を閲覧していると、 PC初心者(が扱うものを作成している)には "非表示"を使用するのは難しいのでは?と考えたのでした。
"非表示"を作成するにあたり、デメリットや PC初心者が注意する点というのはありますか?
(はせぴぃ)
せっかく回答いただいているものを消さないでください。 「コメント:」の欄から投稿するようにしましょう。 (みやほりん)(-_∂)b
二つ例を出しますから検討してみてください。
以下の例を新規ブックで試してください。
例1 メインユーザーフォーム(Book1.XlsのUserForm1)非表示しない
まず、book3.xlsからです。ユーザーフォームを一つ作成してください(UserForm3)。 他のユーザーフォームと区別するためにコマンドボタンを一つ配置します(CommandButton1)。
標準モジュールに
'======================================================================== Option Explicit Sub auto_open() UserForm3.Show End Sub
UserForm3のモジュールに
Private Sub CommandButton1_Click() Unload Me End Sub
'************************************************************************* 次にbook2.xlsです。ユーザーフォームを一つ作成してください(UserForm2)。 UserForm2には、テキストボックス(TextBox1)とコマンドボタン(CommandButton1) 配置してください。
標準モジュールに
'======================================================================== Option Explicit Sub auto_open() UserForm2.Show End Sub
UserForm2のモジュールに
Private Sub CommandButton1_Click() Unload Me End Sub
'****************************************************************************************** 最後にbook1.xlsです。ユーザーフォームを作成してください(UserForm1)。
コマンドボタンを3っつ作成してください。
CommandButton1 ------------- book2.xlsのUserForm2を表示する CommandButton2 ------------- book3.xlsのUserForm3を表示する CommandButton3 ------------- UserForm1を閉じる
標準モジュールに
'=============================================================================== Option Explicit Sub auto_open() UserForm1.Show ThisWorkbook.Close False End Sub
UserForm1のモジュールに
'=============================================================================== Option Explicit Private Sub CommandButton1_Click() Dim wn As Window For Each wn In ThisWorkbook.Windows wn.Visible = False Next With Workbooks.Open(ThisWorkbook.Path & "\book2.xls") Application.Run .Name & "!auto_open" DoEvents .Close False End With For Each wn In ThisWorkbook.Windows wn.Visible = True Next End Sub '==================================================================== Private Sub CommandButton2_Click() Dim wn As Window For Each wn In ThisWorkbook.Windows wn.Visible = False Next With Workbooks.Open(ThisWorkbook.Path & "\book3.xls") Application.Run .Name & "!auto_open" DoEvents .Close False End With For Each wn In ThisWorkbook.Windows wn.Visible = True Next End Sub '============================================================================ Private Sub CommandButton3_Click() Unload Me End Sub
以上です。3ブックとも同じフォルダ上に保存してください。 一度、Excelを閉じてから、再度、book1.xlsのみ開いてください。
Userform1が表示されます。
CommandButton1のクリックで book2.xlsのUserForm2が表示されます。 UserForm2を閉じると再び、UserForm1がアクティブになります。
CommandButton2のクリックで book3.xlsのUserForm3が表示されます。 UserForm3を閉じると再び、UserForm1がアクティブになります。
CommandButton3のクリックで UserForm1が消えて、book1.xlsも閉じます。
いかがですか?book1.xlsは、他のブックが呼び出される度に非表示にしていますが、 UserForm1は、非アクティブになっているだけで表示はされています。
この手のメニュー方式にする場合、私は殆どこのパターンです(場合によっては、book1.xlsだって、 非表示にはしません)。
UserForm1が表示されたままだって、パソコン初心者の方にとって、不都合だとは思いませんが、 いかがですか?
例2では、UserForm1を他のブックが呼び出される度に非表示するコードを提示します。
ichinose@次投稿にて
例2 メインユーザーフォーム(Book1.XlsのUserForm1)非表示する
Book2.xlsとBook3.xlsに関しては、前投稿と同じものをコピーして前投稿とは違うフォルダに 保存してください。
Book1.xlsだけは新たに作成します。ユーザーフォームを作成してください(UserForm1)。
コマンドボタンを3っつ作成してください。
CommandButton1 ------------- book2.xlsのUserForm2を表示する CommandButton2 ------------- book3.xlsのUserForm3を表示する CommandButton3 ------------- UserForm1を閉じる
と機能的には同じです。
標準モジュールに
'=============================================================================== Option Explicit Sub auto_open() Dim wn As Window Dim opnbook As String Load UserForm1 With UserForm1 .Show Do Until .clickbtn = 4 For Each wn In ThisWorkbook.Windows wn.Visible = False Next If .clickbtn = 2 Then opnbook = ThisWorkbook.Path & "\book2.xls" ElseIf .clickbtn = 3 Then opnbook = ThisWorkbook.Path & "\book3.xls" End If With Workbooks.Open(opnbook) Application.Run .Name & "!auto_open" DoEvents .Close False End With For Each wn In ThisWorkbook.Windows wn.Visible = True Next .Show Loop End With Unload UserForm1 ThisWorkbook.Close False End Sub
UserForm1のモジュールに
'=============================================================================== Option Explicit Public clickbtn As Long 'どのボタンが押されたかを示す '2 CommandButton1が押された 3 CommandButton2が押された 4 CommandButton3が押された '======================================================================================= Private Sub CommandButton1_Click() clickbtn = 2 Me.Hide End Sub '======================================================================================== Private Sub CommandButton2_Click() clickbtn = 3 Me.Hide End Sub '======================================================================================== Private Sub CommandButton3_Click() clickbtn = 4 Me.Hide End Sub '======================================================================================== Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) If CloseMode <> 1 Then Cancel = True End If End Sub
以上です。3ブックとも同じフォルダ上に保存してください。 一度、Excelを閉じてから、再度、book1.xlsのみ開いてください。
Userform1が表示されます。
CommandButton1のクリックで book2.xlsのUserForm2が表示されます。 このとき、UserForm1は、非表示になります。 UserForm2を閉じると再び、UserForm1が表示されます。
CommandButton2のクリックで book3.xlsのUserForm3が表示されます。 このとき、UserForm1は、非表示になります。 UserForm3を閉じると再び、UserForm1が表示されます。
CommandButton3のクリックで UserForm1が消えて、book1.xlsも閉じます。
UserForm1を表示したままの仕様と非表示する仕様では、こんなにコードが違ってしまいました。 勿論、理由はありますが、現時点では省略します。
> "非表示"を作成するにあたり、デメリットや >PC初心者が注意する点というのはありますか? Book1.Xlsの標準モジュール内に
With Workbooks.Open(opnbook) Application.Run .Name & "!auto_open" DoEvents .Close False End With
というコードがあります、このDoeventsを入れないと 私の環境ではI/Oエラーが発生しました。 Win2000&Excel2002で確認しています。
又、この手の手法は、Excel2000から行っていたので Excel2000でも確認しています。 メニュー方式の2例を投稿しました。
検討してみてください。
ichinose
こんにちは。佳です。 じつはわたしの環境では、最初からはせぴぃさんのコードでちゃんと動いています。 エクセル97なもので、環境のせいかなと思ったり、 自分がなにか仕様を読み違えているだろうかと思ったりしています。
> ネットなどの解説を閲覧していると、 > PC初心者(が扱うものを作成している)には > "非表示"を使用するのは難しいのでは?と考えたのでした。
こちらはあまり環境に関係ないはなしなので。 わたしの経験から云わせていただくと 初心者のユーザーは、ワケの分からないものが見えると混乱します。 また、見えるはずだと思っているものが見えないときも混乱します。 なので、非表示は無条件でダメとか、表示は無条件でダメとかは言えないです。 理想をいえば、ユーザーが見たいものが見たいときに見えるようにするのが一番です。 まあ、言うは易く行うは難しですが ^^;
ほかの条件が同じなら、シンプルな作りにするほうがよさそうです。 初心者のユーザーにも、複雑なものよりシンプルなほうが理解しやすいはずですし まんいちコードにまずいところが見つかって修正することになったとき、シンプルなもののほうが楽です。
どういうものを作ろうとされているのか教えていただけると、もう少し中身のある回答ができるかと思います。
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.