Как получить идентификатор максимального значения?

Я новичок в Excel и его объектной модели VBA. У меня есть эта таблица (AD), отсортированная по A и B. Для каждой группы строк A-B я хочу найти значение MAX D (стоимость) и C (идентификатор продажи) этого максимального значения. Как и меньшая таблица (F1:J4). Я возился со сводной таблицей, но не смог получить Sale-ID. [Не обращайте внимания на форматирование, добавлено для удобства чтения]

В любом случае я ищу решение VBA. Я уверен, что у меня все получится, если я создам диапазон для каждой группы AB. Но как? Самое близкое, что я смог найти, это этот вопрос: Строки GroupBy и Sum с использованием нескольких столбцов в Excel, но это не дает мне значения идентификатора и кажется довольно неэлегантным.

Есть какие-нибудь указатели?

Преобразование HTML-таблицы в профессиональный документ Excel
Преобразование HTML-таблицы в профессиональный документ Excel
Это самый простой способ создания Excel из HTML-таблицы.
Импорт excel в laravel в базу данных
Импорт excel в laravel в базу данных
Здравствуйте, дорогой читатель, в этой статье я расскажу практическим и быстрым способом, как импортировать файл Excel в вашу базу данных с помощью...
1
0
63
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий
  1. Прежде всего скопируйте столбцы A:D на лист и оставьте следующие 4 столбца пустыми.
  2. Сортировка столбцов по A и B

Надеюсь, этот фрагмент кода поможет.

Sub FindMaxCostForGroups()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("YOUR_WORKSHEET") ' Change to your sheet name
    
    Dim lastRow As Long
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    
    Dim currentA As String, currentB As String
    Dim maxCost As Double
    Dim saleID As String
    Dim outputRow As Long
    outputRow = 1 ' Starting row for output, change as needed
    
    Dim i As Long
    For i = 2 To lastRow ' Assuming headers in row 1
        If ws.Cells(i, 1).Value <> currentA Or ws.Cells(i, 2).Value <> currentB Then
            ' New group detected, output the previous group's results
            If i > 2 Then
                ws.Cells(outputRow, 6).Value = currentA
                ws.Cells(outputRow, 7).Value = currentB
                ws.Cells(outputRow, 8).Value = saleID
                ws.Cells(outputRow, 9).Value = maxCost
                outputRow = outputRow + 1
            End If
            
            ' Initialize new group variables
            currentA = ws.Cells(i, 1).Value
            currentB = ws.Cells(i, 2).Value
            maxCost = ws.Cells(i, 4).Value
            saleID = ws.Cells(i, 3).Value
        Else
            ' Same group, update max cost and sale ID if necessary
            If ws.Cells(i, 4).Value > maxCost Then
                maxCost = ws.Cells(i, 4).Value
                saleID = ws.Cells(i, 3).Value
            End If
        End If
    Next i
    
    ' Output the last group's results
    ws.Cells(outputRow, 6).Value = currentA
    ws.Cells(outputRow, 7).Value = currentB
    ws.Cells(outputRow, 8).Value = saleID
    ws.Cells(outputRow, 9).Value = maxCost
End Sub

В этом коде предполагается, что ваши данные начинаются со строки 2, а столбцы от A до D содержат ваши данные, а выходные данные начинаются со столбца F. При необходимости измените имя листа, начальную строку и ссылки на столбцы.

Спасибо! Это хорошо ВЫПОЛНЯЕТ свою работу. Я вижу, что вы сделали это «трудным путем», со старым добрым расчетом. Полагаю, я мог бы добавить выходное значение COLUMN, чтобы получить нужный мне однострочный формат.

Shmuel A. Kam 05.08.2024 14:17

Как альтернатива; этот код ADO/SQL создает простую таблицу на «Листе1» без использования каких-либо циклов.

Sub Test()
    Dim objConn As Object, RS As Object, strSQL As String, strArgs As String, j As Integer

    Sheets("Sheet1").Range("M2:P" & Rows.Count).ClearContents
    
    Set objConn = CreateObject("ADODB.Connection")

    strArgs = "Driver = {Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)}; Readonly=False; DBQ = " & ThisWorkbook.FullName
    
    objConn.Open strArgs

    strSQL = " Select T1.[Name], T1.[Product], T1.[Sale ID], T1.[Cost] From [Sheet1$] As T1 " & _
             " Left Join [Sheet1$] As T2 " & _
             " On (T1.[Name]= T2.[Name] And T1.[Product]= T2.[Product] And T2.[Cost] > T1.[Cost]) Where T2.[Name] Is Null " & _
             " Order By T1.[Name], T1.[Product]"
        
    Set RS = objConn.Execute(strSQL)
    
    Sheets("Sheet1").Range("M1:P1") = Array("Name", "Product", "Sale ID", "Cost")

    Sheets("Sheet1").Range("M2").CopyFromRecordset RS

    objConn.Close
    Set objConn = Nothing
End Sub

УХ ТЫ. Немного перебор, нет? Ну, я думаю, это зависит от размера стола. Будет ли это работать, даже если в файле есть несохраненные изменения? Я ДОЛГО не смотрел на соединения с БД.

Shmuel A. Kam 05.08.2024 16:33

Я ЗНАЮ, что SQL может легко получить идентификатор из соединения. Я просто немного удивлен, что Excel-VBA не поддерживает это изначально.

Shmuel A. Kam 05.08.2024 16:35

Это не излишество, а скорее профессиональный подход к анализу данных.

Haluk 05.08.2024 16:47

Другие вопросы по теме