• 締切済み

VBA初心者です。プログラム教えてください。

行1にA~Kの値があり、この範囲で、A列に同じ値が入っている限り1、2、3と始まる値が入るよう処理をする。A列の値が変ったら、また1からスタートする値が入るよう処理をしたい。 Sub Work() Dim M As Integer Dim N As Integer M = 2 N = 2 Do While Cells(2 ,N) <> "" Cells(3 , N) <> "" Or C = Cells(3 , N - 1)  (1) N = N + 1 Loop End Sub 上記を作りましたが、(1)の所でデバックしてしまいます。 解決策をぜひ教えてください。よろしくお願いします。

みんなの回答

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

こんばんは。 >今回はLoopを使いたかったのですが、とても参考になりました。 原則的に、Loopで、最終行の判定をセル1つずつとれば、遅くなりますので、通常、Do ~Loop は、大量のセルの判定には使いません。少量に限ります。なお、Do ~ Loopの使い方のほうが難しいです。 また、以下のコードでは、本来は、不要ですが、罫線などは、自分以外の環境の時は、極力、プロパティの省略は避けることにしています。しかし、個々の線は、コレクションとしてまとめてよいということです。罫線を使うと、とたんにスピードが遅くなりますから、それなりにコードの工夫は必要です。まあ、後学のために。 '標準モジュール Sub PlusLineDrawing()   Dim c As Range   Dim N As Long   Dim rng As Range   Set rng = Range("A2", Range("A65536").End(xlUp))   Application.ScreenUpdating = False   '省略は避けます   With rng.Offset(, 1).Resize(, 11)     .Borders.LineStyle = xlNone     .Borders.LineStyle = xlContinuous     .Borders.Weight = xlThin     .Borders.Color = vbBlack   End With   N = 0   For Each c In rng     c.Offset(, 1).Resize(, 11).FormulaLocal = "=" & N & "+COLUMN(A1)"     c.Offset(, 1).Resize(, 11).Value = c.Offset(, 1).Resize(, 11).Value     If StrComp(Trim(c.Value), Trim(c.Offset(1).Value), 1) = 0 Then       N = WorksheetFunction.Max(c.Offset(, 1).Resize(, 11))     Else       N = 0       'オプション--最後を太線にするか、そのままにするか?       'If c.Row = rng.Cells(rng.Count).Row Then Exit For '太線       c.Offset(, 1).Resize(, 11).Borders(9).Weight = xlMedium     End If   Next c   Set rng = Nothing   Application.ScreenUpdating = True End Sub

monfiy
質問者

お礼

ご丁寧にありがとうございました。もう少し上達して、こちらのプログラムも勉強したいと思います。

  • Bickyon
  • ベストアンサー率41% (42/101)
回答No.8

#1です。罫線追加バージョンです。 Dim Col As Integer Dim Col2 As Integer Dim Line As Long Dim Cnt As Long Col = 2 Line = 2 Cnt = 0 Cells.Select Selection.Borders(xlInsideVertical).LineStyle = xlNone Selection.Borders(xlInsideHorizontal).LineStyle = xlNone Range("A1").Select Do While Cells(Line, 1) <> "" Do While Cells(1, Col) <> "" Cnt = Cnt + 1 Cells(Line, Col) = Cnt Col = Col + 1 Col2 = Col Loop Line = Line + 1 Col = 2 If Cells(Line, Col - 1) <> Cells(Line - 1, Col - 1) Then Cnt = 0 Range(Cells(Line - 1, 2), Cells(Line - 1, Col2 - 1)).Borders(xlEdgeBottom).Weight = xlMedium Else Range(Cells(Line - 1, 2), Cells(Line - 1, Col2 - 1)).Borders(xlEdgeBottom).Weight = xlThin End If Loop Range(Cells(2, 1), Cells(Line - 1, Col2)).Borders(xlInsideVertical).Weight = xlThin Range(Cells(2, 2), Cells(Line - 1, Col2 - 1)).Borders(xlEdgeTop).Weight = xlThin Range(Cells(2, 2), Cells(Line - 1, Col2 - 1)).Borders(xlEdgeBottom).Weight = xlThin

