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

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

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

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

Q&A

解決済

4回答

1968閲覧

EXCEL VBA LARGE関数で取得した列にある先頭行の値を取得したい

nuko3

総合スコア31

VBA

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

0グッド

0クリップ

投稿2020/08/26 02:40

編集2020/08/26 02:47

EXCELで集計やまとめをするマクロを作っています。
不良項目と不良数を1位2位3位、とランキング形式でまとめたいです。

不良数の方はLARGE関数を使用して1~3位を簡単に取得できますが、
不良数を取得した先頭行にある不良項目が取得方法がわかりませんでした。

前の質問で頂いた参考を基に書いてみて期待に一番近しくなりましたが、数値が同じだった場合、項目名も同じになってしまいました。
数値が同じだった場合は、左側を優先にした順位にしたいです。
やり方がありましたら教えて頂けると幸いです。

やりたいこと

H1~M6に入っている項目名と数値を取得し、A2~F6にまとめる
1行ごとに1番~3番目に大きかった数値と、1番~3番目大きかった数値の項目名を取得し、
左側に代入する

↓期待結果
イメージ説明
↓下記プログラムの実行結果
イメージ説明

プログラム

VBA

1Sub Huryo_Rank() 2Dim i As Integer 3Dim first As Integer 4Dim second As Integer 5Dim third As Integer 6Dim k_row_first As Integer 7Dim k_name_first As String 8Dim k_row_second As Integer 9Dim k_name_second As String 10Dim k_row_third As Integer 11Dim k_name_third As String 12 13For i = 2 To Cells(Rows.Count, "H").End(xlUp).Row 14 first = WorksheetFunction.Large(Range(Cells(i, 8), Cells(i, 13)), 1) 15 Cells(i, 2).Value = first 16 second = WorksheetFunction.Large(Range(Cells(i, 8), Cells(i, 13)), 2) 17 Cells(i, 4).Value = second 18 third = WorksheetFunction.Large(Range(Cells(i, 8), Cells(i, 13)), 3) 19 Cells(i, 6).Value = third 20 21 22 k_row_first = WorksheetFunction.Match(first, Range(Cells(i, 8), Cells(i, 13)), 0) + 7 23 k_name_first = Cells(1, k_row_first).Value 24 Cells(i, 1).Value = k_name_first 25 26 k_row_second = WorksheetFunction.Match(second, Range(Cells(i, 8), Cells(i, 13)), 0) + 7 27 k_name_second = Cells(1, k_row_second).Value 28 Cells(i, 3).Value = k_name_second 29 30 k_row_third = WorksheetFunction.Match(third, Range(Cells(i, 8), Cells(i, 13)), 0) + 7 31 k_name_third = Cells(1, k_row_third).Value 32 Cells(i, 5).Value = k_name_third 33 34 Next i 35 36End Sub 37

環境

Windows 10
EXCEL 2019

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

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

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

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

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

guest

回答4

0

コードはいくつか他の方があげてくださっているので違ったアプローチを。
VBAを使わない方法です。

作業セルO2~T6
O2に数式を入れてT6までコピー

Excel

1=IF(H2=0,"",RANK.EQ(H2,$H2:$M2)*100+COLUMN())

ワースト
項目名(A2に入れてコピー)
※2位、3位はSMALLの最後の,1)を変更してください。

Excel

1=IFERROR(INDEX($H$1:$M$1,0,MATCH(SMALL($O2:$T2,1),$O2:$T2,0)),"")

個数(B2に入れてコピー)
※こちらも2位,3位はSMALLの中を変更してください

Excel

1=IFERROR(INDEX($H2:$M2,,MATCH(SMALL($O2:$T2,1),$O2:$T2,0)),"")

ベストアンサー出てましたね。失礼しました。

投稿2020/08/26 04:23

編集2020/08/26 04:24
radames1000

総合スコア1925

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

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

0

hatenaさんの後で気が引けますがw
提示されているシート名を「ランキング」
あと、作業用のシートとして「ソート作業」を追加してやってみました。

VBA

1Sub s_Test1() 2 Const cnsColBgn = 8 'H 3 Const cnsColEnd = 13 'M 4 Const cnsRowBgn = 2 5 6 Dim lngRnk As Long 7 Dim lngRowRnk As Long 8 Dim lngColRnk As Long 9 Dim lngRowEnd As Long 10 Dim wshRnk As Worksheet 11 Dim wshSrt As Worksheet 12 13 Set wshRnk = Worksheets("ランキング") 14 Set wshSrt = Worksheets("ソート作業") 15 16 lngRowEnd = wshRnk.Cells(Rows.Count, cnsColBgn).End(xlUp).Row 17 For lngRowRnk = cnsRowBgn To lngRowEnd 18 19 wshRnk.Range(wshRnk.Cells(1, cnsColBgn), wshRnk.Cells(1, cnsColEnd)).Copy wshSrt.Range("A1") 20 wshRnk.Range(wshRnk.Cells(lngRowRnk, cnsColBgn), wshRnk.Cells(lngRowRnk, cnsColEnd)).Copy wshSrt.Range("A2") 21 For lngColRnk = cnsColBgn To cnsColEnd 22 wshSrt.Cells(3, lngColRnk - cnsColBgn + 1) = lngColRnk 23 Next lngColRnk 24 25 With wshSrt 26 .Sort.SortFields.Add Key:=Range(.Cells(2, 1), .Cells(2, cnsColEnd - cnsColBgn + 1)), Order:=xlDescending 27 .Sort.SortFields.Add Key:=Range(.Cells(3, 1), .Cells(3, cnsColEnd - cnsColBgn + 1)), Order:=xlAscending 28 .Sort.SetRange Range(.Cells(1, 1), .Cells(3, cnsColEnd - cnsColBgn + 1)) 29 .Sort.Orientation = xlLeftToRight 30 .Sort.Apply 31 End With 32 33 For lngRnk = 1 To 3 34 wshRnk.Cells(lngRowRnk, lngRnk * 2 - 1).Value = wshSrt.Cells(1, lngRnk).Value 35 wshRnk.Cells(lngRowRnk, lngRnk * 2).Value = wshSrt.Cells(2, lngRnk).Value 36 Next lngRnk 37 38 Next lngRowRnk 39 40 Set wshSrt = Nothing 41 Set wshRnk = Nothing 42 43End Sub

