2012-03-23 19 views
0

変数のスコープと有効期間に関するVBAのやりたいことについて2つの問題があります。VBA 2変数のスコープと有効期間に関する質問

  1. 私は同じ変数を何度も何度も繰り返し使用しています。たとえば、列を日付列、cDate、またはアプリケーションとしてアプリケーションを定義する整数です。かなりの宣言セクションがあるので、私はこれをGlobalを使って別のモジュールに入れたいと思っていましたが、これはうまくいきませんでした。ここで手順のスコープをどのように設定するかは重要ですか?これどうやってするの?

  2. Q1と同様に、変数の初期化はどうですか?具体的には、列ヘッダー(例:cDate)を検出した同じブロックをコピーして貼り付ける代わりに、それを独自の手順に入れます。私はこれを動作させるために多くの問題を走っています。私はこれが可能であると思う、多分そうでないかもしれない。

コードが必要な場合は教えてください。私は何を見たいのか教えてください。私はそれをここに投げます。 (PS-私はVBAヘルプ、MSDN、Gooleなどを通ってきましたが、ここでは理解できないことがあります)

編集:実際のものはかなり長いため、編集済みのコードを追加しています。すべてのセクションは別々の標準モジュールにあります。私は、以下のワークブックレベルで動作するグローバル宣言を読んでいたので、私はまた、各モジュール(ないここに示されている)で、Publicとしてwb、およびwrkを宣言し、app設定しようとした:私の宣言ここで です:

Option Explicit 

Global app As Application 
Global wb As Workbook 
Global wrk As Worksheet 

Global cInvoice As Byte 

Global iEndCol As Integer 
Global lEndRow As Long 
Global x As Integer 

Global sString1 As String 

Global rng As Range 

Private Sub Not_Really_a_sub() 
    'No code. I read that any declaration needed to be in a module 
    ' with a procedure. I tried it with out the dummy sub also 
End Sub 
'green text, read me and notes 

そして、呼び出していたサブ:

Dim modulevariables As Integer 

Sub Calling_Sub() 

'doing things 

lEndRow = 1 'blah blah blah 
iEndCol = 1 ' blah blah blah 
app.Run "'" & ThisWorkbook.Name & "'!Header_Finder" 

    'Code using cInvoice etc. 

End Sub 

とヘッダファインダー:

Private Sub Header_Finder() 
    With wb.ActiveSheet 
    For x = 1 To iEndCol 
     If InStr(UCase(.Cells(x, 1)), UCase("Invoice")) > 0 Then 
      cInvoice = x 
     ElseIf .Cells(1, x) = "next thing" Then 
      cNextThing = x 
     End If 
    Next 
End With 
End Sub 

ありがとうございました。

+0

グローバル変数を別のモジュールに配置することはどういう意味ですか?コードを実行したときにエラーが発生しましたか? グローバル宣言と最初の列見出しルーチンを含めることができますか? – mkingston

+0

入力は、デフォルトでコメントを送信するべきではありません。毎回。オリジナルの編集を参照してください。 – Bippy

+1

あなたはどこにも指定していませんが、変数にアクセスする前に変数の初期化コードを呼び出すと仮定しました。 – mkingston

答えて

1

Q1。

変数は3つの異なるレベルで宣言できます。手続きレベル(あなたがやっているように聞こえて、離れて移動したいと思う)、モジュールレベルまたはプロジェクトレベル。

モジュールレベルで変数を宣言するには、最初の手順の外に変数を宣言するだけです。

Dim app As Application 

Sub mySub() 
... 

この変数は、モジュール内のすべてのプロシージャで使用できます。他のモジュールのプロシージャで変数を使用できるようにするには、public宣言を使用できます。

Public app As Application 

Sub mySub() 
.... 

Q2。

必要に応じて他のプロシージャから呼び出すことができる変数を初期化するプロシージャがある場合は、これを行う最も簡単な方法です。たとえば、以下のコードは、PubStrという名前のパブリック変数を作成し、2番目のプロシージャから呼び出される最初のプロシージャで初期化します。

Option Explicit 
Public PubStr As String 

Sub InitVar() 
PubStr = "Hello World!" 
End Sub 

