質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Q&A

解決済

4回答

405閲覧

VBAで、複数行あるカテゴリーごとの合計値の算出ができない

Shin_go

総合スコア20

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

0グッド

0クリップ

投稿2025/04/22 22:28

実現したいこと

イメージ説明

大項目ごとの合計数字を代入したい。該当する列に。
添付の画像の①30行目と②40行目のカテゴリー別の合計行に、①には、23行目と29行目の小項目の合計を、②には、33行目と39行目の小項目の合計を該当する列に代入したい。
小項目の合計だけをうまく取得して、カテゴリー別の合計行に代入できないかと考えています。

発生している問題・分からないこと

イメージ説明

<困っていること>
合計する行は固定の行ではないので、「合計」という文字列のある行を取得して、合計するようにしていますが、
①だけならうまくいくのですが、
②の合計を算出する際に、①の下の行からカウントしなければならないのですが(1行目からだと二重計上になるため)、それがうまくいきません。
なぜか、②の行には0が代入されてしまいます。

該当のソースコード

※試しに以下のコードで一つの列で合計値を出したのですが、問題なく算出され代入されます。 Sub CalculateSpecificSum() Dim ws As Worksheet Dim lastRow As Long Dim sumRow As Long Dim totalSum As Double Dim currentRow As Long ' シートを指定 Set ws = ThisWorkbook.Sheets("収益状況") ' 合計値を初期化 totalSum = 0 ' A列の最初の「合計」行を取得 sumRow = ws.Columns("A").Find(What:="合計", LookAt:=xlPart, MatchCase:=False).Row ' A列の「合計」行までループ For currentRow = 6 To sumRow - 1 ' 合計行の直前まで ' B列が「合計」の場合のみ処理 If ws.Cells(currentRow, "B").value Like "*合計*" Then ' 12列目(L列)の値を加算 totalSum = totalSum + ws.Cells(currentRow, 12).value End If Next currentRow ' 合計値をA列の「合計」行のL列に代入 ws.Cells(sumRow, 12).value = totalSum MsgBox "指定された合計の計算が完了しました!", vbInformation End Sub ※以下は、各列ごとに合計値を算出するようにしているはずなのですが、0となり算出されません。 Sub ProcessRevenueSums() Dim ws As Worksheet Dim sumRow As Long Dim totalSum As Double Dim currentRow As Long Dim colIndex As Variant Dim sumColumns As Variant ' シートを指定 Set ws = ThisWorkbook.Sheets("収益状況") ' 合計する列を指定 sumColumns = Array(12, 13, 14, 18, 19, 20, 21, 24, 25, 26, 27, 28, 29, 30, _ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48) ' A列の最初の「合計」行を取得 sumRow = ws.Columns("A").Find(What:="合計", LookAt:=xlPart, MatchCase:=False).Row ' 各列を順次処理 For Each colIndex In sumColumns ' 合計値を初期化 totalSum = 0 ' A列の「合計」行までの範囲をループ For currentRow = 6 To sumRow - 1 ' 合計行の直前まで ' B列が「合計」の場合のみ処理 If ws.Cells(currentRow, "B").value Like "*合計*" Then ' 該当列の値を加算 totalSum = totalSum + ws.Cells(currentRow, colIndex).value End If Next currentRow ' 合計値をA列の「合計」行に代入 ws.Cells(sumRow, colIndex).value = totalSum Next colIndex MsgBox "指定された列に順次合計を代入しました!", vbInformation End Sub

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

上記に記載のとおりですが、どうしてもうまくいきません。
Excelの関数でしたら実現できると思うのですが、該当する行が変わるので、その都度入力する手間もかかるため、VBAで実現できないかと考えています。
どなたか力を貸していただければ幸いです。
よろしくお願いいたします。

補足

特になし

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2025/04/23 00:13

もう少し簡素な例で説明できませんか?何をどうしたいかかなり分かりづらいです
Shin_go

2025/04/30 03:25

ご指摘いただきましてありがとうございました。わかりずらく申し訳ございません。 他の方の回答で対応することができました。 またご意見などいただけますと幸いです。
meg_

2025/04/30 05:15

> 他の方の回答で対応することができました。 解決されたとのことで良かったです。 ベストアンサーを選んで質問をクローズしてください。
guest

回答4

0

Excelの関数でしたら実現できると思うのですが

vba

