2017-02-01 2 views
6

名前Rubberduck 2.0.11.2453のコード検査を実行した後、としてタグが付加されます4つの範囲の参照があります。コード検査範囲リファレンス

は、メンバー「レンジ」暗黙のうちにActiveSheet

参照問題の範囲は名前付き範囲を参照しています。名前付き範囲参照を修飾する必要がありますか?

Private Sub RunORatio(ByVal TabNum As Integer) 
    Dim Start As Integer, Cat As Integer, iMth As Integer, CurrentRow As Integer, Report As Integer 
    Dim wsORatio As Worksheet, wsData As Worksheet, wsMacro As Worksheet 
    Dim sMap As String, Test As String 

    With ActiveWorkbook 
    Set wsMacro = .Worksheets("Macro") 
    Set wsORatio = .Worksheets("ORatio" & TabNum) 
    With wsORatio 
     sMap = "oratio" & TabNum & "map"   
     For CurrentRow = 1 To Range(sMap).Rows.Count    '<---1 here 
     Test = Range(sMap).Cells(CurrentRow, 1)    '<---1 Here 
     Set wsData = ActiveWorkbook.Worksheets(Test) 
     Start = Range(Range(sMap).Cells(CurrentRow, 2)).Row '<---2 Here 
     Report = wsMacro.Range(sMap).Cells(CurrentRow, 3) 
     For Cat = 0 To 12 
      For iMth = 1 To 12 
      wsORatio.Cells(Report + Cat, 7 + iMth) = wsData.Cells(Start + Cat, 37 + iMth) 
      Next iMth 
     Next Cat 
     Next CurrentRow 
    End With 
    End With 
End Sub 
+0

'sMap'は' Name'として定義されていますので、コード全体を共有していない(おそらく長すぎます)ので、あなたはそれを 'Range'に設定しましたか? –

+0

私は、除外された唯一のものは宣言です... – Rdster

+0

あなたの名前付き範囲 'oratio1map'の範囲は何ですか...?それはワークブックですか?範囲が定義されているシートを指定して、そのタグを避けるべきです。つまり、 'Sheets(" SheetName ")。Range(...)'! – R3uK

答えて

9

免責事項:私はRubberduckの開発に深く関わっています。

この一般的な誤りを考慮してください

lastRow = Worksheets("Sheet12").Cells(1, Rows.Count).End(xlUp).Row 

Rowsは非修飾であり、したがって暗黙的にアクティブなシートを意味し、従ってRows.Count必ずしも「Sheet12」に行カウントはありません。コードとなる可能性がありますが、アクティブシートの内容によってはlastRowに正しい値が設定されていないという微妙なバグが発生する可能性もあります。

またはこの1:

ActiveWorkbook.Worksheets("SummarySheet") _ 
    .ListObjects("Table1").Sort.SortFields.Add _ 
     Key:=Range("Table1[[#All],["Date]]"), _  
     SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortTextAsNumbers 

はそれを参照してください? Keyパラメータが修飾されていないため、実行時にエラー1004でコールが失敗します - "オブジェクト '_Global'のメソッド 'Range'が失敗しました。それは169 Stack Overflow questionsです。 「エラー1004」は1465 Stack Overflow questionsになります。

アクティブなワークシートへの暗黙的な参照は、バグの非常に一般的な原因です。


RubberduckのVBAコードの検査は、ReSharperののC#の静的コード解析のように、ヒント/提案です。このツールでは、という問題を引き起こす可能性があるか、コードがあまり明示しない可能性があることを伝えています。

はあなたを行います 必要は完全に ひとつひとつRangeコールを修飾するために?もちろん、そうではありません - Rubberduckは、これらの例では ActiveSheetが暗黙のうちに参照されていることを伝えるだけです。それだけです。内部(

ignore once

は、「修正」は、特別なコメントが挿入さ:

あなたはいつもRubberduckを伝えることができる「一度無視」クイックフィックスを使用して、「私は私がやっているものを知って、見て」検査が有効なままにしながら、Rubberduckは、特定の結果を無視するように検査を指示し、それら「注釈」)を呼び出します。

