Xin giúp hàm Vlookup và If (1 người xem)

  • Thread starter Thread starter vnproc
  • Ngày gửi Ngày gửi
Liên hệ QC

Người dùng đang xem chủ đề này

Đoán đại, thử phương án này xem sao

tại K2
=SUM($F2:$J2/1000*TRANSPOSE($P$15:$P$19))

copy công thức trên và bấm Ctrl+Shift+Enter để kết thúc công thức

copy cho cho K3,K4,...

tính theo tấn chắc vậy

Nếu không đổi ra tấn, và có kết quả như bài #18 thì sửa lại công thức cho bài #19 như sau

tại K2
=SUM($F2:$J2*TRANSPOSE($P$15:$P$19))

copy công thức trên và bấm Ctrl+Shift+Enter để kết thúc công thức

lưu ý: thứ tự các SP ở vùng F:J PHẢI GIỐNG như vùng O15:O19
 
Nếu không đổi ra tấn, và có kết quả như bài #18 thì sửa lại công thức cho bài #19 như sau

tại K2
=SUM($F2:$J2*TRANSPOSE($P$15:$P$19))

copy công thức trên và bấm Ctrl+Shift+Enter để kết thúc công thức

lưu ý: thứ tự các SP ở vùng F:J PHẢI GIỐNG như vùng O15:O19

Cái này đúng thay đổi vị trí mã sản phẩm sẽ không đúng với công thức. Cảm ơn bạn nhiều lắm.
 
Minh họa bằng bài toán thực tế:
Cách 1:
- Kiểm tra xem có vé hay không
- Có vé: Cho lên tàu
- Không có vé: không cho lên tàu

Cách 2:
- Cho tất cả lên tàu:
- Kiểm tra có vé: Ở lại
- Kiểm tra không có vé: đuổi xuống

===> Cách nào hay hơn nhỉ?

Như em nói ở bài trước:

Nếu như Thầy nói:

Tôi nói thế vì thấy nhiều trường hợp người dùng xài ISERROR hoặc IFERROR quá thừa. Ví dụ chỉ cần bẫy lỗi cell <> rổng thế này:
=IF(A1="", "", VLOOKUP(A1, bảng dỏ, 2,0))

Thì:

Nếu chỉ là bẫy A1="" thôi thì Thầy lại quá chủ quan, giả sử A1 có giá trị mà giá trị đó lại không có trong bảng dò tìm thì cũng sẽ bị lỗi #N/A.

Thực tế cho thấy, theo minh họa về Vé của Thầy, nếu người có vé thì lên, không vé thì biến, nhưng nếu có vé nhưng vé dỏm thì cũng biến, nhưng Thầy lại không bẫy được cái vụ vé dỏm.

Nôm na như thế này:

=VLOOKUP(A2,$N$2:$O$10,2,0)

Nếu cách cũ ta làm như sau:

=IF(ISNA(VLOOKUP(A2,$N$2:$O$10,2,0)),"LỖI",VLOOKUP(A2,$N$2:$O$10,2,0))

Như cách này thì nó phải "quét" 2 lần bảng dò tìm.

Nhưng với IFERROR thì em nghĩ rằng cơ chế nó sẽ không lặp lại hàm VLOOKUP mà nó cứ thực thi theo kiểu:

=SUBSTITUTE(VLOOKUP(A2,$N$2:$O$10,2,0),"#N/A","LỖI")

Đại khái là thế, mặc dù trong sheet mà ta làm như thế thì không được vì tham chiếu là lỗi thì kết quả sẽ lỗi, nhưng với Anh Bill thì cái lỗi này sẽ replace được.
 
Lần chỉnh sửa cuối:
Như em nói ở bài trước:

Nếu như Thầy nói:



Thì:



Thực tế cho thấy, theo minh họa về Vé của Thầy, nếu người có vé thì lên, không vé thì biến, nhưng nếu có vé nhưng vé dỏm thì cũng biến, nhưng Thầy lại không bẫy được cái vụ vé dỏm.

Nôm na như thế này:

=VLOOKUP(A2,$N$2:$O$10,2,0)

Nếu cách cũ ta làm như sau:

