• 締切済み

VBA 類似処理の件数を同様にする方法について

ExcelVBAの初歩的な質問です。 【質問内容】 [CheckAcolumnBrank]と[CheckBcolumnBrank]の処理を行った際に、[CheckBcolumnBrank]の結果が[CheckAcolumnBrank]の結果と行数が異なるため(5行ほど多く処理されてしまいます)、[CheckAcolumnBrank]の行数に合わせるコードを知りたいです。 ご見識のある方からの、お知恵の拝借をいただきたく、よろしくお願い申し上げます。 【前提条件】 1.シート1のA5からJ500までの範囲のセルに値が入力されています(空欄セルが不規則にあります)。 2.レコード数は10行程度から450行程度です。 3.A列のセルに値が入っていない場合は、1つ上のセルの値をコピーする挙動です。 4.B列についても、A列と同じ挙動をさせたいです。 5.最終行を求める処理は「GetLastRow」にて行います。 -------------------------------------------- Function GetLastRow() As Long ' 最終行を求める処理 Dim i As Long Dim MaxValue As Long For i = 5 To 500 If Cells(i, "A").Value <> "" Then ' A列からJ列に入力されている値の最大値を求める MaxValue = Application.WorksheetFunction.Max(Range("A" & i & ":J" & i)) If MaxValue > GetLastRow Then GetLastRow = i End If End If Next End Function -------------------------------------------- Private Sub CheckAcolumnBrank() ' A列がブランクの場合、1つ上の値をコピペする処理 Dim currentRow As Long Dim emptyColumns As Boolean Dim Lcont As Long Lcont = GetLastRow Dim ws As Worksheet Set ws = Sheets("シート1") emptyColumns = False ' A列を埋めるループ処理開始 currentRow = 6 Do While currentRow <= Lcont If IsEmpty(ws.Cells(currentRow, 1).Value) Then ws.Cells(currentRow, 1).Value = ws.Cells(currentRow - 1, 1).Value End If ' 終了条件のチェック(E列からJ列がすべて空白、かつA列の1つ上の値が異なる場合に終了) If ws.Cells(currentRow, 5).Value = "" _ And ws.Cells(currentRow, 6).Value = "" _ And ws.Cells(currentRow, 7).Value = "" _ And ws.Cells(currentRow, 8).Value = "" _ And ws.Cells(currentRow, 9).Value = "" _ And ws.Cells(currentRow, 10).Value = "" _ And (ws.Cells(currentRow, 1).Value <> ws.Cells(currentRow - 1, 1).Value) Then Exit Do End If currentRow = currentRow + 1 Loop End Sub -------------------------------------------- Private Sub CheckBcolumnBrank() ' B列がブランクの場合、1つ上の値をコピペする処理 Dim currentRow As Long Dim emptyColumns As Boolean Dim Lcont As Long Lcont = GetLastRow Dim ws As Worksheet Set ws = Sheets("シート1") emptyColumns = False ' ループ開始 currentRow = 6 Do While currentRow <= Lcont If ws.Cells(currentRow, 2).Value = "" Then ws.Cells(currentRow, 2).Value = ws.Cells(currentRow - 1, 2).Value End If ' 終了条件のチェック(E列からJ列がすべて空白、かつB列の1つ上の値が異なる場合に終了) If ws.Cells(currentRow, 5).Value = "" _ And ws.Cells(currentRow, 6).Value = "" _ And ws.Cells(currentRow, 7).Value = "" _ And ws.Cells(currentRow, 8).Value = "" _ And ws.Cells(currentRow, 9).Value = "" _ And ws.Cells(currentRow, 10).Value = "" _ And (ws.Cells(currentRow, 2).Value <> ws.Cells(currentRow - 1, 2).Value) Then Exit Do End If currentRow = currentRow + 1 Loop Set ws = Nothing End Sub --------------------------------------------

みんなの回答

  • kkkkkm
  • ベストアンサー率65% (1636/2483)
回答No.11

