2

複数のワークシートから新しいワークシートへの特定の範囲 (「C2:C11」) の平均を計算する必要があります。新しいシートが追加され、データが指定された範囲に入力された場合、関数は引き続き機能するはずです。

これまでのところ、私はこれを持っています

....

Sheets.Add

Dim myavg As Collection
Set myavg = New Collection

For Each wsheet In Worksheets
   myavg.Add wsheet.Range("B2:B11")
Next    
For i = 1 To myavg.Count
   avg1 = Application.WorksheetFunction.Average(Range("B2:B11"))
Next

curColumn = 5
curRow = 4

For i = 1 To myavg.Count
   ActiveSheet.Cells(curRow, curColumn).Value = avg1
   curRow = curRow + 1
Next  

...

新しいシートの目的の範囲に1つの数値を返しますが、正確ではありません

私が間違っていることを理解するのを手伝ってください。前もって感謝します。

4

1 に答える 1

2

Collectionaがこのタスクに適しているかどうかはさておき、コードを調べてみましょう。

一般あなたはすでにこれを行っているかもしれませんが、それはあなたのすべての変数を 使用し
てデカールすることを繰り返すことを保証します
Option Explicit

あなたのコード

Sheets.Add

これによりWorksheet、アクティブWorkbookにnewが追加され、現在アクティブなシートの前に配置されてから、新しいシートがアクティブになります。
問題:新しいシート を取得するためにデフォルトの動作に依存しておりWorksheet、新しいシートがどこにあるかわからず、それへの参照がありません。
提案:
ワークブックオブジェクトへの参照を取得し、コード全体で使用します

Dim wb As Workbook
Set wb = ActiveWorkbook

ブックに何を、どこで、どのように追加するかを制御します

Dim wsSummary as Worksheet
Set wsSummary = wb.Worksheets.Add(After:=wb.Worksheets(wb.Worksheets.Count))
wsSummary.Name = "Summary"

あなたのコード

For Each wsheet In Worksheets
    myavg.Add wsheet.Range("B2:B11")
Next  

これにより、作成したばかりCollectionのものを含め、本のRangeすべてからのが作成されます。Worksheet私はあなたがそれを含めたくないと思います。メンテナンスを容易にするために、範囲を保持する変数を作成し、コード全体でそれを使用する必要があります。上記を適用してみましょう

Dim wsheet as WorkSheet
Dim RangeAddress As String
RangeAddress = "B2:B11"
For Each wsheet In wb.Worksheets
    If wsheet.name <> wsSummary.Name Then
        myavg.Add wsheet.Range(RangeAddress)
    End If
Next  

あなたのコード

For i = 1 To myavg.Count
    avg1 = Application.WorksheetFunction.Average(Range("B2:B11"))
Next

問題:Collectionループでそれを参照していません が、繰り返し処理しています。毎回計算avg1し、次のループで上書きします。
ループを通過するたびに、アクティブシート(追加されたばかりの空白の新しいシートになります)の範囲の平均を計算します。
提案:
先に進むと、新しいシートの平均をシートごとに1つずつリストしたいようです。連続する行。それでは、後で要約シートに配置するために、平均を配列に格納しましょう。Range'のいずれかが空のAverage場合、エラーが発生することに注意してください。

Dim avg() as Variant
Redim avg(1 to myavg.Count, 1 To 1)
For i = 1 To myavg.Count
    avg(i, 1) = Application.WorksheetFunction.Average(myavg(i))
Next

あなたのコード

curColumn = 5
curRow = 4

For i = 1 To myavg.Count
    ActiveSheet.Cells(curRow, curColumn).Value = avg1
    curRow = curRow + 1
Next

問題:このコードは、最後に計算された値を連続する行
に単純に配置しますavg1

結果を新しいシートに配置します。平均を配列に収集したら、それをシートに配置します。

Dim curColumn as Long, curRow As Long
curColumn = 5
curRow = 4

wsSummary.Cells(curRow, curColumn).Resize(UBound(avg, 1), 1) = avg

これまでのところ、何もしていませんError Handling。コードがうまくいかない方法はたくさんあるのでError Handling、コードに含めるのが賢明です。たとえば、「概要」という名前のシートがすでにある場合はどうなりますか?Averageエラーを返した場合はどうなりますか?


これが適切な方法であるかどうかに目を向けると、結果を保持する配列を作成した後、その配列をブックのパスに入力できることは明らかです。

このようなもの

Sub Demo()
    Dim wb As Workbook
    Set wb = ActiveWorkbook

    Dim RangeAddress As String
    RangeAddress = "B2:B11"

    Dim wsSummary As Worksheet

    Dim avg() As Variant
    ReDim avg(1 To wb.Worksheets.Count, 1 To 1)
    For i = 1 To UBound(avg, 1)
        With wb.Worksheets(i).Range(RangeAddress)
            If WorksheetFunction.Count(.Value) > 0 Then
                avg(i, 1) = WorksheetFunction.Average(.Value)
            Else
                avg(i, 1) = "No Values On Sheet"
            End If
        End With
    Next

    Dim curColumn As Long, curRow As Long
    curColumn = 5
    curRow = 4

    On Error Resume Next
    Set wsSummary = wb.Worksheets("Summary")
    If Err.Number <> 0 Then
        ' Summary sheet does not exist, create it
        Err.Clear
        On Error GoTo 0
        Set wsSummary = wb.Worksheets.Add(After:=wb.Worksheets(wb.Worksheets.Count))
        wsSummary.Name = "Summary"
    Else
        On Error GoTo 0
        ' Summary sheet already exists
        ' what do you wnat to do?
    End If

    wsSummary.Cells(curRow, curColumn).Resize(UBound(avg, 1), 1) = avg

End Sub

正確な要件によっては、このコードにまだ問題がある可能性があります(たとえば、「概要」シートがすでに存在する場合、これは平均ループで処理されます)

于 2012-10-21T23:27:33.240 に答える