=IF(ISNA(VLOOKUP(A2,$N$2:$O$10,2,0)),"LỖI",VLOOKUP(A2,$N$2:$O$10,2,0))

Như cách này thì nó phải "quét" 2 lần bảng dò tìm.

Nhưng với IFERROR thì em nghĩ rằng cơ chế nó sẽ không lặp lại hàm VLOOKUP mà nó cứ thực thi theo kiểu:

=SUBSTITUTE(VLOOKUP(A2,$N$2:$O$10,2,0),"#N/A","LỖI")

Đại khái là thế, mặc dù trong sheet mà ta làm như thế thì không được vì tham chiếu là lỗi thì kết quả sẽ lỗi, nhưng với Anh Bill thì cái lỗi này sẽ replace được.

Tất nhiên không ai biết mã nguồn của Excel nên chỉ đoán thôi.
Tôi thử hình dung code của hàm IFERROR như thế nào. Tất nhiên cái dưới đây chỉ là để cho dễ hiểu ý thôi.
Mã:
Function IFERROR(value, value_if_error)
    IF value là #N/A, #VALUE!, #REF!, #DIV/0!, #NUM!, #NAME? hoặc #NULL! then
        IFERROR = value_if_error
    else
        IFERROR = value
    end if
End Function

Nguyên tắc là khi tính giá trị của một hàm nếu thông số là một biểu thức - tức các giá trị cụ thể, gọi hàm được liên kết bởi các toán tử - thì trước tiên giá trị của biểu thức được tính trước. Khi mọi giá trị của mọi biểu thức được tính giá trị rồi thì giá trị của hàm được tính thôi

Vậy công thức =IFERROR(gì_đó;"lỗi") được tính như sau:
Mã:
1. Tính giá trị của thông số thứ nhất: a = gì_đó
2. Tính giá trị của công thức: = IFERROR(a,"lỗi")

Dĩ nhiên "gì_đó" chỉ tính 1 lần.

Tức công thức =IFERROR(VLOOKUP(A1, bảng dỏ, 2,0),"") đượ tính như sau:
Mã:
1. a = VLOOKUP(A1, bảng dỏ, 2,0)
2. giá trị của công thức: = IFERROR(a,"")

Nếu nói về bẫy lỗi thì có khi ta biết trước được với những dữ liệu như thế nào thì sẽ có lỗi nên ta bẫy được. Ví dụ ta có trong công thức đoạn "gì đó/A1" thì ta bẫy A1 thôi. Nhưng nhiều khi ở vị trí A1 ta có một biểu thức phức tạp, có gọi hàm, mà nhiều khi hàm lồng hàm thì ta không thể biết phải loại những giá trị nào. Nhiều khi với "vài dữ liệu" này thì biểu thức trả về kết quả nhưng nhiều khi với "vài dữ liệu" khác thì lại có lỗi chia cho 0. Những giá trị của dữ liệu mà gây lỗi chả phải là 0, 1, hay bất cứ giá trị nào mà nó nhiều khi phụ thuộc vào tương quan giữa chúng. Kiểu như: tuổi A, B, C chả tốt cũng chả xấu nhưng (A, B) kị nhau còn (A, C) thì lại hợp nhau.

Dĩ nhiên là khi có thể "nhìn" thấy dữ liệu như thế nào là xấu thì ta bẫy luôn thôi. ndu nói tới chuyện lạm dụng IFERROR cũng có lẽ là nói về cái này. Vì chả lý gì thay cho, vd. (ô không trống)

Mã:
=IF(A1=0;"";gì_đó)

ta lại có

Mã:
=IFERROR(gì_đó;"")

trong khi gì_đó là một biểu thức phức tạp có chia cho A1
 
Lần chỉnh sửa cuối:
Cơ chế của nó đây:
Mã:
Function IfError2k3([B]Value[/B] As Variant, Value_if_Error As Variant) As Variant
  IfError2k3 = IIf(IsError(Value), Value_if_Error, Value)
End Function
Tức đàng nào cũng phải gọi hàm chính, tức là biến Value (để biết có lỗi hay không)
Trong khi đôi lúc chí cần động tác nhỏ (IF(A1="", "", VLOOKUP(...))) là giải quyết nhanh gọn
Vậy cái nào hiệu quả hơn?

