VBAコードでセルのデータ数を取得する方法

このQ&Aのポイント
  • VBAコードを使用して、指定した条件に基づいてセルのデータ数を取得する方法について教えてください。
  • 具体的には、A列のデータから1を探し、その1つ前と2つ前のB列の値をC列とD列に出力する方法です。
  • また、出力されるデータの数を知りたい場合、どのようにすればいいのかも教えていただきたいです。
回答を見る
  • ベストアンサー

いま以下のコードでA列のデータから1を探してその

1つ前と2つ前のB列の値をC.D列に出力することができるのですが、この時のデータ数を知りたいのですがどうすればいいでしょうか? Sub sample() Dim i As Long, j As Long, flg As Boolean For i = 2 To Cells(Rows.Count, 1).End(xlUp).Row If Cells(i, 1) = 0 Then flg = True ElseIf Cells(i, 1) = 1 And flg = True Then j = j + 1 Cells(j, "BT") = Cells(i - 1, "BS") Cells(j, "BU") = Cells(i - 2, "BS") flg = False Else: flg = False End If Next End Sub これでC1とD2に対応するB?とB?の間のデータ数がE1に、C2とD3に対応するB?とB?の間のデータ数がE2にC3と・・・ という具合です。 わかりにくくてすみません。よろしくお願いします。

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

  • ベストアンサー
  • queuerev2
  • ベストアンサー率78% (96/122)
回答No.3

先ほどのNo.2の回答、間違えてしまいました。 (D列のデータを行番号にしてテストしていたので・・・) 申し訳ありませんがNo.2は無視してこちらをご覧ください。 では以下回答を書き直します。 「A1から最初の1の2つ前(A?)のデータ数もカウントにいれる」というところですが、申し訳ありませんがよくわかりません。 まず、最初の1というのは、 ElseIf Cells(i, 2) = 1 And flg = True Then の条件式が最初に成り立つこととなった1のことでしょうか? (ここまで同じです) 次に、カウントに入れるというのは、Cells(j - 1, 7)に加算するのでしょうか? もしそうであれば、たとえば以下のようになります。 (こなれていないコードで申し訳ありません) しかしこれでは質問者様の意図を理解できていないような気がするのです。 Sub test2() Dim i As Long, j As Long, flg As Boolean Dim i1 As Long, i2 As Long j = 1 For i = 2 To Cells(Rows.Count, 2).End(xlUp).Row If Cells(i, 2) = 0 Then flg = True ElseIf Cells(i, 2) = 1 And flg = True Then i1 = i i2 = i - 2 Cells(j, 5) = Cells(i - 1, 4) Cells(j, 6) = Cells(i - 2, 4) flg = False Exit For Else: flg = False End If Next For i = i To Cells(Rows.Count, 2).End(xlUp).Row If Cells(i, 2) = 0 Then flg = True ElseIf Cells(i, 2) = 1 And flg = True Then j = j + 1 Cells(j - 1, 7) = i - i1 - 2 + i2 i1 = i Cells(j, 5) = Cells(i - 1, 4) Cells(j, 6) = Cells(i - 2, 4) flg = False Else: flg = False End If Next End Sub

xshohei23x
質問者

お礼

なんか色々丁寧にお答えしていただいてるのに申し訳ないです。 確かにこれだと私のやりたいこととはちょっと違います・・・ 要は、条件に対応する1のところでデータの数をしりたいだけなんですが、No1で回答していただいたコードだと条件の1同士のデータ数はカウントできるんですが最初のデータ(A1)から最初の条件の1の間のデータ数がカウントされないんでそこをカウントできるコードがしりたいんです。

その他の回答 (4)

  • queuerev2
  • ベストアンサー率78% (96/122)
回答No.5

Cells(1,7)にしてもうまく実行されない理由は、ここでいったんA1からのデータ数がG1に出力されるものの、あとでE1とF2の間のデータ数で上書きされてしまうからです。 A1からのデータ数をG1に入れるということで、これまでG列に出力していたものを1行ずつ下にずらしてみました。 そのための変更は、No.4の3)のところで、 Cells(j - 1, 7) = i - i1 - 2 (修正前 Cells(j - 1, 7) = i - i1 - 2 + i2) を Cells(j, 7) = i - i1 - 2 にするだけです。 もちろんNo.4の2)のところはCells(1, 8)ではなくCells(1, 7)にしておきます。 いかがでしょうか。

