エクセルVBAの不思議な挙動?

このQ&Aのポイント
  • エクセル2003でのVBAの動作について不思議な現象が起きています。特定の処理が実行されない問題が発生しています。
  • 具体的には、PrintPreviewの指示をすると正常に動作するが、マクロを実行すると予期した動作にならず、プレビュー画面が閉じても元のシートが表示されたままになります。
  • 問題の原因は、Application.OnTime関数が正しく動作しないことにあると考えられます。なぜこの関数がうまく動作しないのか、原因を探る必要があります。
回答を見る
  • ベストアンサー

エクセルVBAの不思議な挙動?

エクセル2003です。 ThisWorkbookには以下の記述があります。 Private Sub Workbook_BeforePrint(Cancel As Boolean) If ActiveSheet.Name <> "Sheet1" Then Exit Sub If Range("A1").Value = "" Then MsgBox "A1が未入力です" Range("A1").Select Cancel = True End If Application.OnTime Now(), "ページ移動" End Sub 標準モジュールには以下の記述があります。 Sub ページ移動() Sheets("Sheet2").Select Range("A1").Select End Sub Sub プリント() ActiveWindow.SelectedSheets.PrintPreview End Sub これでSheet1を開いた状態でツールバーから印刷プレビュー指示をすると、A1セルが入力済みであればプレビュー画面を出し、プレビューを閉じればSheet2が表示されます。 ところが、同じ状態でツールバーからではなく、マクロ Sub プリント を実行すると、プレビュー画面にはなりますが、プレビューを閉じてもSheet1のままです。 なぜ、 Application.OnTime Now(), "ページ移動" が、有効にならないのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • end-u
  • ベストアンサー率79% (496/625)
回答No.1

>なぜ、 >Application.OnTime Now(), "ページ移動" >が、有効にならないのでしょうか? 結論から言うと、『仕様です』という事になります。 イベントプロシージャは手動操作をトリガーにして実行されますが、 他マクロからのネストでイベントが発生する時、 ある種のメソッドが無視されるように作られているようです。 『ある種の..ようです』と書いてるのは、 全容を網羅したドキュメントを見た事がないからです。 個別にはMSsupportで紹介されているものが幾つかあります。 http://support.microsoft.com/kb/294810/ja http://support.microsoft.com/kb/898511/ja 他にはBeforeCloseイベント内でProtectメソッドが利かないとか、 BeforeSaveイベント内でOnTimeメソッドが利かないとか、 同じくBeforeSaveイベント内でAutoFilter操作が利かないとか、 Excel系のQ&A掲示板で経験した事があります。 特にWorkbookイベントにその傾向がありますね。 今回の事例では 1:Sub プリント()開始 2: Workbook_BeforePrint開始 3:  OnTimeメソッド発行 4: Workbook_BeforePrint終了 5: PrintPreview 6:Sub プリント()終了 こういうネスト状態です。 手動では1と6がありませんから OnTimeメソッドで発行されたSub ページ移動()が 5の終了時に実行されるわけですが 上記ネスト状態だと5の終了後は、 まだSub プリント()の制御内にあります。 マクロから呼び出されたイベント内で 全てのメソッドを許してしまうと何らかの不具合が出るため(?) その対策としての仕様かもしれません。 実際、マクロを書いてWorkbook_BeforePrintを呼び出しているのだから そのマクロ内にOnTimeメソッドの内容を書けば良いですよね、 という事なのかもしれません。 これ以上の詳細はMicrosoftに訊いてみるしかないかも。 現実的な対応としては Sub プリント()   ActiveWindow.SelectedSheets.PrintPreview   ページ移動 End Sub とするか、 Sub プリント()   Application.CommandBars.FindControl(ID:=109).Execute End Sub など。

emaxemax
質問者

お礼

ありがとうございます。 そういう『仕様』ならしようがないですね。(笑) > 実際、マクロを書いてWorkbook_BeforePrintを呼び出しているのだから > そのマクロ内にOnTimeメソッドの内容を書けば良いですよね そのように対応しているのですが、二度手間だなと思って質問しました。 有難うございました。

