• ベストアンサー

VBA:カウンターの i の値が開放されなくて困っています。

以下のコードを実行する度に、カウンター i の値がリセット(開放)されずに積算されて困っています。なぜか教えて下さい。宜しくお願い致します。 以下のコードは、簡単に言えばcsvファイルをカウンター i で数えています。したがって、少なくともCSVファイルを一つ作成して実行して下さい。 Option Explicit Dim FiName As String, FoName As String Dim EachFiName As String Dim i As Integer Sub Test() MsgBox i '二回目にこのコードを実行するとiが積算されます。 FiName = Application.GetOpenFilename If FiName = "False" Then Exit Sub Else If Right(FiName, 3) <> "csv" Then MsgBox "Chose a CSV file." Exit Sub End If End If FoName = Left(FiName, InStrRev(FiName, "\", -1, vbTextCompare)) EachFiName = Dir(FoName & "*.csv") Do While EachFiName <> "" i = i + 1 EachFiName = Dir() Loop End Sub

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

  • ベストアンサー
  • akipapa
  • ベストアンサー率38% (34/89)
回答No.1

ご質問のコードの中には、i=0という記述が見当たりません。function()が無いので、カウンタiがsub()以外のどこで使用されているかわかりませんが、リセットしたいイベント(タイミング)でゼロを代入してはいかがでしょうか。

その他の回答 (5)

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.6

こんばんは。 理屈抜きに、i は、ローカル変数のカウンターだと考えて、モジュールレベル変数にしないのが、ふつうではありませんか?もし、残したかったら、別の変数に渡します。 それから、EachFiName,FiName,FoNameも、同じく、使用状況からするとローカル変数のようです。最終値が決まったら、必要に応じて、別のスコープの長い変数に渡します。 最初の、GetOpenFilename は、一応、こういうことでしょう。  FiName = Application.GetOpenFilename("CSV ファイル(*.csv),*.csv")   If FiName = "False" Then    Exit Sub   End If >したがって、少なくともCSVファイルを一つ作成して実行して下さい。 なければ、CSVは、0 と出なくてはならないと思います。 だから、CSVの数を数えるということで、簡単に考えてみましたが、 Sub CSVFilesCounter()   Dim myFolder As Object   Dim FolderName As String   Dim FileName As String   Dim i As Long   'デフォルト・パス   Const DEF_FOLDER As String = "C:\"   'フォルダ選択   Set myFolder = CreateObject("Shell.Application"). _   BrowseForFolder(0, "フォルダを選択してください", 0, DEF_FOLDER)   If Not myFolder Is Nothing Then       FolderName = myFolder.Items.Item.Path    Else      Exit Sub   End If     FileName = Dir(FolderName & "\" & "*.csv")   Do While FileName <> ""    i = i + 1    FileName = Dir()   Loop     MsgBox FolderName & "\には、" & vbCrLf & i & " 個のCSVファイルがありました。", 64 End Sub

  • fortranxp
  • ベストアンサー率26% (181/684)
回答No.5

MsgBox i '二回目にこのコードを実行するとiが積算されます。         ↓ j = MsgBox(i & vbCrLf & "初期化しますか?",vbYesNo) If j = vbYes Then i = 0

  • BellBell
  • ベストアンサー率54% (327/598)
回答No.4

Dim i As Integer 'モジュールレベル変数 Sub Test() 'テストプロシージャ   ・・・・・・・ End Sub この状態では、テストプロシージャを抜けても、モジュールレベル変数は開放されません。 開放されないと言うことは、設定された値が保持され続けると言うことです。 特に規約等の問題がない限りですが、カウンター値のような変数は、最小のスコープ(参照可能範囲)で宣言することが良いとされています。(個人的にはカウンター値以外にも、可能な限り最小スコープで宣言すべきと思っています) 具体例では、下記です。 ↓削除でも構わないが、コメントアウトにしてみました 'Dim i As Integer Sub Test() 'テストプロシージャ   Dim i As Integer  'カウンタ変数   ・・・・・・・ End Sub こうすると、テストプロシージャに入った時点で初めて、変数iが作成されVBA(VB)では、0に初期化されます。(.NETでは明示的に初期化が必要) テストプロシージャを抜けた瞬間に、変数iはメモリ上から開放され、そのとき保持していた値は発散します。 読み込んだファイル数を保存する必要があり、発散されては困る、ということであれば(というより、わざわざ数えているのですからそうなのでしょうが)以下のように書き換えられます。 ↓ファイル数を保存するという意味で、勝手に変数名を作成しました Dim FileCount As Integer'発見したファイル数を保持する変数 Sub Test() 'テストプロシージャ   Dim i As Integer  'カウンタ変数   ・・・・・・・   FileCount = i    '発見したファイル数を退避させる End Sub プログラムがわかっている人から見れば、iが実は不要だ、とすぐにわかると思います。それでは試して見ましょう。 Dim FileCount As Integer'発見したファイル数を保持する変数 Sub Test() 'テストプロシージャ   FileCount = 0    'ファイル数をこれから確認するため、  'その前0に初期化   ・・・・・・・   Do ・・・     FileCount = FileCount + 1 'ファイルが見つかったため+1する Loop End Sub 最後のコードは元のコードと違う部分は、初期化しているかしていないか 他には変数名が変わっている、という違いです。 今回の初期化忘れというポカミスの原因は、小生の個人的意見ですが、変数名iが一番の原因であると思われるため、わざわざ回りくどく書きました。 ちなみに、ファイル数の確認だけであれば、小生はSubで書かずにFunctionで書いて、ファイル数を返り値として返す、というつくりにします。

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

(1)i の初期化がないですね (2)If FiName = "False" Thenは「えっ」と思ったが、 FiName が文字列の場合は、正しいらしいですね。 http://www.officetanaka.net/excel/vba/file/file02.htm (3)If FiName = "False" Then Exit Sub If FiName = "False" Then Exit Sub はこれで完結してますね。EndIfが要らないという意味で。  そこで Else End If End If の位置付けはどうなっているのでしょうか。 誰もご指摘ないので、私の勘違いでしょうか。 If FiName = "False" Then Exit Sub If Right(FiName, 3) <> "csv" Then  MsgBox "Chose a CSV file." Exit Sub Else End If のように、Else が要りませんか。 私の普通やる書き方と違うので。 現状が正しく動くのなら、すみません。

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.2

Dim 文をSub の中にいれて、 (いれなくても)Subの頭書で、i=0 とかしたりして MsgBox i を頭でなく最後にもってきたらどうでしょうか

関連するQ&A