Как найти минимальное значение vba


You can use the following basic syntax to calculate the minimum value in a range using VBA:

Sub MinValue()
    Range("D2") = WorksheetFunction.Min(Range("B2:B11"))
End Sub

This particular example calculates the minimum value in the range B2:B11 and assigns the result to cell D2.

If you would instead like to display the minimum value in a message box, you can use the following syntax:

Sub MinValue()
    'Create variable to store min value
    Dim minValue As Single
    
    'Calculate min value in range
    minValue = WorksheetFunction.Min(Range("B2:B11"))
    
    'Display the result
    MsgBox "Min Value in Range: " & minValue 
End Sub

The following examples shows how to use each of these methods in practice with the following dataset in Excel that contains information about various basketball players:

Related: How to Find Max Value in Range Using VBA

Example 1: Calculate Minimum Value of Range Using VBA and Display Results in Cell

Suppose we would like to calculate the minimum value in the points column and output the results in a specific cell.

We can create the following macro to do so:

Sub MinValue()
    Range("D2") = WorksheetFunction.Min(Range("B2:B11"))
End Sub

When we run this macro, we receive the following output:

Notice that cell D2 contains a value of 10.

This tells us that the minimum value in the points column is 10.

Example 2: Calculate Minimum Value of Range Using VBA and Display Results in Message Box

Suppose we would instead like to calculate the minimum value in the points column and output the results in a message box.

We can create the following macro to do so:

Sub MinValue()
    'Create variable to store min value
    Dim minValue As Single
    
    'Calculate min value in range
    minValue = WorksheetFunction.Min(Range("B2:B11"))
    
    'Display the result
    MsgBox "Min Value in Range: " & minValue 
End Sub

When we run this macro, we receive the following output:

The message box tells us that the minimum value in the range B2:B11 is 10.

Note that in this example we calculated the minimum value in the range B2:B11.

However, if you’d like to instead calculate the minimum value in an entire column you could type B:B instead.

This will calculate the minimum value in all of column B.

Additional Resources

The following tutorials explain how to perform other common tasks in VBA:

VBA: How to Calculate Average Value of Range
VBA: How to Count Number of Rows in Range
VBA: How to Sum Values in Range

For a list like:

Column1     Column2     Column3    
DataA       1           1234    
DataA       2           4678    
DataA       3           8910    
DataB       2           1112    
DataB       4           1314    
DataB       9           1516

How do I get a list like this:

Column4    Column5      Column6    
DataA      1            1234    
DataB      2            1112

The key is to only return the minimum value in column2 and its corresponding column3 value.

Ben McCormack's user avatar

Ben McCormack

31.9k46 gold badges146 silver badges222 bronze badges

asked Dec 9, 2009 at 20:08

John M's user avatar

4

Sorry I misunderstood your Question First. Here is a working code that ended up more complex than I wanted it to be :D

Option Explicit

Private Function inCollection(ByRef myCollection As Collection, ByRef value As Variant) As Boolean
    Dim i As Integer
    inCollection = False

    For i = 1 To myCollection.Count
        If (myCollection(i) = value) Then
            inCollection = True
            Exit Function
        End If
    Next i
End Function

Sub listMinimums()

    Dim source As Range
    Dim target As Range
    Dim row As Range
    Dim i As Integer
    Dim datas As New Collection
    Dim minRows As New Collection

    Set source = Range("A2:C5")
    Set target = Range("D2")
    target.value = source.value

    For Each row In source.Rows
        With row.Cells(1, 1)
            If (inCollection(datas, .value) = False) Then
                datas.Add .value
                minRows.Add row.row, .value
            End If
            If (Me.Cells(minRows(.value), 2) > row.Cells(1, 2)) Then
                minRows.Remove (.value)
                minRows.Add row.row, .value
            End If
        End With
    Next row

    'output'
    For i = 1 To minRows.Count
        target(i, 1) = Me.Cells(minRows(i), 1)
        target(i, 2) = Me.Cells(minRows(i), 2)
        target(i, 3) = Me.Cells(minRows(i), 3)
    Next i

    Set datas = Nothing
    Set minRows = Nothing
