Giúp em tìm lỗi vòng lặp bị lỗi Run time error 13 : Type mismatch (1 người xem)

Liên hệ QC

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

AnhThu-1976

Thành viên tích cực
Tham gia
17/10/14
Bài viết
1,067
Được thích
175
Em đang tập thử code:
đề bài: dựa vào cột A của sheet Ma tìm những mã này ở sheet Data gán xuống sheet KetQua
Mã:
Sub Loc()
    Dim Data, kQarr, i, j, k, lr, lr1, Tmp
    ReDim kQarr(1 To 65000, 1 To 3)
    With Sheets("Data")
        lr = .Range("A" & Rows.Count).End(3).Row
        Data = .Range("A1:C" & lr).Value
    End With
    With Sheets("Ma")
        lr1 = .Range("A" & Rows.Count).End(3).Row
        MsgBox lr1
        Tmp = .Range("A1:A" & lr1).Value
    End With
    For i = 1 To UBound(Data)
        For j = 1 To UBound(Tmp)
            If Data(i, 1) = Tmp(j, 1) Then
                k = k + 1
                kQarr(k, 1) = Data(i, 1)
                kQarr(k, 2) = Data(i, 2)
                kQarr(k, 3) = Data(i, 3)
            End If
        Next j
    Next i
    Sheets("KetQua").Range("B5:D5000").Clear
    Sheets("KetQua").Range("B5:D5").Resize(k).Value = kQarr
End Sub
Code trên vẫn chạy đúng nếu bên sheet Ma có nhiều hơn 1 mã và ít nhất có 1 mã có trong bộ mã của cột A sheet Data
* Code bị lỗi
Nếu bên sheet Ma chỉ có 1 mã hoặc không có mã nào hoặc có nhiều hơn 1 mã nhưng nếu 1 trong các mã này không có trong bộ mã của cột A sheet Data thì đều bị báo lỗi
Các anh/chị giúp em phân tích và sửa lỗi code. Em cảm ơn
* điều chỉnh thêm: Em đã tìm thêm trường hợp không có kết quả thì xét If k>0 ....
 

File đính kèm

Giải thích nhiều quá mà lại thiếu phần quan trọng nhất:
Báo lỗi ở câu nào?
 
Upvote 0
Em đang tập thử code:
đề bài: dựa vào cột A của sheet Ma tìm những mã này ở sheet Data gán xuống sheet KetQua
Mã:
Sub Loc()
    Dim Data, kQarr, i, j, k, lr, lr1, Tmp
    ReDim kQarr(1 To 65000, 1 To 3)
    With Sheets("Data")
        lr = .Range("A" & Rows.Count).End(3).Row
        Data = .Range("A1:C" & lr).Value
    End With
    With Sheets("Ma")
        lr1 = .Range("A" & Rows.Count).End(3).Row
        MsgBox lr1
        Tmp = .Range("A1:A" & lr1).Value
    End With
    For i = 1 To UBound(Data)
        For j = 1 To UBound(Tmp)
            If Data(i, 1) = Tmp(j, 1) Then
                k = k + 1
                kQarr(k, 1) = Data(i, 1)
                kQarr(k, 2) = Data(i, 2)
                kQarr(k, 3) = Data(i, 3)
            End If
        Next j
    Next i
    Sheets("KetQua").Range("B5:D5000").Clear
    Sheets("KetQua").Range("B5:D5").Resize(k).Value = kQarr
End Sub
Code trên vẫn chạy đúng nếu bên sheet Ma có nhiều hơn 1 mã và ít nhất có 1 mã có trong bộ mã của cột A sheet Data
* Code bị lỗi
Nếu bên sheet Ma chỉ có 1 mã hoặc không có mã nào hoặc có nhiều hơn 1 mã nhưng nếu 1 trong các mã này không có trong bộ mã của cột A sheet Data thì đều bị báo lỗi
Các anh/chị giúp em phân tích và sửa lỗi code. Em cảm ơn
* điều chỉnh thêm: Em đã tìm thêm trường hợp không có kết quả thì xét If k>0 ....
Bạn giải thích rõ hơn chổ trùng mã ở sheet data, cụ thể trùng mã 123 nhưng 2 cột B và C khác nhau thì có lấy hay không? hoặc trùng mã 123 nhưng 2 cột B và C giống nhau thì có lấy hay không?
 
