[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『実行時エラー1004』(ぴこ)
EXCEL 2010、WindowsVista です。
9列で1日分の幅をとり、横にずーっと日付を並べたシートを作っています。 当日の9列分をを選択して色をつけてわかりやすいようにしようとマクロを 考えているのですが、エラーが出ます。
コードは以下の通りなのですが、
Private Sub cmdDataInput_Click() Dim Days As Integer '4/1からの日数 Dim C As Long '当日の列
Days = Date - DateValue(Worksheets("Data").Range("F1")) C = 6 + Days * WidthOfDay Worksheets("Data").Activate ActiveSheet.Cells.Interior.ColorIndex = 0 Worksheets("Data").Range(Cells(1, C), Cells(1, C + WidthOfDay - 1)).EntireColumn.Select Selection.Interior.ColorIndex = 24 ActiveSheet.Cells(1, C).Activate
End Sub
実行すると 「実行時エラー1004 アプリケーション定義またはオブジェクト定義のエラーです」 がでて、デバッグを押すと
Worksheets("Data").Range(Cells(1, C), Cells(1, C + WidthOfDay - 1)).EntireColumn.Select
のところがエラーになってます。
このとき、 C=852 になっており、WidthOfDay(定数) は 9 に定義してあります。
ところが、イミディエイトウインドで
Worksheets("Data").Range(Cells(1, 852), Cells(1, 852 + 9 - 1)).EntireColumn.Select
とやってみると、エラーは出ずに、思ったところが選択されます。
このエラーを回避するにはどうすればいいのでしょうか。
なお、関係あるかどうかわかりませんが、1行目だけは 9列ごとにセル結合を しています。F1:N1 を結合して 4/1 と入れており、そのまま同じように1年分 作っています。
with Worksheets("Data") .Range(.Cells(1, C), .Cells(1, C + WidthOfDay - 1)).EntireColumn.Select end With
これでは?
これで作動するなら、理由をよく考えてみてください。
ichinose
すでにichinoseさんから回答が出てるし、このテーマは、頻繁に掲載されるね。 で、ほとんど、「できました。ありがとうございます」になるけど、結構、次も同じ間違いをする。 でも、この間違い、無理はないと思うね。どちらかというと、VBA仕様が四角四面、杓子定規だと思う。 ただ、そう思っても、こちらは一介の平民、相手は天下のMSなのでどうしようもないんだけど。
Worksheets("Data").Range(Cells(1, C), Cells(1, C + WidthOfDay - 1))
この領域の宣言を、日本語で別の表現にしてみると ホテル"Data"の部屋で ○号室【Cell(1,C)】から□号室【Cells(1, C + WidthOfDay - 1)】までということになる。 だからいいじゃないかと思うけど、この○号室とか□号室には、どこのホテルの部屋か、その情報がないので VBAは勝手に、それら部屋に、【近場の】という形容詞を付けてしまう。(実際には ActiveSHeet)
その近場のホテルが "加賀屋"だったら、この構文は ホテル"Data"の部屋で、加賀屋の○号室から加賀屋の□号室まで・・・・ と、論理的に矛盾がありますよ・・ということで1004ではじいている。
繰り返すけど、ホテル"Data"の部屋で ○号室から□号室 と書けば、○号室も□号室も ホテル"Data"に決まってるじゃないか! そう思うけど、がまんがまん。
ぶらっと立ち寄り
ichinoseさん、ありがとうございます。
>これで作動するなら、理由をよく考えてみてください。
うまく作動しましたが、理由がまだわかりません。私の理解では
With AA .bb End With
は
AA.bb
とまったく同じだと思っていました。With を使うのは
AA.bb AA.cc AA.dd
など、同じ繰り返しを
With AA .bb .cc .dd End With
のように簡潔にするためだと思っていました。また、イミディエイトウインドでは
Worksheets("Data").Range(Cells(1, 852), Cells(1, 852 + 9 - 1)).EntireColumn.Select
でエラーにならないので、不思議です。
ぶらっと立ち寄りさん、ありがとうございます。
>ほとんど、「できました。ありがとうございます」になるけど、結構、次も同じ間違いをする。
確かに、理由がわかっていないので、また同じ間違いをくりかえしそうです。
> その近場のホテルが "加賀屋"だったら、この構文は >ホテル"Data"の部屋で、加賀屋の○号室から加賀屋の□号室まで・・・・ >と、論理的に矛盾がありますよ・・ということで1004ではじいている。
何となくわかるような気もするのですが、Range のヘルプの使用例に
Worksheets("Sheet1").Range("A1").Value = 3.14159
とあり、Sheet2 に
Sub test() Worksheets("Sheet1").Range("A1").Value = 3.14159 End Sub
として、 Sheet1 がアクティブでない状態で実行してもエラーになりません。
この場合、
"Sheet1" の部屋で、近場の "Sheet2" の "A1" の部屋
となって矛盾してはじかれる、ということにはならないのでしょうか。
(ぴこ)
Worksheets("Sheet1").Range("A1").Value = 3.14159 この構文の中で、どの部屋(セル)かというのは、Range( ) の括弧の中。 Worksheets("Sheet1").Range までは "Sheet1"ホテルの部屋 という意味。 で、問題になるのは "A1" ! これにはホテルが明記されてないじゃないか! でも、ここが、VBAのえこひいきというか片手落ち(?) Range("A1") と記述すると、括弧の中の "A1" は、かっこの外のRangeに紐つくとみなしている。
よけいに混乱させるかもしれないけど、シート1とシート2のブックを用意して標準モジュールに以下。 TestOKはどちらのシートがアクティブでもOKだけど、TestNGかも のほうは、シート1がアクティブならOK(これは、たまたまOKということ) シート2がアクティブなら実行時エラーになる。
Sub testOK() MsgBox Worksheets("Sheet1").Range("A1:C5").Address End Sub
Sub testNGかも() MsgBox Sheets("Sheet1").Range("A1", Range("C5")).Address End Sub
追記) NGかもの "A1" は、その外の(すぐ左の)Range つまり Sheets("Sheet1").Range に紐つく。 一方、"C5" は、その外の(すぐ左の)Rangeに紐つく。この左のRangeには シート修飾がないので近場のシートだと解釈されてしまう。
ぶらっと立ち寄り
> など、同じ繰り返しを >With AA > .bb > .cc > .dd >End With >のように簡潔にするためだと思っていました これは、間違いではないですねえ!! でも、Withの使う意味は他にもあるんですよ!! http://www.vbalab.net/vbaqa/c-board.cgi?cmd=one;no=45368;id=excel 以前こんな記述をしたことがあります。 これは、後でじっくり見ていただくとして・・・・。
>イミディエイトウインドでは > Worksheets("Data").Range(Cells(1, 852), Cells(1, 852 + 9 - 1)).EntireColumn.Select >でエラーにならないので、不思議です。
なるほど・・・・。 >Private Sub cmdDataInput_Click() このプロシジャーは、イベントプロシジャーでシートモジュールに記述されたものですよね?
CellsやRangeプロパティの親オブジェクトを省略すると、モジュールによって 補うオブジェクトが違うのです。
例
新規ブックにて(Sheet1とSheet2というシート名が最低存在する)、
標準モジュール(Module1)に
Sub 準備() On Error Resume Next With Worksheets("sheet1") .OLEObjects.Delete With .OLEObjects.Add(ClassType:="Forms.CommandButton.1", Link:=False _ , DisplayAsIcon:=False, Left:=202.5, Top:=114.75, Width:=90.75, Height _ :=48.75) .Object.Caption = "NGボタン" .Name = "Commandbutton1"
End With .Buttons.Delete With .Buttons.Add(207, 213, 78.75, 47.25) .Name = "btn1" .Caption = "Goodボタン" .OnAction = "test1" End With End With On Error GoTo 0 End Sub
別に標準モジュール(Module2)に
Option Explicit Sub test1() Worksheets("sheet2").Select Worksheets("sheet2").Range(Cells(1, 1), Cells(1, 3)).EntireColumn.Select End Sub
Sheet1のモジュールに
Option Explicit
Private Sub CommandButton1_Click() Worksheets("sheet2").Select Worksheets("sheet2").Range(Cells(1, 1), Cells(1, 3)).EntireColumn.Select End Sub
準備を実行してみてください。
Sheet1に NGボタンとGoodボタンが作成されます。
NGボタンをクリックすれば、Sheet1のモジュールの CommandButton1_Click が実行します。
Goodボタンをクリックすれば、標準モジュールのTest1が実行します。
でも、よく見てください。 CommandButton1_ClickとTest1の内容は、まったく同じです。
では、Goodボタン、NGボタンとクリックしてみてください。
Goodボタンは、正常にSheet2のA:C列を選択するのに NGボタンは、ぴこさんが提示されたコードと同じようにエラーになりますねえ!!
これがイミディエイトウインドでは正常終了するのに実際にはエラーになる現象と同じです。
問題は、
Worksheets("sheet2").Range(Cells(1, 1), Cells(1, 3)).EntireColumn.Select
Cells(1,1) と Cells(1,3)にあります。 これらの親オブジェクトの記述を省略すると、モジュールによって 決められたオブジェクトを付加して解釈します。
この付加されるオブジェクトが 標準モジュールとSheet1のモジュールでは 違うのです。よって、片方は正常に作動し、もう一方は、エラーになるのです。
標準モジュールの場合、省略すると、
Applicationが付加されます。
よって、Cells(1,1)は、Application.Cells(1,1)と同じです。
Sheet1のモジュールでは、Sheet1のオブジェクトが付加されます Cells(1,1)は、Worksheets("sheet1").Cells(1,1) と同じだと解釈します。
よって、 Worksheets("sheet2").Range(Cells(1, 1), Cells(1, 3)).EntireColumn.Select は、 Worksheets("sheet2").Range(Worksheets("sheet1").Cells(1, 1), Worksheets("sheet1").Cells(1, 3)).EntireColumn.Select
ね?、Sheet2を操作するのにSheet1のセルを中に入れたら、エラーになるよね?
これが原因です。 これで考察してみてください
ichinose
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.