ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

EXCEL VBAコミュのオブジェクト指定の方法が不適切、なのかな??

  • mixiチェック
  • このエントリーをはてなブックマークに追加
Win版2003を使っております。

記録機能を一切使わず、キーボードからステイトメント全文を入力してマクロを書きました。初めての経験です。

そのマクロが思い通りの動作をしてくれません。「実行時エラー。アプリケーションの定義またはオブジェクトの定義のエラーです。」と表示されます。いつも同じステイトメントでエラーが発生しているようでもありません。

まだ細かいところまで検証しておりませんが、アクティブシートがどれであるかによって、違うステイトメントがエラーになるような気がしております。

どこに原因がありうるのかといったヒントや、ここが絶対おかしいというご指摘など、みなさんのお知恵を拝借したく存じます。よろしくお願いします。


やりたいことそのものは、次のURLにあるわりと最近のトピと同等のことなのですが。
http://mixi.jp/view_bbs.pl?id=73395756&comm_id=24524



実際に自分で記述したマクロは次のとおりです。


Sub Trial_Copy&PasteForDataMerge()
'-------------------------------
'要素1
'Sheet"Inv"
'整形用数式を必要数貼り付ける。
'-------------------------------
Worksheets("Inv").Range("H2:N2").Copy _
Worksheets("Inv").Range(Cells(6, 8), _
Cells(Worksheets("Inv").Range("D5").End(xlDown).Row, 8))
'
'---------------------------------------
'要素2
'Sheet"Inv"の整形用数式の計算結果の値を
'Sheet"PivotData"に貼り付ける。
'---------------------------------------
Worksheets("Inv").Range(Cells(6, 8), _
Cells(Worksheets("Inv").Range("D5").End(xlDown).Row, 14)).Copy
'
Worksheets("PivotData").Range("B2").PasteSpecial _
Paste:=xlPasteValues, _
Operation:=xlNone
'
'
'
'------------------------------------
'要素3
'Sheet"Prod"
'整形用数式を必要数貼り付ける。
'------------------------------------
Worksheets("Prod").Range("Q2:W2").Copy _
Worksheets("Prod").Range(Cells(6, 17), _
Cells(Worksheets("Prod").Range("B5").End(xlDown).Row, 17))
'
'----------------------------------------
'要素4
'Sheet"Prod"の整形用数式の計算結果の値を
'Sheet"PivotData"に貼り付ける。
'----------------------------------------
Worksheets("Prod").Range(Cells(6, 17), _
Cells(Worksheets("Prod").Range("B5").End(xlDown).Row, 23)).Copy
'
Worksheets("PivotData").Range(Cells _
(Worksheets("PivotData").Range("B1").End(xlDown).Row + 1, 2)).PasteSpecial _
Paste:=xlPasteValues, _
Operation:=xlNone
'
'----------------------------------------
'以下、別Sheetに対する同一パターンの
'Copy&Pasteに付き、割愛。
'----------------------------------------
'
'
'
End Sub

コメント(14)

1、3 Sedviciousさん、
早速にコメントくださり、感激です!!

>Cellsの親オブジェクトを指定していません。
>Cellsメソッドは、 (ActiveWorkbook.ActivSheet.)Cells の省略と見なされてい>ます。(Cellsのヘルプを参照して下さい。)

ここが今回のつまづきのポイントだったようですね!!

アクティブシートがなんであるかによってマクロの動作が変わると感じていましたが、この理由によって、やっぱり動作が一定していなかったのですね!!


>With 〜 End With 構文
> .Range("B2").PasteSpecial xlPasteValues

参考になります。ステイトメントは短いほうが入力も楽ですし、間違いの可能性も低くなりますし。


>プロシージャ名に「&」は使えません。
ご察しのとおり、投稿時にテキトーに付けたものです。でも使えないことが明示的に分かったことも、ここで新たに得られた知識の一つです。


このマクロは、会社のおシゴトで月初に発生する、ある作業に活用するつもりでおりました。連休明け早速試してみます!!

Cellsをヘルプで調べてみました。すると「Cellsプロパティ」とありました。プロパティとはどうやら特徴やら属性のことを意味しているようです。特徴やら属性であれば、それを持っている対象自体を明確に指定しない限り、ただ特徴やら属性だけを指定しようとしても、それは論理的に不可能です。その理屈はとてもよく理解できます。