Upvote 0
Giải thích nhiều quá mà lại thiếu phần quan trọng nhất:
Báo lỗi ở câu nào?
Bây giờ tại sheet Mã đang có 2 mã 123 và 654 ,nếu ta bỏ bớt mã 654 chỉ còn mã 123 thôi thì khi chạy code nó báo lỗi dòng
For j = 1 To UBound(Tmp)
Bạn giải thích rõ hơn chổ trùng mã ở sheet data, cụ thể trùng mã 123 nhưng 2 cột B và C khác nhau thì có lấy hay không? hoặc trùng mã 123 nhưng 2 cột B và C giống nhau thì có lấy hay không?
Trùng mã vẫn lấy bình thường, ví dụ mã 123 có 2 lần vẫn lấy 2 lần cho dù cột B hay C giống hay khác nhau
 
Upvote 0
- Nếu sheet Ma chỉ có 1 mã, biến tmp nhận 1 giá trị đơn chứ không phải mảng, do đó UBound, truy xuất tmp(i, j) đều bị lỗi
- Nếu k = 0 thì Redim lỗi kích thước không thể bằng không
 
Upvote 0
Bây giờ tại sheet Mã đang có 2 mã 123 và 654 ,nếu ta bỏ bớt mã 654 chỉ còn mã 123 thôi thì khi chạy code nó báo lỗi dòng
For j = 1 To UBound(Tmp)

Trùng mã vẫn lấy bình thường, ví dụ mã 123 có 2 lần vẫn lấy 2 lần cho dù cột B hay C giống hay khác nhau
Bạn kiểm tra xem Tmp có phải mảng không trước khi dùng UBound(Tmp) bằng câu lệnh.
Mã:
If IsArray(Tmp) Then
Bạn tùy biến mà sửa lại code cho đúng là được.
Còn thiếu mã thì bạn khai báo thêm biến như sau:
Mã:
Dim kt As Boolean
Sau đó bạn sửa lại 2 vòng For như sau:
Mã:
For j = 1 To UBound(Tmp)
            kt = True
            For i = 1 To UBound(Data)
                If Data(i, 1) = Tmp(j, 1) Then
                    k = k + 1
                    kQarr(k, 1) = Data(i, 1)
                    kQarr(k, 2) = Data(i, 2)
                    kQarr(k, 3) = Data(i, 3)
                    kt = False
                End If
            Next i
            If kt Then
                    k = k + 1
                    kQarr(k, 1) = Tmp(j, 1)
                End If
    Next j
 
Upvote 0
Dựa vào các trả lời trên, em viết như sau, không biết là code có thể rút gọn hơn không bắt đầu từ phần For ...
Mã:
Sub Loc()
    Dim Data, kQarr, i, j, k, lr, lr1, Tmp
    ReDim kQarr(1 To 65000, 1 To 3)
    With Sheets("Data")
        lr = .Range("A" & Rows.Count).End(3).Row
        Data = .Range("A1:C" & lr).Value
    End With
    With Sheets("Ma")
        lr1 = .Range("A" & Rows.Count).End(3).Row
        MsgBox lr1
        Tmp = .Range("A1:A" & lr1).Value
    End With
    For i = 1 To UBound(Data)
        If IsArray(Tmp) Then
            For j = 1 To UBound(Tmp)
                If Data(i, 1) = Tmp(j, 1) Then
                    k = k + 1
                    kQarr(k, 1) = Data(i, 1)
                    kQarr(k, 2) = Data(i, 2)
                    kQarr(k, 3) = Data(i, 3)
                End If
            Next j
        End If
        If Data(i, 1) = Sheets("Ma").Range("A1") Then
            k = k + 1
            kQarr(k, 1) = Data(i, 1)
            kQarr(k, 2) = Data(i, 2)
            kQarr(k, 3) = Data(i, 3)
        End If
    Next i
    Sheets("KetQua").Range("B5:D5000").Clear
    If k > 0 Then
        Sheets("KetQua").Range("B5:D5").Resize(k).Value = kQarr
    End If
End Sub
Em cảm ơn các anh đã hướng dẫn
 
Upvote 0
Không ai làm vậy cả. Kiểm tra thì kiểm tra ngay khi nó xuất hiện, nhét vào lòng lặp để mắc khổ.

