質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
VB

VB(ビジュアルベーシック)はマイクロソフトによってつくられたオブジェクト指向プログラミング言語のひとつで、同社のQuickBASICが拡張されたものです。VB6の進化版といわれています。

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

Q&A

解決済

3回答

11394閲覧

エクセルのマクロにおいて発生するエラーについて(デバッグ実行時に正常終了する場合)

riorio

総合スコア11

VB

VB(ビジュアルベーシック)はマイクロソフトによってつくられたオブジェクト指向プログラミング言語のひとつで、同社のQuickBASICが拡張されたものです。VB6の進化版といわれています。

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

0グッド

0クリップ

投稿2016/08/04 07:56

前提

先日こちらの質問でお世話になったものです。
先日の質問と関連するところで、本日新たに分からない問題が発生したため、皆様のお力添えをいただきたく質問を投稿させていただきます。

実現したいこと

① 「マクロテスト_削除対象一覧表」ファイルの「削除対象一覧」シートの「略称」を上から順番に見る
② 「削除対象一覧」シートの「略称」が、「マクロテスト」ファイル「データ一覧」シートの「略称」と一致する場合
(i)それに対応するシートを削除する。
(ii)それに対応する行を「データ一覧」から削除する

といった処理を行いたいため、以下のようなマクロを作成しました。

lang

1Sub ファイル間_削除_01() 2 ' 変数の準備 3 Dim 削除対象取得 As Range 4 Dim 略称 As Range 5 6 ' DB設計書を開く 7 ChDir "C:\***" 8 Workbooks.Open Filename:="C:\***\マクロテスト.xlsm" 9 10 ' 削除確認を非表示にする 11 Application.DisplayAlerts = False 12 13 ' 削除対象一覧を上から順番に見て処理 14 For Each 削除対象取得 In ThisWorkbook.Worksheets("削除対象一覧").Range("A6", ThisWorkbook.Worksheets("削除対象一覧").Cells(Rows.Count, 1).End(xlUp)) 15 For Each 略称 In Workbooks("マクロテスト.xlsm").Worksheets("データ一覧").Range("B4", Workbooks("マクロテスト.xlsm").Worksheets("データ一覧").Cells(Rows.Count, 2).End(xlUp)) 16 ' 削除対象が「データ一覧」の略称に一致する場合 17 If 削除対象取得.Value = 略称.Value Then 18 19 ' 削除対象のシートを削除 20 略称.Hyperlinks(1).Follow 21 ActiveSheet.Delete 22 DoEvents 23 24 ' 削除対象と一致する略称を持つ行を「データ一覧」から削除 25 略称.EntireRow.Delete 26 DoEvents 27 28 'ループを抜ける 29 Exit For '略称 30 End If 31 Next 略称 32 Next 削除対象取得 33 34 ' 削除確認を表示にする 35 Application.DisplayAlerts = True 36End Sub

これによりやりたいことはできると思ったのですが、いざこのマクロを実行すると、**「実行時エラー'424:'オブジェクトが必要です」というエラーが[略称.EntireRow.Delete]**のところで起きてしまっています。
途中までは実行されるのですが、ある値の箇所で突然このエラーが出ます。

原因が分からなかったため、デバックで実行してみると何の問題も発生することなく処理を終えることができました。削除しているところで何か良からぬことが起こっているようなので、[DoEvents]関数を利用してみましたが、それでも同じエラーが起きてしまいました。

これは何が原因だと考えられますでしょうか?
よろしくお願いいたします。

参考図

【削除一覧表】
削除一覧表

【マクロテスト/ データ一覧】
データ一覧

【マクロテスト/ ロシア】
イメージ説明
※こちらの「ロシア」シートを消したあとにエラーが発生しています。

【実現してほしい結果】
最終目標
※デバッグを行い、一行ずつ処理を行って句場合はこのように実現したい結果が得られている状況です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

エラー原因

通常の実行とデバッグ実行で処理結果が異なる場合、イベント発生タイミングのずれなどが原因となることが多いです。

今回の場合ですが、
①.Followでリンク先に遷移する
②アクティブシートを削除する
という処理順序になっていますが、①での遷移が完了する前に②が処理されてしまい、結果としてデータ一覧シートが削除されてしまうことで略称のセルがなくなっているのではないでしょうか。

よくあるやり方
①削除したいシートを.Activateする
②アクティブシートを削除する
なら問題ないと思うのですが、.Followの動作が特殊(シートの遷移を促すだけ)なのではないかと思います。

改善案

先に挙げたActivateもひとつの方法ですが、マクロ処理の中でActiveなシートを変更すること自体、避けられるなら避けたいことです。
処理も重くなりますし、画面がちらついたり、最初に開いていたシートと違うシートが開かれたりしてしまいますので、見た目上もよろしくありません。
(関数などによってはActiveにしないと実行できない処理もあるので、やむを得ない場合もありますが。)