Worksheets("xxx").Cells(1, 1)だとか、Worksheets("xxx").Range("AA100:ZZ200").Cells(1, 1)だとか、基本的にそのように記述しなければならないことは、おかげさまで納得できました。


しかし、それでもなおうまくいかない箇所が出てきております。クリアーできた命令文の記述方法と比較しながら、原因を想定しようとしてみました。でも、見当がつきません。前回と同じエラー、アプリケーションの定義またはオブジェクトの定義のエラーがここでも発生してしまいました。

引き続きお知恵を拝借したく、みなさん、よろしくお願いいたします。

その場所は冒頭に書いた要素4の後半部分、つまり、コピー&ペーストのペースト作業の部分です。その前半(コピー作業)までは、要素1、2、3とも無事通過して、コピー対象範囲のデータがちゃんとクリップボードに格納できております。

現在ペーストするためのコードは次のように書いております。


Worksheets("PivotData").Range(Worksheets("PivotData")Cells( _
Worksheets("PivotData").Range("B1").End(xlDown).Row + 1, 2)). _
PasteSpecial _
Paste:=xlPasteValues, _
Operation:=xlNone


これを書きながらふと思ったのですが、Worksheets("PivotData").の記述が頻繁に出てきております。貼り付け先シートをアクティブにする命令文を最初に一行入れて、今ある貼り付けの命令文からWorksheets("PivotData")を取り去ったら、もしかして出来たりして?

でも今は、アクティブシートがなんであるかに依存しない命令文にこだわり続けたい気分です。
6、まっつんごさん、