あと 回答No.3 のお礼の以下の部分 > A列かB列のデータ数が多いほうが範囲内での最大行と考えていた に関して回答がないようなので、一例として Lcont = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row If Lcont < ws.Cells(ws.Rows.Count, "B").End(xlUp).Row Then Lcont = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row End If 元のコードを利用するのでしたら Function GetLastRow() As Long ' 最終行を求める処理 Dim i As Long For i = 5 To 500 If Cells(i, "A").Value <> "" Or Cells(i, "B").Value <> "" Then GetLastRow = i End If Next End Function

全文を見る
すると、全ての回答が全文表示されます。
  • kkkkkm
  • ベストアンサー率65% (1636/2483)
回答No.10

他の方の回答に付帯してとやかく言いたくはありませんが 差が出るのは A列からJ列に入力されている値で最大値がある行が最終行(細かな説明は省いてましたが)としている点にあると思います。 実際は過去の最終行の行番号と現在行の最大値の大きい方が最終行 たとえば、最終行と仮定された行が200行目の時201行目以降で最大値が200を超えなければデータが存在しても最終行は200のまま A列処理後元空欄だった180行が2回目で埋められて条件によって最終行と判断された場合、それ以降の行で最大値が180を超えなければ最終行は180のまま という事もありますからデータによっては下にある行が必ずしも最終行として扱われるわけではありませんし、実際の最終行が取得できないという事もあり得ます。 ちなみに、A列を実行した時に空白のセルに上のセルの値を代入しますが最終行(最終行は空白では無いはず)までなので最終行より下にデータが埋められるという事は無いと思います。 2度目の最終行が上記の理由で上になることはあっても下になることはない思いますが、実際Aの後にBを実行してBの方が下になったのでしょうか。

全文を見る
すると、全ての回答が全文表示されます。
  • chie65535
  • ベストアンサー率43% (8548/19428)
回答No.9

>ちなみに、なぜ5件の差が生じる理屈が恥ずかしながらわかっておりません。 差が出る理由は 1.初回のGetLastRowでは、B~J列に何が入っていてもA列が空欄の行は無視され、それより上の行が最終行として判定される 2.CheckAcolumnBrankで、上記1で「A列が空欄で無視されていた行」のA列に、値がコピーされ、空欄では無くなる 3.2回目のGetLastRowでは、上記1で無視されていた行は、上記2の処理でA列が空欄ではなくなり、無視されなったため、上記1より下にある行が最終行として判定される というのが理由です。 だから「GetLastRowを2回呼んではいけない」のです。

全文を見る
すると、全ての回答が全文表示されます。
  • kkkkkm
  • ベストアンサー率65% (1636/2483)
回答No.8

とりあえずですが、A列からJ列に入力されている値で最大値がある行が最終行ではないという事ですので 最終行の取得で元のコードを利用するとしたら Function GetLastRow() As Long ' 最終行を求める処理 Dim i As Long For i = 5 To 500 If Cells(i, "A").Value <> "" Then GetLastRow = i End If Next End Function

全文を見る
すると、全ての回答が全文表示されます。
  • kkkkkm
  • ベストアンサー率65% (1636/2483)
回答No.7

ちなみに最終行が正しければ、今回のコードでは最終行までしかループしてませんから、途中で最終行が変化することは無いと思いますよ。

全文を見る
すると、全ての回答が全文表示されます。
  • kkkkkm
  • ベストアンサー率65% (1636/2483)
回答No.6

回答No.5で最後に抜けがありました。 たとえば、最終行に関してA列はA列の最後までB列はB列の最後まで操作を実施するのか、それともA列B列とも同じ行まで操作を実施するのかによって最終行の求め方も変わりますから何がいいのか悪いのかとか提案もできないということです。

全文を見る
すると、全ての回答が全文表示されます。
  • kkkkkm
  • ベストアンサー率65% (1636/2483)
回答No.5