xshohei23x
質問者

お礼

なるほど、ありがとうございます。

  • queuerev2
  • ベストアンサー率78% (96/122)
回答No.4

A1から最初の1の2つ前までのデータ数は、加算してはいけなかったのですね。 ならば値を別途セルに入れます。場所はとりあえずセルH1(Cells(1 ,8))にします。 その結果、No.3のコードからの変更点は3か所だけだったので変更点のみ示します。 1) 変数i2は使用しない Dim i1 As Long, i2 As Long   を Dim i1 As Long '   に。 2) A1からB列の最初の有効な1の行の2つ前までのデータ個数をセルH1に i2 = i - 2   を Cells(1, 8) = i - 2 '   に 3) 上記2)の値は加えない Cells(j - 1, 7) = i - i1 - 2 + i2   を Cells(j - 1, 7) = i - i1 - 2 '   に ところで、変更後のコードを実行して気づいたのですが、F1に出力されるデータは、最初の1の2行前のD列のデータです。つまり、A1から最初の1の2行前のデータは、出力されたデータと同じ行を含んだ個数になっています。 一方、G列に出力される個数は、その行のE列に出力されたデータと、次の行のF列に出力されたデータの間のデータの個数になっており、つまり出力されたデータは含まない個数になっています。 もしも出力されたデータの行を含むかどうかを統一する場合は、コードを適宜変更して1を加えるなり引くなりしてください。 これも質問者様の意図と違っていたり、あるいは何か質問事項等ありましたら補足いただければと思います。

xshohei23x
質問者

お礼

回答ありがとうございます。これでやりたいことの実行できます! ただ1つだけなんですが、セルH1でなくてG1に出力することはできますか?Cells(1,7)にしてみたのですがうまく実行されないようで、、、

  • queuerev2
  • ベストアンサー率78% (96/122)
回答No.2

「A1から最初の1の2つ前(A?)のデータ数もカウントにいれる」というところですが、申し訳ありませんがよくわかりません。 まず、最初の1というのは、 ElseIf Cells(i, 2) = 1 And flg = True Then の条件式が最初に成り立つこととなった1のことでしょうか? そうであるならA1から2つ前までのデータの個数はF1の値、つまりCells(1,6)になると思いますがいかがでしょうか。 (B2つまりCells(2,2)が1の場合は出力されないので無効と考えています) 次に、カウントに入れるというのは、Cells(j - 1, 7)に加算するのでしょうか? もしそうであれば、 Cells(j - 1, 7) = i - i1 - 2 を Cells(j - 1, 7) = i - i1 - 2 + Cells(1,6) にするだけです。 でもこれでは質問者様の意図を理解できていないような気がするのです。

  • queuerev2
  • ベストアンサー率78% (96/122)
回答No.1

ちょっと推定を交えて書いてみましたがこんな感じでしょうか? Sub sample() Dim i As Long, j As Long, flg As Boolean Dim i1 As Long For i = 2 To Cells(Rows.Count, 1).End(xlUp).Row If Cells(i, 1) = 0 Then flg = True ElseIf Cells(i, 1) = 1 And flg = True Then j = j + 1 If j >= 2 Then Cells(j - 1, "BV") = i - i1 - 2 End If i1 = i Cells(j, "BT") = Cells(i - 1, "BS") Cells(j, "BU") = Cells(i - 2, "BS") flg = False Else: flg = False End If Next End Sub

xshohei23x
質問者

お礼

回答ありがとうございます。返事遅くなってすいません。表記を以下のように変えたのですがA1から最初の1の2つ前(A?)のデータ数もカウントにいれるにはどうしたらいいですか? Dim i As Long, j As Long, flg As Boolean Dim i1 As Long For i = 2 To Cells(Rows.count, 2).End(xlUp).Row If Cells(i, 2) = 0 Then flg = True ElseIf Cells(i, 2) = 1 And flg = True Then j = j + 1 If j >= 2 Then Cells(j - 1, 7) = i - i1 - 2 End If i1 = i Cells(j, 5) = Cells(i - 1, 4) Cells(j, 6) = Cells(i - 2, 4) flg = False Else: flg = False End If Next