Sub RunMe() 
Call InitVar 
MsgBox PubStr 
End Sub 

Running "RunMe"は、パブリック変数PubStrを初期化するInitVarプロシージャを呼び出します。

うまくいけば、これが役に立ちます。

1

本当に答えはありますが、私はいくつかのコードを含める必要がありました。テストとして、私は1つのモジュール(Module1の)に次のコードを置く:

Public wb As Workbook 

、別のモジュール(モジュール2)でこのコード:

Sub test() 

    Set wb = ThisWorkbook 
    Debug.Print wb.Name 

End Sub 

をこれが私のためにうまく働きました。あなたは新しいワークブックで同じことをしようとすると、それがどうなるか教えていただけますか?これは私の他の(非)の答えに関係しませんが、もう一度、私がする必要があるとして

Sub test() 

    Set wb = ThisWorkbook 
    Debug.Print Module1.wb.Name 

End Sub 
+1

注:Module1のダミープロシージャはありません。 – mkingston

+0

注意、ダミーは許可されていません。明日私の仕事用コンピュータの実際のファイルでこれを試してみます。私はラップトップで「Global」と試してみましたが、私が夢中になっていないことを知っておいてよかったです。 – Bippy

+0

"Module1.wb.Name"は面白いです。最近xl2010に移りました。私はもっと明示的に_everywhere_しようとしました。多くの場合、xlサーバー上には、Public変数を持つマクロが多数実行されており、それぞれが同じ名前を持つことがよくあります。スコープが広すぎるために予期しない自動化エラーが発生しました。したがって、可能な限り明示的であることは良いことです。 – whytheq

2

:また、あなたはそう(まだモジュール2内)のように、あなたが参照しているどの変数を指定する、より明示的に試みることができますいくつかのコードを含めて、私はここに入れます。あなたはこの変数を使用する前に、あなたがすなわち、それをを初期化する(これらの例のいずれかが動作することに価値を与える必要があります

dim wb as Workbook 

:あなたの「変数」で

モジュールは、あなたが変数を宣言しています、それぞれが)異なるシナリオのためのものである:

set wb = ThisWorkbook 
set wb = ActiveWorkbook 
set wb = Application.Workbooks(1) 

あなたははのように、それをアクセスする前に、この変数を初期化していない場合はこの例では:

dim wb as Workbook 
debug.print wb.name 

あなたはエラーを受け取ります:「実行時エラー 『91』:オブジェクト変数またはWithブロック変数が設定されていません」

のみ変数が初期化を必要とオブジェクト。他のデータ型はそうではありません。簡単に言えば、非オブジェクトデータ型は次のとおりです。 (宣言で初期化)デフォルト値は括弧内にある:

  • 整数[0]
  • ロング[0]
  • 文字列[ ""]
  • ダブル[0]
  • シングル[0]
  • 日[0、または1899年12月30日]
  • バイト[0]
  • ブール[偽]
  • 通貨[$ 0]

他のすべてはオブジェクトであり、何らかの初期設定が必要です。例は次のとおりです。

Option Explicit 

Dim wb as Workbook 
Dim app as Excel.Application 
Dim wrk as Worksheet 

Set app = Application 
Set wb = app.workbooks(1) 
Set wrk = wb.sheets(1) 

'If any of the lines preceding this line are skipped, an error will occur. 
debug.print wrk.name 

申し訳ありませんが、あなたはすでにこれを知っていれば(!本当に、私は、これは書くことがたくさんあった)だけで、我々は上記の私たちのコメントを議論した後、同じページにしていることを確認したかったです。

+0

謝罪しておらず、あなたの努力は高く評価されます。私は試行錯誤で学んだので、知識のギャップがたくさんある。私が知っていたビットと私がしなかったビットがあります。加えて、多くの用語と定義がありますが、私は完全に理解していません。 – Bippy

+0

さて、潜水艦にいくつかの宣言が残っていて、他のミステリーがまだ初期化されていないという問題が複数ありました。しかし、モジュールを新しいワークブックに移動すると、これがクリアされました。これを助けていただきありがとうございます。 – Bippy

+0

全く問題ありません。お力になれて、嬉しいです :) – mkingston

関連する問題