monfiy
質問者

お礼

ありがとうございました。お蔭様で支障なく業務に関われそうです。 また何か問題がありましたら、どうぞ宜しくお願い致します。

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

こんにちは。 難しく考えないで、数式で作ればよいのではありませんか? 私の場合は、文字の比較に対して、TextCompare を用いています。 Aもa も、全角のAもaも同じだとします。 Sub NumberingTest1() Dim c As Range Dim N As Long N = 0 For Each c In Range("A2", Range("A65536").End(xlUp))  c.Offset(, 1).Resize(, 11).FormulaLocal = "=" & N & "+COLUMN(A1)"  '定数化  c.Offset(, 1).Resize(, 11).Value = c.Offset(, 1).Resize(, 11).Value  '文字列比較  If StrComp(Trim(c.Value), Trim(c.Offset(1).Value), 1) = 0 Then    N = WorksheetFunction.Max(c.Offset(, 1).Resize(, 11))  Else    N = 0  End If Next c End Sub

monfiy
質問者

お礼

ありがとうございます。今回はLoopを使いたかったのですが、とても参考になりました。Wendy02様の方法は別の機会に参考にさせていただきたいと思います。

  • Bickyon
  • ベストアンサー率41% (42/101)
回答No.6

#1です。#4氏が既に回答されていますが、私はLoopを使う方法ということで... Dim Col As Integer Dim Line As Long Dim Cnt As Long Col = 2 Line = 2 Cnt = 0 Do While Cells(Line, 1) <> "" Do While Cells(1, Col) <> "" Cnt = Cnt + 1 Cells(Line, Col) = Cnt Col = Col + 1 Loop Line = Line + 1 Col = 2 If Cells(Line, Col - 1) <> Cells(Line - 1, Col - 1) Then Cnt = 0 End If Loop 以上です。

monfiy
質問者

補足

ありがとうございました。思う通りにできました。 また併せて教えていただきたいのですが、罫線を引く場合の設定はどのようにしたらいいのでしょうか。 希望はB2セルから値が入ってる部分を細線で格子状にしたいのです。 またA1列の値が変る部分(aとbの行の境目)を太線にしたいのですが、 With Selection  Range(Cells(2,Line),Cells(Col,2)).Select   Selection.Borders(xlDiagonalDown).LineStyle = xlNone   Selection.Borders(xlDiagonalUp).LineStyle = xlNone   Selection.Borders(xlEdgeLeft).LineStyle = xlNone   Selection.Borders(xlEdgeTop).LineStyle = xlNone   Selection.Borders(xlEdgeBottom).LineStyle = xlNone   Selection.Borders(xlEdgeRight).LineStyle = xlNone   Selection.Borders(xlInsideVertical).LineStyle = xlNone   Selection.Borders(xlInsideHorizontal).LineStyle = xlNone End With では作動しませんでした。よろしくお願いいたします。

  • papayuka
  • ベストアンサー率45% (1388/3066)
回答No.5

#3です。 #4さんへの補足&回答を見て書いています。 回答者はシート内容を見ている訳ではないので、このように座標と結果が視覚的に解ると答えやすいです。 Do ~ Loop を使う方法ではありませんが、参考まで。 Sub Test() Dim cnt As Long, myRow As Long, myCol As Integer  'カウント変数を初期化  cnt = 1  With ActiveSheet   'A2からCtrl+↓のA列最終行までループ   For myRow = 2 To .Cells(2, 1).End(xlDown).Row    'B列からL列までループして連番を代入    For myCol = 2 To 12      .Cells(myRow, myCol).Value = cnt      cnt = cnt + 1    Next myCol    '次の行に移る前にA列の文字を判定し、違っていたらCntを初期化    If .Cells(myRow, 1).Value <> .Cells(myRow + 1, 1).Value Then      cnt = 1    End If   '次の行へ   Next myRow  End With End Sub

