Excelマクロは生データに基づいてレポートを生成します


2

私は現在、学生のスコアのレポートを作成し、各学生の終わりにパーセンテージを表示するためのマクロに取り組んでいます。

ここに画像の説明を入力してください

写真は一目瞭然だと思います。左側に示すような学生のデータがあり、右側にそのようなレポートが必要です。私は1人の生徒用にマクロを作成し、各生徒ごとに毎回再実行することができましたが、すべての生徒に対して一度にレポートを作成し、すべての生徒が終了したら停止する方法がわかりません。

次のコードは、新しい学生名が発生するたびに新しい行を作成するためのものです。

Dim iRow As Integer, iCol As Integer
Dim oRng As Range

Set oRng = Range("A4")

iRow = oRng.Row
iCol = oRng.Column

Do
'
If Cells(iRow + 1, iCol) <> Cells(iRow, iCol) Then
    Cells(iRow + 1, iCol).EntireRow.Insert Shift:=xlDown
    iRow = iRow + 2


Else
    iRow = iRow + 1
End If
'
Loop While Not Cells(iRow, iCol).Text = ""

しかし、パーセンテージ計算のためにコードを入力する場所がわかりません。

ActiveCell.FormulaR1C1 = "=(R[-3]C+R[-2]C+R[-1]C)/COUNT(R[-3]C:R[-1]C)"

計算は非常に簡単ですが、ループの方法はわかりません。セルをマージして、セル用のボックスを作成できます。私はそれを正しくやっているかどうかわかりません。しかし、これを実現する簡単な方法があれば、教えてください。私は長い道のりを進んでいると思うが、私はこれの初心者です。そして、人の名前がマージされるように、マージコードをどこに入力する必要があります。

不明な点がある場合はお知らせください。

前もって感謝します。

PS私は教師ではありません。このようなレポートを作成したいだけです


3
「マクロで作業する」とは、既に開始し、共有するコードと特定の質問があることを意味します。質問に追加してください。ソリューション全体を求める質問は、ここではトピック外です。
マテジュハス

すでにVBAスクリプトを書いているので、ここに投稿した方が良いので、修正を提案するのに役立ちます。
ラジェッシュS

VBA(マクロ)に重複した名前の列をマージすることをお勧めします。VBAの一部を小計に使用するか、手動で行う必要があります。
ラジェシュS

1
パーセンテージは出力のどこから来ますか?Aが物理学で65、生物学で75になったのはなぜですか?
ブルースウェイン

1
ピボットテーブルを使用しない特別な理由はありますか?これはまさに彼らがすることです。
フリーマン

回答:


1

あなたはしたい:

  1. 各学生名の下に行を挿入します
  2. 学生の名前のセルを結合します(文字が表すものと想定しています)
  3. 生徒の太い境界線を含む境界線を追加します
  4. 各生徒の平均を計算する

解決策は次のとおりです。

Dim iRow As Integer, iCol As Integer
Dim oRng As Range
Dim nRng As Range
Dim persRng As Range
Dim avgRng As Range

Set oRng = Range("A4")

iRow = oRng.Row
iCol = oRng.Column

Do

    If Cells(iRow + 1, iCol) <> Cells(iRow, iCol) Then
        ' Insert row below student name
        Cells(iRow + 1, iCol).EntireRow.Insert Shift:=xlDown
        ' merge name cells
        Set nRng = Range(Cells(iRow + 1, iCol), Cells(iRow - 2, iCol))
        With nRng
            Application.DisplayAlerts = False
            .Merge
            Application.DisplayAlerts = True
            .VerticalAlignment = xlVAlignCenter
            .HorizontalAlignment = xlHAlignCenter
            .Font.Bold = True
        End With
        ' Add borders
        Set persRng = Range(Cells(iRow + 1, iCol), Cells(iRow - 2, iCol + 2))
        With persRng.Borders
            .LineStyle = xlContinuous
            .Color = vbBlack
            .Weight = xlThin
        End With
        ' Thick border around average cells
        Set avgRng = Range(Cells(iRow + 1, iCol + 1), Cells(iRow + 1, iCol + 2))
        avgRng.BorderAround LineStyle:=xlContinuous, Weight:=xlMedium, Color:=vbBlack
        ' Add percent sign and calculate average
        Cells(iRow + 1, iCol + 1).Value = "%"
        Cells(iRow + 1, iCol + 2) _
            .FormulaR1C1 = "=(R[-3]C+R[-2]C+R[-1]C)/COUNT(R[-3]C:R[-1]C)"
        Cells(iRow + 1, iCol + 2).Font.Bold = True
        iRow = iRow + 2


    Else
        iRow = iRow + 1
    End If