1Sub SetFormulaCells() 2 3 Const targetSuffix = "合計" 4 5 Dim ws As Worksheet 6 7 Set ws = ThisWorkbook.Sheets("収益状況") 8 9 Dim firstRow As Long 10 Dim lastRow As Long 11 12 With ws 13 firstRow = 6 14 lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row 15 16 If firstRow > lastRow Then 17 Set ws = Nothing 18 Exit Sub 19 End If 20 21 End With 22 23 Dim targetColumns As Variant 24 25 targetColumns = Array(Array(12, 14), _ 26 Array(18, 21), _ 27 Array(24, 30), _ 28 Array(34, 48)) 29 30 Dim currentRow As Long 31 Dim rowHeader1 As Excel.Range 32 Dim rowHeader2 As Excel.Range 33 Dim groupName1 As String 34 Dim groupName2 As String 35 Dim targetColumn As Variant 36 Dim sumRange As String 37 Dim criteriaRange1 As String 38 Dim criteria1 As String 39 Dim criteriaRange2 As String 40 Dim criteria2 As String 41 Dim formulaRange As Excel.Range 42 Dim formulaString As String 43 44 Application.Calculation = xlCalculationManual 45 46 For currentRow = firstRow To lastRow 47 48 groupName1 = "" 49 groupName2 = "" 50 51 Set rowHeader1 = ws.Cells(currentRow, "A") 52 Set rowHeader2 = ws.Cells(currentRow, "B") 53 54 If rowHeader1.Value Like ("*" & targetSuffix) Then 55 56 groupName1 = Left(rowHeader1.Value, Len(rowHeader1.Value) - Len(targetSuffix)) 57 groupName2 = "*" & targetSuffix 58 59 criteria1 = "LEFT(" & rowHeader1.Address(False, True) & "," & _ 60 "LEN(" & rowHeader1.Address(False, True) & ")" & _ 61 "-" & Len(targetSuffix) & ")" 62 criteria2 = """*" & targetSuffix & """" 63 64 ElseIf rowHeader2.Value Like ("*" & targetSuffix) Then 65 groupName1 = rowHeader1.Value 66 groupName2 = Left(rowHeader2.Value, Len(rowHeader2.Value) - Len(targetSuffix)) 67 68 criteria1 = rowHeader1.Address(False, True) 69 criteria2 = "LEFT(" & rowHeader2.Address(False, True) & "," & _ 70 "LEN(" & rowHeader2.Address(False, True) & ")" & _ 71 "-" & Len(targetSuffix) & ")" 72 End If 73 74 If groupName1 <> "" And groupName2 <> "" Then 75 76 Debug.Print "グループ1: " & groupName1 77 Debug.Print "グループ2: " & groupName2 78 79 criteriaRange1 = rowHeader1.EntireColumn.Address(True, True) 80 criteriaRange2 = rowHeader2.EntireColumn.Address(True, True) 81 82 For Each targetColumn In targetColumns 83 84 Set formulaRange = ws.Range(ws.Cells(currentRow, targetColumn(0)), _ 85 ws.Cells(currentRow, targetColumn(1))) 86 87 sumRange = ws.Columns(targetColumn(0)).Address(False, False) 88 89 formulaString = "=SUMIFS(" & sumRange & "," & _ 90 criteriaRange1 & "," & _ 91 criteria1 & "," & _ 92 criteriaRange2 & "," & _ 93 criteria2 & ")" 94 95 Debug.Print vbTab & "数式セル範囲: " & formulaRange.Address(False, False) 96 Debug.Print vbTab & "設定する数式: " & formulaString 97 98 formulaRange.Formula = formulaString 99 100 Set formulaRange = Nothing 101 Next 102 103 End If 104 105 Set rowHeader1 = Nothing 106 Set rowHeader2 = Nothing 107 108 Next 109 110 Application.Calculation = xlCalculationAutomatic 111 112 Set ws = Nothing 113 114End Sub

投稿2025/04/23 10:35

sk.exe

総合スコア1070

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Shin_go

2025/05/01 04:50

回答ありがとうございます。 ベストアンサーは別の方を選ばせていただきましたが、こちらの回答も非常に参考になりました。
guest

0

ベストアンサー

A列の合計セルをFindで探していますが、Findは最初に一致したセルしか探しません。次のセルを探すには、FindNextを使います。この2つのメソッドを使ってループさせるのことになります。(下記参照)

【VBA入門】Find、FindNextで検索(完全一致、部分一致、複数一致)

ただし、このメソッドは遅いし、複雑なコードになります。
B列はFor ... Next でループして1セルずつチェックしているので、A列も同様にチェックすれば一つのループですみシンプルなコードになります。
つまり、下記のような考え方になります。
ループ処理で先頭行から順に行移動
B列に「合計」が含まれるなら集計列の値を変数に加算、
A列が「合計」なら集計列のセルに出力、変数は0にリセット

ということで、まず、CalculateSpecificSum は下記のようなコードになります。

vba