関連するQ&A

  • 素数を求めるマクロを

    走らすと暴走したようになり、素数=151で止まります。 どこが悪いのでしょうか。正常に終わるようにしたいです。 ====================== Sub 素数を求める()   Dim i As Long   Dim j As Long   Dim m As Long   Dim p As Long   Dim flg As Boolean   i = 1   j = 1   p = 2   Do     flg = False     For m = 2 To Int(Sqr(p))       If p Mod m = 0 Then         flg = True         Exit For       End If     Next     If flg = False Then       Cells(i, j) = p       i = i + 1       If i > Rows.Count Then         i = 1         j = j + 1       End If     End If     p = p + 1   Loop End Sub ======================

  • VBAのコードに関する質問です。

    以下のコードで実行しているのですが上手くデータ数のカウンタが上手くいきません。助言をお願いしたいです。 Range("D2").Select ActiveCell.Formula = "=0.001*C2+D1" Range("D2").Select Selection.AutoFill Destination:=Range("D2:D" & fin), Type:=xlFillDefault Range("D2:D" & fin).Select Dim i As Long, j As Long, flg As Boolean Dim i1 As Long j = 1 For i = 2 To Cells(Rows.count, 2).End(xlUp).Row If Cells(i, 2) = 2 Then flg = True ElseIf Cells(i, 2) = 3 And flg = True Then i1 = i Cells(1, 7) = i - 1 Cells(j, 5) = Cells(i, 4) Cells(j, 6) = Cells(i - 1, 4) flg = False Exit For Else: flg = False End If Next For i = i To Cells(Rows.count, 2).End(xlUp).Row If Cells(i, 2) = 2 Then flg = True ElseIf Cells(i, 2) = 3 And flg = True Then j = j + 1 Cells(j, 7) = i - i1 - 2 i1 = i Cells(j, 5) = Cells(i, 4) Cells(j, 6) = Cells(i - 1, 4) flg = False Else: flg = False End If Next Range("E1").Select Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove Cells(1, 5) = Cells(2, 4) Cells(Rows.count, 6).End(xlUp).Offset(1).Value = _ Cells(Rows.count, 4).End(xlUp).Value Cells(Rows.count, 7).End(xlUp).Offset(1).Value = 200 Range("H1").Select ActiveCell.Formula = "=(F1-E1)/G1" Range("H1").Select Selection.AutoFill Destination:=Range("H1:H16"), Type:=xlFillDefault Range("H1:H16").Select Range("E1").Select Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove Range("F1").Select Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove Range("G1").Select Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove Range("H1").Select Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove Dim rowStr As Long, rowEnd As Long Dim A, D, Da, H, K '演算:K=D-Da-H*A Dim cntS As Integer, cntA As Integer Dim cntD As Integer, cntH As Integer Dim r As Long, t As Long rowStr = 2 '開始行 rowEnd = Cells(Rows.count, 7).End(xlUp).Row 'G列で最終行を求める cntS = 1 '周期初期値 cntD = rowStr 'D列行数初期値 cntH = rowStr 'H列行数初期値 For r = rowStr To rowEnd cntA = rowStr For t = 1 To Cells(r, 7) '各周期の繰り返し処理 A = Cells(cntA, 1).Value D = Cells(cntD, 4).Value If t = 1 Then If r = rowStr Then Da = 0 '1周期目は0とする Else '2週期目以降は最初の値に固定 Da = Cells(cntD, 4).Value End If '周期の区切りをF列に出力 Cells(cntD, 11).Value = cntS & "周期" End If H = Cells(cntH, 8).Value K = D - Da - H * A '演算 Cells(cntD, 10).Value = K cntA = cntA + 1 'A列カウンタ更新 cntD = cntD + 1 'D列カウンタ更新 Next t cntS = cntS + 1 '周期カウンタ更新 cntH = cntH + 1 'H列カウンタ更新 Next r

  • 連続データのVBAの質問

    お世話になります。 Private Sub Worksheet_Change(ByVal Target As Range) Dim i As Long, k As Long, myNum As Long If Range("C1") <= Date - Day(Date) Then Exit Sub If Not Intersect(Target, Range("C1,B9:B39")) Is Nothing And Target.Count = 1 Then Application.EnableEvents = False With Target If .Column = 3 Then myNum = WorksheetFunction.Max(Range("B9:B39")) If IsDate(.Value) Then For i = 9 To 39 If Cells(i, "A").Value = "" Then Cells(i, "B").Value = "" Else Cells(i, "B") = myNum + i - 8 End If Next i End If Else i = .Row If .Value = "" Then Range(Cells(i + 1, "B"), Cells(39, "B")).ClearContents Else For k = i + 1 To 39 If Cells(k, "A").Value = "" Then Cells(k, "B").Value = "" Else Cells(k, "B") = Cells(k - 1, "B") + 1 End If Next k End If End If End With Application.EnableEvents = True ElseIf Not Intersect(Target, Range("R8:R38")) Is Nothing Then Application.EnableEvents = False Range(Cells(Target.Row, 18), Cells(39, 18)).Value = Target.Value Application.EnableEvents = True End If End Sub これはセルC1に年月を表記させ、そのC1セルの年月を変更した場合B9~B39のセルが自動で連続データの数字を記入し、B9~B39のどこかのセルを空白にすると、そのセル以降も空白になります。 そこで質問ですが、例えばB14の数字を消すとB15~39まで空白のセルになります。そして、B20に1と入力するとB21~39に連続データの数字が自動記入されます。 そしてC1の年月を次の月に更新した際は、B39で示された数字以降の連続データをB9に表示させるには、どうすれば良いでしょうか?

  • ExcelにおけるVBAで、データの振り分けをしたい

    Sub a() Dim i As Long Dim s As Long Dim b As Worksheet Dim c As Worksheet Dim maxi As Long Dim maxs As Long Application.ScreenUpdating = False With ThisWorkbook Set b = .Worksheets("bbb") Set c = .Worksheets("ccc") End With maxi = b.Range("A1").CurrentRegion.Rows.Count maxs = c.Range("A1").CurrentRegion.Rows.Count For i = maxi To 2 Step -1 For s = maxs To 2 Step -1 If c.Cells(s, 1) = b.Cells(i, 1) And c.Cells(s, 2) = b.Cells(i, 2) Then c.Cells(s, 14) = b.Cells(i, 3) End If Next s Next i Application.ScreenUpdating = True End Sub ワークシートcとワークシートbの1列目と2列目が一致したときにだけ、cの14列目にbの3列目のデータを代入したく思い、以上のようなコードを書きましたが、重くて終わる様子がありません。 ・そもそもあっているのか、あっていないならどこを修正すればよいか ・早く終わるようにするにはどうしたらいいか アドバイスをよろしくお願いします。

  • 連続データのVBAの質問

    お世話になります。 Private Sub Worksheet_Change(ByVal Target As Range) Dim i As Long, k As Long, myNum As Long If Not Intersect(Target, Range("C1,B9:B39")) Is Nothing And Target.Count = 1 Then Application.EnableEvents = False With Target If .Column = 3 Then myNum = WorksheetFunction.Max(Range("B9:B39")) If IsDate(.Value) Then For i = 9 To 39 If Cells(i, "A").Value = "" Then Cells(i, "B").Value = "" Else Cells(i, "B") = myNum + i - 8 End If Next i End If Else i = .Row If .Value = "" Then Range(Cells(i + 1, "B"), Cells(39, "B")).ClearContents Else For k = i + 1 To 39 If Cells(k, "A").Value = "" Then Cells(k, "B").Value = "" Else Cells(k, "B") = Cells(k - 1, "B") + 1 End If Next k End If End If End With Application.EnableEvents = True ElseIf Not Intersect(Target, Range("R8:R38")) Is Nothing Then Application.EnableEvents = False Range(Cells(Target.Row, 18), Cells(39, 18)).Value = Target.Value Application.EnableEvents = True End If End Sub これはセルC1に年月を表記させ、そのC1セルの年月を変更した場合B9~B39のセルが自動で連続データの数字を記入し、B9~B39のどこかのセルを空白にすると、そのセル以降も空白になります。 そしてR8~R38は、指定範囲のセルに数字を入力したら、そのセル以降の指定した範囲のセルに同じ数字を自動入力するVBAです。 そこで質問ですが、質問した現在は2013年12月ですが、日本時間の現在の年月以前の年月(今で言うと2013年11月以前)をC1に記入した場合はB9~B39の連続データの数字が切り替わらない様にするには、どうすれば宜しいでしょうか?

  • vba boolean変数を開放する方法

    エクセルのセルに「○○○○○○○○○○××××××××××」と入っているものをランダムに並べ代えるマクロを探してみました。 Sub macro2() Dim i, m As Integer Dim b, c As String Dim flg(1 To 20) As Boolean b = Cells(1, 1).Value Randomize For i = 1 To 20 Do m = Int(20 * Rnd + 1) If flg(m) = False Then flg(m) = True Exit Do End If Loop c = c & Mid(b, m, 1) Next i Cells(1, 2).Value = c End Sub これはうまく動くのですが、10行分やろうとして、以下のように変更すると暴走(終わらない)します。 Sub macro2() Dim i, m, n As Integer Dim b, c As String Dim flg(1 To 20) As Boolean For n = 1 To 10 b = Cells(n, 1).Value Randomize For i = 1 To 20 Do m = Int(20 * Rnd + 1) If flg(m) = False Then flg(m) = True Exit Do End If Loop c = c & Mid(b, m, 1) Next i Cells(n, 2).Value = c next n End Sub 一行目が終わってもboolean変数の値がそのまま残っているのが原因らしいのですが開放する方法がわかりません。 取りあえずもう一つマクロを追加してやりたいことはできたのですが、 Sub macro1() Dim n As Integer For n = 1 To 10 Call macro2(n) Next n End Sub Sub macro2(n As Variant) 以下略 なんかスッキリしません。 boolean変数を開放し、マクロひとつですます方法を教えて頂きたくお願いします。 flg(m) = Falseを挿入してもダメでした。

  • 2つのVBAを組み合わせる方法

    お世話になります、2つのVBAを組み合わせる方法で迷っています。 1つ目が Private Sub Worksheet_Change(ByVal Target As Range) Dim i As Long, k As Long, myNum As Long If Intersect(Target, Range("C1,B9:B39")) Is Nothing Or Target.Count > 1 Then Exit Sub Application.EnableEvents = False With Target If .Column = 3 Then myNum = WorksheetFunction.Max(Range("B9:B39")) If IsDate(.Value) Then For i = 9 To 39 If Cells(i, "A").Value = "" Then Cells(i, "B").Value = "" Else Cells(i, "B") = myNum + i - 8 End If Next i End If Else i = .Row If .Value = "" Then Range(Cells(i + 1, "B"), Cells(39, "B")).ClearContents Else For k = i + 1 To 39 If Cells(k, "A").Value = "" Then Cells(k, "B").Value = "" Else Cells(k, "B") = Cells(k - 1, "B") + 1 End If Next k End If End If End With Application.EnableEvents = True End Sub です。 2つめが Private Sub Worksheet_Change(ByVal Target As Range)  Application.EnableEvents = True If Intersect(Target, Range("R8:R38")) Is Nothing Then Exit Sub Application.EnableEvents = False Range(Cells(Target.Row, 18), Cells(39, 18)).Value = Target.Value Application.EnableEvents = True End Sub です。2つのPrivate Sub Worksheet_Change(ByVal Target As Range)イベントのVBAですが、どのようにして組み合わせれば良いのでしょうか?

  • VBAデータ元から新規ブックに出力

    現在のブック内に出力されるとメモリの都合上時間がかかりすぎますそこで新規ブック1個に出力する構文を教えていただきたいのですが、宜しくお願いします。 Sub 1111() Dim c As Range Dim i As Integer, LastRow As Long Dim NewSheetName As String, MatchFlag As Boolean Application.ScreenUpdating = False NewSheetName = "" With Sheets("データ元") For Each c In .Range(.Cells(3, "B"), .Cells(Rows.Count, "B").End(xlUp)) MatchFlag = False If NewSheetName <> Year(c.Value2) & "年" & Month(c.Value2) & "月" Then NewSheetName = Year(c.Value2) & "年" & Month(c.Value2) & "月" For i = 1 To Worksheets.Count If Sheets(i).Name = NewSheetName Then Sheets(i).Cells.ClearContents MatchFlag = True Exit For End If Next i If MatchFlag = False Then Worksheets.Add after:=Worksheets(Worksheets.Count) ActiveSheet.Name = NewSheetName End If End If LastRow = Sheets(NewSheetName).Cells(Rows.Count, "A").End(xlUp).Row Sheets(NewSheetName).Cells(LastRow + 1, "A").Resize(1, 6).Value = .Cells(c.Row, "A").Resize(1, 6).Value Sheets(NewSheetName).Columns("A:F").EntireColumn.AutoFit '↑A列からF列まで自動幅調整してます Next .Activate End With Application.ScreenUpdating = True MsgBox "終了しました", vbInformation End Sub

  • excelVBAコードを教えていただけませんか

    excel2000です。 下記コードが簡単そうと思いつつ、いざやろうとすると自分では作ることができず投稿させていただきました。どうかご教授の程よろしくお願いいたします。 excel2000 VBAのコードを教えていただけませんか ・「差し込み表示.xls」から「実験データ」へ値を読みに行き、表示させようとしています。 一日だけの日付をする場合は、下記に記載しているようなコードで対応できるのですが、月を指定して、30(31)日分のデータを読みにいく場合、どういうコードに変更していいか分からず、投稿させていただきました。 ■やりたいこと ・年月を「差し込み表示」のE1セルに記載して、データ読み込みを押すと、したのNO1~31(日付をあらわしています)にそれぞれ対応する値を表示させたい。 ■現物ファイル 現物ファイルを、下記にUPさせて頂きました。差し支えなければ確認いただけると幸いです。よろしくお願いいたします。 ■アップローダー 投稿NO4662 http://www.kent-web.com/pubc/book/test/uploader/uploader.cgi ■一日で読み込むときのプロシ-ジャー Sub datatyuusyutu() Const sashikomiDisplay As String = "差し込み表示.xls" Const dataFile As String = "実験データ.xls" Dim i As Long Dim j As Long Dim k As Long Dim objectionrow As Long Dim lastRow As Long Dim targetDate As String Dim targetTime As String Dim data(1 To 43) As Double Dim dataFindFlag As Boolean Dim 対象フォルダ As String '検索する年月日を取得 targetDate = Range("E5").Value 対象フォルダ = ThisWorkbook.Path & "\" Workbooks.Open 対象フォルダ & dataFile lastRow = Cells(Rows.Count, "B").End(xlUp).Row 'B列の最終行を得る '年月日で検索 For i = 2 To lastRow If Cells(i, 2) = targetDate Then Cells(i, 2).Select dataFindFlag = True For k = 1 To 43 data(k) = Val(Cells(i, k)) Next k Exit For End If Next i Windows(sashikomiDisplay).Activate With Workbooks(dataFile) If dataFindFlag = True Then Cells(1, 2) = data(1) Cells(12, 3) = data(4) Cells(14, 6) = data(5) MsgBox "実行しました" Else MsgBox "データがありません" End If End With Workbooks(dataFile).Close savechanges:=False End Sub

  •  条件付き書式での色付けで以下のコードを教えて頂いたんですが、色付けを

     条件付き書式での色付けで以下のコードを教えて頂いたんですが、色付けを 適用する範囲をどうやって変更すればいいのでしょうか? もしよろしければ、範囲の変更の仕方と、コードの意味を教えて頂けますか? めんどうですがよろしくお願いします・・・。 Private Sub Worksheet_SelectionChange(ByVal Target As Range) Columns(3).Interior.ColorIndex = xlNone Dim i, j As Long For i = 1 To Cells(Rows.Count, 3).End(xlUp).Row For j = 1 To Cells(Rows.Count, 6).End(xlUp).Row If Cells(i, 3) = Cells(j, 6) Then Cells(i, 3).Interior.ColorIndex = Cells(j, 7).Interior.ColorIndex End If Next j Next i End Sub

専門家に質問してみよう