With ActiveWorkbook 
    Set wsMacro = .Worksheets("Macro") 
    Set wsORatio = .Worksheets("ORatio" & TabNum) 
    With wsORatio 
     sMap = "oratio" & TabNum & "map" 
     '@Ignore ImplicitActiveSheetReference   
     For CurrentRow = 1 To Range(sMap).Rows.Count    
     '@Ignore ImplicitActiveSheetReference   
     Test = Range(sMap).Cells(CurrentRow, 1)     
     Set wsData = ActiveWorkbook.Worksheets(Test) 
     '@Ignore ImplicitActiveSheetReference   
     Start = Range(Range(sMap).Cells(CurrentRow, 2)).Row  
     Report = wsMacro.Range(sMap).Cells(CurrentRow, 3) 
     For Cat = 0 To 12 
      For iMth = 1 To 12 
      wsORatio.Cells(Report + Cat, 7 + iMth) = wsData.Cells(Start + Cat, 37 + iMth) 
      Next iMth 
     Next Cat 
     Next CurrentRow 
    End With 
    End With 

これらのアノテーションはあなたを(読者に伝える未来の利点を持っている、または誰でも)の上にコードを取りますそれここには何かが起こっています。

今後のバージョンでは最終的にモジュールレベルで@Ignore注釈を指定することができ、モジュール全体で特定の検査のすべての結果を無視することができます。検査は保守性と​​可読性の問題カテゴリの下にあることを


注意。実際に名前付き範囲は、ワークブックレベルでのスコープ引っ張っているように読み込む

ActiveWorkbook.Names("DefinedName").RefersToRange 
あなたに同じ範囲を与える

Range("DefinedName")は、明示的として半分とフェイルセーフとしてではありません。

+2

わかりました。私はコードがスローする警告からかなりのことを学びました。これはActiveWorkbook.Names( "Oratio1map")= "= Macro!$ I $ 14:$ L $ 16"というワークシートが指定された範囲にあるということですが、ActiveWorkbook.Sheets( "Macro" )。Range( "oratio1map")シート名が既に範囲内にある場合。しかし、そうすることでエラーやバグを取り除くことができれば、私はそれをやりはじめ、Rng as Shaiを使うことも示唆しています。 – Rdster

7

免責事項:私はRubberduckの開発にも携わっています。

@ Mat'sMugがすでに指摘しているように、検査ではコードに関する情報が提供されています。あなたは何ですかはその情報を優先します。

この場合、検査ではコードにエラーがありますが、潜在的な暗黙的なオブジェクト参照によって、コードが予期しない動作をする可能性があります。 この特定の検査では、どのオブジェクトを参照しているかをExcelがどのように解釈するかを決めることができます。Application.Rangeためthe documentationから

オブジェクト修飾子なしで使用する場合、このプロパティは ActiveSheet.Rangeのショートカットである(それはアクティブシートの範囲を返す。 アクティブシートISN」場合ワークシートでは、プロパティは失敗します)。

最後の文章は、あなたがこの検査無視してはならない第一の理由です - あなたが選択したChartを持っている場合、修飾子なしRangeがスローされます。 Worksheet(実際はon the Rubberduck inspection wish-list)に割り当てる場合は、Workbook.Sheets(foo)の代わりにWorkbook.Worksheets(foo)を使用するのと同じ理由があります。

第2の理由は、第1の理由と関連しています。あなたがコメントで正しく指摘したように、「名前付き範囲はその参照の一部としてシート名を持っています」と言い換えるか、「名前付き範囲は一意であるとみなすことができます」と言い換えます。しかし、は、複数のワークブックを開いている場合は、が一意でなければなりません。 ActiveSheetので、コードが期待Workbookがアクティブでない場合、このコードはスローするか、または他Workbookは偶然でRangeが含まれている場合(間違ったRangeを返し、呼び出しの時点でActiveWorkbookから返さ常にです同じ名前)。

ブロックはへのハードリファレンスをキャプチャしますが、Applicationは無効ですが、ActiveWorkbookはコードの実行中に変更することができます。これはすべてActiveFooオブジェクトの使用を避けるべき理由につながります。「正しい」コードからエラーが発生する可能性があります。

解決策は簡単です。ちょうどそれらの前にドットを追加します。そうすれば、彼らはApplication.Rangeではなく、の代わりにWithブロックからキャプチャされたハードリファレンスを経由してWorkbook.Rangeを呼び出すことになります。

+3

それは理にかなっていて、私の前にいた人は、すべてのブックに「マクロ」シートを置いていると考えています。私は名前付きの範囲には何とかシート名と共にそのワークブックが含まれると仮定したと思います。 – Rdster

+2

@Rdster - 簡単に作成することができます。 2つのワークブックに "Foo"という名前の範囲を定義し、それぞれDebug.Print Range( "Foo")。Valueを実行することで、これを見ることができます。 – Comintern