1Sub CalculateSpecificSum() 2 Dim ws As Worksheet 3 Dim lastRow As Long 4 Dim totalSum As Currency 5 Dim currentRow As Long 6 7 ' シートを指定 8 Set ws = ThisWorkbook.Sheets("収益状況") 9 10 ' 合計値を初期化 11 totalSum = 0 12 13 ' A列の最終行を取得 14 lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row 15 16 ' A列の最終行までループ 17 For currentRow = 6 To lastRow 18 ' B列が「合計」の場合 19 If ws.Cells(currentRow, "B").Value Like "*合計*" Then 20 ' 12列目(L列)の値を加算 21 totalSum = totalSum + ws.Cells(currentRow, 12).Value 22 ' A列が「合計」の場合 23 ElseIf ws.Cells(currentRow, "A").Value Like "*合計*" Then 24 ' 合計値をA列の「合計」行のL列に代入 25 ws.Cells(currentRow, 12).Value = totalSum 26 totalSum = 0 27 End If 28 Next currentRow 29 30 MsgBox "指定された合計の計算が完了しました!", vbInformation 31End Sub

※ちなみに、totalSum は浮動小数点数型(Double)で宣言していますが、 浮動小数点数は演算誤差が出るので、集計するなら整数ならLong型、小数も含むならCurrency型で宣言するべきです。


ProcessRevenueSums は複数列の集計を格納する必要があるので、配列変数に集計値を格納するようにします。
あとは上のコードと同様の考え方でワンループで順次処理します。

vba

1Sub ProcessRevenueSums() 2 Dim ws As Worksheet 3 Dim LastRow As Long 4 Dim totalSums() As Long 5 Dim currentRow As Long 6 Dim aryIndex As Long 7 Dim sumColumns As Variant 8 9 ' シートを指定 10 Set ws = ThisWorkbook.Sheets("収益状況") 11 12 ' 合計する列を指定 13 sumColumns = Array(12, 13, 14, 18, 19, 20, 21, 24, 25, 26, 27, 28, 29, 30, _ 14 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48) 15 ' 各列の合計値を格納する配列を初期化 16 ReDim totalSums(UBound(sumColumns)) 17 18 ' A列の最終行を取得 19 LastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row 20 21 ' A列の最終行までループ 22 For currentRow = 6 To LastRow 23 ' B列が「合計」の場合 24 If ws.Cells(currentRow, "B").Value Like "*合計*" Then 25 ' 各列の集計に加算 26 For aryIndex = 0 To UBound(sumColumns) 27 totalSums(aryIndex) = totalSums(aryIndex) + ws.Cells(currentRow, sumColumns(aryIndex)).Value 28 Next aryIndex 29 ElseIf ws.Cells(currentRow, "A").Value Like "*合計*" Then 30 ' 各列を集計をセルに出力 31 For aryIndex = 0 To UBound(sumColumns) 32 ws.Cells(currentRow, sumColumns(aryIndex)).Value = totalSums(aryIndex) 33 totalSums(aryIndex) = 0 34 Next aryIndex 35 End If 36 Next currentRow 37 38 MsgBox "指定された列に順次合計を代入しました!", vbInformation 39End Sub

Excelの関数でしたら実現できると思うのですが、該当する行が変わるので、その都度入力する手間もかかるため、VBAで実現できないかと考えています。

VBAで集計関数(SUMIF)を使った数式を生成してセルに代入するサンプルコードも置いておきます。

vba

1Public Sub SetSumFormula() 2 Dim ws As Worksheet 3 Set ws = ThisWorkbook.Sheets("収益状況") 4 5 Dim LastRow As Long ' A列の最終行 6 LastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row 7 8 Dim SumCells As Range ' 集計セル 9 Set SumCells = ws.Range("L1:N1,R1:U1,X1:AD1,AH1:AV1") 10 11 Const conFormula = "=SUMIF($B#1:$B#2,""*合計*"",L#1:L#2)" '集計数式テンプレート, #1=集計開始行,#2=集計最終行 12 13 Application.Calculation = xlCalculationManual 14 15 Dim beginRow As Long '集計開始行 16 beginRow = 6 17 Dim currentRow As Long 18 For currentRow = 6 To LastRow 19 If ws.Cells(currentRow, "A").Value Like "*合計*" Then 20 With SumCells.Offset(currentRow - 1) 21 .Value = Replace(Replace(conFormula, "#1", beginRow), "#2", currentRow - 1) 22 End With 23 beginRow = currentRow + 1 24 End If 25 Next currentRow 26 27 Application.Calculation = xlCalculationAutomatic 28 29 MsgBox "指定された列に順次集計式を設定しました!", vbInformation 30End Sub

投稿2025/04/23 03:24

編集2025/04/24 14:52
hatena19

総合スコア34352

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Shin_go

2025/05/01 04:51

