Tính giúp tổng cực trị trong các dòng của 1 vùng dữ liệu

Liên hệ QC

ChanhTQ@

0901452không62
Tham gia
5/9/08
Bài viết
4,254
Được thích
4,861
Các bạn giúp tôi viết hàm tự tạo để tính tổng các số lớn nhất hay nhỏ nhất trong từng hàng của một vùng dữ liệu (A1:C10), như sau:
| A | B | C | D |
| 26 | 48 |26||
|70| 7 | 88 ||
| 75 | 24 |39|Tổng cực tiểu (Màu xanh)|
| 21 | 37 |27|=> 258 |
| 38 |61| 82 |Tổng cực đai trong dòng|
| 27 |57| 61 |=> 710 |
| 92 | 5 |69||
| 56 | 47 |56||
| 54 | 93 |62||
| 78 | 9 |13||
|||||
 
Lần chỉnh sửa cuối:
Em làm thế này:
PHP:
Function TongCT(Rng As Range, Optional CT = "Mi") As Double
  Dim i As Long, Temp As Double
  For i = 1 To Rng.Rows.Count
    With Rng.Resize(1).Offset(i - 1)
      Select Case CT
        Case "Mi": Temp = WorksheetFunction.Min(.Cells)
        Case "Ma": Temp = WorksheetFunction.Max(.Cells)
      End Select
      TongCT = TongCT + Temp
    End With
  Next i
End Function
Không biết em hiểu vấn đề có đúng ý anh không?
(code chắc cũng chưa được tối ưu lắm)
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Viết chay nha:

PHP:
Function SumMax(Data)
Set ArrData = Data
For i = 1 To ArrData.Rows.Count
    For j = 1 To ArrData.Columns.Count
        Maxi = IIf(IsNumeric(ArrData(i, j)) And ArrData(i, j) >= Maxi, ArrData(i, j), Maxi)
    Next j
    SumMax = SumMax + Maxi
    Maxi = 0
Next i
End Function

SumMin tương tự.

Nếu gộp lại vừa min vừa max chỉ thêm 1 vài dòng
 
Lần chỉnh sửa cuối:
Upvote 0
Nhờ toán tử XOR sẽ gọn hơn chúng ta tưởng & là 2 trong 1

Viết chay nha:
SumMin tương tự.
Nếu gộp lại vừa min vừa max chỉ thêm 1 vài dòng
Xin PTM0412 chuyển hàm của bạn thành hàm tổng hợp, như sau:

PHP:
Function TgCucTri(ByVal InRange As Range, Optional CucTieu As Boolean = True) As Double
Dim ArrRange As Range:                Dim CucTri As Double
Dim Ff As Long, Jj As Long

Set ArrRange = InRange
For Ff = 1 To ArrRange.Rows.Count '
    CucTri = Val(ArrRange(Ff, 1))
    For Jj = 1 To ArrRange.Columns.Count
        If Val(ArrRange(Ff, Jj)) > CucTri Xor CucTieu Then CucTri = ArrRange(Ff, Jj)
    Next Jj
    TgCucTri = TgCucTri + CucTri
Next Ff
End Function
 
Upvote 0
Nhờ toán tử XOR sẽ gọn hơn chúng ta tưởng & là 2 trong 1
Kính nhờ Bác giải thích hộ XOR và Xgìgìđó hộ, em thấy trong sách nhưng chưa biết xài.
Xin cám ơn Bác trước.

Chỉ biết rằng:

A|B|A or B|A xor B|A and B
True|True|True|False|True
True|False|True|True|False
False|True|True|True|False
False|False|False|False|False
 
Lần chỉnh sửa cuối:
Upvote 0
Kính nhờ Bác giải thích hộ XOR và Xgìgìđó hộ, em thấy trong sách nhưng chưa biết xài.
Xin cám ơn Bác trước.

Chỉ biết rằng:

A|B|A or B|A xor B|A and B
True|True|True|False|True
True|False|True|True|False
False|True|True|True|False
False|False|False|False|False

bác tham khảo tại đây xíu :