End Sub

Note: You might want to replace Me with the name of your sheet.

answered Dec 9, 2009 at 21:01

marg's user avatar

margmarg

2,7871 gold badge30 silver badges33 bronze badges

An example using ADO.

Dim cn As Object
Dim rs As Object
Dim strFile As String
Dim strCon As String
Dim strSQL As String
Dim i As Integer

''http://support.microsoft.com/kb/246335

strFile = ActiveWorkbook.FullName
strCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strFile _
    & ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"

Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")

cn.Open strCon

strSQL = "SELECT Column1, Min(Column3) As MinCol3 FROM [Sheet8$] GROUP BY Column1"

rs.Open strSQL, cn, 3, 3

For i = 0 To rs.fields.Count - 1
    Sheets("Sheet7").Cells(1, i + 1) = rs.fields(i).Name
Next

Worksheets("Sheet7").Cells(2, 1).CopyFromRecordset rs

answered Dec 10, 2009 at 19:39

Fionnuala's user avatar

FionnualaFionnuala

90.2k7 gold badges112 silver badges151 bronze badges

2

Try this:

Public Sub MinList()
    Const clColKey_c As Long = 1&
    Const clColVal_c As Long = 3&
    Dim ws As Excel.Worksheet, objDict As Object
    Dim lRow As Long, dVal As Double, sKey As String
    Dim lRowFrst As Long, lRowLast As Long, lColOut As Long
    Set ws = Excel.ActiveSheet
    Set objDict = CreateObject("Scripting.Dictionary")
    lRowFrst = ws.UsedRange.Row
    lRowLast = ws.UsedRange.Rows.Count
    lColOut = ws.UsedRange.Columns.Count + 1&
    For lRow = lRowFrst To lRowLast
        dVal = Val(ws.Cells(lRow, clColVal_c).Value)
        sKey = ws.Cells(lRow, clColKey_c).Value
        If objDict.Exists(sKey) Then
            If dVal > objDict.Item(sKey) Then objDict.Item(sKey) = dVal
        Else
            objDict.Add sKey, dVal
        End If
    Next
    For lRow = lRowFrst To lRowLast
        ws.Cells(lRow, lColOut).Value = objDict.Item(ws.Cells(lRow, clColKey_c).Value)
    Next
    ws.Cells(1&, lColOut).Value = "Min"
End Sub

answered Dec 11, 2009 at 13:35

Oorang's user avatar

OorangOorang

6,6201 gold badge35 silver badges52 bronze badges

all_angarsk, Вы меня не поняли. Я имел ввиду, что не нужно усложнять. Любой модуль/процедуру Вы легко отправите в экспорт на флэшку в формате *.bas. И так точно вытянете его оттуда в любом месте, на любом компе, в любой документ. А с модулем кнопки — тяжелее. Ну и с самой кнопкой — нарисуйте встроенными инстр-ми фигуру (или обьект WordArt) что Вам нравится, и назначьте ей нужную процедуру (правая кнопка > Назначить макрос (или как там у Вас по локализации)). Всего пару кликов. И практично, и веселее, и проще, а не унылая серость.
А про «…регулярные выражения…«. Что Вы имели ввиду? Я их там не вижу.

Добавлено через 25 минут
Кажется, я понял про регулярку. Смотрите, у Тoiai грамотный и лаконичный код. Лично я бы все-таки сгенерированный массив выгрузил на лист, чтоб было видно. I.e., после next я бы добавил строку:

[a1].resize(1, ubound(a)).value=a

Дальше он вызывает окно сообщения MsgBox, в котором использует фукции не VBA, а Excel — Min и Max. Поэтому его тяжелая жизнь заставила вызывать их такими фразами Application.Max(a), Application.Min(a)…
Кстати, что б, если не нужно, не выкладывать массив на лист, его тоже можно одним движение загнать в этот же MsgBox.

 

tvit

Пользователь

Сообщений: 60
Регистрация: 01.04.2014

Дано:
В ячейках B1:B4 правильные даты в текстовом формате, выгружаются из внешней СУБД. мне нужно найти минимальную дату и максимальную дату. Есть вариант через вспомогательный столбик =Значен(«B1», есть вариант через формулу массива  {=МИН(ЗНАЧЕН(B1:B4))}
Мне нужно это сделать через VBA без вспомогательных ячеек. Макрорекордер записал Range(«B6»].FormulaArray = «=MIN(VALUE(R[-5]C:R[-2]C))» , а мне нужно что то типа ааа = MIN(VALUE(R[-5]C:R[-2]C))

Подскажите пожалуйста как это сделать?

Прикрепленные файлы

  • Книга1.xlsm (22.06 КБ)

 

gling

Пользователь

Сообщений: 4030
Регистрация: 01.01.1970

А почему не преобразовать в числа?  

Прикрепленные файлы

  • Книга1.xlsm (20.74 КБ)

 

JeyCi

Пользователь

Сообщений: 3387
Регистрация: 27.11.2013

а

Поиск

не помогает? :) — например,

здесь

… переменные брать типа As Date по логике тех строк — и будет вам вариант получше формулы на вба, полагаю… (изначально весь ваш Range возьмите в массив — arr)… успехов

Изменено: JeyCi17.03.2015 21:41:32

чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок — обратитесь к собеседнику на ВЫ — ответ на ваш вопрос получите — а остальное вас не касается (п.п.п. на форумах)

 

МВТ

Пользователь

Сообщений: 1198
Регистрация: 01.02.2015

#4

17.03.2015 21:41:26

Выводит максимальную дату в выделенном диапазоне

Код
Sub tt()
MsgBox (Format(Application.WorksheetFunction.Max(Selection), "dd/mm/yyyy"))
End Sub

 

Мотя

Пользователь

Сообщений: 3218
Регистрация: 25.12.2012

Уважаемый

tvit

!
Зачем нужны такие «заковыристые» формулы?
См. макрос: ищет MIN (MAX) в любом количестве дат в столбе А.

Изменено: Мотя17.03.2015 21:54:23

 

tvit

Пользователь

Сообщений: 60
Регистрация: 01.04.2014

Спасибо за ответы. но к сожалению все не то.

to Gling: то что предлагаете Вы у меня уже есть в моем вопросе. но тут используется дополнительная ячейка. а мне нужно сразу присвоить переменной.
to MBT: Ваш вариант вообще не работает
to Мотя: вариант решения через цикл я знаю. но мне нужно именно как одной формулой присвоить значение переменной.
Прошу прощения если не точно сформулировал свой вопрос

 

Может так? (честно не совсем понял как надо)

 

tvit

Пользователь

Сообщений: 60
Регистрация: 01.04.2014

Вы сначала вычисления присваиваете ячейке, а затем значение ячейки присваиваете переменной. А я спрашиваю как сразу присвоить переменной, не используя вспомогательных ячеек

 

JeyCi

Пользователь

Сообщений: 3387
Регистрация: 27.11.2013

#9

18.03.2015 10:23:36

Цитата
tvit написал: А я спрашиваю как сразу присвоить переменной, не используя вспомогательных ячеек

tvit

я вам посоветовала воспользоваться Поиском (линки сбились — но эта вкладка находится вверху страницы около Пользователи и Правила) — MIN в Поиск — и уже с первого листа Поисковика видны примеры… вариант для любого числа (включая дробное)

Код
Sub е()
Dim arr(), min#, max#
'arr = Selection.Value
min = Application.min(Selection)
    MsgBox "min - " & min
max = Application.max(Selection)
    MsgBox "max - " & max
End Sub

в вашей ситуации, как видите, проблема НЕ в способе поиска мин и макс, а в нач

форматах

ваших данных… ищите способ объяснить xl что он смотрит на даты — я с ходу точно не знаю как… успехов
P.S. если же вы хотите использовать формулу ячейки для расчёта значения, которое нужно в переменную, то придётся итог работы этой формулы сначала выгрузить в ячейку… имхо… потом взять в переменную

Изменено: JeyCi09.05.2015 14:40:38

чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок — обратитесь к собеседнику на ВЫ — ответ на ваш вопрос получите — а остальное вас не касается (п.п.п. на форумах)

 

Максим Зеленский

Пользователь

Сообщений: 4655
Регистрация: 11.06.2014

Microsoft MVP 2018-2022

#10

18.03.2015 12:11:55

tvit, думаю, что без цикла никак. Попытки запихнуть вашу функцию в Evaluate не увенчались успехом (что странно, так как массивные функции обрабатываются ею нормально), возможно, причина в том, что EVALUATE не хочет работать с вложенной VALUE или DATEVALUE из-за того, что даты не в буржуйском формате.
условно говоря, вот это работает:

Код
Worksheets(1).Evaluate("=VALUE(" & "" & "1+1" & "" & ")" & "" ) = 2 

а это нет

Код
Worksheets(1).Evaluate("=VALUE(" & "" & "05.05.15" & "" & ")" & "" ) = Error 2015

а вот это — работает, если в С1:С4 поместить например 1,2,3,4 в текстовом формате:

Код
Worksheets(1).Evaluate("=MIN(VALUE(C1:C4))")

F1 творит чудеса

 

МВТ

Пользователь

Сообщений: 1198
Регистрация: 01.02.2015

#11

18.03.2015 12:25:02

tvit,вообще-то, работает, просто не присваивает значения переменной, а выводит в текстовом формате. А для того, чтобы код знал, что вам нужна дата, то и объявите переменную, как дату:

Код
Sub tt()
Dim D As Date
D = Application.WorksheetFunction.Max(Selection)
MsgBox (D + 2)
End Sub

У меня, во всяком случае, этот макрос работает

 

JeyCi

Пользователь

Сообщений: 3387
Регистрация: 27.11.2013

#12

18.03.2015 12:53:32

Цитата
Максим Зеленский написал: думаю, что без цикла никак.

думаю так же… ещё один вариант (от поисковика ;) yandex)

Код
Sub DateMinMax()
'http://www.mrexcel.com/forum/excel-questions/426072-compare-dates-visual-basic-applications.html
'compare dates in VBA
'ZVI Oct 29th, 2009, 10:57 PM
  Dim d1, min As Date, max As Date, c As Range
    min = [b1].Value: max = [b1].Value
    For Each c In Range("b1:b4")
        d1 = Split(c.Text, ".")
        d1 = DateSerial(d1(2), d1(1), d1(0))
            If d1 < min Then
                min = d1
            ElseIf d1 > max Then
                max = d1            
            End If
    Next c
  Debug.Print min & "-min; max-" & max
End Sub

Изменено: JeyCi09.05.2015 14:40:53

чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок — обратитесь к собеседнику на ВЫ — ответ на ваш вопрос получите — а остальное вас не касается (п.п.п. на форумах)

 

JeyCi

Пользователь

Сообщений: 3387
Регистрация: 27.11.2013

#13

18.03.2015 13:10:01

Цитата
МВТ написал: У меня, во всяком случае, этот макрос работает

у меня выдает 01.01.1900 — xl 2010 ru
может быть дело в системных настройках, наверно…

Изменено: JeyCi09.05.2015 14:41:04

чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок — обратитесь к собеседнику на ВЫ — ответ на ваш вопрос получите — а остальное вас не касается (п.п.п. на форумах)

 

МВТ

Пользователь

Сообщений: 1198
Регистрация: 01.02.2015

JeyCi, а Вы диапазон с датами выделили? Макрос работает с Selection

 

tvit

Пользователь

Сообщений: 60
Регистрация: 01.04.2014

Спасибо всем откликнувшимся. Если без цикла никак, тогда проще найти свободную ячейку в Excel и воспользоваться формулой массива :-)

 

JeyCi

Пользователь

Сообщений: 3387
Регистрация: 27.11.2013

#16

18.03.2015 13:28:54

Цитата
МВТ написал: макрос работает с Selection

в том то и дело, что как только не выделяла — работает только на две ячейки, в которых вставлена формула (b6:b7) — на (b1:b4) не работает… выдаёт то 00:00:00, то 01.01.1900… пробовала поколдовать с форматом ячеек — тоже какие-то странные итоги… вобщем, слабо поняла, как меня понимает xl… ну и ладно, :) не тревожьтесь…  — решение по ветке общими усилиями нашли и отлично… всем успехов  