回答ありがとうございます。 試したところ問題が解決しました! 丁寧に解説やご参考情報もいただきまして、とても勉強になりました。 ベストアンサーに選ばせていただきました。
guest

0

B列の文字に”合計”がある行の値を加算して、A列の文字に”合計”がある行に加算したい。
対象となる列は、12,13,14,途中省略,46,47,48列である。
と解釈しました。
以下のようにしてください。

VBA

1Option Explicit 2 3Public Sub 合計算出() 4 Dim ws As Worksheet 5 Dim lastRow As Long 6 Dim startRow As Long 7 Dim wrow As Long 8 Dim sumColumns As Variant 9 ' シートを指定 10 Set ws = ThisWorkbook.Sheets("収益状況") 11 ' 合計する列を指定 12 sumColumns = Array(12, 13, 14, 18, 19, 20, 21, 24, 25, 26, 27, 28, 29, 30, _ 13 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48) 14 lastRow = ws.Cells(Rows.Count, "A").End(xlUp).Row 15 startRow = 6 16 For wrow = 6 To lastRow 17 If ws.Cells(wrow, "A").Value Like "*合計*" Then 18 Call set_total(ws, startRow, wrow, sumColumns) 19 startRow = wrow + 1 20 End If 21 Next 22 MsgBox "指定された合計の計算が完了しました!", vbInformation 23End Sub 24'指定範囲の合計を算出し、A列合計行に設定する 25Private Sub set_total(ByRef ws As Worksheet, ByVal startRow As Long, ByVal sumRow As Long, ByRef sumColumns As Variant) 26 Dim colIndex As Variant 27 Dim totalSum As Double 28 Dim currentRow As Long 29 ' 各列を順次処理 30 For Each colIndex In sumColumns 31 ' 合計値を初期化 32 totalSum = 0 33 34 ' A列の「合計」行までの範囲をループ 35 For currentRow = startRow To sumRow - 1 ' 合計行の直前まで 36 ' B列が「合計」の場合のみ処理 37 If ws.Cells(currentRow, "B").Value Like "*合計*" Then 38 ' 該当列の値を加算 39 totalSum = totalSum + ws.Cells(currentRow, colIndex).Value 40 End If 41 Next currentRow 42 43 ' 合計値をA列の「合計」行に代入 44 ws.Cells(sumRow, colIndex).Value = totalSum 45 Next colIndex 46 47End Sub 48

投稿2025/04/23 02:07

編集2025/04/23 02:09
tatsu99

総合スコア5533

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Shin_go

2025/05/01 04:51

回答ありがとうございます。 ベストアンサーは別の方を選ばせていただきましたが、こちらの回答も非常に参考になりました。 大変助かりました、ありがとうございました。
guest

0

こういうことですよね?

VBA

1Sub Calc() 2 Dim ws As Worksheet 3 Dim i As Long 4 Dim R As Long 5 Dim C As Variant 6 Dim Total() As Variant 7 Dim Subtotal() As Variant 8 9 ' シートを指定 10 Set ws = ThisWorkbook.Sheets("収益状況") 11 12 ' 合計する列を指定 13 C = Array(12, 13, 14, 18, 19, 20, 21, 24, 25, 26, 27, 28, 29, 30, _ 14 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48) 15 16 ReDim Subtotal(UBound(C)) As Variant 17 ReDim Total(UBound(C)) As Variant 18 19 For i = LBound(C) To UBound(C) 20 Subtotal(i) = 0 21 Total(i) = 0 22 Next i 23 24 R = 6 25 With ws 26 Do While R < 41 27 For i = LBound(C) To UBound(C) 28 If InStr(.Cells(R, 1).Value, "合計") > 0 Then 29 'A列に「合計」の文字が含まれる場合 30 .Cells(R, C(i)).Value = Total(i) 31 Total(i) = 0 32 ElseIf InStr(.Cells(R, 2).Value, "合計") > 0 Then 33 'B列に「合計」の文字が含まれる場合 34 .Cells(R, C(i)).Value = Subtotal(i) 35 Total(i) = Total(i) + Subtotal(i) 36 Subtotal(i) = 0 37 Else 38 'いずれの文字が含まれない場合 39 Subtotal(i) = Subtotal(i) + .Cells(R, C(i)).Value 40 End If 41 Next i 42 R = R + 1 43 Loop 44 End With 45 46 MsgBox "指定された列に順次合計を代入しました!", vbInformation 47End Sub

投稿2025/04/23 01:10

編集2025/04/23 02:21
Black_Velvet

総合スコア116

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Shin_go

2025/05/01 04:51

回答ありがとうございます。 ベストアンサーは別の方を選ばせていただきましたが、こちらの回答も非常に参考になりました。 大変助かりました、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問