Kỹ thuật xử lý chép Range vào Array mình hướng dẫn nhiều rồi cơ mà.
Đơn giản nhất là +1 và -1 vào biến lR1
PHP:
lR1 = .Range("A" & Rows.Count).End(3).Row + 1
Tmp = .Range("A1:A" & lR1).Value2
lR1 = Ubound(Tmp,1) -1
'...
For j = 1 To lR1 'Đừng tính đi tính lại cái UBound(Tmp) trong vòng lặp cho khổ cuộc đời
 
Upvote 0
If IsArray(Tmp) Then
Câu này phải để ra ngoài vòng lặp, vì nếu là mảng mới lặp, không phải mảng mà lặp thì lại lỗi UBound nữa.
Còn nếu Else thì sao? vẫn phải chạy cái gì đó chứ?
Bạn sửa theo ý IsArray, còn nếu là tôi thì sẽ xét ngay lr1 và If ngay trên lr1.
 
Upvote 0
Em đang tập thử code:
đề bài: dựa vào cột A của sheet Ma tìm những mã này ở sheet Data gán xuống sheet KetQua
Mã:
Sub Loc()
    Dim Data, kQarr, i, j, k, lr, lr1, Tmp
    ReDim kQarr(1 To 65000, 1 To 3)
    With Sheets("Data")
        lr = .Range("A" & Rows.Count).End(3).Row
        Data = .Range("A1:C" & lr).Value
    End With
    With Sheets("Ma")
        lr1 = .Range("A" & Rows.Count).End(3).Row
        MsgBox lr1
        Tmp = .Range("A1:A" & lr1).Value
    End With
    For i = 1 To UBound(Data)
        For j = 1 To UBound(Tmp)
            If Data(i, 1) = Tmp(j, 1) Then
                k = k + 1
                kQarr(k, 1) = Data(i, 1)
                kQarr(k, 2) = Data(i, 2)
                kQarr(k, 3) = Data(i, 3)
            End If
        Next j
    Next i
    Sheets("KetQua").Range("B5:D5000").Clear
    Sheets("KetQua").Range("B5:D5").Resize(k).Value = kQarr
End Sub
Code trên vẫn chạy đúng nếu bên sheet Ma có nhiều hơn 1 mã và ít nhất có 1 mã có trong bộ mã của cột A sheet Data
* Code bị lỗi
Nếu bên sheet Ma chỉ có 1 mã hoặc không có mã nào hoặc có nhiều hơn 1 mã nhưng nếu 1 trong các mã này không có trong bộ mã của cột A sheet Data thì đều bị báo lỗi
Các anh/chị giúp em phân tích và sửa lỗi code. Em cảm ơn
* điều chỉnh thêm: Em đã tìm thêm trường hợp không có kết quả thì xét If k>0 ....
Nếu mà là mình thì mình viết a1:b là được.Nhưng có 1 cái là nó sẽ làm cho mảng đó nặng hơn.Nhưng chắc cũng không sao.
 
Upvote 0
Không ai làm vậy cả. Kiểm tra thì kiểm tra ngay khi nó xuất hiện, nhét vào lòng lặp để mắc khổ.

Kỹ thuật xử lý chép Range vào Array mình hướng dẫn nhiều rồi cơ mà.
Đơn giản nhất là +1 và -1 vào biến lR1
PHP:
lR1 = .Range("A" & Rows.Count).End(3).Row + 1
Tmp = .Range("A1:A" & lR1).Value2
lR1 = Ubound(Tmp,1) -1
'...
For j = 1 To lR1 'Đừng tính đi tính lại cái UBound(Tmp) trong vòng lặp cho khổ cuộc đời
Mình sửa lại như sau
Mã:
Sub Loc()
    Dim Data, kQarr, i, j, k, lr, lr1, Tmp
    ReDim kQarr(1 To 65000, 1 To 3)
    With Sheets("Data")
        lr = .Range("A" & Rows.Count).End(3).Row
        Data = .Range("A1:C" & lr).Value
    End With
    With Sheets("Ma")
        lr1 = .Range("A" & Rows.Count).End(3).Row + 1' cộng 1 vào chỗ này
        MsgBox lr1
        Tmp = .Range("A1:A" & lr1).Value
    End With
    For i = 1 To UBound(Data)
        For j = 1 To UBound(Tmp) - 1' trừ 1 vào chỗ này
            If Data(i, 1) = Tmp(j, 1) Then
                k = k + 1
                kQarr(k, 1) = Data(i, 1)
                kQarr(k, 2) = Data(i, 2)
                kQarr(k, 3) = Data(i, 3)
            End If
        Next j
    Next i
    Sheets("KetQua").Range("B5:D5000").Clear
    If k > 0 Then
        Sheets("KetQua").Range("B5:D5").Resize(k).Value = kQarr
    End If