関連するQ&A

  • 印刷後のVBAの実行 (3)

    Private Sub Workbook_BeforePrint(Cancel As Boolean) If ActiveSheet.Name = "Sheet1" Then If Range("D6").Value = "" Then Cancel = True MsgBox ("名前を入力してください") Range("D6").Select Exit Sub End If Else If ActiveSheet.Name = "Sheet2" Then If Range("C11").Value = "" Then Cancel = True MsgBox ("受付時間を入力してください") Range("C11").Select Exit Sub End If Else Exit Sub End If End If If Worksheets("Sheet1").Range("D5") = "不要" Then GoTo P1 ActiveSheet.Range("A70:Y70").Copy If Worksheets("Sheet3").Range("A1").Value = "" Then Worksheets("Sheet3").Range("A1").PasteSpecial Paste:=xlPasteValues Else Worksheets("Sheet3").Range("A65536").End(xlUp).Offset(1, 0).PasteSpecial _ Paste:=xlPasteValues End If Application.CutCopyMode = False P1: ActiveSheet.Range("A1").Select End Sub sheet1のD5に「不要」と入っていたら 24~33行目の作業がキャンセルになりますが sheet2のD5にも「不要」と入っていたら、同じ様にキャンセルできる様に出来ますでしょうか? ご回答お願いします

  • 印刷後のVBAの実行 (2)

    Private Sub Workbook_BeforePrint(Cancel As Boolean)   If ActiveSheet.Name = "Sheet1" Then     If Range("D6").Value = "" Then       Cancel = True       MsgBox ("名前を入力してください")       Range("D6").Select       Exit Sub     End If   Else     If ActiveSheet.Name = "Sheet2" Then       If Range("C11").Value = "" Then         Cancel = True         MsgBox ("受付時間を入力してください")         Range("C11").Select         Exit Sub       End If     Else              Exit Sub     End If   End If   ActiveSheet.Range("A70:Y70").Copy   If Worksheets("Sheet3").Range("A1").Value = "" Then     Worksheets("Sheet3").Range("A1").PasteSpecial Paste:=xlPasteValues   Else     Worksheets("Sheet3").Range("A65536").End(xlUp).Offset(1, 0).PasteSpecial _       Paste:=xlPasteValues   End If   Application.CutCopyMode = False   ActiveSheet.Range("A1").Select End Sub 先日、上記のコードを回答者の方から教えてもらい、とても助かっていますが sheet1のD5に「不要」という文字が入っていた場合、 sheet3への貼り付け(23~30行目の作業)をキャンセルして、最後にsheet1のA1を選択するようにはどの様にしたらいいでしょうか?

  • excel vba ジャンプ

    excel2003のUserFormにてtextbox作成しました。 textbox1にページを入力すると指定のページにジャンプする コードを作成したのですが、動作的には目的とする事ができました。 ただ、初心者レベルで作成したので、コード記述が長く、 ページが増えるたびにコードを追記していかなければなりません。 下記に作成したコードを記述します。 もっと簡単に記述する方法はありますか? ---------------------------------------------------------- Private Sub TextBox1_Change() If TextBox1.Value = 1 Then ActiveWindow.ScrollRow = 1 ActiveWindow.ScrollColumn = 1 Range("$A$15").Select End If If TextBox1.Value = 2 Then ActiveWindow.ScrollRow = 38 ActiveWindow.ScrollColumn = 1 Range("$A$38").Select End If If TextBox1.Value = 3 Then ActiveWindow.ScrollRow = 69 ActiveWindow.ScrollColumn = 1 Range("$A$69").Select End If If TextBox1.Value = 4 Then ActiveWindow.ScrollRow = 100 ActiveWindow.ScrollColumn = 1 Range("$A$100").Select End If If TextBox1.Value = 5 Then ActiveWindow.ScrollRow = 131 ActiveWindow.ScrollColumn = 1 Range("$A$131").Select End If End Sub ---------------------------------------------------------- 上記記述で行っていることは、 textbox1に 1 と入力すると1ページ目が表示  キーボードでctrl+Homeの操作をした状態でカーソルがA15選択 textbox1に 2 と入力すると2ページ目が表示  表示の先頭が38行目、カーソルがA38選択 ページの行数が1ページ目だけ37行 2ページ目以降が31行ごとです。 実際は、200ページ以上あるのでなんとかしたいのですが・・・・

  • エクセルVBA

    VBAの素人です。 以下のようなVBAを実行しようと、何とか形にしました。 単独のBOOKではうまくいくのですが、同時に他のBOOKを開くと 「インデックスが有効範囲にありません」とエラーになります。 エラー箇所は、With Sheets("Sheet1").Range("B1")部分です。 修正をご教示頂ける方、何卒よろしくお願い致します。 全くVBA無知なのにすみません。 Private Sub Workbook_Open() test01 test02 Application.OnTime Now + TimeValue("00:10:00"), "終了" End Sub Sub 終了() Application.OnTime Now + TimeValue("0:00:02"), "test01", , False ThisWorkbook.Close Savechanges:=False Application.Quit End Sub Sub test01() With Sheets("Sheet1").Range("B1") .Value = Time .NumberFormatLocal = "mm:ss" End With Application.OnTime Now + TimeValue("0:00:02"), "test01" End Sub Sub test02() With Sheets("Sheet1").Range("B2") .Value = Time .NumberFormatLocal = "mm:ss" End With End Sub

  • エクセルVBEについて

    VBE初心者です。以下のプログラムを実行すると「testが見つかりません」とエラーが出てしまいます。application.ontimeの使い方がよく分かりません。どこが違うんでしょうか?よろしくお願いします。 Sub test() Range("D10").Value = Second(Time) If Range("D10").Value >= 55 Then Exit Sub End If Application.OnTime Now + TimeValue("00:00:01"), "test" End Sub

  • VBA beforeprintについて

    Private Sub Workbook_BeforePrint(Cancel As Boolean) If ActiveSheet.Name = "sheet1" Then If Range("M1").Value = "" Then Cancel = True MsgBox ("名前を入力してください") Range("M1").Select Exit Sub End If ElseIf ActiveSheet.Name = "sheet2" Then If Range("A47").Value = 文字 Then Cancel = True    MsgBox ("日付を入力してください") Range("A47").Select Exit Sub End If Exit Sub End If End Sub 上記は印刷をする前に実行されるコードですが、上記を実行して印刷をした後に自動で下記のVBAを実行したいのですが Sub データー取り込み() ActiveSheet.Range("B2000:Z2000").Copy ChDir "\\データーA\データーB\データーC\データーD" Workbooks.Open Filename:="\\データーA\データーB\データーC\データーD\データーシート1.xls" Sheets("顧客データー").Select If Worksheets("顧客データー").Range("B18").Value = "" Then Worksheets("顧客データー").Range("B18").PasteSpecial Paste:=xlPasteValues Else Worksheets("顧客データー").Range("B65536").End(xlUp).Offset(1, 0).PasteSpecial _ Paste:=xlPasteValues End If ActiveWorkbook.Save ActiveWindow.Close End Sub 上記のコードと下記のコードをどのように絡めたらいいのかわかりません。アドバイスお願いします。

  • EXCEL 異なるVBA

    教えて下さい、EXECL以下の異なるVBA (A>,B>)が2つあります、同じシートでそれぞれ動くようにさせたいです1つに合わせる事は出来ないでしょうか? 当方初心者の為わかりません教えて下さい。 A> Private Sub Worksheet_Change(ByVal Target As Excel.Range) If Target.Address(0, 0, xlA1, 0) <> "A1" Then Exit Sub With Range("F9:I9,K17:K36").Borders(xlDiagonalUp) If Left$(Target.Value, 1) = "S" Then .LineStyle = xlContinuous .Weight = xlThin .ColorIndex = xlAutomatic Else .LineStyle = xlNone End If End With End Sub B> Private Sub Worksheet_Change(ByVal Target As Range) With Sheet2 Select Case Target.Address Case Is = "$D$1" .Range("A1").Insert Shift:=xlDown .Range("A1").Value = Target.Value Case Is = "$D$2" .Range("B1").Insert Shift:=xlDown .Range("B1").Value = Target.Value End Select End With End Sub

  • エクセルVBAで Cancel=Trueの使い方

    Private Sub Worksheet_Change(ByVal Target As Range) If Target.Address <> "$A$1" Then Exit Sub Cancel = True MsgBox "キャンセルしました" End Sub Private Sub Worksheet_Deactivate() Cancel = True MsgBox "キャンセルしました" End Sub Private Sub Worksheet_SelectionChange(ByVal Target As Range) Cancel = True MsgBox "キャンセルしました" End Sub 以上のように使ってみましたが、どれも「キャンセルしました」とメッセージは出るものの、直前の操作(入力、シート切替、セル移動)はキャンセルされませんでした。 どこが間違っているのでしょうか?

  • どこが間違ってますか? (エクセルVBAです)

    質問をご覧くださりありがとうございます。 どなたか助けていただけないでしょうか。 以下のコードの場合、B2セルをダブルクリックすればシート(1)が開くと思っていたのですが、B2以外のセルをダブルクリックしてもシート(1)が開いてしまいます。 どこが悪いのでしょうか。 詳しい方がいらっしゃいましたら、どうか教えてください。 Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, cancel As Boolean) If Target = Range("B2") Then cancel = True Worksheets("シート(1)").Activate End If End Sub どうか、宜しくお願いいたします。

  • エクセル2007です。VBA不具合について教えてください。

    不具合ついてですが、任意のセルに何か入力中の時にA1の表示が停止してしまうことです。 入力中でもこれを回避する方法がありましたら是非お知恵を拝借したいと思います。よろしくお願いします。 現在の環境は以下のとおりです。 セルA1は=now()で秒まで表示。 横軸に日付(B2=2010/1/18~I2=2010/1/25)の8日、縦軸に時間(A3=0~A27=24)の24時間割があるシートです。 日付と時間(HOUR)がマッチしたリアルタイムセルのみを緑色(条件付き書式にて)に塗りつぶすスケジュール表を作成中です。 標準モジュールは次のとおりです。 Sub Auto_Open() Application.OnTime Now + TimeValue("00:00:01"), "timer" End Sub Sub timer() With Worksheets("Sheet1") If .Cells(1, 2) <> "" Then Exit Sub .Cells(1, 1).Calculate End With Application.OnTime Now + TimeValue("00:00:01"), "timer" End Sub

専門家に質問してみよう