[[20110704084620]] 『実行時エラー1004』(ぴこ) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『実行時エラー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.