Loop While Not Cells(iRow, iCol).Text = ""

私はコーディング作品に非常に新しいです。あなたのコードは、それらがどのように機能しているかを理解するのに時間がかかります。後ほどここに戻りますが、その間、ありがとうございました。
バーキニラ

1
#グレッグ、あなたは完璧な10に値する。それはうまく機能しています。
ラジェシュS

まだ問題があります。私のコードは非常に長くて混乱しているので、私は削減したいです。それで、テキスト挿入コードを短くし、列幅コードを設定する方法はありますか。Columns( "A:A")。ColumnWidth = 2 Columns( "B:B")。ColumnWidth = 10 Columns( "C:C")。ColumnWidth = 10 Range( "A1")。Select ActiveCell.FormulaR1C1 = "NAME "Range(" B2 ")。Select ActiveCell.FormulaR1C1 =" SUBJECT "Range(" C2 ")。Select ActiveCell.FormulaR1C1 =" Score "これを単一行ごとに行うのではなく、単一行で解決する方法はありますか一つずつ。
バアキニラ

最初に列幅を設定します。複数回行う理由はありません。残りについては、あなたが何を求めているのか分かりません。この答えはあなたの元の質問をカバーしています。不明な点がある場合は、新しい質問を投稿して、ここへのリンクを投稿してください。まず、VBAでセルを選択する必要はほとんどありません(実際、選択するのは非常に非効率的です)。2.必要でない限り、FormulaR1C1は使用しないでください(範囲相対式)。代わりに、セルの値を直接設定しますRange("A1").value = "NAME"
グレッグカレカ

提案ありがとう。役に立ちます。これが私の質問です。 superuser.com/questions/1328173/...
Baakiニラ

0

上記のコードを少し変更して、複数のサブジェクトを作成できるようにしましたが、式を変更する方法がわかりません。

Dim iRow As Integer, iCol As Integer, nRow As Integer, mRow As Integer
Dim oRng As Range
Dim nRng As Range
Dim persRng As Range
Dim avgRng As Range

Set oRng = Range("A4")

iRow = oRng.Row
iCol = oRng.Column
nRow = Application.WorksheetFunction.CountIf(Range("A1:A12"), "a")
mRow = nRow - 1

Do

    If Cells(iRow + 1, iCol) <> Cells(iRow, iCol) Then
        ' Insert row below student name
        Cells(iRow + 1, iCol).EntireRow.Insert Shift:=xlDown
        ' merge name cells
        Set nRng = Range(Cells(iRow + 1, iCol), Cells(iRow - mRow, iCol))
        With nRng
            Application.DisplayAlerts = False
            .Merge
            Application.DisplayAlerts = True
            .VerticalAlignment = xlVAlignCenter
            .HorizontalAlignment = xlHAlignCenter
            .Font.Bold = True
        End With
        ' Add borders
        Set persRng = Range(Cells(iRow + 1, iCol), Cells(iRow - mRow, iCol + 2))
        With persRng.Borders
            .LineStyle = xlContinuous
            .Color = vbBlack
            .Weight = xlThin

        End With
        ' Thick border around average cells
        Set avgRng = Range(Cells(iRow + 1, iCol + 1), Cells(iRow + 1, iCol + 2))
        avgRng.BorderAround LineStyle:=xlContinuous, Weight:=xlMedium, Color:=vbBlack
        ' Add percent sign and calculate average
        Cells(iRow + 1, iCol + 1).Value = "%"
        Cells(iRow + 1, iCol + 2) _
            .FormulaR1C1 = "=SUM(R[-5]C:R[-1]C)/COUNT(R[-5]C:R[-1]C)"
        Cells(iRow + 1, iCol + 2).Font.Bold = True
        iRow = iRow + mRow


    Else
        iRow = iRow + 1
    End If

Loop While Not Cells(iRow, iCol).Text = ""

これまでは、大丈夫です。ただし、5以外の場合は、被験者の平均を取得できません。整数値を変更しようとしましたが、機能しないようです。

Cells(iRow + 1, iCol + 2) _
                .FormulaR1C1 = "=SUM(R[-nRow]C:R[-1]C)/COUNT(R[-nRow]C:R[-1]C)"

どうやってやるの?このために別のループを作成する必要がありますか?


これに関する別の問題nRow = Application.WorksheetFunction.CountIf(Range("A1:A12"), "a") mRow = nRow - 1は、最初の人の名前が「a」である場合にのみ機能することです。関数がループを行うためにサブジェクトの名前の繰り返しを選択する方が良いと思います。
バーキニラ

値を取得するようにメッセージボックスを入力しようとしましたが、まだ機能していません。 myNum = Application.InputBox("Enter the number of subjects")
バーキニラ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.