monfiy
質問者

お礼

参考になります。次の機会にぜひ使わせていただきたいと思います。ありがとうございました。

  • Bickyon
  • ベストアンサー率41% (42/101)
回答No.4

再度#1です。しつこくて申し訳ないです。 #3氏の補足に書かれたものもみましたが、やはり質問者様の意図するところが見えません。 行1のA~Kの値というのは、範囲を示しているだけで、ナンバリングの条件には関係ないのですね? c1とかr1とか新しい情報(条件)も出てきてますので、まだ問題が解決されていないようなら、改めて条件の整理をお願いします。 ・A列の値により付与する1、2、3~という値はどのセル(どの列)に入れたいのでしょうか?B列ですか? ・A列から1列おきにK列までaa,bbb,ccって入れてあるから、間の空白列にナンバリングしたいってことですか?

monfiy
質問者

お礼

誤って上記を転送してしまいましたので、こちらに補足させていただきます。 A~K列はセルB1~L1にあります。また縦方向のa、b、cはA2セルから始まります。   A   B  C  D   E  F  G  H  I  J  K a 1  2  3  4  5  6  7  8  9  10 11 a 12 13  14 15 16 17 18 19 20  21 22 b 1  2  3  4  5  6  7  8  9  10 11 c 1  2  3  4  5  6  7  8  9  10 11 d 1  2  3  4  5  6  7  8  9  10 11 d 12 13  14 15 16 17 18 19 20  21 22 のようにしたいのです。A2セルの値が変ったら数字は1から始まる。 どうぞよろしくご指導ください。

monfiy
質問者

補足

こちらこそ説明不足ですみません。 条件は下記のようになります。  A  B  C  D  E  F  G  H  I  J  K a1  2  3  4  5  6  7  8  9  10 11 a12 b b b c d ・ ・ ・

  • papayuka
  • ベストアンサー率45% (1388/3066)
回答No.3

ご質問に「1行目に A~K の値が入っている」「A列の値が変わったら」とありますが、  N = 2  Do While Cells(2 ,N) <> ""    Cells(3 , N) <> "" Or C = Cells(3 , N - 1) 上記コードを見る限り 1行目も A列もほとんど無視して、セル B2 と B3 と A3を起点に処理をしようとしていますね。 B1~I1 に A,A,B,B,B,C,C,C と値があった場合、 B2~I2 に 1,2,1,2,3,1,2,3 と番号を振りたい のように、セル座標を提示して質問された方が回答者の環境で再現させやすいと思いますよ。 仮に上記の条件だとしたら Sub Test() Dim N As Integer, M As Integer M = 1 With ActiveSheet   For N = 2 To .Cells(1, 256).End(xlToLeft).Column     If .Cells(1, N).Value = .Cells(1, N - 1).Value Then       M = M + 1     Else       M = 1     End If       .Cells(2, N).Value = M   Next N End With End Sub

monfiy
質問者

補足

C1に縦方向にa,a,a,b,bなどを、またR1に横方向にA、B、Cと入力したいので、起点はB2セルになります。 そのような表現がわかりやすいのですね、ご指摘いただいてありがとうございました。

  • Bickyon
  • ベストアンサー率41% (42/101)
回答No.2

#1です。 意味が今一理解できないといったのは、A~Kの値が横にならんでいるのか、縦に並んでいるのかです。 「行1にA~Kの値があり」だと横に並んでいるし、 「A列に同じ値が入っている限り」だと縦に並んでいることになります。 お書きになっているCellsの書き方だと列方向に変数が使われていますので、横方向に並んでいると想定します。 そうすると、以下のコードでOKなはずです。 Dim N As Integer N = 1 Do While Cells(1, N) <> "" If N = 1 Then Cells(2, N) = 1 Else If Cells(1, N) = Cells(1, N - 1) Then Cells(2, N) = Cells(2, N - 1) + 1 Else Cells(2, N) = 1 End If End If N = N + 1 Loop ワークシート関数を使うなら、a2セルには初期値として1を入力しておき、B2のセルに=If(b1=a1,a2+1,1)と入力し、それを横にコピーしていけばできます。

monfiy
質問者

補足

説明不足でもうしわけありません。ご指摘の通り、「行1」に横方向にアルファベットをKまで並べてあります。また「列A」にも上から縦にアルファベットがありまして、こちらはa、bなどの表記にすればよかったのですね。失礼いたしました。

  • Bickyon
  • ベストアンサー率41% (42/101)
回答No.1

直接の原因は(1)の行が、If ~ Then ~ Else ~ End If の形になっていないからだと思います。 それとCという変数の宣言や値設定もありませんね。 あと「行1にA~Kの値があり~~」の意味が今一理解できませんので、ピンとはずれかもしれませんが、 =IF(a2<>a1,1,a1+1)というワークシート関数はダメ?

monfiy
質問者

補足

(1)のCはNの間違いでした。すみません。 Cells(3 , N) <> "" Or N = Cells(3 , N - 1) です。 ここを If N <> "" Then Else End If でしょうか。Elseの前と後にはどのような条件を入れたらいいですか? 1行目にA,B,C・・・J,Kまでの値が入っている状態です。説明不足で申し訳ありません。関数を使ったらどのようになるのでしょうか?その場合でもVBAでできますか?

関連するQ&A

  • エクセルVBAの繰り返し処理の質問

    C列にある項目とG列にある項目を比較して、 一致し、H列にある数字が10以上ならば、B列にフラグ1を立てる という処理を行いたいんですが、 下記ぐらいまでしか作れず、うまくいきません・・・ Sub フラグを立てる処理() Dim i As Integer Dim j As Integer Dim k As Integer i = 1 j = 1 Do j = j + 1 Do i = i + 1 If Cells(j, 8) > 9 Then Cells(i - 1, 4) = 1 End If Loop Until Cells(i, 3) <> Cells(j, 7) Or Cells(i, 3) = "" Loop Until Cells(j, 7) = "" End Sub わかる方がいらっしゃいましたら、お願いします。

  • VBAで空欄にデータに表示

    エクセルVBAのIFを使って、シートaのA列に値があって、B列が空欄の場合のみ、空欄のセルにシートbの値を表示させたいです。 上手くできませんでしたので、教えてください。 Sub Do文2() Dim i As Integer i = 1 If Worksheets("a").Cells(i, 2) = "" Then Do While Worksheets("a").Cells(i, 1) <> "" Worksheets("a").Cells(i, 2) = Worksheets("b").Cells(1, 1) i = i + 1 Loop End If End Sub

  • VBAで行を挿入する

    VBAを始めた初心者です。 Exel2002使用です。 VBAでA列の4行目から10行目に行の挿入をできるようにしようと下記のように書きましたが、Rows("i:i").Selectの部分でデバックがかかってしまいます。間違っている理由がわからないのですがよろしくお願いします。 また、DO While Loopステートメントを使ってA列が空白になるまで(例えばA4セル以下の)行を挿入とする場合の方法も教えていただけましたら幸いです。 Sub 4行目から10行目まで() Dim i As Integer For i = 4 To 10 Cells(i, 1).Value = i Rows("i:i").Select Selection.Insert Shift:=xlDown Next i End Sub Sub 4行目から空白になるまで() Dim i As Integer Range("A4").serect Do While activecell.value = "" Cells(i, 1).Value = i Rows("i:i").Select Selection.Insert Shift:=xlDown activecell.offset(1,0).select Loop End Sub

  • 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を挿入してもダメでした。

  • vba初心者

    いつもお世話様です。 A列にあらかじめデータを入れといてinboxでデータを検索してもしあったらPDFファイルを開いて印刷でもしデータがなかったらinboxに戻るかたちにしたいんですけど、do...loopの使い方が分からないのと、デバックがでてしまってどう直せばいいかわかりません。サンプルコードがあれば助かります。よろしくお願いします。 Dim a As Integer Dim inbox As String Dim Localpath As Variant Dim c As Range, myFadd As String Dim flag As Variant Dim MyShell As Object Dim Mysh As String Dim newHour As Variant Dim newMinute As Variant Dim newSecond As Variant Dim waitTime As Variant Localpath = ThisWorkbook.Path a = 1 inbox = InputBox("番号") Do If inbox = Empty Then Exit Sub End If If inbox = Cells(a, 1) Then MsgBox ("あります") Exit Do Else a = a + 1 ←ここでデバックがでてしまいます。 ElseIf Cells(a, 1) <> inbox Then MsgBox ("ない") End If Loop Set MyShell = CreateObject("WScript.Shell") MyShell.Run ("AcroRd32.exe /n") MyShell.Run ("AcroRd32.exe /p") & Localpath & "\" & Myfile & ".pdf" newHour = Hour(Now()) newMinute = Minute(Now()) newSecond = Second(Now()) + 10 waitTime = TimeSerial(newHour, newMinute, newSecond) Application.Wait waitTime Application.SendKeys "{Enter}", True '次の使用例は、10 秒を過ぎるとメッセージを表示します。 If Application.Wait(Now + TimeValue("0:00:10")) Then MsgBox "時間が過ぎました。" End If End Sub

  • VBA 時間の足し算

    windowsは7、Excelは2013を使用しています。 下記のマクロで、Q列のキーワードを基に、 Q列=H列の時に、C列の時間(表記は、1:00:00)をnに格納していき、 時間の合計を、S列に入る様にしていますが、 C列の値が、0:30:00や0:15:00などの場合、 S列に入る値が 0.291666666666667 とかに小数点以下の値になってしまいます。 例えば、1:00:00+0:30:00+0:45:00=2:15という値が帰ってくるようにするにはどうしらいいのか教えて下さい。 あと、もし合計が24以上になった場合、25や26などの値になる様にもしたいです。 よろしくお願い致します。 -------------------------------------- Sub test() Dim h As Integer Dim q As Integer Dim n As Variant Dim maxRow As Integer maxRow = Range("A65536").End(xlUp).Row For q = 2 To 10 n = 0 For h = 2 To maxRow If Cells(q, 17) = Cells(h, 8) Then n = n + Cells(h, 3).Value End If Next h Cells(q, 19).Value = n Next q

  • A列の値を元にフォルダを作成するVBAの質問です

    A列の値を元にフォルダを作成するVBAで 富士通の緑の本を参考にして作ってみたのですが、 うまく動作しません。 1.Sub フォルダ作成() 2. 3. Dim MyFSO As New FileSystemObject 4. Dim Folderpath As String 5. Dim i As Integer 6. 7. i = 1 8. 9. Do While Cells(i, 1).Value <> "" 10. 11. Folderpath = ThisWorkbook & "\Cells(i, 1).value" 12. 13. MyFSO.CreateFolder Path:=Folderpath 14. 15. i = i + 1 16. 17. Loop 18. 19.Set MyFSO = Nothing 20. 21.End Sub 目的の動作は 今のワークブックのある場所にSheet1のA列の1~データがなくなるまで、 そのセルの値のフォルダを作成する。 になります。 よろしくお願いします。

  • エクセルマクロ配列で変数は使えますか

    エクセル2013です。 初めて配列を使います。 以下のように作成し思ったようにできました。 Sub 計算() '成功 Dim a As Integer Dim c As Integer Dim b(5) As Integer Dim 最終行 Dim 値列  値列 = 17 最終行 = Cells(Rows.Count, 1).End(xlUp).Row For 処理業 = 1 To 最終行 For a = 1 To 5 b(a - 1) = Cells(1, 値列) 値列 = 値列 + 1 Next 値列 = 17 For a = 1 To (22 - 値列) c = c + b(a - 1) Next Cells(処理業, 30) = c a = 0 c = 0 Next 処理業 End Sub ただ計算する列の範囲をインプットボックスで入力した値 にしたい為以下のように改造しました。 Dim b(対象列) As Integerでエラーになります 配列には変数は使用できないのでしょうか? よろしくお願いします。 Sub 計算() '失敗 Dim a As Integer Dim c As Integer Dim b(対象列) As Integer’★ここでERRになる Dim 最終行 Dim 対象列 Dim 値列  対象列 = 22'インプットボックスで入力した値 値列 = 17 最終行 = Cells(Rows.Count, 1).End(xlUp).Row For 処理業 = 1 To 最終行 For a = 1 To (対象列 - 17) b(a - 1) = Cells(1, 値列) 値列 = 値列 + 1 Next 値列 = 17 For a = 1 To (22 - 値列) c = c + b(a - 1) Next Cells(処理業, 30) = c a = 0 c = 0 Next 処理業 End Sub

  • VBAのプログラムでうまく動かなくて困っています。

    VBA初心者です。 エクセルのVBAのプログラムでうまく動かなくて困っています。教えていただける方がいらしたら、ぜひ教えて下さい!よろしくお願いします。エクセルの内容は以下のとおりです。 (内容) セル    E H J L N P R・・・ 8行目100 200 50 40 30 80 9行目130 350 10 50 60 120 110 ・ ・ (1)列Hの値が列Eの値より大きい場合その下に行を追加します。 (2)セルJ+セルL+セルN+・・をしてセルEの値を超えたセル以降の値を追加した行のセルJ列から順にコピペする処理です。 上のセルの1行目の内容でいいますと、 (1)列Hの値「200」が列Eの値「100」より大きいのでその下に行追加 (2)セルJ、L、N「50」+「40」+「30」でセルEの値「100」より大きいので、追加した行のセルJ列にセルN、Pの値をコピペするです。 以下が私が書いたプログラムです。 Sub test() Dim x As Integer Dim s As Integer Dim t As Integer x = Range("B8").End(xlDown).Row r = Range("J8").End(xlToRight).Column '8行目から最終行までループ For i = x To 9 Step -1 If Cells(i, 5) < Cells(i, 8) Then ☆【For r = y To 11 Step -2 Cells(s, t).Value = Cells(i, r) + Cells(i, r + 2) If Cells(i, 5).Value < Cells(s, t).Value            Then Exit For Next】 Rows(i + 1).Insert Shift:=xlDown '超えたセルをコピーして、1行下の"J列以降"に代入 ★ x = x + 1 End If Next i End Sub 上記プログラムで★の部分がうまく書けません。☆の部分も間違っているような気がします。よろしくお願いします。

  • エクセルVBAについて

    エクセルVBA初心者です。 左の表からある一定以上の売上を得た人を抽出し、右の表に表示したいのですが以下のプログラムだと上手くいきません。 どこがダメなのでしょうか? Private Sub cmdUriken_Click() Dim k As Integer Dim l As Integer Dim m As Integer k = 2 l = 2 m = 2 Do Until Cells(m, 32) = "" Range(Cells(m, 19), Cells(m, 34)).Select Selection.ClearContents m = m + 1 Loop Do Until Cells(k, 14) = "" If Cells(k, 14) >= txtUriken.Text Then Range(Cells(k, 1), Cells(k, 16)).Select Selection.Copy Range(Cells(l, 19), Cells(l, 34)).Select ActiveSheet.Paste l = l + 1 Application.CutCopyMode = False End If k = k + 1 Loop End Sub ちなみに If Cells(k, 14) = txtUriken.Text Then とするとちゃんと同等の売上が表示されるので >= の使い方が間違っていると思うのですが よろしくお願いします。

専門家に質問してみよう