投稿2020/08/26 04:10

kitasue

総合スコア314

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

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

0

ベストアンサー

とりあえず現状のコードから最小限の変更でするという方針で。

vba

1Option Explicit 2 3Sub Huryo_Rank() 4Dim i As Integer 5Dim first As Integer 6Dim second As Integer 7Dim third As Integer 8Dim k_row_first As Integer 9Dim k_name_first As String 10Dim k_row_second As Integer 11Dim k_name_second As String 12Dim k_row_third As Integer 13Dim k_name_third As String 14Dim leftCol As Long 15 16 17For i = 2 To Cells(Rows.Count, "H").End(xlUp).Row 18 first = WorksheetFunction.Large(Range(Cells(i, 8), Cells(i, 13)), 1) 19 If first = 0 Then GoTo Continue 20 Cells(i, 2).Value = first 21 leftCol = 8 22 k_row_first = WorksheetFunction.Match(first, Range(Cells(i, leftCol), Cells(i, 13)), 0) + leftCol - 1 23 k_name_first = Cells(1, k_row_first).Value 24 Cells(i, 1).Value = k_name_first 25 26 27 second = WorksheetFunction.Large(Range(Cells(i, 8), Cells(i, 13)), 2) 28 If second = 0 Then GoTo Continue 29 Cells(i, 4).Value = second 30 If first = second Then leftCol = k_row_first + 1 Else leftCol = 8 31 k_row_second = WorksheetFunction.Match(second, Range(Cells(i, leftCol), Cells(i, 13)), 0) + leftCol - 1 32 k_name_second = Cells(1, k_row_second).Value 33 Cells(i, 3).Value = k_name_second 34 35 36 third = WorksheetFunction.Large(Range(Cells(i, 8), Cells(i, 13)), 3) 37 If third = 0 Then GoTo Continue 38 Cells(i, 6).Value = third 39 If second = third Then leftCol = k_row_second + 1 Else leftCol = 8 40 k_row_third = WorksheetFunction.Match(third, Range(Cells(i, leftCol), Cells(i, 13)), 0) + leftCol - 1 41 k_name_third = Cells(1, k_row_third).Value 42 Cells(i, 5).Value = k_name_third 43 44Continue: 45 Next i 46 47End Sub

前の順位の値と同じなら、検索範囲をそれよりに右に狭めるというロジックです。

投稿2020/08/26 03:47

hatena19

総合スコア34075

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

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

nuko3

2020/08/26 04:16

最小限の変更、わかりやすくてとても助かります... 期待通りに動きました。ありがとうございます!
guest

0

(参考程度)

VBA

1Sub Test_Sample_Miniature() 2 3 Dim i As Integer 4 Dim first As Integer 5 Dim second As Integer 6 Dim third As Integer 7 Dim k_row_first As Integer 8 Dim k_name_first As String 9 Dim k_row_second As Integer 10 Dim k_name_second As String 11 Dim k_row_third As Integer 12 Dim k_name_third As String 13 14 For i = 2 To Cells(Rows.Count, "H").End(xlUp).Row 15 16 first = WorksheetFunction.Large(Range(Cells(i, 8), Cells(i, 13)), 1) 17 Cells(i, 2).Value = first 18 second = WorksheetFunction.Large(Range(Cells(i, 8), Cells(i, 13)), 2) 19 Cells(i, 4).Value = second 20 third = WorksheetFunction.Large(Range(Cells(i, 8), Cells(i, 13)), 3) 21 Cells(i, 6).Value = third 22 23 Dim iX As Integer: Dim iY As Integer: Dim iZ As Integer 24 Dim MyRange As Range 25 Dim intHitCol() As Integer 26 Dim iWork As Integer: Dim iWorkCol As Integer 27 Dim blnNext As Boolean 28 ReDim Preserve intHitCol(0): iZ = 0: intHitCol(iZ) = 0 29 '(first~third繰返し) 30 For iX = 1 To 3 31 iWork = 0 32 iWorkCol = 0 33 '(行繰返し) 34 For Each MyRange In Range(Cells(i, 8), Cells(i, 13)) 35 If iWorkCol = 0 Then 36 Select Case iX 37 Case 1: iWork = first: iWorkCol = 1 38 Case 2: iWork = second: iWorkCol = 3 39 Case 3: iWork = third: iWorkCol = 5 40 End Select 41 End If 42 If MyRange = iWork Then 43 '(書込み済み列チェック) 44 blnNext = False 45 For iY = 0 To UBound(intHitCol) 46 If MyRange.Column = intHitCol(iY) Then 47 blnNext = True 48 End If 49 Next 50 '(ターゲット列ヒット) 51 If blnNext = False Then 52 Cells(i, iWorkCol).Value = Cells(1, MyRange.Column).Value 53 iZ = iZ + 1: ReDim Preserve intHitCol(iZ) 54 intHitCol(iZ) = MyRange.Column 55 Exit For 56 End If 57 End If 58 Next 59 Next 60 Next i 61End Sub

投稿2020/08/26 04:55

tosi

総合スコア553

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問