> 「GetLastRow」が正しく動いていないため、せっかくご提示いただいたにもかかわらず、行数がズレた結果となってしまいます。kkkkkmさんのコードは正しく動作すると思われますが、前段階で私のコードが誤っていることに起因しており、誠に申し訳ございません。 元のコードを引数付きにしただけなので行数が違う事については何もさわっていません。 と説明しているように行数のズレに関しては何もさわってませんからズレたままでしょう。 最終行が違うデータを基にしてあれこれ考えても無駄ですのでとりあえず最終行を取得するようにしてみたほうがいいと思いますよ。 ws.Cells(ws.Rows.Count, "A").End(xlUp).Row とかで求められたりしますが、他にも方法がありますから検索してご自身がこれと思うものを採用してください。 行数がずれたというのが何を基にしているのか分かりませんし、どのようなデータでどのような結果を期待してるのかもわかりませんから良いとか悪いとかは何とも言えませんし、こうするのですという提案もできないと思いますよ。

全文を見る
すると、全ての回答が全文表示されます。
  • kkkkkm
  • ベストアンサー率65% (1636/2483)
回答No.4

No.1でちょっと説明下手だった所を補足 > A列からJ列に入力されている値の最大値が最終行なのですか? A列からJ列に入力されている値で最大値がある行が最終行なのですか?

retweet
質問者

お礼

補足のご連絡ありがとうございます。 >> A列からJ列に入力されている値の最大値が最終行なのですか? >A列からJ列に入力されている値で最大値がある行が最終行なのですか? いえ、最大値が最終行ではございません。 と、kkkkkmさんからの上記ご連絡で、私が何を間違えていたかが気付けそうな予感がします……具体的な考えまで浮かぶほど私は賢くないので、時間がかかりそうですが。 お気にかけていただき、ありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。
  • chie65535
  • ベストアンサー率43% (8548/19428)
回答No.3

>[CheckAcolumnBrank]と[CheckBcolumnBrank]の処理を行った際に、[CheckBcolumnBrank]の結果が[CheckAcolumnBrank]の結果と行数が異なるため 現状では、結果が異なる事を回避できません。 CheckAcolumnBrankを実行した後には「A列の状況が変わっている」つまり「今までブランクだったセルに、ブランクじゃない物がコピーされている」ので、CheckAcolumnBrankの中で呼び出しているGetLastRowの返り値と、CheckBcolumnBrankの中で呼び出しているGetLastRowの返り値は「異なる値」になります。 これを防ぐには「A列が手付かずの状態で求めた、GetLastRowの返り値の値を、どこかに記録しておいて、CheckAcolumnBrankとCheckBcolumnBrankの両方で、その記録しておいた値を使う」という事をしないとなりません。 言い換えると「GetLastRowを2回以上呼び出してはいけない」と言う事です。 ですので「根本的な部分から作り直す必要がある」と思われます。現状では回避不可能です。 「結果が正しいのであれば、異なる行数を実行してしまうのも仕方が無い」と諦めるか「GetLastRowを1回しか使わないように根本的な部分から作り直す」か、どちらかを選択して下さい。 なお、この考察を確かめたい場合は、 CheckAcolumnBrankの Lcont = GetLastRow の次の行に msgbox "A=" & Lcount と言う行を挿入し、同様に CheckBcolumnBrankの Lcont = GetLastRow の次の行に msgbox "B=" & Lcount と言う行を挿入してみて下さい。 きっと A=493 B=498 のように「AとBで異なる値が表示される筈」です。 ここで異なる値が表示される限り、AとBで実行される行数が異なるのは、絶対に避けられません。

retweet
質問者

お礼