Em thử viết một hàm na ná hàm VLOOKUP và một hàm mà em nghĩ thằng IFERROR nó vận hành thì như sau:

Nếu như mọi kiểu báo lỗi của hàm VLOOKUP cho ra một giá trị lỗi và được hoán đổi lỗi đó thành "N/A" thì hàm sẽ được xử lý như sau:

Mã:
Function VLOOKUP_TEST(ByVal Lookup_Value As String, ByVal Table_Array As Variant, ByVal Col_Index_Num As Long) As Variant
On Error GoTo ErrorHandler
    Dim TabArr As Variant, c As Long, r As Long, lbd As Long, ubd As Long
    TabArr = Table_Array
    If IsArray(TabArr) Then
        lbd = LBound(TabArr)
        ubd = UBound(TabArr)
        For r = lbd To ubd
            If TabArr(r, lbd) = Lookup_Value Then
                VLOOKUP_TEST = TabArr(r, Col_Index_Num)
                Exit Function
            End If
        Next
        If r > ubd Then
ErrorHandler:
            VLOOKUP_TEST = [B][COLOR=#ff0000]"N/A"[/COLOR][/B]
        End If
    End If
End Function

[COLOR=#008000]'Chi dung rieng cho ham VLOOKUP_TEST[/COLOR]
Function IFERROR_TEST(ByVal VLOOKUP_TEST_Result As Variant, Value_If_Error As Variant) As Variant
    If VLOOKUP_TEST_Result = [COLOR=#ff0000][B]"N/A" [/B][/COLOR]Then
        IFERROR_TEST = Value_If_Error
    Else
        IFERROR_TEST = VLOOKUP_TEST_Result
    End If
End Function

Như thế em đã chứng minh được rằng hàm IFERROR không dùng đến 2 lần hàm VLOOKUP trong một công thức xử lý lỗi.

Nếu Thầy chỉ bẫy lỗi IF(A1="", "", VLOOKUP(...)) thì vẫn còn tiềm ẩn những lỗi khác đấy, xin vui lòng xem file sẽ thấy các lỗi đó!

===========================================
P/s: Theo em nghĩ vấn đề tranh luận là vấn đề mở rộng đối với Hàm và Công thức, nên không thể gọi là lạc đề được.
 

File đính kèm

Tất nhiên không ai biết mã nguồn của Excel nên chỉ đoán thôi.
Tôi thử hình dung code của hàm IFERROR như thế nào. Tất nhiên cái dưới đây chỉ là để cho dễ hiểu ý thôi.
Mã:
Function IFERROR(value, value_if_error)
    IF value là #N/A, #VALUE!, #REF!, #DIV/0!, #NUM!, #NAME? hoặc #NULL! then
        IFERROR = value_if_error
    else
        IFERROR = value
    end if
End Function

Sau khi em gửi bài lên thì mới thấy bài của Thầy. Nhìn vào bài thì em thấy Thầy nhận xét như em đã nghĩ.

Em nghĩ hàm IFERROR sẽ viết như dưới đây, và em đã thử trong mọi trường hợp lỗi thì nó cũng như hàm gốc:

Mã:
Function IFERROR_TEST(ByVal Value As Variant, Value_If_Error As Variant) As Variant
    [COLOR=#ff0000][B]If IsError(Value) Then[/B][/COLOR]
        IFERROR_TEST = Value_If_Error
    Else
        IFERROR_TEST = Value
    End If
End Function
 
Như thế em đã chứng minh được rằng hàm IFERROR không dùng đến 2 lần hàm VLOOKUP trong một công thức xử lý lỗi.

Có lẽ tôi nói "gọi 2 lần" là chưa sát nghĩa
Ý tôi muốn nói:
- Giả định ta dùng IFRROR(Values...) tại cell B1 và kéo fill xuống đến B100
- Vậy thì thằng Values này sẽ được tính toán 100 lần (dù muốn hay không)
- Trong khi nếu tôi biết trước được những lỗi có thể xảy ra (chẳng hạn nếu A1="" thì lỗi). Vậy tôi dùng IF(A1="", "", Values)
- Ở những dòng mà giá trị kiểm tra là rổng thì Values không hề được gọi ra ---> Vậy có phải là tiết kiệm bộ nhớ không (Giả định thêm rằng cái thằng Values ấy là 1 công thức mảng thì càng tiết kiệm)
Nếu Thầy chỉ bẫy lỗi IF(A1="", "", VLOOKUP(...)) thì vẫn còn tiềm ẩn những lỗi khác đấy
.
Tôi chỉ ví dụ thôi mà... Lỗi gì thì ta cố mà tìm. Trường hợp như trong file, cùng lắm tôi dùng COUNTIF để kiểm tra vẫn rất nhẹ nhàng
Tôi nghĩ Nghĩa thừa hiểu điều này mà
---------------
Tóm lại: Tôi không phủ nhận công dụng của IFERROR, ISNA, ISERROR... chỉ là tôi muốn nói cái mà anh siwtom vừa nói ở tôi: KHÔNG NÊN LẠM DỤNG nếu như tìm thấy cách khác triệt tiêu lỗi hay hơn
 
Tôi chỉ ví dụ thôi mà... Lỗi gì thì ta cố mà tìm. Trường hợp như trong file, cùng lắm tôi dùng COUNTIF để kiểm tra vẫn rất nhẹ nhàng

Như trường hợp lỗi 2 ở file của em là lỗi #REF! thì cho dù dùng COUNTIF vẫn gặp lỗi này. Cho nên khi đã bẫy lỗi thì ngại chi phải xét tới bao nhiêu trường hợp lỗi mà bẫy cho hợp lý? Chỉ cần quy chung là lỗi thì bẫy lỗi mà thôi.

Cũng nói rộng hơn là nếu ô A1 tính toán với cái gì đó ra một giá trị, sau khi có giá trị thì ta tra giá trị đó bằng VLOOKUP. Nếu giá trị đó thõa điều kiện thì OK, nhưng nếu A1 nó tính toán làm sao đó mà ra một trong những lỗi {#N/A, #VALUE!, #REF!, #DIV/0!, #NUM!, #NAME? hoặc #NULL!} thì làm sao?

Vì thế, ta không thể lường trước mọi việc mà lỗi phát sinh được, cho nên ta dùng hàm IFERROR là một chuyện rất bình thường.
 
Lần chỉnh sửa cuối:
Như trường hợp lỗi 2 ở file của em là lỗi #REF! thì cho dù dùng COUNTIF vẫn gặp lỗi này. Cho nên khi đã bẫy lỗi thì ngại chi phải xét tới bao nhiêu trường hợp lỗi mà bẫy cho hợp lý? Chỉ cần quy chung là lỗi thì bẫy lỗi mà thôi.

Cũng nói rộng hơn là nếu ô A1 tính toán với cái gì đó ra một giá trị, sau khi có giá trị thì ta tra giá trị đó bằng VLOOKUP. Nếu giá trị đó thõa điều kiện thì OK, nhưng nếu A1 nó tính toán làm sao đó mà ra một trong những lỗi {#N/A, #VALUE!, #REF!, #DIV/0!, #NUM!, #NAME? hoặc #NULL!} thì làm sao?

Vì thế, ta không thể lường trước mọi việc mà lỗi phát sinh được, cho nên ta dùng hàm IFERROR là một chuyện rất bình thường.

Không thế nói vậy được! Tại sao? Vì dữ liệu là của ta, dữ liệu phải có cấu trúc nhất định và chỉ có loại dữ liệu tào lao mới không thể lường trước đó là lỗi gì
Ngoài ra, cái ví dụ về lỗi #REF! trong file của Nghĩa thì đó là sự CỐ TÌNH
=VLOOKUP(A8,$L$2:$M$7,3,0)
Và nếu đây không phải là CỐ TÌNH thì chỉ có thể nói là: Nghỉ xài Excel, mời chuyển sang "nghề" khác đi cho rồi (vì anh chẳng biết gì về Excel cả)
(Đừng nói Nghĩa "thường" xài công thức loại này nha)
 
Lần chỉnh sửa cuối:
Không thế nói vậy được! Tại sao? Vì dữ liệu là của ta, dữ liệu phải có cấu trúc nhất định và chỉ có loại dữ liệu tào lao mới không thể lường trước đó là lỗi gì
Ngoài ra, cái ví dụ về lỗi #REF! trong file của Nghĩa thì đó là sự CỐ TÌNH
=VLOOKUP(A8,$L$2:$M$7,3,0)
Và nếu đây không phải là CỐ TÌNH thì chỉ có thể nói là: Nghỉ xài Excel, mời chuyển sang "nghề" khác đi cho rồi (vì anh chẳng biết gì về Excel cả)
(Đừng nói Nghĩa "thường" xài công thức loại này nha)

Khi đi học, ông Thầy ổng bắt xử lý lỗi các hàm, ổng đưa ra dữ liệu và công thức có chứa lỗi, bắt phải xử lý lỗi, như thế thì bắt buộc phải xử lý chứ không nói là Thầy đưa ra hàm sai, cấu trúc "kỳ cục" v.v...
 
Khi đi học, ông Thầy ổng bắt xử lý lỗi các hàm, ổng đưa ra dữ liệu và công thức có chứa lỗi, bắt phải xử lý lỗi, như thế thì bắt buộc phải xử lý chứ không nói là Thầy đưa ra hàm sai, cấu trúc "kỳ cục" v.v...

Cái vụ "ông Thầy" gì đó tôi không biết. Giờ hỏi Nghĩa câu này: Nếu có thành viên nào trên GPE nhờ xử lý lỗi công thức VLOOKUP(A8,$L$2:$M$7,3,0) thí Nghĩa sẽ khuyên họ làm gì:
- Lồng IFERROR vào?
- Bảo rằng người ta đã gõ sai, nên sửa con số 3 thành số 2?
Nếu Nghĩa khuyên người ta lòng IFERROR vào thì đúng là tôi không còn gì để nói nữa
 
Cái vụ "ông Thầy" gì đó tôi không biết. Giờ hỏi Nghĩa câu này: Nếu có thành viên nào trên GPE nhờ xử lý lỗi công thức VLOOKUP(A8,$L$2:$M$7,3,0) thí Nghĩa sẽ khuyên họ làm gì:
- Lồng IFERROR vào?
- Bảo rằng người ta đã gõ sai, nên sửa con số 3 thành số 2?
Nếu Nghĩa khuyên người ta lòng IFERROR vào thì đúng là tôi không còn gì để nói nữa

Đương nhiên là sửa lại số cột rồi mà Thầy, tuy nhiên đó là cái mà ông Thầy ổng "bẫy" học trò nên đứa nào mà sửa đúng số cột thì điểm cao hơn!

Nhưng cái quan trọng là ở ô A8 nó chứa các lỗi {#N/A, #VALUE!, #REF!, #DIV/0!, #NUM!, #NAME? hoặc #NULL!} thì cũng phải dùng IFERROR thôi, chứ không thể bẫy lỗi kiểu =IF(A8="","",xxxx) được!
 
Nhưng cái quan trọng là ở ô A8 nó chứa các lỗi {#N/A, #VALUE!, #REF!, #DIV/0!, #NUM!, #NAME? hoặc #NULL!} thì cũng phải dùng IFERROR thôi, chứ không thể bẫy lỗi kiểu =IF(A8="","",xxxx) được!

Thế sao không "trị" ô A8?
TRỊ NGUYÊN NHÂN chứ không TRỊ HẬU QUẢ (tức không dùng IFERROR)
 
Thế sao không "trị" ô A8?
TRỊ NGUYÊN NHÂN chứ không TRỊ HẬU QUẢ (tức không dùng IFERROR)

Ví như không dùng cột phụ để tính là ô A8, mà công thức tính trực tiếp thế này:

Công thức như thế này: =VLOOKUP(VLOOKUP(A8,$L$2:$M$7,3,0),$R$2:$X$7,3,0)

Thì phải làm sao để tránh được lỗi #N/A được chứ Thầy?
 
Ví như không dùng cột phụ để tính là ô A8, mà công thức tính trực tiếp thế này:

Công thức như thế này: =VLOOKUP(VLOOKUP(A8,$L$2:$M$7,3,0),$R$2:$X$7,3,0)

Thì phải làm sao để tránh được lỗi #N/A được chứ Thầy?

Trời đất!
- Thứ nhất: Công thức viết sai ---> Mời học lại Excel
- Thứ hai: Sửa lại =VLOOKUP(VLOOKUP(A8,$L$2:$M$7,2,0),$R$2:$X$7,3,0)
- Thứ ba: Bẫy lỗi cho VLOOKUP --> Chuyện quá thường: 2 thằng VLOOKUP thì 2 thằng COUNTIF
 
Trời đất!
- Thứ nhất: Công thức viết sai ---> Mời học lại Excel
- Thứ hai: Sửa lại =VLOOKUP(VLOOKUP(A8,$L$2:$M$7,2,0),$R$2:$X$7,3,0)
- Thứ ba: Bẫy lỗi cho VLOOKUP --> Chuyện quá thường: 2 thằng VLOOKUP thì 2 thằng COUNTIF

Em không nói công thức trong cái file đó mà em nói VLOOKUP lồng trong VLOOKUP

Trong trường hợp các hàm này lồng vô nhau như vậy, nếu phát sinh lỗi thì hoặc là cả 2 hoặc là 1 hàm bị lỗi.

Và nếu dùng COUNTIF cho cả 2 thì công thức quá rườm rà, nó phải đếm trước 2 lần, rồi mới thực hiện dò tìm 2 lần. Trong khi nếu ta thêm IFERROR thì các anh cứ tính đã đi, nếu tính xong mà lỗi thì ta báo lỗi, thế thôi.

=IFERROR(VLOOKUP(VLOOKUP(A8,$L$2:$M$7,3,0),$R$2:$X$7,3,0),"LỖI")

=VLOOKUP(IF(COUNTIF($L$2:$L$7,A8)=0,"LỖI",VLOOKUP(A8,$L$2:$M$7,3,0)),$R$2:$X$7,3,0)

2 công thức cái nào rườm rà hơn? Mới bẫy lỗi VLOOKUP ở trong đó, rồi làm sao bẫy được cái VLOOKUP ngoài bằng COUNTIF nữa ta? Hay phải lặp lại công thức bên trong lần nữa?

------------------------------------------------------------------------
P/s: Mà em nghĩ do mỗi môi trường, mỗi CSDL của mỗi công việc mà có hướng bẫy lỗi khác nhau, nên chỉ bàn tới đây, ai cũng biết mình phải làm gì với file của mình.
Trân trọng.
 
Lần chỉnh sửa cuối:
2 công thức cái nào rườm rà hơn? Mới bẫy lỗi VLOOKUP ở trong đó, rồi làm sao bẫy được cái VLOOKUP ngoài bằng COUNTIF nữa ta? Hay phải lặp lại công thức bên trong lần nữa?

------------------------------------------------------------------------
P/s: Mà em nghĩ do mỗi môi trường, mỗi CSDL của mỗi công việc mà có hướng bẫy lỗi khác nhau, nên chỉ bàn tới đây, ai cũng biết mình phải làm gì với file của mình.
Trân trọng.

Bẫy lỗi luôn là bài toán mà người dùng sợ nhất, và nó luôn rườm rà
Trong VBA, cứ On Error Resume Next hoặc On Error Goto... cũng là để giải quyết cái khoản lười, khỏi suy nghĩ cho người dùng. Trên bảng tính, IFERROR cũng mang ý nghĩa tương tự
Riêng tôi, dù tự mình bẫy lỗi có rườm rà nhưng tôi vẫn thích ---> Ít nhất câu lệnh On Error Resume Next mà tôi hay đặt ở đầu code cũng chưa khi nào được dùng tới (xóa luôn cũng được)
--------------
Đó là quan điểm, giải thuật của mỗi người! Nghĩa hoặc ai đó thích bẫy lỗi theo kiểu IFERROR thì cứ xài. Riêng tôi KHÔNG KHOÁI
Thế thôi!
 
Web KT

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

Back
Top Bottom