このため、Activeにせずにシート名を指定して削除するという方法をご紹介します。

' 削除対象のシートを削除 '略称.Hyperlinks(1).Follow 'ActiveSheet.Delete Dim strShtNm As String strShtNm = 略称.Hyperlinks(1).SubAddress 'リンク文字列を取得("USA!A1"のような値が取得できると思います) strShtNm = Left(strShtNm, InStr(strShtNm, "!") - 1) 'リンク文字列の!以降を除去してシート名だけの文字列にする Dim shtDel As Worksheet Set shtDel = Workbooks("マクロテスト.xlsm").Worksheets(strShtNm) shtDel.Delete

前回の質問より、略称セルの値ではなくリンク先情報を取得することに意義があるようでしたので、ちょっと面倒なシート名取得になっていますが、参考になれば幸いです。

投稿2016/08/04 10:02

編集2016/08/04 10:10
jawa

総合スコア3013

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

riorio

2016/08/08 01:54

いつもご回答いただきありがとうございます! 返信が遅くなってしまって申し訳ございません。 > ①での遷移が完了する前に②が処理されてしまい、結果としてデータ一覧シートが削除> されてしまうことで略称のセルがなくなっているのではないでしょうか。 なぜ②が先に処理されてしまうのでしょうか? VBAは上から処理していくため、普通に考えれば①のあとに②が実行されると思うのですが、、、。 そして確かにjawaさんのおっしゃるように、エラーが起こるまでどのような処理が行われているか確認したところ、最終的にデータ一覧シートが削除されてしまっていました。 ここの動作がどうしてこのようになってしまっているのか良く理解できないというか、しっくりこないというか、、、。 すみません、よろしくお願いいたします。
riorio

2016/08/08 02:18

連投してしまい申し訳ございません。 略称.Hyperlinks(1).Follow ActiveSheet.Delete のあとに Workbooks("マクロテスト.xlsm").Worksheets("データ一覧").Activate としてアクティブなシートを明示的に指定することでひとまずはエラーなしで処理することができました。 でもなんだかやはり腑に落ちないです、、、。 そして、これだと処理が重くなるということなので、jawaさんの教えてくださった処理を参考にさせていただき、実装してみたいと思います。
jawa

2016/08/08 04:38 編集

簡易的に環境を作成して動作確認しました。 確認したのは以下のような内容です。 ①リンク先にネットワーク上のxlsファイルを指定  ⇒開いてから処理される ②削除対象のROSとGMNを入れ替える  ⇒エラー発生せず ③削除対象のINDをCANに変更  ⇒CAN処理時にエラー 原因が掴みきれていないのですが、どうやら削除した次の行のリンクをFollowした後のDeleteでエラーが発生するようです。 .Followは「リンク先を開く」命令ですが、開ききるのを待たずに次の処理に進んでいるのではないかと思い①のテストをしました。 結果は、ちゃんと開ききってから次処理をしているようです。 次に"ROS"のセルやシートに問題がないかと思い②のテストを行いましたが、順序を入れ替えるとROSも正常に削除されました。 次に"IND⇒ROS"の流れ(削除した直後に次の行を処理)に問題があるのではないかと思い③のテストを行ったところ、予想していたCANの行でエラーが発生しました。 --- テストする際、エラーが出るソースに以下のようにHyperLink.SubAddressとActiveSheeet.Nameを表示する処理を追加して動作確認を行いました。 ``` ' 削除対象のシートを削除 略称.Hyperlinks(1).Follow '↓Debug ThisWorkbook.Worksheets("削除対象一覧").Cells(削除対象取得.Row, 5) = 略称.Hyperlinks(1).SubAddress ThisWorkbook.Worksheets("削除対象一覧").Cells(削除対象取得.Row, 6) = ActiveSheet.Name '↑Debug ActiveSheet.Delete DoEvents ``` 動作結果から察するに ・エラー発生時も.SubAddressは取得できている ・エラー発生時、ActiveSheetが切り替わっておらず「データ一覧」のまま表示される。 ということから.Followの遷移が遅くなるのか、またはリンクが混乱している?ように見えます。 よくわからない現象つぃて ・.FollowからActiveSheet.Deleteの間にメッセージボックスやSleepを追加し、充分時間をおいてから.Deleteを行っても「データ一覧」シートを削除してしまいエラーとなる。 ・.FollowからActiveSheet.Deleteの間でデバッグポイントを置いて処理中断してから続きを進めて.Deleteを行うとリンク先のシートを削除して正常終了する。 という部分です。 原因が分からないので断定的なことは言えませんが、「リンクによる遷移の直後にActiveSheetを取得するのは不安定」と言わざるを得ない状態です。 気持ちよく解決できないので、原因がわかる人がいたら解説お願いしたいです。。(T_T)
riorio