ご回答ありがとうございます。また、お礼が遅くなり大変恐縮でございます。 >言い換えると「GetLastRowを2回以上呼び出してはいけない」と言う事です。 そういうことなんですね。最終行を求める処理が2回あったので、プロシージャ化すれば便利かと思っていたのですが……。 chie65535さんから、ご提案いただいた通り、Msgboxで各々のプロシージャで変数の値を確認したところ、AとBで異なる値が表示されました。件数の差は、chie65535さんが例示された通りBの方が「5件」多かったです。誠に恐れ入りました。 ちなみに、なぜ5件の差が生じる理屈が恥ずかしながらわかっておりません。と申しますのは、A列とB列以外の列に存在するデータ数は、A列とB列に比べ少ないため、私としてはA列かB列のデータ数が多いほうが範囲内での最大行と考えていたのですが、実際はB列の方がA列よりもデータ数が5こ多くなる仕組みがわかりません。自分で作った仕組みの落ち度がわからないという情けない状況です。 もしよろしければ、上記の現象を言い当てた、chie65535さんのご知見を仰げると幸いです。 以上、よろしくお願い申し上げます。

全文を見る
すると、全ての回答が全文表示されます。
  • kkkkkm
  • ベストアンサー率65% (1636/2483)
回答No.2

あと、余計なお世話だと思いますが、二つの処理はA列とB列の違いだけであとは全く同じだと思いますから、引数のあるサブプロシージャにしたら修正したりする場合に二つ同じように直さなくていいので楽になると思います。元のコードを引数付きにしただけなので行数が違う事については何もさわっていません。 Sub Test() Call CheckcolumnBrank(Columns("A").Column) Call CheckcolumnBrank(Columns("B").Column) End Sub Private Sub CheckcolumnBrank(ByVal mCol As Long) ' 指定列がブランクの場合、1つ上の値をコピペする処理 Dim currentRow As Long Dim emptyColumns As Boolean Dim Lcont As Long Lcont = GetLastRow Dim ws As Worksheet Set ws = Sheets("シート1") emptyColumns = False 'これの意味が分かりません。 ' ループ開始 currentRow = 6 Do While currentRow <= Lcont If ws.Cells(currentRow, mCol).Value = "" Then ws.Cells(currentRow, mCol).Value = ws.Cells(currentRow - 1, mCol).Value End If ' 終了条件のチェック(E列からJ列がすべて空白、かつ指定列の1つ上の値が異なる場合に終了) If ws.Cells(currentRow, 5).Value = "" _ And ws.Cells(currentRow, 6).Value = "" _ And ws.Cells(currentRow, 7).Value = "" _ And ws.Cells(currentRow, 8).Value = "" _ And ws.Cells(currentRow, 9).Value = "" _ And ws.Cells(currentRow, 10).Value = "" _ And (ws.Cells(currentRow, mCol).Value <> ws.Cells(currentRow - 1, mCol).Value) Then Exit Do End If currentRow = currentRow + 1 Loop Set ws = Nothing End Sub

retweet
質問者

お礼