End Sub
 
Upvote 0
Tôi thì thua sì tin code GPE lâu rồi.
Một mảng dữ liệu đàng hoàng đọc từ bảng tính ra và dùng để so sánh mà đặt cho cái tên Tmp.
Nếu bảo tạm thời thì biến nào trong chương trình lại chẳng tạm thời.
Cái biến thực sự là tạm thời (dùng tạm và dùng lại được) thì chẳng chịu dùng.

Trên tính cách thì Tmp nó xứng đáng cho lr và lr1 hơn.
 
Upvote 0
Vậy nhờ bạn bạn viết thẳng vô code, cảm ơn bạn!
Befaint mất kiên nhẫn với bạn rồi. Mà cũng phải thôi, bạn ấy nói 2 chuyện mà bạn chẳng làm theo chuyện nào:
- End row + 1 sau đó tính UBound rồi -1
- Đừng tính UBound trên vòng lặp
Tiếp theo là bạn cũng mất kiên nhẫn và không muốn tự làm nữa.

Nếu bạn thích thì bạn làm cả tôi mất kiên nhẫn bằng cách đọc bài 9 và thử làm theo
 
Upvote 0
@AnhThu-1976
Hình như ý bài 8 là bên dưới đây thì phải
Mã:
Sub Loc_()
    Dim Data, kQarr, i, j, k, lr, lr1, Tmp
    ReDim kQarr(1 To 65000, 1 To 3)
    With Sheets("Data")
        lr = .Range("A" & Rows.Count).End(3).Row
        Data = .Range("A1:C" & lr).Value
    End With
    With Sheets("Ma")
        lr1 = .Range("A" & Rows.Count).End(3).Row + 1 ' cô?ng 1 va`o chô~ na`y
        MsgBox lr1
        Tmp = .Range("A1:A" & lr1).Value
        lr1 = UBound(Tmp) - 1'Hình như là trừ 1 ở đây
    End With
    For i = 1 To UBound(Data)
        For j = 1 To lr1'Hình như là dùng luôn lr1 ở đây
            If Data(i, 1) = Tmp(j, 1) Then
                k = k + 1
                kQarr(k, 1) = Data(i, 1)
                kQarr(k, 2) = Data(i, 2)
                kQarr(k, 3) = Data(i, 3)
            End If
        Next j
    Next i
    Sheets("KetQua").Range("B5:D5000").Clear
    If k > 0 Then
        Sheets("KetQua").Range("B5:D5").Resize(k).Value = kQarr
    End If
End Sub
 
Upvote 0
@AnhThu-1976
Hình như ý bài 8 là bên dưới đây thì phải
Mã:
Sub Loc_()
    Dim Data, kQarr, i, j, k, lr, lr1, Tmp
    ReDim kQarr(1 To 65000, 1 To 3)
    With Sheets("Data")
        lr = .Range("A" & Rows.Count).End(3).Row
        Data = .Range("A1:C" & lr).Value
    End With
    With Sheets("Ma")
        lr1 = .Range("A" & Rows.Count).End(3).Row + 1 ' cô?ng 1 va`o chô~ na`y
        MsgBox lr1
        Tmp = .Range("A1:A" & lr1).Value
        lr1 = UBound(Tmp) - 1'Hình như là trừ 1 ở đây
    End With
    For i = 1 To UBound(Data)
        For j = 1 To lr1'Hình như là dùng luôn lr1 ở đây
            If Data(i, 1) = Tmp(j, 1) Then
                k = k + 1
                kQarr(k, 1) = Data(i, 1)
                kQarr(k, 2) = Data(i, 2)
                kQarr(k, 3) = Data(i, 3)
            End If
        Next j
    Next i
    Sheets("KetQua").Range("B5:D5000").Clear
    If k > 0 Then
        Sheets("KetQua").Range("B5:D5").Resize(k).Value = kQarr
    End If