2016/08/10 00:46 編集

いつもお世話になっております。 > ・.FollowからActiveSheet.Deleteの間にメッセージボックスやSleepを追加し、充分時間をおいてから.Deleteを行っても「データ一覧」シートを削除してしまいエラーとなる。 >・.FollowからActiveSheet.Deleteの間でデバッグポイントを置いて処理中断してから続きを進めて.Deleteを行うとリンク先のシートを削除して正常終了する。 という部分です。 ここまで調べられていませんでした。 エラーの探り方等大変勉強になります! ありがとうございます。 うーん、やはりこのような処理は行わない方が良いということなのですね。 jawaさんに教えていただいた、変数を使ってリンク先の文字列を取得して処理する方法を試してみたところうまくいったのでこれでやっていきたいと思います! それにしても.followでのリンク先をうまく取得できない理由分からなくて気持ちが悪いですね、、、。
guest

0

ひとつ前のループのときに略称.EntireRowつまり対応する行を削除してしまっているため、ターゲットとなるオブジェクトが存在しない状態になっているのだと思います。
ExcelVBAではよくつまづくポイントですが、後ろから順に処理をする(下の行から順に見ていき、削除しても次の行の番号が変わらないようにする)必要があるのではないかと思います。

投稿2016/08/04 08:03

NatsumiOki

総合スコア1298

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

riorio

2016/08/04 08:14 編集

早速のご回答ありがとうございます! > ひとつ前のループのときに略称.EntireRowつまり対応する行を削除してしまっている デバッグで見ていくと対応する行は一つ前のループではなく、該当ループのなかで削除されているように見えるのですが違うということでしょうか? 確認してみると、「中国」と「インド」までは問題なく削除でき、「ロシア」のところでエラーが発生します。 理解が足りず申し訳ないのですが、NatsumiOkiさんのご指摘のポイントをもう少し具体的に教えていただくことはできますでしょうか? よろしくお願いいたします。
NatsumiOki

2016/08/04 08:21

うまくいっているように見えてもターゲットがずれていっているのではないかな?と思ったのですが…違う原因なのかな。 ちなみにロシアの行以降が別の名前だったり、またはロシアより前の行が別の名前だったりしても必ずその行で問題が起きますか? 同じ件数・同じ名前のテストデータだけでなく、ほかのデータでも試してみてほしいです。
riorio

2016/08/04 09:13

ターゲットがずれてしまっているんですかね、、、。 だから「オブジェクトが必要です」というエラーが出てしまうのか。 一度、NatsumiOkiさんのおっしゃるように他のデータでも試してみたいと思います!
riorio

2016/08/08 02:10

いつもお世話になっております。 ロシアでだけ引っかかるのが気になって、データを変えてみた結果をお伝えします。 元のデータでは「削除対象一覧表」で削除する対象として中国、インド、ロシア、ドイツとしており、「マクロテスト」では「データ一覧」シートの順番をアメリカ、中国、カナダ、インド、ロシア、メキシコ、ドイツ、ブラジル、日本としていました。 そして気になるロシアですが、同じく削除対象であるインドのあとすぐの削除対象となっています。 そこで、「データ一覧」シートのインドとロシアの間にダミーのデータを追加してみたのですが、そうすると作成したマクロは問題なく最後まで処理が行われました。 ただやはり、他の方々もおっしゃっているようにシートの削除後にオブジェクト(略称)が拾ってこれなくなってしまってエラーとなっているようなので、このあたりの処理を改善していく必要があるようです、、、。
guest

0

斜め読んだだけなので違うかもしれませんが、

VBA

1 For Each 削除対象取得 In ThisWorkbook.Worksheets("削除対象一覧").Range("A6", ThisWorkbook.Worksheets("削除対象一覧").Cells(Rows.Count, 1).End(xlUp)) 2 For Each 略称 In Workbooks("マクロテスト.xlsm").Worksheets("データ一覧").Range("B4", Workbooks("マクロテスト.xlsm").Worksheets("データ一覧").Cells(Rows.Count, 2).End(xlUp))

この辺で出てくる Rows オブジェクトの親要素が、動作状況によって確定しない気がします。

投稿2016/08/04 08:30

kaz.Suenaga

総合スコア2037

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

riorio

2016/08/04 09:14

ご回答いただきありがとうございます! やはりオブジェクトの親要素が確定されていないのが原因なのですね、、、。 もうちょっと他のデータ作成なども行ってみて確認してみます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問