再び、ご回答ありがとうございます。 >emptyColumns = False 'これの意味が分かりません。 ご指摘の通り、無意味なコードでした。試行錯誤しながら書いていたため、残骸を放置したままでした。 コードのご提案もいただき、重ねて御礼申し上げます。 先のご回答に対する御礼で申し上げましたが、「GetLastRow」が正しく動いていないため、せっかくご提示いただいたにもかかわらず、行数がズレた結果となってしまいます。kkkkkmさんのコードは正しく動作すると思われますが、前段階で私のコードが誤っていることに起因しており、誠に申し訳ございません。 kkkkkmさんから、新たな視点をいただき感謝しております。 以上、よろしくお願い申し上げます

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • VBA 請求データ一覧からの複数の処理

    先週 kkkkkmさんに質問をさせて頂きまして、 いろいろご指導を頂いたものです。 続編の様な形になってしまいますが、 抽出するデータの環境設定を変更致しました。 ご質問させて頂く内容は前回とほとんど変更がないのですが、 あらためて下記に記載させて頂きます。 <Worksheet1のデータ> J列~AM列までが課税金額 「J,K,L」「M,N,O」・・・「AK,AL,AM」と3列1組(コード・費目・金額) 1組の行もあれば、複数組の行もあり。 AN列~BB列までが非課税金額 課税金額と同じく3列1組 1組の行もあれば、複数組の行もあり。 「BC」=消費税、「BD」=合計金額 ※AN列の前に不規則な空白セルあり   BC列の前に不規則な空白セルあり 文章で上手く説明出来ているか自信がありませんので、 エクスポートした元データ Worksheet1と、 vbaを用いて作成した Worksheet3 をご参考に添付致します。 Worksheet1の2行目がWorksheet3の2行目に対応しています。 3行目、4行目も同様です。 不規則な空白が原因でしょうか・・・。 M列、O列は問題ないのですが、 金額が合わなかったり、N列に金額を引いてこないのです。 実行しているコードは下記になります。 Dim i As Long, j As Long, k As Long Dim Ws1 As Worksheet, Ws2 As Worksheet, Ws3 As Worksheet Dim mTotal(4) As Long Dim LastRow As Long Dim List(4) As Variant Set Ws1 = Sheets("Sheet1") Set Ws2 = Sheets("Sheet2") Set Ws3 = Sheets("請求書ひな形") List(1) = Ws2.Range(Ws2.Cells(1, "A"), Ws2.Cells(Rows.Count, "A").End(xlUp)).Value List(2) = Ws2.Range(Ws2.Cells(1, "B"), Ws2.Cells(Rows.Count, "B").End(xlUp)).Value List(3) = Ws2.Range(Ws2.Cells(1, "C"), Ws2.Cells(Rows.Count, "C").End(xlUp)).Value List(4) = Ws2.Range(Ws2.Cells(1, "D"), Ws2.Cells(Rows.Count, "D").End(xlUp)).Value LastRow = UBound(List(1)) For i = 2 To 4 If LastRow < UBound(List(i)) Then LastRow = UBound(List(i)) End If Next For i = 2 To Ws1.Cells(Rows.Count, "J").End(xlUp).Row mTotal(1) = 0 mTotal(2) = 0 mTotal(3) = 0 mTotal(4) = 0 For j = Columns("J").Column To Columns("BB").Column Step 3 For k = 2 To LastRow If UBound(List(1)) >= k Then If Ws1.Cells(i, j).Value = List(1)(k, 1) Then mTotal(1) = mTotal(1) + Ws1.Cells(i, j).Offset(0, 2).Value Exit For End If End If If UBound(List(2)) >= k Then If Ws1.Cells(i, j).Value = List(2)(k, 1) Then mTotal(2) = mTotal(2) + Ws1.Cells(i, j).Offset(0, 2).Value Exit For End If End If If UBound(List(3)) >= k Then If Ws1.Cells(i, j).Value = List(3)(k, 1) Then mTotal(3) = mTotal(3) + Ws1.Cells(i, j).Offset(0, 2).Value Exit For End If End If If UBound(List(4)) >= k Then If Ws1.Cells(i, j).Value = List(4)(k, 1) Then mTotal(4) = mTotal(4) + Ws1.Cells(i, j).Offset(0, 2).Value Exit For End If End If Next Next Ws3.Cells(i, "J").Value = mTotal(1) Ws3.Cells(i, "K").Value = mTotal(2) Ws3.Cells(i, "L").Value = mTotal(3) Ws3.Cells(i, "N").Value = mTotal(4) Ws3.Cells(i, "M").Value = Ws1.Cells(i, "BC").Value Ws3.Cells(i, "O").Value = Ws1.Cells(i, "BD").Value Next Set Ws1 = Nothing Set Ws2 = Nothing Set Ws3 = Nothing End Sub 本当に何度も申し訳ございません。 お時間がある時に見て頂けると有り難いです。 どうぞ宜しくお願い致します。

  • Excel VBAで文字列の部分一致の文字列を表示

    以前、こちらで頭5文字までの一致で文字列を表示するVBAを教えて頂きました。今回はFINDなどの部分一致での文字列を表示することをしたいのですが、ご教示いただけますと幸いです。 下記はSheet1のA3に文字を5文字以内いれるとSheet2のC列からピックアップしてSheet1のA列に文字列を表示する及びSheet2のB列のデータをSheet1のC列に表示させるVBAです。 Sub Test2() Dim Ws1 As Worksheet, Ws2 As Worksheet Dim SData As String, i As Long, VRet As Variant Dim c As Range, LastRow As Long Set Ws1 = Sheets("Sheet1") Set Ws2 = Sheets("Sheet2") SData = CStr(Ws1.Range("A3").Value) If SData = "" Then Exit Sub i = 5 LastRow = Ws1.Cells(Rows.Count, "A").End(xlUp).Row If LastRow < i Then LastRow = i End If Ws1.Range(Ws1.Cells(i, "A"), Ws1.Cells(LastRow, "C")).ClearContents With Ws2 For Each c In .Range(.Cells(1, "C"), .Cells(Rows.Count, "C").End(xlUp)) VRet = InStr(1, CStr(c.Value), SData, vbTextCompare) If VRet = 1 And Len(c.Value) >= 10 Then Ws1.Cells(i, "A").Resize(1, 2).Value = c.Resize(1, 2).Value 'とりあえずSheet2のB列のデータ(C列のデータに同期したデータ)をSheet1のC列に Ws1.Cells(i, "C").Value = .Cells(c.Row, "B").Value i = i + 1 End If Next End With End Sub 宜しくお願い致します。

  • エクセル2007 参照セルの値が認識されない

    エクセル2007の環境で下記マクロを実行すると、 アクティブシートのセルA1に数字が入っている場合、Sheet1のセルA1に値を転記しても そのセルA1の値をVLOOKUP関数で参照できません。 マクロに問題があるためなのか何処に問題があるのか分からないので教えてください。 宜しくお願いいたします。 【sheet】は アクティブシートの3行目から1000行目までのA列のセルをクリックしたらセルA1に値を表示 その後、下記【モジュール】を使用し、 アクティブシートのセルA1が空白の場合、 A列の数値をSheet1のセルA1に転記し、アクティブシートのA列の数値が空白になるまで循環する。 Sheet1のセルA1の値をVLOOKUP関数で参照した内容を表示、印刷します。 ----------------------------------------------------------------- '【sheet】 Private Sub Worksheet_SelectionChange(ByVal Target As Range) With Target If .Count > 1 + IsEmpty(.Value) Then Exit Sub If Application.Intersect(.Cells, Range("A3:A1000")) Is Nothing Then Exit Sub ActiveSheet.Cells(1, 1).Value = .Value End With End Sub ----------------------------------------------------------------- '【モジュール】 Sub TEST() Dim myBtn As Integer Dim myMsg As String, myTitle As String Dim WS1 As Worksheet, WS2 As Worksheet Dim i As Long myMsg = "●●●" myTitle = "確 認" myBtn = MsgBox(myMsg, vbYesNo + vbExclamation, myTitle) If myBtn = vbYes Then Set WS1 = ActiveSheet Set WS2 = Sheet1 If WS1.Cells(1, 1).Value = "" Then With WS1 For i = 3 To 65536 If .Cells(i, 1).Value = "" Then Exit For WS2.Cells(1, 1).Value = .Cells(i, 1).Value WS2.Cells(1, 2).Value = ActiveSheet.Name 'WS2.PrintOut Copies:=1 Next i End With ElseIf WS1.Cells(1, 1).Value >= 1 Then WS2.Cells(1, 1).Value = WS1.Cells(1, 1).Value WS2.Cells(1, 2).Value = WS1.Name 'WS2.PrintOut Copies:=1 Else End If End If End Sub -----------------------------------------------------------------

  • VBAのループ処理について

    VBA(Excel2000)にて、参考書等を見て下記のコードを作成しました。 「セルA1かA10において、同じ数値が続けて入力されたら、最後のセル(一番下のセル)をB列にコピーする。」 Sub ループ() Dim a As Long With Range("a1:a10") For a = 1 To .Count - 1 If .Cells(a).value <> .Cells(a + 1).value Then .Cells(a, 2).value = .Cells(a).value End If Next .Cells(.Count, 2).value = .Cells(.Count).value End With End Sub 上記の「For idx = 1 To .Count - 1」の意味が分かりません。 よろしくお願いします。

  • VBA 値、セル操作

    お世話になります [現状] 実行させると 1列目を残して2列づつ処理をさせています Sub Macro1() Dim idxR, idxC, ptr As Integer Dim ws As Worksheet Set ws = ActiveSheet Worksheets.Add after:=ws ptr = 2 With ws .Rows(1).Copy Destination:=Range("A1") For idxR = 2 To .Range("A65536").End(xlUp).Row Cells(ptr, "A").Value = .Cells(idxR, "A").Value For idxC = 2 To 255 Step 2 If .Cells(idxR, idxC) = "" Then Exit For Else .Cells(idxR, idxC).Resize(1, 2).Copy Destination:=Cells(ptr, "B") ptr = ptr + 1 End If Next idxC Next idxR End With End Sub [判らないこと] 前7列を残して(A:G) 8列目から(H列)より9列づつ処理をさせたいのですが判らなく大変困っております。 どなたかご教授よろしくお願いします。

  • VBA 高速化

    以下のコードを改良して早く処理できるようにしたいです。素因数分解をして、素因数の数を数えるプログラムです。 Sub 素因数を数える() Application.ScreenUpdating = False Application.Calculation = xlCalculationManual Dim I As Long, j As Long, cnt As Long, wS As Worksheet, k As Long, Set wS = Worksheets("Sheet2") k = Worksheets("Sheet1").Range("A100010").End(xlUp).Row - 1 For dd = 3 To k Call aaa(Range("A" & dd)) Next dd Application.ScreenUpdating = True Application.Calculation = xlCalculationAutomatic End Sub Private Sub aaa(ByVal Target As Range) Set wS = Worksheets("Sheet2") If Intersect(Target, Range("A:A")) Is Nothing Or Target.Count > 1 Then Exit Sub With Target If Not IsNumeric(.Value) Then Exit Sub If .Value Mod 1 = 0 Then Range("D1") = .Value For I = 1 To wS.Cells(Rows.Count, "A").End(xlUp).Row Do While Cells(Rows.Count, "D").End(xlUp) Mod wS.Cells(I, 1) = 0 cnt = cnt + 1 Cells(Rows.Count, "D").End(xlUp).Offset(1) = Cells(Rows.Count, "D").End(xlUp) / wS.Cells(I, 1) Loop If Cells(Rows.Count, "D").End(xlUp) = 1 Then Exit For Next I End If .Offset(, 1) = cnt End With Range("D:D").Clear End Sub 以前教えていただいたコードを使って書きました。 どういう状況で使っているかといいますと、シート1のA列に自然数を2から順番に並べ、シート2のA列に素数を並べておき、プログラムを実行すると、B列に素数の数が表示されるという具合です。 大変役に立っていたのですが、10萬ほどのデータを扱おうとすると、自分のコンピュータでは時間がかかりすぎます。そこでコードを改良して高速化をしたいのです。 いま考えられる改良点は、 1、D列を使って行っている処理をメモリで行うようにして、セルへのアクセスを省けないか 2、aaaの5行目の、"wS.Cells(Rows.Count, "A").End(xlUp).Row"この処理を簡単な変数の処理で代用できないか ということです。他にも高速化できる方法があれば教えてください。 よろしくお願いします。

  • msgboxの表示

    A列の値とC列の値をMsgboxに表示するにはどうしたらいいのでしょうか?C列で一番高い商品とその品名A列を表示させたいのですが・・ Sub hinmei() Dim i As Long For i = 2 To Range("C65535").End(xlUp).Row Dim x As Long Dim a As Long x = Cells(i + 1, 5) If Cells(i, 5).Value < x Then a = x End If Next MsgBox a End Sub

  • 空白セルと0値を識別させたい。(VBA)

    すみません、誰か教えていただけますか。 シートの53、54、55行目にそれぞれ値入っています。 それを3行目にビジュアル的に表現させています。 55行目はセルの色で、53行目は数値があり同じ値が 続く部分の合計を出しています。 しかし、下記の記述ですと数値が0(変数D=0)の時に うまくいきません。空白セルと認識されてしまうと思います。 何か、良い方法があれば教えて頂けませんでしょうか。 宜しくお願いします。 Sub 表示() Dim a As Long Dim c As Long Dim D As Long Dim e As String Dim f As String c = 3 For a = 3 To 64 With Worksheets("Sheet1") If .Cells(53, a) <> .Cells(53, a + 1) Then .Range(.Cells(53, c), .Cells(53, a)).Select D = WorksheetFunction.Sum(Selection) e = D f = Selection(1).Offset(1, 0).Value G = Selection(1).Offset(2, 0).Value If D <> 0 Then Selection(1).Offset(-50, 0).Value = f + "//" + e .Range(.Cells(53, c), .Cells(53, a)).Offset(-50, 0).Select Selection.Interior.ColorIndex = G End If If Selection(1).Value = "" Then .Range(.Cells(53, c), .Cells(53, a)).Offset(-50, 0).Select Selection.ClearContents Selection.Interior.ColorIndex = xlNone End If c = a + 1 End If End With Next End Sub

  • Excelマクロ 複数の条件と範囲条件

    色々と自分でもやってみたのですがうまくいかないので教えて頂けたら嬉しいです。 添付画像の左側の様な伝票番号と通し番号と商品名がふってあるシートが存在します。 同じ伝票番号内で商品に「松」もしくは「梅」が含まれているときのみ、その伝票番号の最終行に「送料」の行を追加したいです。その際に通し番号も加算したものを追加します。 これが上手く作れません。 ↓とりあえず作りかけたものの変に行が挿入されるマクロを記載します。ここからの修正でうまくいくなら修正点を教えて頂けると幸いです。 Sub 更新伝票情報() Dim lastRow As Long Dim currentRow As Long Dim currentInvoice As String Dim currentNumber As Integer ' シートの最終行を取得 lastRow = Cells(Rows.Count, 1).End(xlUp).Row ' 初期値の設定 currentInvoice = Cells(2, 1).Value currentNumber = 1 ' 行ごとに処理 For currentRow = 2 To lastRow ' 伝票番号が変わった場合 If Cells(currentRow, 1).Value <> currentInvoice Then ' 新しい伝票番号の設定 currentInvoice = Cells(currentRow, 1).Value ' 通し番号をリセット currentNumber = 1 End If ' 商品名に「松」または「梅」が含まれる場合 If InStr(1, UCase(Cells(currentRow, 3).Value), UCase("松")) > 0 Or InStr(1, UCase(Cells(currentRow, 3).Value), UCase("梅")) > 0 Then ' 最終行の下に新しい行を挿入 Rows(currentRow + 1 & ":" & currentRow + 1).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove ' 通し番号を加算し、B列を更新 Cells(currentRow + 1, 2).Value = currentNumber ' C列を「送料」に更新 Cells(currentRow + 1, 3).Value = "送料" ' 通し番号を1つ加算 currentNumber = currentNumber + 1 End If Next currentRow End Sub

  • VBA どこでもセル選択

    教えて頂いたVBAなのですがもう一つ Sub Macro1() Dim Ws01 As Worksheet Dim Counter As Long, i As Long, j As Long Dim INP As String Set wS = Worksheets("Sheet4") wS.Cells.ClearContents For i = 3 To ActiveSheet.UsedRange.Rows.Count INP = "" For j = Selection(1).Column To Selection(Selection.Count).Column If Cells(i, j) = 1 Then INP = INP & Cells(2, j) & "," End If Next j Counter = Counter + 1 If INP <> "" Then wS.Cells(Counter, "A") = Left(INP, Len(INP) - 1) End If Next i End Sub -------------------------------------------------------------- For i = 3 のところを3としないでどのセル(行)にも対応させたいのですが どうすればいいでしょうか?