Range関数で不思議な挙動が起こる理由とは?

このQ&Aのポイント
  • Excel VBAでRange関数を使用すると、アクティブなシートに依存しない範囲指定が可能です。
  • 例えば、ActiveSheet.Range("Sheet2!A1")とするとエラーが発生しますが、Range("Sheet2!A1")とすると問題なく指定したセルを取得できます。
  • これはRangeオブジェクトの仕様によるもので、Microsoft Docsには詳細な説明はなかったです。
回答を見る
  • ベストアンサー

Range("Sheet2!A1")が何故通る?

Excel VBAでRange関数を使っていて不思議に思う事があったので、少し質問させて下さい。 バージョンは、Office Standard 2010のVer14(32bit)です。 [Range]は、実際には[ActiveSheet.Range]の省略という認識でした。 そして、例えばSheet1がアクティブな状態で[ActiveSheet.Range("Sheet2!A1")]とすればエラーがでます。 [Range(Worksheets("Sheet2").Range("A1"))]でもエラーになります。 ところがこれが、[Range("Sheet2!A1")]だけにすると、問題なくSheet2のA1セルが取得できるのです。 セルに名前を付けた場合も、同じようにアクティブでないシートのセルが取得できました。 場合によって、Rangeの親オブジェクトがActiveSheetであったりなかったりするようなのですが、これはどのような仕様なのでしょうか? Microsoft Docsをざっと見たのですが、載ってなさそうだったので。 以下、自分がチェックに使ったコードです。 Sheet2!A1セルにShTwoという名前を付けています。 Sub test()  Debug.Print Range("A1").Address  Debug.Print Range("A1").Parent.Name ' Debug.Print ActiveSheet.Range("Sheet2!A1").Address '1004:アプリケーション定義またはオブジェクト定義のエラーです  Debug.Print Range("Sheet2!A1").Address  Debug.Print Range("Sheet2!A1").Parent.Name ' Debug.Print ActiveSheet.Range("ShTwo").Address'1004:アプリケーション定義またはオブジェクト定義のエラーです  Debug.Print Range("ShTwo").Address  Debug.Print Range("ShTwo").Parent.Name ' Debug.Print ActiveSheet.Range(Worksheets("Sheet2").Range("A1")).Address '1004:アプリケーション定義またはオブジェクト定義のエラーです ' Debug.Print Range(Worksheets("Sheet2").Range("A1")).Address ''Range'メソッドは失敗しました:'_Global'オブジェクト End Sub

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

  • ベストアンサー
  • kkkkkm
  • ベストアンサー率65% (1607/2444)
回答No.3

こちらの説明が見つかりました。 Range("Sheet2!A1")の場合 Application.RangeのApplicationが略されているという感じです。 Rangeオブジェクトの使い方(1) の中の外部参照の使用 http://hp.vector.co.jp/authors/VA016119/range1.html

Mathmi
質問者

お礼

答ありがとうございます。 (回答者が同一であると気付かず、回答No.2のお礼が変になってしまいました。申し訳ありません) 紹介していただいたサイト、疑問にそのままずばりな内容でした。 >対象オブジェクトは省略するか Application を指定します。 ・オブジェクト修飾子(ピリオドの左側に記述するオブジェクト)を指定しない場合、エクセル全体(Excel.Application)が省略されている ・シートが指定されない場合、デフォルトシートが選択される。 ・オブジェクト修飾子であろうが範囲の名前であろうが、シートが指定された場合そのシートが選択される。 ・引数が一つの場合、Rangeプロパティには範囲の名前を現す文字列しか渡せない(Rangeオブジェクトは渡せない)。 と、理解してしまえば当たり前の事でした。 ですが、普段Applicationを使わないので、全く思い浮かびませんでした。 また一つエクセルに詳しくなる事ができました。どうもありがとうございます。 ただ、MicrosoftDocsのApplication. Range プロパティ (Excel)では >オブジェクト修飾子を指定せずにこのプロパティを使用すると、ActiveSheet.Range のショートカットとなります。 とあります。 もしかして、Microsoftの公式資料でも仕様通りではない……?

その他の回答 (4)

  • kkkkkm
  • ベストアンサー率65% (1607/2444)
回答No.5

> もしかして、Microsoftの公式資料でも仕様通りではない……? そうですね。資料が多すぎて手が回らない感じかもしれません。 ただ、Rangeあたりを説明するとかなりややこしくなるというのをかなり前にどこかで見た気がします。

Mathmi
質問者

お礼

回答ありがとうございます。

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.4

