Nhờ diễn đàn viết hộ đoạn code trong excel

Liên hệ QC

pham van an

Thành viên mới
Tham gia
22/4/09
Bài viết
45
Được thích
22
Nghề nghiệp
Giảng viên Xây dựng
em đang có mấy cột dữ liệu ở các cột. Bây giờ em muốn chuyển các phần dữ liệu o mỗi cột lên dòng đầu tiên của cột (hoặc bất kỳ). Như F1,G1,H1. Em dùng code xóa ô trống nhưng nó lọc chậm quá. Mong các bác giúp em.
 

File đính kèm

em đang có mấy cột dữ liệu ở các cột. Bây giờ em muốn chuyển các phần dữ liệu o mỗi cột lên dòng đầu tiên của cột (hoặc bất kỳ). Như F1,G1,H1. Em dùng code xóa ô trống nhưng nó lọc chậm quá. Mong các bác giúp em.
Nếu viết code thì dùng Array mới cho tốc độ nhanh được!
Tặng bạn hàm này:
PHP:
Function RemoveBlanks(ByVal SrcRng As Range)
  Dim TmpArr, Arr(), Tmp() As Long, i As Long, j As Long
  TmpArr = SrcRng.Value
  ReDim Tmp(1 To UBound(TmpArr, 2))
  ReDim Arr(1 To UBound(TmpArr, 1), 1 To UBound(TmpArr, 2))
  For j = 1 To UBound(TmpArr, 2)
    For i = 1 To UBound(TmpArr, 1)
      If TmpArr(i, j) <> "" Then
        Tmp(j) = Tmp(j) + 1
        Arr(Tmp(j), j) = TmpArr(i, j)
      End If
    Next i
  Next j
  RemoveBlanks = Arr
End Function
Áp dụng:
Giả sử vùng dữ liệu gốc là B3:D18 ---> Giờ bạn muốn xóa các cell rổng rồi chuyển dữ liệu mới đặt vào cell J1, bạn thêm code sau:
PHP:
Sub Main()
  Dim SrcRng As Range, Arr
  Set SrcRng = Sheet1.Range("B3:D18")
  Arr = RemoveBlanks(SrcRng)
  Sheet1.Range("J1").Resize(UBound(Arr, 1), UBound(Arr, 2)).Value = Arr
End Sub
 

File đính kèm

Upvote 0
em đang có mấy cột dữ liệu ở các cột. Bây giờ em muốn chuyển các phần dữ liệu o mỗi cột lên dòng đầu tiên của cột (hoặc bất kỳ). Như F1,G1,H1. Em dùng code xóa ô trống nhưng nó lọc chậm quá. Mong các bác giúp em.
Thêm một cách
Mã:
Public Sub GomGom()
    Dim iCot, Mg(), I, J, K
    [f1].CurrentRegion.ClearContents
        For I = 2 To 4
            iCot = Range(Cells(1, I), Cells(10000, I).End(xlUp)).Value
            ReDim Mg(1 To UBound(iCot), 1 To 1)
                For J = 1 To UBound(iCot)
                    If iCot(J, 1) <> vbNullString Then
                        K = K + 1
                        Mg(K, 1) = iCot(J, 1)
                    End If
            Next J
                        [d1].Offset(, I).Resize(K) = Mg
                        Mg = [w1].Resize(K).Value
                        K = 0
        Next I
End Sub
 

File đính kèm

Upvote 0
Em chẳng biết nói gì hơn để cám ơn 2 bác trên diễn đàn. code chạy rất tốt nhưng cái của em là các cột không liên tục nhau. em sẻ gửi lại file tính của em để nhờ các bác giúp luôn.Mục đích cuối cùng của em là sắp xếp lại T4:t3000, X4:X3000,ab4:ab3000,af4:af3000, aj4:aj3000 thành ao, ap,aq,ar,as....
 
Lần chỉnh sửa cuối:
Upvote 0
Thêm một cách
Mã:
Public Sub GomGom()
    Dim iCot, Mg(), I, J, K
    Mg = [w1].Resize(K).Value
Next I
End Sub
Anh concogia cho em hỏi đoạn Mg=[W1].resize(k).value có tác dụng gì. Em thấy nếu bỏ đoạn đó đoạn code vẫn chạy rất OK, Mà em thấy cũng lạ là khi anh khai báo biến không bao giờ khai báo kiểu dữ liệu mà chạy vẫn đúng!!!;;;;;;;;;;;;;;;;;;;;;;
To Ndu: Em thích nhất là hàm Removeblanks đó cái đó, em mới biết mình có thể đặt vào Function được. Thanks Ndu
 
Lần chỉnh sửa cuối:
Upvote 0
Anh concogia cho em hỏi đoạn Mg=[W1].resize(k).value có tác dụng gì. Em thấy nếu bỏ đoạn đó đoạn code vẫn chạy rất OK, Mà em thấy cũng lạ là khi anh khai báo biến không bao giờ khai báo kiểu dữ liệu mà chạy vẫn đúng!!!;;;;;;;;;;;;;;;;;;;;;;
To Ndu: Em thích nhất là hàm Removeblanks đó cái đó, em mới biết mình có thể đặt vào Function được. Thanks Ndu
Híc, lại bị bạn bắt giò nữa rồi
- Đơn giản vì mình cho kết quả chạy qua 3 cột mà chỉ gán bằng 1 mảng nên khi gán xong một cột mình muốn hủy mảng đó đi cho "chắc cú", bi giờ xem lại mới thấy chỉ cần gán biến K=0 là Ok rồi (dù sao cũng tìm được cách hủy mảng mà không dùng vòng lặp, lúc trước cứ phải "pho pho" hoài mới hủy được nó, bực lắm)
- Không khai báo kiểu dữ liệu cho biến thì không có vẻ "trường lớp" lắm nhưng được cái lợi là yên tâm về kết quả của nó, không khai báo kiểu dữ liệu, biến sẽ có kiểu Variant - kiểu của các kiểu dữ liệu - VBA sẽ tự động chuyển đổi kiểu dữ liệu cho phù hợp trong quá trình tính toán - "Phẻ re"
Có thể vì lẽ này, nếu ta không khai báo có nhiều trường hợp code sẽ chạy mất nhiều thời gian hơn khai báo "đàng hoàng" ( những code cần "đua" tốc độ mình đều khai báo kiểu dữ liệu của biến đầy đủ )
Mình cũng mới biết viết code thôi, đang trong quá trình tìm hiểu & đây cũng là suy nghĩ riêng của mình
Học kiểu "giang hồ" không trường lớp khổ thế đấy
Thân
 
Upvote 0
Híc, lại bị bạn bắt giò nữa rồi
- Đơn giản vì mình cho kết quả chạy qua 3 cột mà chỉ gán bằng 1 mảng nên khi gán xong một cột mình muốn hủy mảng đó đi cho "chắc cú", bi giờ xem lại mới thấy chỉ cần gán biến K=0 là Ok rồi (dù sao cũng tìm được cách hủy mảng mà không dùng vòng lặp, lúc trước cứ phải "pho pho" hoài mới hủy được nó, bực lắm)
Thân
Em, đâu dám đâu tại vì em đang học về array nên mới thấy lạ hỏi anh thôi cảm ơn anh giải thích
- Không khai báo kiểu dữ liệu cho biến thì không có vẻ "trường lớp" lắm nhưng được cái lợi là yên tâm về kết quả của nó, không khai báo kiểu dữ liệu, biến sẽ có kiểu Variant - kiểu của các kiểu dữ liệu - VBA sẽ tự động chuyển đổi kiểu dữ liệu cho phù hợp trong quá trình tính toán - "Phẻ re"
Có thể vì lẽ này, nếu ta không khai báo có nhiều trường hợp code sẽ chạy mất nhiều thời gian hơn khai báo "đàng hoàng" ( những code cần "đua" tốc độ mình đều khai báo kiểu dữ liệu của biến đầy đủ )
Thân
Thì em đọc mấy bài của bác SA_QC, thấy PTM thì khuyên nên khai báo biến thì đoạn code sẽ cho tốc độ cao hơn, mà anh khai báo biến thì nó vẫn hiểu theo kiểu là Variant, nếu người mới như em thì đọc không hiểu dẫn đến hơi mơ mơ về kiều dữ liệu, nhằm khi thấy những đoạn code của các anh chị khác viết có khai báo, còn nhằm đoạn thì khôngthì học cũng khó
Mình cũng mới biết viết code thôi, đang trong quá trình tìm hiểu & đây cũng là suy nghĩ riêng của mình
Học kiểu "giang hồ" không trường lớp khổ thế đấy
Thân
Em thấy anh Concogia viết code quá trùm đó mà. Thanks anh Concogia đã giải thích mong gặp anh trong sinh nhật GPE
 
Upvote 0
anh concogia chắc là dân chuyên nghiệp về code nhỉ. mạn phép cho hỏi anh là giảng viên, sinh viên hay...Chỉ muốn biết về anh chứ không có mục đích gì đâu nhé. Nếu có thể anh gửi nickname cho em làm quen với. Email của em là "phamvanan@aa.edu.vn".Thanks
 
Upvote 0
Giải pháp của thầy ndu cao cấp quá, cần có thời gian để tiếp thu.
Code của anh concogia thì quá OK rồi. Học được thêm 1 cách xử lý dữ liệu.
Đâu đó trên diễn đàn thỉnh thoảng lại bắt gặp anh concogia có nhiều chiêu rất hay.
Có điều riêng với yêu cầu như bài này vẫn có thể rút gọn code của concogia cho đơn giản thêm chút nữa:

PHP:
Sub Loc1()
Dim cell As Range, Rng As Range
Dim I, J As Integer
    [F1].CurrentRegion.ClearContents
    For I = 2 To 4
        Set Rng = Range(Cells(1, I), Cells(10000, I).End(xlUp))
        For Each cell In Rng.SpecialCells(2)
            J = J + 1
            Cells(J, I + 4).Value = cell.Value
        Next
        J = 0
    Next I
End Sub
Hoặc gọn hơn nữa:
PHP:
Sub Loc2()
Dim I As Integer
Dim Rng As Range
[F1].CurrentRegion.ClearContents
For I = 2 To 4
    Set Rng = Range(Cells(1, I), Cells(10000, I).End(xlUp))
    Rng.SpecialCells(2).Copy Cells(1, I + 4)
Next I
End Sub
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Giải pháp của thầy ndu cao cấp quá, cần có thời gian để tiếp thu.
Code của anh concogia thì quá OK rồi. Học được thêm 1 cách xử lý dữ liệu.
Đâu đó trên diễn đàn thỉnh thoảng lại bắt gặp anh concogia có nhiều chiêu rất hay.
Có điều riêng với yêu cầu như bài này vẫn có thể rút gọn code của concogia cho đơn giản thêm chút nữa:

PHP:
Sub Loc1()
Dim cell As Range, Rng As Range
Dim I, J As Integer
    [F1].CurrentRegion.ClearContents
    For I = 2 To 4
        Set Rng = Range(Cells(1, I), Cells(10000, I).End(xlUp))
        For Each cell In Rng.SpecialCells(2)
            J = J + 1
            Cells(J, I + 4).Value = cell.Value
        Next
        J = 0
    Next I
End Sub
Hoặc gọn hơn nữa:
PHP:
Sub Loc2()
Dim I As Integer
Dim Rng As Range
[F1].CurrentRegion.ClearContents
For I = 2 To 4
    Set Rng = Range(Cells(1, I), Cells(10000, I).End(xlUp))
    Rng.SpecialCells(2).Copy Cells(1, I + 4)
Next I
End Sub
Code của bạn dùng SpecialCells nên cần phải bẫy lỗi trong trường hợp không có dữ liệu.
 
Upvote 0
To Ndu: Em thích nhất là hàm Removeblanks đó cái đó, em mới biết mình có thể đặt vào Function được. Thanks Ndu
Thấy bạn chịu khó nghiên cứu Array, tôi tặng bạn hàm mới dùng được trên vùng dữ liệu không liên tục
PHP:
Function RemoveBlanks(ParamArray sArray())
  Dim Arr(), SubArr, Item, Tmp, lR As Long, lC As Long, lRs As Long, lCs As Long
  On Error GoTo ExitFunc
  For Each SubArr In sArray
    Tmp = SubArr
    If lRs < UBound(Tmp, 1) Then lRs = UBound(Tmp, 1)
    lCs = lCs + 1
  Next
  ReDim Arr(1 To lRs, 1 To lCs)
  For Each SubArr In sArray
    lR = 0: lC = lC + 1: Tmp = SubArr
    For Each Item In Tmp
      If CStr(Item) <> "" Then
        lR = lR + 1
        Arr(lR, lC) = Item
      End If
    Next
  Next
  RemoveBlanks = Arr
ExitFunc:
End Function
PHP:
Sub Main()
  Dim SrcRng As Range, Arr, TG As Double
  TG = Timer
  On Error GoTo ExitSub
  With Sheet1
    .Range("AO4:AS60000").Clear
    Arr = RemoveBlanks(.Range("T4:T60000"), .Range("X4:X60000"), .Range("AB4:AB60000"), .Range("AF4:AF60000"), .Range("AJ4:AJ60000"))
    .Range("AO4:AS4").Resize(UBound(Arr, 1)).Value = Arr
  End With
ExitSub:
  MsgBox Timer - TG
End Sub
Thử nghiệm với dữ liệu 60000 dòng, ra kết quả trong vòng dưới 1 giây!
 

File đính kèm

Upvote 0
Rất tuyệt vời với code của bác "ndu96081631". Nó giúp ích rất nhiều trong các bảng tính của em. Cám ơn rất nhiều, sau này cần bác chỉ giáo thêm cho anh em trên GPE nhiều code hay nữa.
 
Upvote 0
Web KT

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

Back
Top Bottom