End Sub
Nếu lr = Rows.Count: Tiêu tùng
For i = 1 To UBound(Data) vẫn còn tính UBound(Data) rất nhiều lần
If Data(i, 1) = Tmp(j, 1) Then: Data(i, 1) phải lấy nhiều lần

For i = 1 To UBound(Data)
For j = 1 To lr1'Hình như là dùng luôn lr1 ở đây
.....
Next j
Next i
Chạy chậm do phải duyệt hết i, j. Cần có Exit For của For j
 
Upvote 0
Nếu lr = Rows.Count: Tiêu tùng
For i = 1 To UBound(Data) vẫn còn tính UBound(Data) rất nhiều lần

For i = 1 To UBound(Data)
For j = 1 To lr1'Hình như là dùng luôn lr1 ở đây
.....
Next j
Next i
Chạy chậm do phải duyệt hết i, j. Cần có Exit For của For j
Bài trên chỉ muốn giải thích góp ý của bài 8 thôi bác. Với lại hình như là thớt cũng chỉ chạy thử code nên sửa như bài 8 xong, thấy chạy là dừng, không làm gì nữa bác ạ.
 
Upvote 0
Đã làm thì nên làm tới bến sáng về sớm. Khà khà:):)
Thớt học code theo kiểu Cô Tô Mộ Dung gom tất cả chiêu thức thiên hạ về thư viện mình mà luyện.
Đã nhiều lần tôi cảnh báo rằng Kiều Phong chỉ cần Hàng Long Thập Bát Chưởng vũ lộng Tụ Hiền Trang. Cái quan trọng là bản chất nội lực, một tiếng quát đủ đe doạ Đoàn Diên Khánh không dám dở trò phúc ngữ.

(*) tôi nói theo ý của chính truyện Kim Dung, không phải phiên bản phim Hồng Kông đã chỉnh sửa nhân vật Mộ Dung Phục để câu nước mắt khán giả.
 
Upvote 0
AnhThu-1976

Phương hướng để giải quyết code của Bạn đơn giản là thế này:

1. Khi lấy Row Cuối cùng chứa dữ liệu bắt đầu từ một Range thì bạn vận dụng đoạn code sau:

PHP:
LR = WS.Range("A5")(Rows.Count  - WS.Range("A5").Row, 1).End(xlUp).Row - WS.Range("A5").Row + 1

Và Tạo mảng bằng phương thức Resize, Range("A5").Resize(LR, Col)


2. Kiểm soát nếu Mảng nhận được Từ phương thức End là Không đủ điều kiện

PHP:
If (WS.Range("A5").Value = vbNullString And LR = 1) Or LR < 1 Then Exit Sub

*Nếu là bạn đang học VBA thì học thêm khai báo Static
Đơn giản là gọi 10 lần Test_Static liên tục sẽ hiểu:

PHP:
Sub Test_Static()
   Static I As Long: I = I + 1
   Debug.Print I
   If I > 5 Then End 'Khởi tạo lại toàn bộ biến Toàn cục Và các khai báo kiểu Static, đồng thời dừng mọi tiến trình của Application'
   'If I > 5 Then I = 0'
End Sub

Static áp dụng cho bài trên: Bỏ qua các phần tử đã duyệt trước đó ở Sheet("Ma") chẳng hạn

*Bạn tham khảo đoạn code dưới đây để vận dụng
Nếu bạn biết ReDim Preserve thì vận dụng thêm



PHP:
Sub Loc()
  Dim WB As Workbook
  Set WB = ThisWorkbook
  '-----------------------------'
  Const MaxCol = 3
  '-----------------------------'
  Dim Data_A, Data_B
  Dim I&, J&, m&, K&, LR_A&, LR_B&
  Dim Data, sRng$, LR&, Col%, WS As Worksheet
  '-----------------------------'
  Set WS = WB.Worksheets("Data")
  sRng = "A1": Col = MaxCol
  GoSub GetData: LR_A = LR: Data_A = Data
  '-----------------------------'
  Set WS = WB.Worksheets("Ma")
  sRng = "A1": Col = 1
  GoSub GetData: LR_B = LR: Data_B = Data
  '-----------------------------'
  ReDim kQarr(1 To LR_A, 1 To MaxCol)
  '-----------------------------'
  For J = 1 To LR_B
    For I = 1 To LR_A
      If Data_A(I, 1) = Data_B(J, 1) Then
        K = K + 1 'Or ReDim Preserve -> Transpore'
        For m = 1 To MaxCol
          kQarr(K, m) = Data_A(I, m)
        Next m
      End If
  Next I, J
  '-----------------------------'
  If K = 0 Then GoTo Ends
  With WB.Worksheets("KetQua").[B5]
    .Resize(Rows.Count - .Row, MaxCol).ClearContents
    .Resize(K, MaxCol).Value = kQarr
  End With
Ends:
  Set WB = Nothing: Set WS = Nothing
  Exit Sub
GetData:
  With WS.Range(sRng)
    LR = .Offset(Rows.Count - .Row, 1).End(xlUp).Row - .Row + 1
    If (.Value = vbNullString And LR = 1) Or LR < 1 Then GoTo Ends
    Data = .Resize(LR, Col).Value
  End With
Return
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Thớt trúng số nhé. Muốn học nhiều chiêu thì chuyến này được ngay cái "quái chiêu" tuyệt đỉnh.
Nếu hiểu được chiêu này của tác giả thì đường lên luận kiếm Hoa Sơn không còn xa đâu.
 
Upvote 0
Nếu hiểu được chiêu này của tác giả thì đường lên luận kiếm Hoa Sơn không còn xa đâu.
Đối với mỗi người thì sẽ học code chuyên sâu hay là không chuyên sâu
Đối với em, học code để áp dụng vào lĩnh vực mình làm việc sao nó mang tính chính xác nhất, rồi đến không bị lỗi, còn thời gian nhanh hay chậm vài giây thì không thành vấn đề
Vì thế em chẳng cần học tuyệt chiêu gì, miễn sao nó đạt được yêu cầu như trên là được, chứ không phải để hơn thua với ai.
Trong quá trình học rồi thử nghiệm mà thấy code sai hay bị lỗi thì sẽ hỏi
và những vấn đề hỏi thì em cũng đã tìm hiểu rồi và vấn đề đó nó vượt kiến thức mình đang có thì em mới hỏi
Nói thật, dù sao em thấy mình vẫn hơn những người không biết mà không dám hỏi (những người dấu dốt) thế thôi
 
Upvote 0
Ủa hôm nào mới đòi học "đủ mọi kiểu" sao bây giờ thành "áp dụng" và "chính xác" vậy.
áp dụng thuộc về phân tích vấn đề, chính xác thuộc về kiểm soát kết quả.

Nói chuyện chơi chút thôi. Thớt muốn học gì tôi chẳng quan tâm lắm. Chỉ là lâu lắm mới thấy có người dùng từ khoá GoSub cho nên sẵn tiện tôi nhắc nhở các bạn (khác) muốn học code thì nên hỏi lại tác giả giải thích lý do tại sao dùng từ khoá này.
Đây là lời khuyên thật chứ không đùa. Phân biệt được GoSub và Call là trình độ code đã trên căn bản rồi. Nên nắm cơ hội mà học.
 
Lần chỉnh sửa cuối:
Upvote 0
Ủa hôm nào mới đòi học "đủ mọi kiểu" sao bây giờ thành "áp dụng" và "chính xác" vậy.
Ở chủ đề trên, bài 9 có viết
VetMini đã viết:
Thắc mắc: học chi nhiều cái chi tiết thế này. Nhớ sao hết.
Đúng là nhớ không hết
Nhưng em lập chủ đề này để nhiều người khác cùng đọc
1/ Để họ tự chọn 1 cách nào để áp dụng
2/ Khi họ đọc 1 chủ đề khác mà có code tương tự thì họ sẽ hiểu đoạn code đó làm gì
 
Upvote 0
Lý luận không giúp cho việc học code đâu.

Muốn học để "hiểu đoạn code đó làm gì" [sic] thì đã được nhắc rồi đó.
Tôi nhắc là vì tôi biết người mới học không hiểu nổi nếu không có giải thích.
 
Lần chỉnh sửa cuối:
Upvote 0

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

Back
Top Bottom