正面からの、理由の回答でないのが残念ですが、 エクセル関数のINDIRECT関数のような処理(文字列指定なのだが、セル範囲を指定しての扱いで、取り込む処理)をRangeの引数に対し事前に行うのではないでしょうか。ワークシート関数の引数のような(下記例)書き方は通り、WorkSheets(”Sheet1")のように、VBA的な指定が通らないのは、何か内部処理のやり方に起因するのでは。VBAでフルパス指定文字列でも似たようなことだあると思いませんか。 ーー 小生がやってみると、質問の例に加え、下記の例がOKでした。 Sub test05() x = "Sheet4!B5" Range(x) = "AAvv" End Sub Sub test06() x = "[Book1]Sheet3!B7" Range(x) = "AApp" End Sub ーー もう一つ、Shitキーを押しながら、エクセルのアイコンをクリックして Book2を起動して(名前を付けて保存する前に) Sub test07() x = "[Book2]Sheet2!B2" Range(x) = "AAFFF" End Sub もOKでした。

Mathmi
質問者

お礼

回答ありがとうございます。 >WorkSheets(”Sheet1")のように、VBA的な指定が通らないのは、何か内部処理のやり方に起因するのでは。 真に申し訳ありません。これは私のミスです。 自分は[Range(Range("A1"), Range("B2"))]のように、引数にRangeオブジェクトを指定したつもりでした。 ですが[Range(Worksheets("Sheet2").Range("A1"))]だと、実は[Range(Worksheets("Sheet2").Range("A1").Value]、つまりセルの文字列を引数に指定する事になる事に、質問を投稿してから気付きました。 何も指定しなかった場合、Rangeオブジェクトを返す場合とValueプロパティを返す場合の二通りがあるのを忘れていました。 色々なパターンを試していただき、ありがとうございました。 保存前だと、ブックを指定するブック名に拡張子が付かないんですね。

  • kkkkkm
  • ベストアンサー率65% (1607/2444)
回答No.2

> 「今の知識ではエラーになる筈なのにエラーにならない理由」なんです。 単にRangeがActiveSheet.Range略ではないという事なのではないでしょうか。 標準モジュールにおいてRangeの親は既定ではActiveSheetだけど中で明示されたらそれが優先するとか。 Range("Sheet2!A1").Address は Sheets("Sheet2").Range("A1").Address と書いたとみなされると思いこんでみるとか。 Range("A1") が Range("A1").Value とみなされると同じかなくらいで。ちょっと違うけど。 どこかにそのような説明がないか知りたいということだとしたら、わかりません。

Mathmi
質問者

お礼

回答ありがとうございます。 >単にRangeがActiveSheet.Range略ではないという事なのではないでしょうか。 別のエクセルの解説ページで >Range("A1").Value >というオブジェクト式は、実は、 >Application.ActiveWorkbook.ActiveSheet.Range("A1").Value >と同じことを意味しています。 とあったので、Rangeプロパティ(でいいのか不安ですが)は、Worksheetオブジェクトのプロパティだとばかり思い込んでいました。 実際はNo.3の方に回答頂いた通り、WorksheetではなくApplicationのプロパティっぽいです。 なお、オブジェクトの構造としてはWorksheetの下にRangeがあるので、 Application.Range("A1").ParentはApplicationオブジェクトではなくWorksheetオブジェクトを返しました。

  • kkkkkm
  • ベストアンサー率65% (1607/2444)
回答No.1

> [Range]は、実際には[ActiveSheet.Range]の省略という認識でした。 よくわかりませんが、そうなんですか。 Sheet1のシートモジュールで Sheets("Sheet2").Activate Range("a1").Value = 111 と Sheets("Sheet2").Activate ActiveSheet.Range("a1").Value = 111 は同じ結果ではないのですが…。 また 標準モジュールでしたら Sheets("Sheet2").Activate Debug.Print ActiveSheet.Range("Sheet2!A1").Address や Debug.Print Sheet2.Range("Sheet2!A1").Address でエラーにはならないと思います。

Mathmi
質問者

お礼

回答ありがとうございます。 >Sheet1のシートモジュールで 自分は基本的にシートモジュールを使わないので、その視点は抜けていました。 作業は全て標準モジュールで行っていました。 >エラーにはならないと思います。 いえ、質問したいのは「エラーにならないコード」ではなく「今の知識ではエラーになる筈なのにエラーにならない理由」なんです。

関連するQ&A

  • VBAのRangeオブジェクトについて

    いつもお世話になっております。 VBAのRangeオブジェクトについてご教示下さい。 例えば下記のPGを組みます。 Sub test() Dim r As Excel.Range Set r = Me.Range("A1") Debug.Print r.Cells.Count End Sub この時、Debug.Printには"1"と表示されます。 Debug.Printでブレイクを置き、ここでA列を削除するとDebug.printでエラーが出てしまいます。 Rangeオブジェクト生成後、もしも参照先のセルが削除してしまった場合、条件分岐の処理を入れたいのですが、どのように処理をいれればよろしいでしょうか? セル削除後、Rangeのプロパティを参照した時点でエラーが発生してしまいます。 Typeで確認するとRangeがちゃんと取れるのですが・・・。 "参照先のセルが消されたかどうか"を判別する方法はあるのでしょうか?

  • VBA:2つの異なるシートからグラフを作成する

    VBA初心者です。(はじめてから3日目。。。) もしかすると、すごい簡単なことなのかもしれなくて申し訳ないのですが、質問させてください。 二つの異なるシートのデータを使って、円グラフを作製しようとしています。 ですが、「アプリケーション定義またはオブジェクト定義のエラー」が出てしまいます。 どこが間違っているのかをご教授願えませんでしょうか。 よろしくお願いします。 Sub graph() Charts.Add With ActiveChart .ChartType = xlPie .SeriesCollection(1).XValues = Worksheets(1).Range(Cells(2, 3), Cells(2, 5)) .SeriesCollection(1).Values = Worksheets(2).Range(Cells(3, 2), Cells(3, 4)) .SeriesCollection(1).Name = Worksheets(1).Cells(1, 1) .Location where:=xlLocationAsObject, Name:="sheet3" End With End Sub ちなみに、各セルにはちゃんとデータが入っております。 よろしくお願いいたします。

  • ExcelVBAにて異なるシート間での値貼り付け

    Excel VBAの異なるシート間での値のコピーと貼り付けに関して質問をさせてください。 私はExcel2007を使って、Sheet1のセルの値をsheet2に貼り付けようとして以下のコード(1)を書きましたが、うまくいきません。動作確認のためsheet1内での値のコピペを行うコード(2)を作成し実行したところ、正常に動作しました。 コード(1)をコンパイルしたときに表示されるメッセージは、[実行時エラー'1004':アプリケーション定義またはオブジェクト定義のエラーです] です。 質問としては、 Q1:等号(=)を用いた値の貼り付けは、異なるシート間に対応していないのでしょうか。 Q2:コード(1)を改良する場合、どのように書き直せばよいでしょうか。 アドバイスいただけましたら幸いです。 コード(1) Worksheets("Sheet2").Range(Cells(1, 10), Cells(5, 10)).Value = Worksheets("Sheet1").Range(Cells(1, 1), Cells(5, 1)).Value コード(2) Worksheets("Sheet1").Range(Cells(1, 10), Cells(5, 10)).Value = Worksheets("Sheet1").Range(Cells(1, 1), Cells(5, 1)).Value

  • VBA シート指定とファイル名入力

    部署ごとに分割し、ブックで保存するコードです。 sheet名は「部署」です。 Sub macro1() Dim w As Worksheet Dim n As Long Dim r As Long Dim s As String Dim WSH As Variant Dim myPath As String Set w = ActiveSheet n = Worksheets.Count Application.ScreenUpdating = False On Error GoTo errhandle For r = 5 To w.Range("B65536").End(xlUp).Row s = w.Cells(r, "B") w.Rows(r).Copy Worksheets(s).Range("B65536").End(xlUp).Offset(1, -1) Next r On Error GoTo 0 Set WSH = CreateObject("Wscript.Shell") myPath = ActiveWorkbook.Path & "\1\" For r = Worksheets.Count To n + 1 Step -1 Worksheets(Worksheets.Count).Copy ActiveSheet.Columns.AutoFit ActiveWorkbook.SaveAs Filename:=myPath & ActiveSheet.Name ActiveWorkbook.Close False Application.DisplayAlerts = False Worksheets(Worksheets.Count).Delete Application.DisplayAlerts = True Next r w.Select Exit Sub errhandle: Worksheets.Add after:=Worksheets(Worksheets.Count) ActiveSheet.Name = s w.Rows(1).Copy Range("A1") w.Rows(2).Copy Range("A2") w.Rows(3).Copy Range("A3") w.Rows(4).Copy Range("A4") Resume Application.ScreenUpdating = True End Sub (1)sheet1にマクロ実行ボタンを配置し、部署seedにマクロ実行命令をする。 (2)sheet1のB2セルにファイル名を入力して、そのファイルに保存する。(例部署ファイル) (1)Dim w As Worksheets("部署")と変更したのですが、エラーが出ました。 (2)myPath = ActiveWorkbook.Path & "\部署ファイル\"   ↑ これをsheet1のB2セルから指定できるようにしたいです。 宜しくお願いします。

  • 隣のシートでのコピーのマクロ

    隣のシートでコピーをするマクロを作成しようとしたところ、エラーがでます。 具体的には、以下のようなマクロを作成したところ、 最後の、「 WC.Range(Rows(1), Rows(RowNum)).PasteSpecial」で、 「アプリケーション定義またはオブジェクト定義のエラーです」というメッセージがでてきます。 試しに、 WC.Range("a1").Select としても同様のエラーがでるので、 他のシートでのRangeの使い方に問題があるようだ、というのがわかるのですが、 具体的に何が問題で、どのように解決をしたらいいのかがわかりません。 よろしくお願い致します。 =====以下、マクロ===== Dim WA As Worksheet Dim WC As Worksheet Dim i As Integer Dim LastRow As Long Dim RowNum As Long i = ActiveSheet.Index Set WA = Worksheets(i) Set WC = Worksheets(i + 1) WC.Rows(1).Copy WC.Range(Rows(1), Rows(RowNum)).PasteSpecial

  • Range.Name プロパティの使い方

    VBAの勉強中のものです。(エクセル) 一つ一つヘルプを見て、検証して勉強していこうと思ってるのですが 使い方がわからないので教えてください。 Range.Value プロパティならうまくいくのですが、 Range.Name プロパティの使い方がわかりません。 ----------------------- Sub test1() MsgBox Range("a1").Name End Sub Sub test2() Dim R As Range Set R = Range("a1") MsgBox R.Name End Sub ----------------------- どちらも、アプリケーション定義またはオブジェクト定義のエラーです。になります。 ----------------------- Sub test1() MsgBox Range("a1").Value End Sub Sub test2() Dim R As Range Set R = Range("a1") MsgBox R.Value End Sub ----------------------- rangeにすればうまくいきます。 Range.Name プロパティの使い方を教えてください。アドバイスよろしくお願いします。

  • エクセル VBA)) CheckBox_Clickでちょっとわからないことがあるのですが。

    すいません、VBAかなり初心者ですごい簡単な質問かもしれません。 VB.netやVB6を触っていればわかるとおもうのですが、 シート内でCheckBox_Clickイベントの実行文のなかでセルを参照する記述を書いているのですが、 1) Dim a as String 2) a = WorkSheets("??").Range(E9) 2)の場所でエラー(アプリケーション定義またはオブジェクト定義エラーです。)とセル位置を参照できないのですが、シート内で記述しており他のSUB ??() のプロシージャーでは問題なく参照できるのですが、なぜなんでしょうか?  

  • エクセルでシートのコピー

    いつもお世話になっています、マクロ初心者です。 カレンダーの1月分をシートごと12月までコピーするのに、サンプル集をそのまま引用したのですが、シート名を指定する所でエラーになってしまいます。 $"月"の部分を削除すればうまくいきます。 エクセル2000パーソナルだからなのでしょうか? 'シートコピー Worksheets(1).Cells.Copy For i = 2 To 12 Worksheets.Add after:=Worksheets(ActiveSheet.Index) ActiveSheet.Name = CStr(i) & "月"(この行がエラーになります) ActiveSheet.Paste Range("A1").Select Next i エクセル2000パーソナルで処理する方法がありましたら教えてください。

  • sheetの中身もコピーしたい

    表題通りの質問になります。以下のソースを実行すると、コピーはされますが、中身はコピーされません。どうすればよろしいでしょうか? アドバイスお願いいたします。 Sub sheetの連続コピー() Dim sheet_name As String '文字型変数の宣言 sheet_name = ActiveSheet.Name '現在アクティブになっているシート名の取得 'Range("A1") = sheet_name '取得したsheet名をA1のセルに表示 Dim NewWS As Worksheet For i = 1 To 10 'Worksheets.Add ~ 空のSheetが ○個 挿入される Set NewWS = Worksheets.Add(Before:=Worksheets(sheet_name)) NewWS.Name = sheet_name & i Next End Sub

  • excelのマクロでrangeの選択がうまくいきません。

    excelのマクロでrangeの選択がうまくいきません。 以下のマクロをsheet2に書きました。testcopyは動きますが、testcopy2は動きません。なぜなのでしょうか。どうすればいいのでしょうか。それ以外のマクロの部分との関係から、cellsを使い、数字を使ってrangeの処理をしたいのです。よろしくお願いします。 Sub testcopy() Worksheets("sheet1").Range("B3:C10").Copy Worksheets("sheet2").Range("e5").Select ActiveSheet.Paste End Sub Sub testcopy2() Worksheets("sheet1").Range(Cells(3, 2), Cells(10, 3)).Copy Worksheets("sheet2").Range("e5").Select ActiveSheet.Paste End Sub

専門家に質問してみよう