済みません、失礼いたしました。実は、
Worksheets("PivotData").Range(Worksheets("PivotData")Cells( _
は、単にそのコメントに書くときに書き誤っただけで、実際のマクロの命令文には、
Worksheets("PivotData").Range(Worksheets("PivotData").Cells( _
とピリオドを入れております。スクロールを避ける意味で、改めてその一文をこのスレッドに記します。

Worksheets("PivotData").Range(Worksheets("PivotData").Cells( _
Worksheets("PivotData").Range("B1").End(xlDown).Row + 1, 2)). _
PasteSpecial _
Paste:=xlPasteValues, _
Operation:=xlNone

>アクティブシートに依存しない書き方は必須と考えますので是非こだわり続けて欲しいですw。
やっぱり、それが基本ですよね!!

プログラミングが本職ではないので、多少基本を逸脱した命令文であれ、結果を出したらそれでもよいのですが、お遊び気分にせよ、せっかく始めたVBA。なんとかそこにはこだわってみようと思います。

現実のおシゴトでは、今まで通り手作業に頼っておりますが、マクロ化を考える中で、自分がなんとなくしている手作業の中身を見直すことができて、そこに付随して発生していた手作業をエクセルの数式で対応して、作業時間は僅かではありますが、確実に短縮できております。そこは、ひとつのマクロ化の成果うちだと思っております。


8、Sedviciousさん、

なるほど、よ〜くわかりました。RangeとCellsの関係ですね。

Range(Cells(1, 1), Cells(2, 2))
これなら問題ありませんよね。結果的にRange("A1:B2")と同義ですよね。

でも、わたしが気がつかずにしていたことは、
Range(Cells(1, 1))
だったんですね!!!

おかげさまでコピー&ペーストを繰り返す工程は完全クリアー出来ました。


今まで、ちまちま手作業でしていたことが、なんと、瞬きを二回ぐらいする間に、あっけないぐらいに出来ちゃいました!!

大変役立ちました。ありがとうございます!!

予想外の速さで結果が得られたことにびっくりして、思わずしてしまった瞬きが二回目の瞬きだったのかもしれません。



さて、ここまでは良いのですが、コピー&ペーストを繰り返す工程に続く別の工程で、『またしても』ApplicationまたはObject定義のエラーが発生してしまいました。

ここに至る体験から、Worksheets()などの、上位オブジェクトとの関連性を排除したらどうなるかを調べたら、恐らく問題のありかが更に見えてくるだろうと感じます。

そこで、ワンブック単一シートにして、そこにサンプルデータを入力し、その状態に応じた同等の命令文を作って実行させてみました。更に、ダメ押しのため対象シートをアクティブの状態にしておきました。

それでもApplicationまたはObject定義のエラーが発生しました。


単純化したファイル構成での命令文を次に記します。

もう少し、一人であがいてみるつもりでおりますが、皆さん、何かヒントのようなことがあれば教えてください。



For n = Range("C5").End(xlDown).Row To 6 Step -1
'
If Cells(n, 4).Value = 0 Then
Rows("n:n").Delete
End If
'
Next n


定義のエラーが発生した命令文は、指定条件合致時にその行を削除しようとする文です。

削除するアクションの対象であるRows("n:n")しか、ほかに原因は思い当たりません。でも、例文集などには、10行目を削除する事例として、Rows("10:10").Deleteとあります。

nと10とでは何が違うのか、恐らくそのあたりに原因があるだろうと想定してしております。

値が0のデータが全くない状態で同一命令を実行したら、見かけ上何も起こらずにマクロは終了しております。ですからこの命令文で問題があるのは唯一削除する文だけだと思います。
"n:n"では「N列」を指定しているものと解釈されるため、
単一行あるいは行範囲として解釈不能なパラメータを与えているせいでは?
皆さん、ついに出来ました!!

VBAのヘルプでRows調べたら、まっつんごさんが12でおっしゃるようなRows(1).Deleteの用例が載っておりました。

"1:1"ではなく、1でもできるなら、今やりたいことの場合なら簡単に解決できるじゃない。ってなわけで、For Nextでカウントするために使っている変数nを、"n:n"とはせず、素直にそのままnと入れて完成。


ところで、カウントするための変数nに対しては、データの形式を何も定義していません。その場合はVariant型として定義される、と何かに書いてあったような記憶が残っておりました。

そこで、Rows("10:10")の用例を見た時に、Variant型ならば、そこに代入された数値は、10なら10という文字としても扱われるかもしれない、と少し期待しておりました。

しかし、そうではなかったようです。"n:n"とすると、そこにあるnは、もやは変数ではなくただの文字に扱われてしまうようです。


失敗の体験の後に、Minonさんやまっつんごさんの説明を読み、言わんとすることが実感が伴って理解出来ました。


皆さん、ありがとうございました。
夏休みに入り自由な時間を取れるのに任せて、オブジェクト指定について、わたしなりのまとめをしてみます。

独り言のようなことなので、スルーしてくださっても構いません。


マクロを実際に書いてみて思ったのは、オブジェクトという概念を理解することの重要性です。

そしてもう一つは、単独セルなりセル範囲をマクロで扱う場合、Cellsプロパティで行・列を数値として扱うほうがマクロ記述には向いているのかもしれないということです。

その割に、巷にはRangeプロパティの説明はよく見かけても、Cellsプロパティを説明したものがあまり見当たらないような気がします。ということで、Cellsプロパティを使う時のオブジェクト指定のまとめです。


1. オブジェクト指定が不適切な例
Worksheets("xxx").Range(Cells(1, 1), Cells(2, 2)).Select


2. オブジェクト指定が適切にできている例
Range(Worksheets("xxx").Cells(1, 1), Worksheets("xxx").Cells(2, 2)).Select


3. オブジェクト指定はできているが、そこまでする必要がない例
Worksheets("xxx").Range( _
Worksheets("xxx").Cells(1, 1), _
Worksheets("xxx").Cells(2, 2) _
).Select



更にWith構文を適用して簡潔にした例
With Worksheets("xxx")

Range(.Cells(1, 1), .Cells(2, 2)).Select

End With


オブジェクトとは、命令文の中で相対的に決まるもののようです。
反対の視点から言えば、プロパティやメソッド単体では、オブジェクトという概念は存在し得ないのかもしれません。


上記命令文の例で言えば、Selectというメソッドから見たオブジェクトは、
Range(Worksheets("xxx").Cells(1, 1), Worksheets("xxx").Cells(2, 2))
です。これがSelectという動作の対象物。

Cells(1, 1)というプロパティから見たオブジェクトは、
Worksheets("xxx")
です。これがCells(1, 1)というプロパティが存在する対象物。

といった具合に理解すれば良いのだろうと思いました。

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

EXCEL VBA 更新情報

EXCEL VBAのメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。