Изменено: JeyCi09.05.2015 14:41:16

чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок — обратитесь к собеседнику на ВЫ — ответ на ваш вопрос получите — а остальное вас не касается (п.п.п. на форумах)

 

МВТ

Пользователь

Сообщений: 1198
Регистрация: 01.02.2015

Прикрепляю файл с вставленными макросом и пояснениями

 

МВТ, так в том и дело, что изначально даты сохранены как текст.
Вы попробуйте макрос запустить на B1:B4 в исходном файле автора. Получите результат 0.

 

МВТ

Пользователь

Сообщений: 1198
Регистрация: 01.02.2015

#19

18.03.2015 14:28:55

Максим Зеленский,понял: протупил — я сам даты вводил. Так может, проще поменять формат дат на Дату :)? Нет, можно и без этого, но не очень удобно. Тогда можно чтобы макрос сам преобразовывал текстовые значения в даты:

Код
Sub tt()
Dim D As Date, Rng As Range
Application.ScreenUpdating = False
If Selection.Count < 2 Then
    MsgBox ("Выделено менее двух ячеек. Выделите диапазон дат, например, А1:А5")
    Exit Sub
End If
Set Rng = Selection
For Each Cell In Rng
If Not IsNumeric(Cell) Then Cell.Value = CDate(Cell.Value)
On Error Resume Next
Next Cell
Rng.NumberFormat = "dd/mm/yyyy"
Rng.Value = Rng.Value
D = Application.WorksheetFunction.Max(Rng)
Application.ScreenUpdating = True
MsgBox ("Максимальная дата в выделенном диапазоне " & Replace(Selection.Address, "$", "") & ": " & D)
End Sub


Изменено: МВТ18.03.2015 15:00:00
(Добавил макрос)

 

JeyCi

Пользователь

Сообщений: 3387
Регистрация: 27.11.2013

#20

18.03.2015 17:25:45

Цитата
МВТ написал: проще поменять формат дат на Дату

как вариант (с Selection) без цикла

Код
Sub e1()
Dim min As Date, max As Date
Selection.TextToColumns DataType:=xlDelimited, FieldInfo:=Array(1, 4)  '4 - DMY Date format
min = Application.min(Selection)
max = Application.max(Selection)
MsgBox min & vbNewLine & max
End Sub

ВСЁ  — думаю, короче и без цикла у меня уже точно не получится… 8)  (поправила)

Изменено: JeyCi09.05.2015 14:41:29

чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок — обратитесь к собеседнику на ВЫ — ответ на ваш вопрос получите — а остальное вас не касается (п.п.п. на форумах)

 

tvit

Пользователь

Сообщений: 60
Регистрация: 01.04.2014

#21

18.03.2015 18:42:51

Цитата
JeyCi написал: ВСЁ  — думаю, короче и без цикла у меня уже точно не получится…

Немного не то, что я просил (все таки идет изменение исходного файла), но решение очень красивое, нужно запомнить. Мне часто нужно делать нечто подобное, но все как-то извращенными способами приходилось это делать :D

Изменено: tvit09.05.2015 14:41:47

 

tvit

Пользователь

Сообщений: 60
Регистрация: 01.04.2014

Максим Зеленский, пытался осмыслить, что Вы написали. Действительно, если в исходном файле заменить в датах точку на слеш «/» , то все начинает работать. Похоже глюк VBA, в оболочке русификация отрабатывает отлично,  а в VBA нет.

 

МВТ

Пользователь

Сообщений: 1198
Регистрация: 01.02.2015

tvit,если для вас настолько критично сохранять даты в текстовом формате, можете прописать в макросе создание в свободной колонке временного массива в правильном формате, его обработку и последующее удаление

 

tvit

Пользователь

Сообщений: 60
Регистрация: 01.04.2014

