『シートにまたがるデータの平均を求めるマクロは』(Noz)
1月〜12月までの12枚のシートがあり、そこには日付とその日の売り上げを入力します(Aのセルには日 Bのセルにはその日の売り上げ)
そして13枚目のシートに任意の10日間の売り上げ平均を表示したいと考えています。同じ月内(同一シート)の10日間の平均を求める場合と次の月(次のシート)にまたがる10日間(たとえば10月25日から11月3日までの10日間の平均)がありますが、これを表示できるマクロを教えてください。
よろしくお願いします。
< 使用 Excel:Excel2021、使用 OS:Windows11 >
1日目と10日目が同じ月か
SUMIFS関数で1〜10日目の合計値を求めて10で割る
ちがうなら
SUMIFS関数で1日目の月のシートを対象に1〜10日目の合計値を求める
SUMIFS関数で10日目の月のシートを対象に1〜10日目の合計値を求める
上記を合算して10で割る
分岐処理終了
結果出力
上記のような感じで考えればよいとおもいます。
(マクロ以外だったらもっと妙案ありそうですが、思いつきませんでした。)
(もこな2) 2025/10/31(金) 08:20:35
関数なら
=LET(sday,DATEVALUE("2025/10/4"),eday,DATEVALUE("2025/10/14"),
AVERAGE(
FILTER('1月'!B:B,('1月'!A:A>=sday)*('1月'!A:A<=eday),""),
FILTER('2月'!B:B,('2月'!A:A>=sday)*('2月'!A:A<=eday),""),
・
・
・
FILTER('12月'!B:B,('2月'!A:A>=sday)*('12月'!A:A<=eday),"")
)
)
と、シートの分だけFILTER関数を使うとできそうです。
2021なので便利な関数が使えないのが痛いですね。
マクロなら地道にセルの値を拾っていけば良さそう (´・ω・`) 2025/10/31(金) 11:04:38
雰囲気はこんな感じですが、B列が空だと0として扱われるので、AVERAGE関数とはちょっと違います。
Function Average10Days(sday As Date)
Dim eday As Date
Dim S As Double, Ccount As Double
eday = sday + 10
S = 0
For m = 1 To 12
With Worksheets(Format(m, "0月"))
For r = 1 To 40
If .Cells(r, 1) >= sday And .Cells(r, 1).Value <= eday Then
S = S + .Cells(r, 2)
count = count + 1
End If
Next
End With
Next
Average10Days = S / count
End Function
(´・ω・`) 2025/10/31(金) 11:25:53
質問の例:「10月25日から11月3日までの10日間の平均」
で考えてみます。
1、平均を表示するシートに日付(いつから)と日付(いつまで)を入力する 2、日付(いつから)と日付(いつまで)の間が何日あるか計算しておく(今回の例ではは10日) 3、日付(いつから)、10日間を足して月末日付を超える場合、日付(いつから)から月末まで何日あるか計算しておく 4、10日間−(日付(いつから)から月末まで何日あるか)で翌月の何日分を取ればよいか計算しておく 5、日付(いつから)の月のシートを選択する 6、日付(いつから)の日のセルを選択する 7、その日から10日分のB列(売り上げ)をのセルを選択する ただし、日付(いつから)から10日分が月末日付を超える場合、3で計算された分の売り上げを足す 8、日付(いつから)から10日分が月末日付を超える場合、次の月のシートを選択する 9、日付(いつから)から10日分が月末日付を超える場合、次の月の4で計算された日数分の売り上げを足す 10、足された売り上げを2で計算された日数(今回は10日間)で割る
という感じです。
これってExcelのスキルとしては、シートの選択、セルの選択、セルの範囲を指定する
というくらいですよね。
>「初心者に毛がはえた程度」
でも可能ですよね。
そして、これら1つずつをVBAのコードで書いてみる。
2でつまづいているのなら、2の部分だけを質問してみる。
2がうまくいったら3をやってみる。
3でつまづいたら、また3の部分だけを質問してみる
・
・
・
という様にやってみてください。
そうすれば、自分がどこでつまづいているか明確になりますし、
まず日本語で箇条書きにするという習慣をつけてみてください。
こんなことを繰り返していると、自然とある程度できるようになりますよ。
(匿名) 2025/10/31(金) 13:51:32
また、完成していなくとも現状のコードを示していただくことで、シートの構成などがわかったり、どの辺を勘違いされているのかわかったりします。
なので、何らかの着手をされているのであれば、コードを示した上で、〜〜になるはずが〜〜になってしまうなど具体的な説明をされた方が、回答者とのキャッチボールが少なくなると思います。
■2
今回のケースで気になるところは「Aのセルには日」と表現されているところです。
A列が"日付"(年月の情報を含んでいる)のであれば話は単純で、
=SUMIFS('1月'!B1:B31, '1月'!A1:A31, ">="&A1, '1月'!A1:A31, "<"&A1+10)
=SUMIFS('2月'!B1:B31, '2月'!A1:A31, ">="&A1, '2月'!A1:A31, "<"&A1+10)
・
・
のような感じで、ほかの月シートにダブって存在するわけ無いので、一旦各月シートでSUMIFS関数で合計を求め、さらにその合計を求めてから10で割ればよいでしょう
■3
そうで無くて、日だけ(年月の情報が含まれない)ならば、先に示したようにどの月を見ればよいか特定した上で、最大で2つのシートの合計を出した上で10で割ればよいでしょう
■4
いずれにせよ、勉強しながらやってみるということなので、とりあえず手を付けてみて、うまくいかなければ、コード(と必要に応じてデータ例)を示して質問されるとよいと思います。
(もこな2) 2025/11/02(日) 16:33:51
自分で学習・実装するのであればそちら優先ください。 中身は完全に理解できなくとも機能が実現できれば良いという場合は御参考に。
AIの回答と書けというARA5H1もいるので、一応AI回答ですと明記します。 --------------------------------- 以下に「1月〜12月」までのシート(名前が「1月」「2月」…「12月」)に、 それぞれ A列=日付、B列=売上 がある前提で、 「13枚目のシート」(名前は「平均計算」など)において、 任意の開始日と10日間平均の売上を表示するVBAマクロ を示します。
🔧 マクロの概要 「平均計算」シートに セルB1:開始日(例:2025/10/25) セルB2:平均日数(例:10) セルB3:計算結果(売上平均値)が表示される
各月シート(1月〜12月)に A列:日付(例:2025/10/1 のように日付型で入力)
B列:売上 期間が月をまたいでも自動で平均計算します。
💻 VBAコード
Sub 平均売上計算()
Dim wsAvg As Worksheet
Dim ws As Worksheet
Dim dStart As Date
Dim dEnd As Date
Dim total As Double
Dim count As Long
Dim i As Long
Dim monthName As String
Dim d As Date
Dim val As Variant
' 平均計算シートを指定
Set wsAvg = ThisWorkbook.Sheets("平均計算")
' 開始日と日数を取得
dStart = wsAvg.Range("B1").Value
dEnd = dStart + wsAvg.Range("B2").Value - 1
total = 0
count = 0
' 開始日から終了日まで繰り返し
For d = dStart To dEnd
' 月名(シート名)を取得(例:10月)
monthName = Month(d) & "月"
' 対応する月シートが存在する場合のみ処理
On Error Resume Next
Set ws = ThisWorkbook.Sheets(monthName)
On Error GoTo 0
If Not ws Is Nothing Then
' 該当日付を検索
For i = 1 To ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
If ws.Cells(i, "A").Value = d Then
val = ws.Cells(i, "B").Value
If IsNumeric(val) And Not IsEmpty(val) Then
total = total + val
count = count + 1
End If
Exit For
End If
Next i
End If
Set ws = Nothing
Next d
' 平均を出力
If count > 0 Then
wsAvg.Range("B3").Value = total / count
Else
wsAvg.Range("B3").Value = "データなし"
End If
End Sub
🧭 使い方 シート名を確認 各月のシート名を「1月」「2月」…「12月」にしておきます。 平均計算シートを作成し、B1に開始日、B2に日数を入力。 例: B1:2025/10/25 B2:10
VBAエディタ(Alt + F11)で新しいモジュールを挿入し、上のコードを貼り付けます。 実行(F5)すると、B3に平均値が出ます。
✅ 補足 開始日や日数を変えれば、どんな範囲でも対応可能です。 日付は 正しい日付型(2025/10/25 など)で入力してください。
10日間のうち売上が未入力の日があっても、自動で除外されます。 月をまたいでも自動で次の月シートを参照します。
ご希望があれば、 「平均値のほかに合計も出す」 「B3以降に履歴として複数行で結果を出す」 などに対応した拡張版も作れます。
どちらの形にしたいですか?
おまけ シート名に依存しているので、以下、テストデータを作成するマクロです。 白紙で作成したEXCELに下記のマクロを置き、CreateMonthlySheetsを実行で、上のマクロを実行する準備ができます。
Sub CreateMonthlySheets()
Dim ws As Worksheet
Dim monthName As String
Dim i As Long, d As Long
Dim daysInMonth As Long
Dim startDate As Date
Application.ScreenUpdating = False
Set ws = CreateSheet("平均計算")
ws.Range("A1:A3") = WorksheetFunction.Transpose(Array("開始日", "日数", "平均値"))
' 1月〜12月のシートを作成
For i = 1 To 12
Set ws = CreateSheet (i & "月")
' その月の初日と末日を取得
startDate = DateSerial(Year(Date), i, 1)
daysInMonth = Day(DateSerial(Year(Date), i + 1, 0))
' 見出し行
ws.Range("A1").Value = "日"
ws.Range("B1").Value = "売上(乱数)"
ws.Range("A1:B1").Font.Bold = True
' A列に日付、B列に乱数を設定
For d = 1 To daysInMonth
ws.Cells(d + 1, 1).Value = startDate + d - 1
ws.Cells(d + 1, 2).Value = Int((100000 - 10000 + 1) * Rnd + 10000)
Next d
' 列幅調整
ws.Columns("A:A").NumberFormatLocal = "YYYY/MM/DD"
ws.Columns("A:B").AutoFit
Next i
Application.ScreenUpdating = True
MsgBox "1月〜12月と集計シートを作成しました!", vbInformation
End Sub
Function CreateSheet(wsName) As Worksheet
On Error Resume Next
Application.DisplayAlerts = False
Worksheets(wsName).Delete
Application.DisplayAlerts = True
On Error GoTo 0
Set CreateSheet = Worksheets.Add(After:=Sheets(Sheets.count))
CreateSheet.Name = wsName
End Function
自分で回答しないのか、という話もありましたが、 後ろのおまけはAI回答を少しアレンジしました。 といってもシート作成機能の関数化と集計シートの追加だけですが。 (英愛) 2025/11/08(土) 13:31:20
課題として棚上げされてしまったようで残念です。 メモしておいたものを供養のため投稿しておきます。南無。
Sub test()
Dim 開始日 As Date, 終了日 As Date
Dim 日数 As Long
Dim ws As Worksheet, wsNext As Worksheet
Dim startRng As Range
Dim rng1 As Range, rng2 As Range
Dim days1 As Long
Dim sum1 As Long, sum2 As Long
Dim count1 As Long, count2 As Long
Dim averageAmount As Double
開始日 = Worksheets("計算").Range("A1")
終了日 = Worksheets("計算").Range("A2")
日数 = 終了日 - 開始日 + 1
Set ws = Worksheets(Month(開始日) & "月")
Set startRng = ws.Cells(Day(開始日), "A")
days1 = Application.EoMonth(開始日, 0) - 開始日 + 1
If days1 >= 日数 Then '(1)10日間以上であれば、10日間の売上の合計を求める
Set rng1 = startRng.Offset(0, 1).Resize(日数, 1)
sum1 = Application.SUMIF(rng1, "<>""""") '単にSUMを使用しても結果は同じ
count1 = Application.COUNT(rng1)
averageAmount = sum1 / count1
Else '(2)10日に満たない場合は、当月末までの売上合計と翌月分を加算して平均を求める
Set wsNext = Worksheets(Month(終了日) & "月") '存在チェックは省略
Set rng1 = startRng.Offset(0, 1).Resize(days1, 1)
sum1 = Application.SUMIF(rng1, "<>""""")
count1 = Application.COUNT(rng1)
Set rng2 = wsNext.Range("B1").Resize(日数 - days1, 1)
sum2 = Application.SUMIF(rng2, "<>""""")
count2 = Application.COUNT(rng2)
averageAmount = (sum1 + sum2) / (count1 + count2)
End If
Worksheets("計算").Range("A3") = averageAmount
End Sub
(xyz) 2025/11/08(土) 15:52:59
私も、既に提案した方法も含めて3案ほど披露しておきます。
Sub 研究用1()
'「■2」のアプローチ 全シートを巡回
Dim シート番号 As Long
Dim 開始日 As Date
Dim buf As Double '売上だから整数?
開始日 = Worksheets(13).Range("A1").Value
Stop 'ブレークポイントの代わり
For シート番号 = 1 To 12
With Worksheets(シート番号)
buf = buf + WorksheetFunction.SumIfs(.Range("B2:B1000"), .Range("A2:A1000"), ">=" & 開始日, .Range("A2:A1000"), "<" & 開始日 + 10)
End With
Next シート番号
Worksheets(13).Range("A2").Value = buf / 10
End Sub
'=====================================================================================================
Sub 研究用2()
'「■3」のアプローチ 最大2つのシートを巡回
Dim MyArr As Variant
Dim SH As Worksheet
Dim 開始日 As Date
Dim buf As Double '売上だから整数?
開始日 = Worksheets(13).Range("A1").Value
If Month(開始日) = Month(開始日 + 9) Then
MyArr = Array(Month(開始日) & "月")
Else
MyArr = Array(Month(開始日) & "月", Month(開始日 + 9) & "月")
End If
Stop 'ブレークポイントの代わり
For Each SH In Worksheets(MyArr)
buf = buf + WorksheetFunction.SumIfs(SH.Range("B2:B1000"), SH.Range("A2:A1000"), ">=" & 開始日, SH.Range("A2:A1000"), "<" & 開始日 + 10)
Next SH
Worksheets(13).Range("A3").Value = buf / 10
End Sub
'=====================================================================================================
Sub 研究用3()
'別案 10日間のうち稼働日のみ
Dim Mydic As Object
Dim シート番号 As Long
Dim データ行 As Long
Dim 開始日 As Date, MyDate As Date
Set Mydic = CreateObject("Scripting.Dictionary")
開始日 = Worksheets(13).Range("A1").Value
Stop 'ブレークポイントの代わり
For シート番号 = 1 To 12
With Worksheets(シート番号)
For データ行 = 2 To .Cells(.Rows.Count, "A").End(xlUp).Row
If .Cells(データ行, "A").Value >= 開始日 And .Cells(データ行, "A").Value < 開始日 + 10 Then
MyDate = Int(.Cells(データ行, "A").Value)
If Mydic.Exists(MyDate) Then
Mydic(MyDate) = Mydic(MyDate) + .Cells(データ行, "B").Value
Else
Mydic.Add MyDate, .Cells(データ行, "B").Value
End If
End If
Next データ行
End With
Next シート番号
Worksheets(13).Range("A4").Value = WorksheetFunction.Sum(Mydic.Items) / Mydic.Count
End Sub
(もこな2) 2025/11/18(火) 21:54:56
Dim ws As Worksheet
Dim wsResult As Worksheet
Dim startDate As Date, endDate As Date
Dim sumSales As Double, sumExpense As Double, sumProfit As Double
Dim cnt As Long
Dim lastRow As Long
Dim i As Long
Set wsResult = ThisWorkbook.Sheets("各平均")
startDate = wsResult.Range("C2").Value
endDate = wsResult.Range("C3").Value
sumSales = 0
sumExpense = 0
sumProfit = 0
cnt = 0
For Each ws In ThisWorkbook.Sheets
If ws.Index <= 12 Then
lastRow = ws.Cells(ws.Rows.count, "A").End(xlUp).Row
For i = 3 To lastRow
If IsDate(ws.Cells(i, "A").Value) Then
If ws.Cells(i, "A").Value >= startDate And ws.Cells(i, "A").Value <= endDate Then
sumSales = sumSales + ws.Cells(i, "B").Value
sumExpense = sumExpense + ws.Cells(i, "C").Value
sumProfit = sumProfit + ws.Cells(i, "D").Value
cnt = cnt + 1
End If
End If
Next i
End If
Next ws
If cnt > 0 Then
wsResult.Range("C4").Value = sumSales / cnt
wsResult.Range("C5").Value = sumExpense / cnt
wsResult.Range("C6").Value = sumProfit / cnt
Else
wsResult.Range("C4").Value = "該当データなし"
wsResult.Range("C5").Value = ""
wsResult.Range("C6").Value = ""
End If
End Sub
(N) 2025/11/21(金) 11:04:50
私が前に挙げた例で説明します。
1、平均を表示するシートに日付(いつから)と日付(いつまで)を入力する 2、日付(いつから)と日付(いつまで)の間が何日あるか計算しておく(今回の例ではは10日) 3、日付(いつから)、10日間を足して月末日付を超える場合、日付(いつから)から月末まで何日あるか計算しておく 4、10日間−(日付(いつから)から月末まで何日あるか)で翌月の何日分を取ればよいか計算しておく 5、日付(いつから)の月のシートを選択する 6、日付(いつから)の日のセルを選択する 7、その日から10日分のB列(売り上げ)をのセルを選択する ただし、日付(いつから)から10日分が月末日付を超える場合、3で計算された分の売り上げを足す 8、日付(いつから)から10日分が月末日付を超える場合、次の月のシートを選択する 9、日付(いつから)から10日分が月末日付を超える場合、次の月の4で計算された日数分の売り上げを足す 10、足された売り上げを2で計算された日数(今回は10日間)で割る
1は都度手入力するものなので、コードはいりません。
2は、例えば、
「A1(いつから)とB1(いつまで)の間が何日あるか計算した結果をC1に表示する」
というコードを自分で調べながら書いてみてください。
【例】これは普段の私の欠き方とは違いますが、あえて「わかりやすく」書いてみました
Dim dateFrom As Date Dim dateTo As Date Dim ret As Long
dateFrom = Cells(1, 1).Value dateTo = Cells(1, 2).Value
ret = dateTo - dateFrom Cells(1, 3).Value = ret
3は、C1の値に10日を足したものをD1に表示して、E1にA1から月末まで何日あるか計算した結果をF1に表示する
・
・
・
という様に1つずつ書いていく方法がよいと思います。
1つ1つコードを書こうとして、わからなければ、
このような掲示板に1つずつ質問していく。
これを繰り返すうちにVBAのコーディングができるようになると思います。
・・・
なので
「自分が手作業ですることを箇条書きで書き上げてみてください」
という事を例を挙げて説明したのです。
(匿名) 2025/11/21(金) 12:27:21
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.