• ベストアンサー

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

  • e-l
  • お礼率45% (158/349)

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

  • ベストアンサー
  • 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/17068)
回答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

  • Excel VBAで検索(Win2000 Excel2000)

    現在、下記のようなコードを書いています。データテーブルの縦と横の検索値を探してその列数と行数を返したいのですが、下記の Sub検索1 と Sub検索2 を1つのSubで実行させるにはどうしたらよいのでしょうか?よろしくお願い致します。 ----------------------------------------- Sub 検索1() Worksheets("Data").Activate Dim x As Integer For x = 3 To 22 If Cells(2, x).Value >= 12 Then MsgBox x Exit Sub End If Next MsgBox "見つかりません" End Sub --------------------------------------------- Sub 検索2() Worksheets("Data").Activate Dim i As Integer For i = 4 To 42 If Cells(i, 2).Value = "A" Then MsgBox i Exit Sub End If Next MsgBox "見つかりません" End Sub

  • vbaで環境編巣のパスだけ取得したい

    Sub Sample() Dim Env As String, i As Integer Do i = i + 1 If Environ(i) = "" Then Exit Do Env = Env & Environ(i) & Chr(13) & Chr(10) Loop MsgBox Env End Sub このコードを実行すると、パス以外にもいろいろ取得されてしまうのですが パスのみ取得するにはどうすればいいでしょうか?

  • iと言う変数の値が1から10の間にないならば

    「iと言う変数の値が1から10の間にないならば」、としたいのですが どのようなコードを書けばいいのでしょうか? Sub test1() Dim i As Integer i = 11 If 1 < i < 10 Then MsgBox i & "は1から10の間にはありません" End If End Sub だと、メッセージが表示されてしまいます。

  • VBAでMP3を鳴らしたい

    vbaについて質問です。 MP3ファイルを鳴らしたいのですがうまくいきません。 --------------------------------------------------------- Sub Macro1() Dim SoundFile As String SoundFile = "C:\終了音.mp3" If Dir(SoundFile) = "" Then MsgBox SoundFile & vbCrLf & "がありません。", vbExclamation Exit Sub End If Shell "mplay32.exe /play /close " & SoundFile End Sub --------------------------------------------------------- を実行すると、 「Shell "mplay32.exe /play /close " & SoundFile」 の部分で 実行時エラー53 ファイルが見つかりません。 になります。 しかし、 If Dir(SoundFile) = "" Then MsgBox SoundFile & vbCrLf & "がありません。", vbExclamation Exit Sub End If の部分では問題ないので、ファイルはある事になってると思うのですが、 なぜ「Shell "mplay32.exe /play /close " & SoundFile」の部分でエラーになるのでしょうか? スペックは、エクセル2007、windows7です。 ご回答よろしくお願いします。

  • AccessのVBAに関しての質問です。

    クエリで抽出したファイルをCSVで出力させ、出力したファイル名を「連番&ファイル名」の形にしたく 下記のコードを使用しました。 6ファイルは出力は成功したのですが、7ファイル目を出力しようとしたところ、「#6:オーバーフロウしました。」とエラーがでてきてしまいます。 原因やここのコードを変えれば直るというのが、お分かりになる方がいればご教示頂けますでしょうか。 初心者ですのでコードも書いて頂けると非常に助かります。 Private Sub コマンド4_Click() On Error GoTo ErrorTrap Dim varAccess As Variant Dim varCPass As Variant Dim strmsg As String varAccess = "ASN抽出" Dim FolderPass As String Dim FileName As String Dim CheckCount As Integer FolderPass = "C:¥Users¥エクスポート¥" FileName = "_STORE_ASN_TRN.csv" CheckCount = 0 Do Until Dir(FolderPass & FileName) = "" CheckCount = CheckCount + 1 FileName = Format(CheckCount, Len(CStr(CheckCount)) + 1) & "_STORE_ASN_TRN" & ".csv" Loop varTextPass = FolderPass & FileName strmsg = "csvファイルへ出力します。" & Chr(13) & _ "出力先は" & varTextPass & "です。" & _ "よろしければ、OKをクリックして下さい。" If MsgBox(strmsg, vbOKCancel) = vbOK Then DoCmd.TransferText acExportDelim, , varAccess, varTextPass, False MsgBox "データ出力は、正常に完了しました。" End If Exit Sub ErrorTrap: If Err.Number = 3044 Then ' MsgBox "パス指定が誤っています。", vbCritical Else MsgBox "予期せぬエラーが発生しました。(#" & Err.Number & " : " & Err.Description & ")", vbCritical End If End Sub

  • If文中のExit Sub

    Dim i As String i = TextBox1.Value If i ="" Then MsgBox "入力なし" Exit Sub End If Exit Subは何の意味が有るのでしょう? Exit Subを調べたり試したりしたのですが、良く、解りません。 宜しくお願い致します。

  • 返ってくる値が違う

    VBAでフォルダの中のファイルの個数を取得するコードなのですが Sub test1() Dim i As Long, buf, Path As String Path = ActiveWorkbook.Path & "\" buf = Dir(Path & "*.*") Do While buf <> "" i = i + 1 buf = Dir() Loop MsgBox "「" & ActiveWorkbook.Path & "」には、全部で" & i & "個のファイルがあります。" End Sub Sub test2() Dim Path As String Dim i As Long, FSO As Object, f As Object Path = ActiveWorkbook.Path & "\" Set FSO = CreateObject("Scripting.FileSystemObject") MsgBox "「" & ActiveWorkbook.Path & "」には、全部で" & FSO.GetFolder(Path).Files.Count & "個のファイルがあります。" Set FSO = Nothing End Sub Test1とtest2では返ってくる値が違うのですが なぜでしょうか? Test2はフォルダの個数も取得されてるのですか?

  • 以下のVBAについて

    Option Compare Database Option Explicit Private Sub バックアップ開始_Click() Dim strBaseName As String Dim strFileName As String If IsNull(Me.バックアップ日付) = True Or Len(Me.バックアップ日付) = 0 Then MsgBox "バックアップ日付をyyyymmdd形式で入力してください。", vbOKOnly + vbCritical, "" Me.バックアップ日付.SetFocus Exit Sub End If strBaseName = "C:\Data\在庫管理.mdb" strFileName = "C:\Backup\" & Format(Me.日付, "yyyymmdd") & "StockData.mdb" If Dir(strFileName) <> "" Then If MsgBox(strFileName & Chr(13) & "は存在します。" & Chr(13) & _ "上書しますか?", vbYesNo + vbQuestion, "") = vbNo Then Exit Sub End If End If On Error GoTo LBL_ERROR FileCopy strBaseName, strFileName MsgBox "バックアップが完了しました。", vbInformation, "" LBL_EXIT: Exit Sub LBL_ERROR: Resume LBL_EXIT End Sub 上記のVBAでバックアップを行いたいのですが、フォルダ等も設定しているの実行されません。上記の文に間違いがあるのでしょうか? ソフトはAccessです。

  • エクセルVBAでConsolidate

    以下は、ネット検索で見つけたサンプルコードです。 同じフォルダ内の全ブックのSheet1のA1:B10をThisWorkbookのSheet1に統合しています。 Sub test2() Dim MyFile As String, MyPath As String Dim SumFile() As Variant, i As Long MyPath = ThisWorkbook.Path & "\" MyFile = Dir(MyPath, vbNormal) Do Until MyFile = "" If MyFile <> ThisWorkbook.Name Then ReDim Preserve SumFile(i) 'A1からB10の値を変数に代入 SumFile(i) = "'" & MyPath & "[" & MyFile & "]Sheet1'!R1C1:R10C2" i = i + 1 End If MyFile = Dir Loop If i = 0 Then MsgBox "データが有りません": Exit Sub Worksheets("Sheet1").Range("A1").Consolidate Sources:=SumFile() End Sub 質問1 Sheet1だけでなく全シートのA1:B10をThisWorkbookのSheet1に統合するためにはどう書き換えればよいのでしょうか? 質問2 上記コードではなぜ、ブックを開かずにデータがとれるのでしょうか?

  • VBAにてアクティブでは無いシートの値が参照されてしまいます。

    こんばんは、以前二回程質問させていただいた物です。 過去のアドバイスから少しずつ疑問をつぶしていった所再び問題が発生してしまいました。 同じプログラムを何度も載せるのは大変恐縮ですが、どうしても解決出来ない為(私の努力不足は重々承知です)皆様の力を貸して頂きたいと思います。 以下のようなループの際、途中にMsgBox(strFILENAME)を入れたり、Active.sheetでウオッチ式で見ても参照してほしいシート名を表示するにも関わらず、計算結果を書き込むシートのセルを参照してしまいます。 なぜ、WS1のセルの値を参照してしまうのかわからず困っています。 確実にMsgBox(strFILENAME)で表示されるファイル名のシートのセルを参照する方法を教えて頂きたく、よろしくお願いいたします。(Workbook.Worksheet.のように明示する方法を教えていただいたのですがエラーが発生してしまいうまく使いこなすことが出来ませんでした) どうか、宜しくお願いいたします。 Option Explicit Sub syoutotumen() Dim i As Long Dim j As Long Dim k As Long Dim kyori As Long Dim n As Integer n = 1 i = 1 j = 1 k = 1 Const cnsYEN = "\" Dim swESC As Boolean Dim ws1 As Worksheet Dim xlAPP As Application Dim objWBK As Workbook Dim strPATHNAME As String Dim strFILENAME As String strPATHNAME = "C:\Documents and Settings\tata41\デスクトップ\画像処理2\" If strPATHNAME = "" Then Exit Sub strFILENAME = Dir(strPATHNAME & "demo******", vbNormal) If strFILENAME = "" Then MsgBox "このフォルダにはExcelワークブックは存在しません" Exit Sub End If Set xlAPP = Application With xlAPP .ScreenUpdating = False .EnableEvents = False .EnableCancelKey = xlErrorHandler .Cursor = xlWait End With Set ws1 = Worksheets("sheet1") Range("A1") = "0" Range("A2") = "1" Range("A1:A2").Select Selection.AutoFill Destination:=Range("A1:A1022") Do While strFILENAME <> "" DoEvents If swESC = True Then If MsgBox("ESCが押されました。ここで終了しますか?", vbInformation + vbYesNo) = vbYes Then GoTo Button1_Click_Exit Else swESC = False End If End If xlAPP.StatusBar = strFILENAME & "処理中・・・" Set objWBK = Workbooks.Open(Filename:=strPATHNAME & cnsYEN & strFILENAME, UpdateLinks:=False, ReadOnly:=True) Do If Cells(i, 2) = 0 Then Exit Do i = i + 1 Loop Do If Cells(j, 3) = 0 Then Exit Do j = j + 1 Loop Do If Cells(k, 4) = 0 Then Exit Do k = k + 1 Loop kyori = (i + j + k - 21) / 3 ws1.Cells(n, 2) = kyori n = n + 1 i = 1 j = 1 k = 1 objWBK.Close savechanges:=False strFILENAME = Dir Loop GoTo Button1_Click_Exit Button1_Click_ESC: If Err.Number = 18 Then swESC = True Resume ElseIf Err.Number = 1004 Then Resume Next Else MsgBox Err.Description End If Button1_Click_Exit: With xlAPP .StatusBar = False .ScreenUpdating = True .EnableEvents = True .EnableCancelKey = xlInterrupt .Cursur = xlDefault Set objWBK = Nothing Set xlAPP = Nothing End With End Sub

専門家に質問してみよう