Обрабатываемые данные выгружаются в текстовые файлы из централизованной АС и на них я повлиять ни как не могу. А поскольку объем каждого из этих файлов может занимать 300-400 Мб по 500 тысяч строк и более, то вопрос с нехваткой памяти стоит достаточно остро, поэтому прежде чем добавить вспомогательный столбец, я 10 раз подумаю.

 

Казанский

Пользователь

Сообщений: 8839
Регистрация: 11.01.2013

#25

19.03.2015 00:38:58

Цитата
tvit написал: Обрабатываемые данные выгружаются в текстовые файлы из централизованной АС и на них я повлиять ни как не могу

Но Вы можете влиять на импорт текстов в Excel. Используйте Мастер импорта текстов (он запускается автоматически при открытии файлов .txt) и задайте формат Дата:ДМГ нужному столбцу.
Можно написать макросы для импорта каждого типа файлов.

 

Максим Зеленский

Пользователь

Сообщений: 4655
Регистрация: 11.06.2014

Microsoft MVP 2018-2022

#26

19.03.2015 09:30:03

Цитата
tvit написал: Похоже глюк VBA, в оболочке русификация отрабатывает отлично,  а в VBA нет.

связано скорее с тем, что функции преобразования типов в VBA не работают с массивами напрямую (только с элементами), а прямого аналога функции ЗНАЧЕН в объекте WorksheetFunction нет. Фактически, в рамках поставленных вами условий (без циклов, без задействования дополнительных столбцов) получить результат можно было только при использовании метода Evaluate, запихивая в него готовую формулу. EVALUATE — наследие XML, предшественника VBA, и кроме даты в US-формате, есть еще некоторые ограничения. Для прочих сложностей с международными стандартами в VBA есть Application.International с кучей региональных настроек.

Изменено: Максим Зеленский09.05.2015 14:42:48

F1 творит чудеса

The Excel MIN function returns the smallest value from a specified range of numeric values

Example: Excel MIN Function

Excel MIN Function

METHOD 1. Excel MIN Function

EXCEL

Result in cell C10 (-7) — returns the smallest numeric value from the selected range.

Result in cell D10 (2) — returns the smallest numeric value from the selected range.

METHOD 2. Excel MIN function using the Excel built-in function library

EXCEL

Formulas tab > Function Library group > More Functions > Statistical > MIN > populate the input box

=MIN(C5:C9)
Note: in this example we are populating an input box with a single range.
Built-in Excel MIN Function

METHOD 1. Excel MIN function using VBA

VBA

Sub Excel_MIN_Function()

‘declare a variable
Dim ws As Worksheet

Set ws = Worksheets(«MIN»)

‘apply the Excel MIN function
ws.Range(«C10») = Application.WorksheetFunction.Min(ws.Range(«C5:C9»))
ws.Range(«D10») = Application.WorksheetFunction.Min(ws.Range(«D5:D9»))

End Sub

OBJECTS
Worksheets: The Worksheets object represents all of the worksheets in a workbook, excluding chart sheets.
Range: The Range object is a representation of a single cell or a range of cells in a worksheet.

PREREQUISITES
Worksheet Name: Have a worksheet named MIN.

ADJUSTABLE PARAMETERS
Output Range: Select the output range by changing the Range references («C10») and («D10») in the VBA code to any cell in the worksheet, that doesn’t conflict with the formula.

Usage of the Excel MIN function and formula syntax

EXPLANATION

DESCRIPTION
The Excel MIN function returns the smallest value from a specified range of numeric values.

SYNTAX
=MIN(number1, [number2], …)

ARGUMENT(S)
number1: (Required) A single numeric cell or a range of numeric cells.
number2: (Optional) A single numeric cell or a range of numeric cells.

ADDITIONAL NOTES
Note 1: In Excel 2007 and later the MIN function can accept up to 255 number arguments. In Excel 2003 the MIN function can only accept up to 30 number arguments.

Понравилась статья? Поделить с друзьями:
  • Как найти письма ди в зомби
  • Как включить сервис найти устройство на телефон
  • Как найти закладки в телефоне redmi
  • Как найти подругу для секса без обязательств
  • Как исправить свою фамилию в контакте