Nói đơn giản :
- And : Cùng phải thỏa mãn (Các phần tử đều là True) -> TRUE
- Or : Chỉ cần 1 phần tử thỏa mãn (Có ít nhất 1 phần tử là True) -> TRUE
- XOr : Các phần tử không giống nhau (Có cả True, False) --> TRUE

Thân!
 
Upvote 0
Mình gửi các bạn thêm một cách khác ngắn gọn hơn

PHP:
Function SumMaxMin(Rng As Range, Optional Cond As Byte = 1) As Double
  For i = 1 To Rng.Rows.Count
    With WorksheetFunction
        SumMaxMin = SumMaxMin + Choose(Cond, .Max(Rng.Rows(i)), .Min(Rng.Rows(i)))
    End With
  Next i
End Function
 

File đính kèm

Upvote 0
Tiếp lời của BAB 1 tẹo

Nói đơn giản :
PHP:
        - And : Cùng phải thỏa mãn (Các phần tử đều là True) -> TRUE
        - Or : Chỉ cần 1 phần tử thỏa mãn (Có ít nhất 1 phần tử là True) -> TRUE
        - XOr : Các phần tử không giống nhau (Có cả True, False) --> TRUE
Thân!

Ta xét hàm sau (được viết lại từ 'Help' về toán tử này trong VBA, chắc rõ hơn ít nhiều

PHP:
Function MyCheck(Cas As Byte) As Boolean
Dim A, B, C, D
A = 10: B = 8: C = 6: D = Null    ' Initialize variables.'
 Select Case Cas
 Case 1
    MyCheck = A > B Xor B > C    ' True;True => False.'
 Case 2
    MyCheck = B > A Xor B > C    ' False;True => True.'
 Case 3
    MyCheck = B > A Xor C > B    ' False;False => False.'
 Case 4
    MyCheck = B > D Xor A > B    ' Returns Null.'
 Case 5
    MyCheck = A Xor B    ' Returns 2 (bitwise comparison).'
 Case 6
    MyCheck = A Xor D       ' Returns NULL.?'
 End Select
End Function
 
Upvote 0
Cái XOR này trong ngành điện tự động hóa em xài hoài ---> Ứng dụng của nó thì vô vàn... Ví dụ đơn cử là mạch flip-flop (ví dụ cụ thể về ứng dụng: mở cửa--> đèn sáng --> đóng cửa ---> đền vẫn sáng ---> mở cửa tiếp ---> đèn tắt ---> đóng cửa lại ---> đèn tắt...)
Không ngờ trong Excel cũng chơi món này
Biểu diển nó trong công thức Excel sẽ là:
=OR(AND(A1,NOT(B1)),AND(NOT(A1),B1))
(Với A1, B1 là các giá trị logic)
 
Lần chỉnh sửa cuối:
Upvote 0
Kính nhờ Bác giải thích hộ XOR và Xgìgìđó hộ, em thấy trong sách nhưng chưa biết xài. Xin cám ơn Bác trước. Chỉ biết rằng:
A|B|A or B|A xor B|A and B
True|True|True|False|True
True|False|True|True|False
False|True|True|True|False
False|False|False|False|False
Thú thật mình cũng chỉ mới lõm bõm về nó ở trang WEB Ozgrid.com mà thôi
Ví dụ hàm xếp trật tự các ký tự trong 1 chuỗi, như sau:

PHP:
Function StrSort(ByVal StrC As String, Optional bDescending As Boolean = False) As String
     ' sorts a blank-delimited string.'
 Dim Matric() As String, GPE As String         ' temp string for exchange.'
 Dim Ww As Long, Zz As Long, Jj As Long
     
 Matric = Split(StrC, " "):                           Ww = UBound(Matric)
 For Zz = 0 To Ww
    Matric(Zz) = Trim(Matric(Zz))
 Next
     
 If Ww <= 1 Then
    StrSort = StrC
 Else
    For Zz = 0 To Ww - 1
        For Jj = Zz + 1 To Ww
            If (Matric(Jj) < Matric(Zz)) Xor bDescending Then
                GPE = Matric(Zz):                     Matric(Zz) = Matric(Jj)
                Matric(Jj) = GPE
            End If
        Next Jj
    Next Zz
    StrSort = Join(Matric, ", ")
 End If
End Function

Xin đề nghị các bạn thử tìm cách khác mà không sử dụng toán tử khó hiểu này được hay không?
Xin cảm ơn trước nhiều lắm đó nha!!
Không ngờ trong Excel cũng chơi món này
Không chỉ VBA trong excel đâu NDU à, mà mình cũng thấy nó trong Pascal, VB gì đó V.V. . .
Hình như là toàn bộ đó!
 
Lần chỉnh sửa cuối:
Upvote 0
Dùng xOR tạo biểu thức điều kiện

Thú thật mình cũng chỉ mới lõm bõm về nó ở trang WEB Ozgrid.com mà thôi
Ví dụ hàm xếp trật tự các ký tự trong 1 chuỗi, như sau:

PHP:
Function StrSort(ByVal StrC As String, Optional bDescending As Boolean = False) As String
     ' sorts a blank-delimited string.'
 Dim Matric() As String, GPE As String         ' temp string for exchange.'
 Dim Ww As Long, Zz As Long, Jj As Long
 
 Matric = Split(StrC, " "):                           Ww = UBound(Matric)
 For Zz = 0 To Ww
    Matric(Zz) = Trim(Matric(Zz))
 Next
 
 If Ww <= 1 Then
    StrSort = StrC
 Else
    For Zz = 0 To Ww - 1
        For Jj = Zz + 1 To Ww
            If (Matric(Jj) < Matric(Zz)) Xor bDescending Then
                GPE = Matric(Zz):                     Matric(Zz) = Matric(Jj)
                Matric(Jj) = GPE
            End If
        Next Jj
    Next Zz
    StrSort = Join(Matric, ", ")
 End If
End Function

Xin đề nghị các bạn thử tìm cách khác mà không sử dụng toán tử khó hiểu này được hay không?
Xin cảm ơn trước nhiều lắm đó nha!!

Không chỉ VBA trong excel đâu NDU à, mà mình cũng thấy nó trong Pascal, VB gì đó V.V. . .
Hình như là toàn bộ đó!


Trong code sắp xếp trên, người ta dùng toán tử xOR để xây dựng điều kiện:
Mã:
If (Matric(Jj) < Matric(Zz)) Xor bDescending Then
điều này tương đương với việc tách điều kiện của biến bDescending:

Nếu không dùng xOR, thì phải dùng 2 câu IF:
PHP:
If bDescending Then ' sắp giảm '
    If Matric(Jj) < Matric(Zz) then
      ...
    End If
Else
    If ...
       ...
    End If
End If

Toán tử xOR còn được gọi là toán tử "mặt nạ" vì nó cho phép tạo các phép "che" bit. Ví dụ, áp dụng vào việc chuyển đổi chữ hoa sang chữ thường:

Ta biết chữ A mã ASCII là 65, a: 97, space (blank) là 32 (kí hiệu sp)
giá trị 32 biểu diễn trong hệ nhị phân 8 bit:
00100000 (= 2^5 = 32)
ký tự a được biểu diễn là: 01100001 ( = 64 + 32 + 1) = 2^6 + 2^5 + 2^0
ký tự A được biểu diễn là: 01000001 ( = 64 + 1)
các ký tự hoa-thường trong bảng mã ASCII sai khác nhau chỉ 1 bit số 5 (đếm từ phải sang trái, từ 0 đến 7, bit cao nhât là 7)
do đó phép toán: a xOR sp -> sẽ tắt bit số 5 của a tạo ra kết quả là 65 = A (a hoa)
tương tự A xOR sp -> bật bit số 5 -> 97 = a (a thường)

Trở lại code trên: điều kiện: (x < y) xOR z
(với z = -1 hoặc 0 là 2 giá trị boolean True và False trong VBA) (lưu ý z=-1 biểu diễn 8 bit là 10000000 (bit 7 bằng 1)
Nếu chỉ quan tâm đến khía cạnh logic thì điều kiện trên sẽ có các trường hợp sau:

False xOR False -> False
False xOR True -> True ===> sắp giảm thì xét điề kiện khi x<y sai
True xOR False -> True ====> sắp tăng thì xét điều kiện khi x<y đúng
True xOR True -> False

Thân!
 
Upvote 0
Xin giới thiệu hàm tìm cực trị của thang đo trên đồ thị, chúng ta cùng ngâm cứu

PHP:
Function CucTri(rData As Range) As Variant
 'Returns a two-element variant containing a min and max value for chart'
 'scales based on the min and max values in the data range, computing'
 'values with the least number of significant digits necessary for the'
 'data range to cover some minimum fraction (dMinFrac) of the chart range.'
 Const dMinFrac As Double = 0.8
 Dim NumMin As Double, NumMax As Double 'min and max of data range'
 Dim GHD As Double, GHT As Double ' min and max of chart range'
 Dim dLog    As Double:                     Dim nDigit  As Integer
 With WorksheetFunction
    'Get the min and max of the data range'
    NumMin = .Min(rData):                 NumMax = .Max(rData)
    'If the data has a zero-span range, return that range'
    If NumMin = NumMax Then
        CucTri = Array(NumMin, NumMax)
        Exit Function '- - - - - - - - - - - - - - - - - - - - - - - - ->'
    End If
    'Compute the digit position for one significant digit'
    dLog = Log(.Max(Abs(NumMax), Abs(NumMin))) / Log(10)
    nDigit = CInt(dRndUpDn(-dLog, 1, False))
    Do
        'Round the min down, and the max up, to the computed significance'
        GHD = dRndUpDn(NumMin, nDigit, False)
        GHT = dRndUpDn(NumMax, nDigit, True)
        'If this chart range is sufficiently narrow for data range, finish;'
        'otherwise, add another significant digit and try again'
        If (NumMax - NumMin) / (GHT - GHD) >= dMinFrac Then
            Exit Do '- - - - - - - - - - - - - - - - - - - - - - - - ->'
        Else
            nDigit = nDigit + 1
        End If
    Loop
 End With
 'Return the computed values as a two-element variant
 CucTri = Array(GHD, GHT)
End Function
PHP:
Function dRndUpDn(dNum As Double, nDigit As Integer, bUpdn As Boolean) As Double
 'Returns a Double rounded up or down to the specified significance.'
 'Unlike ROUNDDOWN() and ROUNDUP(), this function rounds in absolute'
 'direction, rather than toward or away from zero.'
 'bUpDn = False => Round Down'
 '= True  => Round Up'
 If dNum = 0 Then Exit Function '- - - - - - - - - - - - - - - - - ->'
 With WorksheetFunction
    If dNum > 0 Xor bUpdn Then
        dRndUpDn = .RoundDown(dNum, nDigit)
    Else
        dRndUpDn = .RoundUp(dNum, nDigit)
    End If
 End With
End Function

| A | B | C | D |
||. . .|||
5|50|1250|||
6|41| 2487 |||
7| 11 | 110 | 10 | 60|
8| 60 |596| 100 | 2500 |
9|26|125|||
10|18|587|||
|||:=\+||
Ta chọn 2 ô C7:D7 ta nhập cú pháp =CucTri(A5:A10) & kết thúc bằng tổ hợp 3 phím cho hàm mảng
Tại C8:D8 ta lại nhập cú pháp hàm =CucTri(B5:B10) & cũng kết thúc như trên; Ta sẽ nhận được kết quả như trong
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Em góp thêm một cách làm bằng công thức thuần túy của Excel và không cần bất cứ một cột phụ hay Name nào cả

Hãy thử công thức này xem sao:

- Ví dụ dữ liệu có tại [A1:C10]:

1. Tổng các giá trị cực đại của mỗi dòng:
=SUMPRODUCT(SUBTOTAL(4,OFFSET($A$1:$C$10,ROW($A$1:$C$10)-ROW($A$1),0,1)))

2. Tổng các giá trị cực tiểu của mỗi dòng:
Thay đối số trong hàm Subtotal từ 4 --> 5
=SUMPRODUCT(SUBTOTAL(5,OFFSET($A$1:$C$10,ROW($A$1:$C$10)-ROW($A$1),0,1)))
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Vầy mới tổng quát hơn chứ:
=SUMPRODUCT(SUBTOTAL(4, OFFSET($A$1:$C$10,ROW(INDIRECT("1:"&ROWS($A$1:$C$10)))-1,,1,)))
Nên đặt name cho vùng dử liệu:
=SUMPRODUCT(SUBTOTAL(4, OFFSET(Vung,ROW(INDIRECT("1:"&ROWS(Vung)))-1,,1,)))
Với Vung = $A$1:$C$10
 
Upvote 0
Cám ơn quý vị đại ca. Lão cheet tit hiểu rồi.

Nói thêm: Với cách giải thích này của ndu:
trong hàm Excel:
A Xor B = OR(AND(A, NOT(B)), AND(NOT(A), B))

trong VB:
A Xor B = (A And Not B) Or (Not A And B)

thì phù hợp với cách diễn đạt logic học nhất!

Nhưng thú thiệt, hiểu là 1 chuyện, tìm đúng chỗ để ứng dụng thì chả dễ tí nào!
 
Upvote 0
Cám ơn quý vị đại ca. Lão cheet tit hiểu rồi.

Nói thêm: Với cách giải thích này của ndu:
trong hàm Excel:
A Xor B = OR(AND(A, NOT(B)), AND(NOT(A), B))

trong VB:
A Xor B = (A And Not B) Or (Not A And B)

thì phù hợp với cách diễn đạt logic học nhất!

Nhưng thú thiệt, hiểu là 1 chuyện, tìm đúng chỗ để ứng dụng thì chả dễ tí nào!
Ứng dụng thì nhiều lắm anh ơi... em diển nôm 1 kiểu ứng dụng trong ngành điện của em (chuyển thuật toán sang VBA)
PHP:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  If Target.Address = "$B$1" Then
    [A1] = -([A1] Xor Not Target)
  End If
End Sub
Trong điện tự động, em gọi mạch này là INC (Tăng trưởng)
Hoặc:
PHP:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  If Target.Address = "$B$1" Then
    [A1] = -([A1] + 1 Xor Not Target)
  End If
End Sub
Tăng trưởng rồi gấp đôi
vân vân và vân vân ---> Ôi bao la... Ẹc... Ẹc...
 
Upvote 0
Em góp thêm một cách làm bằng công thức thuần túy của Excel và không cần bất cứ một cột phụ hay Name nào cả

Hãy thử công thức này xem sao:

- Ví dụ dữ liệu có tại [A1:C10]:

1. Tổng các giá trị cực đại của mỗi dòng:


2. Tổng các giá trị cực tiểu của mỗi dòng:
Thay đối số trong hàm Subtotal từ 4 --> 5

Chuyển sang ROW cũng tốt, tuy nhiên nếu không giới hạn các số thì khi số lớn hơn số dòng của excel thì công thức sẽ bị sai.

-- Chúc vui--
 
Upvote 0
Lần chỉnh sửa cuối:
Upvote 0
Với công thức của em, anh có thể nói rõ hơn cụ thể là với ngưỡng số nào thì công thức sẽ bị sai không anh!?

hãy thử mấy mấy số có số lớn hơn số dòng của excel thì thấy ngay thôi mà.
Vì hàm row chỉ làm việc đúng với số >0 và không vượt quá số dòng tối đa của excel.

-- CV--
 
Upvote 0
hãy thử mấy mấy số có số lớn hơn số dòng của excel thì thấy ngay thôi mà.
Vì hàm row chỉ làm việc đúng với số >0 và không vượt quá số dòng tối đa của excel.
-- CV--

Trong vùng A1:C10, em gõ vào một ô bất kỳ một con số là 1 tỷ, em có thấy sai gì đâu anh! Tiếp theo em gõ tiếp con số (-2 tỷ), cũng chẳng thấy sai gì cả!
 
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom