Chú ý: Các thành viên học lớp "Lập trình VBA trong Excel" có thể trao đổi bài ở đây

Liên hệ QC
Vâng đúng ạ, em test bỏ if đi thì có vùng đúng, có vùng nó chọn sai dòng
Trong code của tôi, nếu muốn bỏ IF thì phải đổi cấu trúc vòng lập, quét dòng trước cột sau
PHP:
Sub xLastCell()
  Dim sRng As Range, i As Long, j As Long, MaxR As Long, Answer As String
  Set sRng = Selection
  For i = sRng.Rows.Count To 1 Step -1
    For j = 1 To sRng.Columns.Count
      If Not IsEmpty(sRng(i, j)) Or Not sRng(i, j).Comment Is Nothing Then MaxR = sRng(i, j).Row
    Next
    If MaxR Then Exit For
  Next
  Answer = IIf(MaxR, "Dong cuoi cùng la " & MaxR, "Vùng du liêu toàn dòng trang")
  MsgBox Answer, 6, "Thông báo"
End Sub
 
Đã gọi là CÓ DỮ LIỆU thì phải tính luôn Comment nữa nha
Ngoài ra, nếu dùng vòng lập, nên quét từ dưới lên, theo nguyên tắc:
- Cho trước biến MaxRow = 0
- Quét từng cột
- Quét từng dòng, từ dưới lên, nếu Cell không rổng hoặc có Comment thì xét tiếp:
* Nếu MaxRow < Vị trí dòng đang xét thì gán MaxRow = Vị trí dòng ấy
- Thoát vòng lập, chuyển sang cột khác
Em chưa hiểu
Mã:
Comment Is Nothing Then
để làm gì, trên lớp thầy chưa dạy về lệnh này, mong các AC chỉ giúp
 
Em chưa hiểu
Mã:
Comment Is Nothing Then
để làm gì, trên lớp thầy chưa dạy về lệnh này, mong các AC chỉ giúp
Range(...).Comment Is Nothing nghĩa là Range(...) này không có Comment (Nothing mà lị)
Not Range(...).Comment Is Nothing thì có nghĩa ngược lại, Range(...) có Comment
Phát biểu gần như ta nói (hiểu tiếng Anh là hiểu ý nghĩa của lệnh)
 
Đây là BT2: Xoá ô
PHP:
Sub Xoa_O()
    Dim Vung As Range
    Dim MyCell As Range
    Set Vung = Selection
    Application.ScreenUpdating = False
    For Each MyCell In Vung
        If MyCell.Value = Empty Then
            MyCell.Delete Shift:=xlUp
        End If
    Next
    Application.ScreenUpdating = True
    Set Vung = Nothing
End Sub
Code này em mới làm được xoá 1 ô trống trong vùng thôi. Em muốn xoá 2 hay nhiều ô trống gần nhau thì vẫn chưa Ok ah. Mong thầy và các AC chỉ dùm thêm nha!!!
 

File đính kèm

  • GPE_btXoa.rar
    6 KB · Đọc: 12
Lần chỉnh sửa cuối:
Đây là BT2: Xoá ô
PHP:
Sub Xoa_O()
    Dim Vung As Range
    Dim MyCell As Range
    Set Vung = Selection
    Application.ScreenUpdating = False
    For Each MyCell In Vung
        If MyCell.Value = Empty Then
            MyCell.Delete Shift:=xlUp
        End If
    Next
    Application.ScreenUpdating = True
    Set Vung = Nothing
End Sub
Code này em mới làm được xoá 1 ô trống trong vùng thôi. Em muốn xoá 2 hay nhiều ô trống gần nhau thì vẫn chưa Ok ah. Mong thầy và các AC chỉ dùm thêm nha!!!
Mấy vụ xóa cell này phải quét từ dưới lên đồng chí ơi! Kiểu vầy:
PHP:
Sub Xoa_O()
  Dim sRng As Range, i As Long, j As Long
  Set sRng = Selection
  Application.ScreenUpdating = False
  For j = 1 To sRng.Columns.Count
    For i = sRng.Rows.Count To 1 Step -1
      If IsEmpty(sRng(i, j)) Then sRng(i, j).Delete Shift:=xlUp
    Next
  Next
  Application.ScreenUpdating = True
End Sub
Còn nếu cố tình quét từ trên xuống hoặc dùng For Each... thì không được xóa liền, phải dùng Union thu gom những cell rổng thành 1 nhóm ---> Cuối vòng lập mới xóa 1 lượt
PHP:
Sub Test()
  Dim sRng As Range, Tmp As Range, Clls As Range
  Set sRng = Selection
  Application.ScreenUpdating = False
  For Each Clls In sRng
    If IsEmpty(Clls) Then
      If Tmp Is Nothing Then
        Set Tmp = Clls
      Else
        Set Tmp = Union(Tmp, Clls)
      End If
    End If
  Next
  If Not Tmp Is Nothing Then Tmp.Delete Shift:=xlUp
  Application.ScreenUpdating = True
End Sub
Xét về mặt tốc độ thì cách 2 sẽ nhanh hơn (dù rắc rối hơn)
 
Lần chỉnh sửa cuối:
Kho tàng ẩn chứa trong fương thức Delete đây, xem thêm thử nha

Code trên này em mới làm được xoá 1 ô trống trong vùng thôi. Em muốn xoá 2 hay nhiều ô trống liện kề nhau thì vẫn chưa Ok ah. Mong thầy và các AC chỉ dùm thêm nha!!!
Bạn dùng chuột tô chọn từ 'Delete' trong macro & bấm {F1} ta sẽ được đưa đến sự hỗ trợ đắc lực từ VBE, mà trong đó mình muốn giới thiệu dòng này để bạn quan tâm
Mã:
[SIZE=3]
[B]Delete[/B][/SIZE] [SIZE=3] method as it applies to the [B]Range[/B]  object.
[I]expression[/I][/SIZE] [SIZE=3].[B]Delete[/B][B]([I]Shift[/I])
[/B][I]expression   [/I] Required. An expression that returns a [B][URL="http://www.giaiphapexcel.com/forum/xlobjRange1.htm"]Range[/URL][/B] object.
 [B][I]1
[/I][/B]
[B][I] Shift[/I][/B][/SIZE] [SIZE=3] Optional [B]Variant[/B].  Used only with [B]Range[/B] objects. Specifies how to shift cells to  replace deleted cells. 
Can be one of the following [B]XlDeleteShiftDirection[/B] constants: [B]xlShiftToLeft[/B] or [B]xlShiftUp[/B]. 
If this argument  is omitted, Microsoft Excel decides based on the shape of the range.[/SIZE]
Nếu bạn hiểu sâu câu sau số 1 đó thì bạn sẽ biết cách khắc fục nhược điểm của macro 1 cách tạm thời.

Hay thế này đi: Giả dụ tôi & bạn, chúng ta có bảng dữ liệu sau:

| B | C 1 |GPE|
2 |5|
3 |6|
4 |7|
5 ||8
6 ||9
7 |4|
8 |3|(8 dòng)

Bạn thêm tham số này vô lệnh xóa ô trên : xlShiftToLeft

Tô chọn vùng cột 'B' bên trên & cho macro chạy; Fa li càfê để gặm nhắm những gì vừa xuất hiện trong đầu của bạn.



 
Lần chỉnh sửa cuối:
Đây là code bài xoá dòng & cột của em (chỉ dùng for next)
Mã:
Option Explicit

Sub XoaDongTrong()
Dim i As Long, j As Long, SoHang As Long, SoCot As Long, VungChon As Range
Set VungChon = Selection
SoHang = Selection.Rows.Count
SoCot = Selection.Columns.Count
    For i = 1 To SoHang
        For j = 1 To SoCot - 1
        j = j + 1
                    If VungChon(i, j).Value = Empty And VungChon(i, j + 1).Value = Empty Then
                        VungChon.Rows(i).Delete
                    End If
        Next j
    Next i
Set VungChon = Nothing
End Sub
'------------------------------------------------------------------------------------------------------
Sub XoaCotTrong()
Dim i As Long, j As Long, SoHang As Long, SoCot As Long, VungChon As Range
Set VungChon = Selection
SoHang = Selection.Rows.Count
SoCot = Selection.Columns.Count
    For j = 1 To SoCot
        For i = 1 To SoHang - 1
        i = i + 1
                    If VungChon(i, j).Value = Empty And VungChon(i + 1, j).Value = Empty Then
                        VungChon.Columns(j).Delete
                    End If
        Next i
    Next j
Set VungChon = Nothing
End Sub
Anh ChanhTQ@ hướng dẫn ở trên nhưng em chưa hiểu lắm làm thế nào để chỉ xoá 1 hàng (cột) trong phạm vi vùng chọn mà không ảnh hưởng đến các cell khác bên cạnh giống như Shift Cell Up hay Shift Cell Left trong excel.
 

File đính kèm

  • XoaHangCot.rar
    12.8 KB · Đọc: 7
Lần chỉnh sửa cuối:
nhưng em chưa hiểu lắm làm thế nào để chỉ xoá 1 hàng (cột) trong phạm vi vùng chọn mà không ảnh hưởng đến các cell khác bên cạnh giống như Shift Cell Up hay Shift Cell Left trong excel.
Tựu chung vấn đề là: Khi xài fương thức Delete ta hiểu thêm nó có 2 tham số, mà 1 trong chúng đã ngầm định;

đó là xlShiftUp; Với tham số này, khi ta xóa 1 ô, thì DL (dữ liệu) ô dưới nó sẽ được đôn lên chỗ ô bị xóa, & cứ thế đôn lên cho hết cột của ô bị xóa.

Nếu ta xóa nguyên hàng có ô đó, thì DL hàng dưới liền kề sẽ được đôn lên thay chỗ cho hàng vừa bị xóa.
Điều này diễn ra thật sự trên trang tính excel, như lâu nay bạn đã thấy đó nha!

Trở lại vụ dùng vòng lặp để xóa các ô trống trong cột:

Khi [B5] trống, ta dùng fương thức Delete để xóa ô này, thì DL ô [B6] đã được đôn lên thế chỗ ngay tấp lư. ([B7] thay cho [B6],. . . ) Sau thời điểm thế chỗ xong, vòng lặp lại tiếp tục, nhưng các bạn có biết không, nó nhãy vô ô [B6], mà ô này đang chứa DL của anh chàng dưới nó trước đây;

Như vậy nếu cả 2 ô [B5] & [B6] ban đầu là rỗng, thì fương thức xóa ô trống từ đầu cột đến cuối cột sẽ để sót, một khi có 2 ô trống trong cột liền kề nhau; (Các bạn thử với 3 & 4 ô trống liền kề & tự rút ra kết luận nha!)

Cách khắc phục việc này:

Ta duyệt từ ô tận cùng của cột để dò lên cho đến đầu. (Tất nhiên nếu thầy Tuân đã hướng dẫn cách duyệt vòng lặp ngược từ cuối trở lên đầu;
Nếu chưa hướng dẫn thì các bạn sẽ không xóa được 2 ô trống liền kề trong 1 lần chạy macro;
Mà các bạn fải chạy bao nhiêu lần í, mới hết các ô trong có thể có trong 1 cột; Số lần chạy đó cũng xin nhường các bạn tính sao cho fải đạo, nhứt là các bạn đã & trãi qua fỗ thông trung học.)

Rất vui, nếu những gì viết trên đây hữu ích cho các bạn trong lớp!

Thân ái!






 
Chỉnh sửa lần cuối bởi điều hành viên:
Vì các bạn đang học vòng lập nên ta giải quyết mọi chuyện bằng vòng lập... Thật ra bài này có cách khác hay hơn rất nhiều:
PHP:
Sub Test2()
  Dim sRng As Range
  On Error Resume Next
  Set sRng = Selection
  If sRng.Count > 1 Then sRng.SpecialCells(4).Delete 2
End Sub
 
Vì các bạn đang học vòng lập nên ta giải quyết mọi chuyện bằng vòng lập... Thật ra bài này có cách khác hay hơn rất nhiều:
PHP:
Sub Test2()
  Dim sRng As Range
  On Error Resume Next
  Set sRng = Selection
  If sRng.Count > 1 Then sRng.SpecialCells(4).Delete 2
End Sub

Em hiểu được con số 4 SpecialCells(4) như vầy:

If sRng.Count > 1 Then sRng.SpecialCells(xlCellTypeBlanks).Delete 2

Bác ơi ndu cho em hỏi số 2 nghĩa là gì ạ. E có thể xem thêm giá trị kiểu gán Delete 2 này ở đâu?

Thanks Bác!
 
Lần chỉnh sửa cuối:
Em hiểu được con số 4 SpecialCells(4) như vầy:



Bác ơi ndu cho em hỏi số 2 nghĩa là gì ạ. E có thể xem thêm giá trị kiểu gán Delete 2 này ở đâu?

Thanks Bác!
Theo cách hiểu của Mình là: Bạn bấm chọn 1 ô bất kỳ -> Bấm phải chuột chọn Delete -> Nó sẽ xuất hiện hộp thoại Delete -> Xem thứ tự từ trên xuống
Delete Shist Cells Left (Tương ứng là 1)
Delete Shist Cells Up (Tương ứng là 2)
.......
 
Tôi thấy yêu cầu bài là tìm LastRow, yêu cầu này thấy thiết thực. Các Bác lại chuyển sang xóa (delete) 1 cell hay nhiều Cell, vấn đề này sẽ ảnh hưởng đéb cấu trúc cơ sở dữ liệu (CSDL). Thú thật với CSDL nói chung thì việc xóa 1 cell là không nên.
Xóa nguyên dòng hay nguyên cột thì OK hay chỉ dừng lại ở Clear...
Các Bạn làm giúp mình hàm MinMaxIf mình nhờ có vẻ thực tế hơn.
Bác NDU và Bác Sa khoan đưa các bạn ấy vào vòng luẩn quẩn.
 
Em hiểu được con số 4 SpecialCells(4) như vầy:. . .
Bác ơi ndu cho em hỏi số 2 nghĩa là gì ạ. E có thể xem thêm giá trị kiểu gán Delete 2 này ở đâu?

Đó là cách viết không được tường minh cho lắm; Mình biết chắc rằng thầy Tuân đang yêu cầu các bạn viết theo kiểu tường minh
Vậy các bạn chỉ tham khảo lúc rỗi thôi, vậy nha. . . !

To ThuNghi

Delete Cells là bài tập thứ 2 của chương trình mà,. . .
 
Mã:
[Xin phép các bác cho em khởi động bài tập về nhà ngày hôm qua. Thầy cho 2 bài, đây là bài 1:
Đề bài: Viết thủ tục tìm dòng cuối cùng của 1 vùng nào đó
Đây là bài làm của em (Mặc dù em biết có cách sử dụng .End(xlUp) cũng có thể xác định được dòng cuối cùng, nhưng em đang làm theo nhưng vòng lặp đã học (Do While, For) để xác định, có thể bài hơi dài, mong các bác góp ý.

Code:
Sub LastCell()
    Dim rngNum As Range
    Dim i As Integer
    Dim j As Integer
    Dim x As Integer
        
    Set rngNum = Selection
    i = rngNum.Rows.Count
    x = 1
    Do While i <> 0
    For j = 1 To rngNum.Columns.Count
        If IsEmpty(rngNum.Cells(i, j)) = False Then
        userrespond = MsgBox("Dong cuoi cung la " & rngNum.Cells(i, j).Row, vbOKOnly, "Thong bao!")
        x = 0
        Exit Do
        End If
    Next
    i = i - 1
    Loop
    If x = 1 Then
    userrespond = MsgBox("Vung du lieu toan dong trang", vbOKOnly, "Thong bao!")
    End If
End Sub
P/S: Bác Ngọc NH_DK có thể gửi PM kho vào hòm thư email [email]thangacc@gmail.com[/email] .email cho em nhé, có gì anh em cùng trao đổi. Cảm ơn bác
thay đổi nội dung bởi: ThangAcc, 05-11-10 lúc 09:33 AM]

[/em nghĩ hình như mọi người đang hiểu nhầm ý thầy Tuân muốn chúng ta làm bài tập này. em cho chạy thử code anh Thắng post lên (và 1 số người nữa) thì thấy rằng khi chạy em phải chọn vùng dữ liệu cần tìm dòng cuối cùng hoặc là chỉ vào dòng cuối cùng của vùng đó. nếu thế thì cần gì phải làm code đi tìm dòng cuối làm gì nữa chứ vì khi em chọn vùng dữ liệu là em đã biết dòng cuối là dòng nào rồi đúng ko.
theo em thì ý của thầy là khi mình đặt con chỏ vào đâu thì nó cũng sẽ thông báo msgbox dòng cuối cùng là dòng nào và tự động chạy đến đấy luôn chứ ko cần phải chọn vùng dữ liệu.]
 
Lần chỉnh sửa cuối:
Mã:
[Xin phép các bác cho em khởi động bài tập về nhà ngày hôm qua. Thầy cho 2 bài, đây là bài 1:
Đề bài: Viết thủ tục tìm dòng cuối cùng của 1 vùng nào đó
Đây là bài làm của em (Mặc dù em biết có cách sử dụng .End(xlUp) cũng có thể xác định được dòng cuối cùng, nhưng em đang làm theo nhưng vòng lặp đã học (Do While, For) để xác định, có thể bài hơi dài, mong các bác góp ý.

Code:
Sub LastCell()
    Dim rngNum As Range
    Dim i As Integer
    Dim j As Integer
    Dim x As Integer
        
    Set rngNum = Selection
    i = rngNum.Rows.Count
    x = 1
    Do While i <> 0
    For j = 1 To rngNum.Columns.Count
        If IsEmpty(rngNum.Cells(i, j)) = False Then
        userrespond = MsgBox("Dong cuoi cung la " & rngNum.Cells(i, j).Row, vbOKOnly, "Thong bao!")
        x = 0
        Exit Do
        End If
    Next
    i = i - 1
    Loop
    If x = 1 Then
    userrespond = MsgBox("Vung du lieu toan dong trang", vbOKOnly, "Thong bao!")
    End If
End Sub
P/S: Bác Ngọc NH_DK có thể gửi PM kho vào hòm thư email [email]thangacc@gmail.com[/email] .email cho em nhé, có gì anh em cùng trao đổi. Cảm ơn bác
thay đổi nội dung bởi: ThangAcc, 05-11-10 lúc 09:33 AM]

[/em nghĩ hình như mọi người đang hiểu nhầm ý thầy Tuân muốn chúng ta làm bài tập này. em cho chạy thử code anh Thắng post lên (và 1 số người nữa) thì thấy rằng khi chạy em phải chọn vùng dữ liệu cần tìm dòng cuối cùng hoặc là chỉ vào dòng cuối cùng của vùng đó. nếu thế thì cần gì phải làm code đi tìm dòng cuối làm gì nữa chứ vì khi em chọn vùng dữ liệu là em đã biết dòng cuối là dòng nào rồi đúng ko.
theo em thì ý của thầy là khi mình đặt con chỏ vào đâu thì nó cũng sẽ thông báo msgbox dòng cuối cùng là dòng nào và tự động chạy đến đấy luôn chứ ko cần phải chọn vùng dữ liệu.]

He..he...Anh đã bảo rùi mà tuỳ từng trường hợp. Bài của Thangacc và mọi người anh nghĩ là ko sai chút nào. Đúng hoà toàn luôn.

em cho chạy thử code anh Thắng post lên (và 1 số người nữa) thì thấy rằng khi chạy em phải chọn vùng dữ liệu cần tìm dòng (*)cuối cùng hoặc là chỉ vào dòng (*) cuối cùng của vùng đó. nếu thế thì cần gì phải làm code đi tìm dòng cuối làm gì nữa chứ vì khi em chọn vùng dữ liệu là em đã biết dòng cuối là dòng nào rồi đúng ko.

- Cái quan trọng nhất thì em bỏ qua trong dấu (*) phải là: "chứa dữ liệu". Viết lại dòng màu đỏ là: Tìm dòng chứa dữ liệu cuối cùng trong vùng được chọn. Em có biết hàm Row trong Excel không? Nhìn là biết dòng nào rùi mà. Sao phải bày đặt hàm ROW() làm gì? Trả lời được câu này, từ đó huongchuoi suy ra được cái mọi người đang làm là đúng.

- Hơn nữa trong phạm vi kiến thức mình được học và làm được đúng cái mình muốn là được.

- Còn thực tiển cái code của mọi người ứng dụng như thế nào. Nếu muốn anh cho huongchuoi vd cụ tỷ lun.


-
 
Có bài này là lấy trên GPE từ TransferData của NDU đã làm, các bạn viết cho 1 hàm Max và Min Price theo 2 điều kiện là Company Name và Services. Tuỳ chọn tại F2 và G2 của file.
Tôi mới làm ct mà ct mảng nên chậm quá, các bạn giúp tôi làm 1 UDF nhé.
Hy vọng bài loại này có nhiều áp dụng thực tế.
Cám ơn các bạn nhiều.

Bác kiểm tra giúp em
PHP:
Function MyMaxIf(ByVal rngCompany As Range, ByVal rngServices As Range, _
                 ByVal sComTest As String, ByVal sSerTest As String, ByVal rngValue As Range)
    Dim i As Long
    MyMaxIf = -9.99999999999999E+307
    For i = 1 To rngCompany.Rows.Count
        If rngCompany(i, 1) = sComTest And rngServices(i, 1) = sSerTest Then
            If MyMaxIf < rngValue(i, 1) Then
                MyMaxIf = rngValue(i, 1)
            End If
        End If
    Next
End Function
 

File đính kèm

  • MinMaxIf.rar
    12.3 KB · Đọc: 12
Lần chỉnh sửa cuối:
Bác kiểm tra giúp em
PHP:
Function MyMaxIf(ByVal rngCompany As Range, ByVal rngServices As Range, _
                 ByVal sComTest As String, ByVal sSerTest As String, ByVal rngValue As Range)
    Dim i As Long
    MyMaxIf = -9.99999999999999E+307
    For i = 1 To rngCompany.Rows.Count
        If rngCompany(i, 1) = sComTest And rngServices(i, 1) = sSerTest Then
            If MyMaxIf < rngValue(i, 1) Then
                MyMaxIf = rngValue(i, 1)
            End If
        End If
    Next
End Function
Hay quá, nó giúp mình nhiều lắm, nhưng còn trường hợp khi chọn Company 02 và Service1 thì nó không ra. Vì thực tế kg có price của Company 02 và Service1.
Và giúp mình khi chọn All ở G2 là tính Max và Min theo all Service ie chỉ tính theo company thôi.
Cám ơn bạn nhiều.
 
Hay quá, nó giúp mình nhiều lắm, nhưng còn trường hợp khi chọn Company 02 và Service1 thì nó không ra. Vì thực tế kg có price của Company 02 và Service1.
Và giúp mình khi chọn All ở G2 là tính Max và Min theo all Service ie chỉ tính theo company thôi.
Cám ơn bạn nhiều.
Em nghĩ mãi không ra, có cao thủ nào gợi ý cho em chút:D
 
Web KT
Back
Top Bottom