Các câu hỏi về mảng trong VBA (Array) (1 người xem)

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

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

viehoai

Thành viên gắn bó
Tham gia
22/5/09
Bài viết
2,599
Được thích
2,908
Xin các anh chị giúp đỡ Code Gán các giá trị của một Range là các phần tử của Mãng
Ví dụ: Tôi có các giá trị của Range("A1:A10"). Tôi muốn viết code để gán giá trị của các cells từ A1:A10 là các phần tử của Mãng Arr chẳn hạn.
Xin cảm ơn các anh chị
 
Em lại có ví dụ sau để học mảng
- Sheet 1 có dữ liệu từ A1:C10
- Trong một hàng dữ liệu (ví dụ từ A1:C1) chỉ được nhận là trống hết, nếu đã điền, thì phải điền đủ dữ liệu
Ví dụ:
- TH1: Điền hết dữ liệu
Cột A------Cột B----------Cột C
TM..... 09/03/2012--------201203
- TH2: để trống hết
Cột A------Cột B----------Cột C
..............................................

Yêu cầu
Dùng mảng để duyệt những dòng điền dữ liệu không đủ

Em có đoạn code sau như nó báo lỗi "Object required"
PHP:
Sub blank()
Dim sArr()
    sArr = Sheet1.Range("A1:A10").Value
    
    For i = 1 To UBound(sArr) 
        If WorksheetFunction.CountBlank(sArr(i, 1).Resize(, 3)) <> 3 Then
             MsgBox "Sheet1 dong thu" & i & " chua dien du thong tin "
        End If
   Next i
End Sub

Anh/Chị xem giúp em với ạh?
 
Upvote 0
Em lại có ví dụ sau để học mảng
- Sheet 1 có dữ liệu từ A1:C10
- Trong một hàng dữ liệu (ví dụ từ A1:C1) chỉ được nhận là trống hết, nếu đã điền, thì phải điền đủ dữ liệu
Ví dụ:
- TH1: Điền hết dữ liệu
Cột A------Cột B----------Cột C
TM..... 09/03/2012--------201203
- TH2: để trống hết
Cột A------Cột B----------Cột C
..............................................

Yêu cầu
Dùng mảng để duyệt những dòng điền dữ liệu không đủ

Em có đoạn code sau như nó báo lỗi "Object required"
PHP:
Sub blank()
Dim sArr()
    sArr = Sheet1.Range("A1:A10").Value
    
    For i = 1 To UBound(sArr) 
        If WorksheetFunction.CountBlank(sArr(i, 1).Resize(, 3)) <> 3 Then
             MsgBox "Sheet1 dong thu" & i & " chua dien du thong tin "
        End If
   Next i
End Sub

Anh/Chị xem giúp em với ạh?
Đơn giản vì COUNTBLANK chỉ làm việc với Range, không làm việc với mảng đâu
Thêm nữa sArr(i, 1).Resize(, 3) là sai cú pháp ---> Mảng không cho phép Resize (chỉ dùng được Resize với Range mà thôi)
 
Upvote 0
Ẹc
Em sửa lại thành, code chạy veo véo
PHP:
Sub blank()
Dim sArr()
    sArr = Sheet1.Range("A1:C10").Value
    
    For i = 1 To UBound(sArr, 1) ' 1 la chieu thu nhat de phan biet chieu thu 2
        If sArr(i, 1) = "" And sArr(i, 2) = "" And sArr(i, 3) = "" Then
             MsgBox "Sheet1 dong thu" & i & " chua dien du thong tin "
             Exit Sub
        End If
   Next i
End Sub
 
Upvote 0
Ẹc
Em sửa lại thành, code chạy veo véo
PHP:
Sub blank()
Dim sArr()
    sArr = Sheet1.Range("A1:C10").Value
    
    For i = 1 To UBound(sArr, 1) ' 1 la chieu thu nhat de phan biet chieu thu 2
        If sArr(i, 1) = "" And sArr(i, 2) = "" And sArr(i, 3) = "" Then
             MsgBox "Sheet1 dong thu" & i & " chua dien du thong tin "
             Exit Sub
        End If
   Next i
End Sub
Nếu có 20 cột thì bạn AND bằng cách nào đây?
Ẹc... Ẹc...
 
Upvote 0
Hai cách viết sau có hoàn toàn giống nhau không

Em có 2 Code sau
PHP:
Sub loc()
    Dim sArr(), Arr(), i As Long, j As Long
    sArr = Sheet1.Range("A1:A100").Value
    ReDim Arr(1 To UBound(sArr, 1), 1 To 1)
    For i = 1 To UBound(sArr, 1)
        If sArr(i, 1) > 0 Then
            j = j + 1
            Arr(j, 1) = sArr(i, 1)
        Sheet1.[B1].Resize(j).Value = Arr
        End If
    Next
End Sub

PHP:
Sub loc()
    Dim sArr(), Arr(), i As Long, j As Long
    sArr = Sheet1.Range("A1:A100").Value
    ReDim Arr(1 To UBound(sArr, 1), 1 To 1)
    For i = 1 To UBound(sArr, 1)
        If sArr(i, 1) > 0 Then
            j = j + 1
            Arr(j, 1) = sArr(i, 1)
        End If
    Next
    Sheet1.[B1].Resize(j).Value = Arr
End Sub

Em xin hỏi nó có giống nhau hoàn toàn về mọi phương diện tính toán không?

(Em test thấy kết quả như nhau)
 
Upvote 0
Em có 2 Code sau
PHP:
Sub loc()
    Dim sArr(), Arr(), i As Long, j As Long
    sArr = Sheet1.Range("A1:A100").Value
    ReDim Arr(1 To UBound(sArr, 1), 1 To 1)
    For i = 1 To UBound(sArr, 1)
        If sArr(i, 1) > 0 Then
            j = j + 1
            Arr(j, 1) = sArr(i, 1)
        Sheet1.[B1].Resize(j).Value = Arr
        End If
    Next
End Sub

PHP:
Sub loc()
    Dim sArr(), Arr(), i As Long, j As Long
    sArr = Sheet1.Range("A1:A100").Value
    ReDim Arr(1 To UBound(sArr, 1), 1 To 1)
    For i = 1 To UBound(sArr, 1)
        If sArr(i, 1) > 0 Then
            j = j + 1
            Arr(j, 1) = sArr(i, 1)
        End If
    Next
    Sheet1.[B1].Resize(j).Value = Arr
End Sub

Em xin hỏi nó có giống nhau hoàn toàn về mọi phương diện tính toán không?

(Em test thấy kết quả như nhau)
Kết quả giống nhau nhưng code thứ 2 sẽ nhanh hơn:
- Code thứ nhất, cứ lập 1 lần thì gán dữ liệu vào sheet
- Code thứ hai, làm xong vòng lập mới gán 1 lần vào sheet
------------
Hãy test với dữ liệu 10000 dòng trở lên để cảm nhận sự khác nhau về tốc độ 2 code nhé
 
Upvote 0
Hai code trên giống nhau về việc xử lý dữ liệu nguồn cho ra dữ liệu kết quả (có tính toán gì đâu?)

Nhưng khác nhau ở trình tự gán xuống sheet.
Code 1: Mỗi vòng lặp thoả điều kiện sẽ gán xuống 1 lần, lần sau ghi đè lên lần trước, lần 1 chỉ có 1 ô có dữ liệu, còn toàn là gán ô trống, lần sau ít ô trống hơn, và lần cuối là dữ liệu kết quả đầy đủ nhất.
Code 2: Chỉ gán xuống sheet 1 lần khi kết quả đã đầy đủ.
 
Upvote 0
Nhờ các pác giải thích dùm đoạn code trong bài tổng hợp số liệu

Em chưa hiểu được dòng lệnh With .Resize(.Rows.Count - 1, .Columns.Count - 1) trong Code

PHP:
Option Explicit
Private Sub Worksheet_Activate()
  Dim Sh As Worksheet
  Application.ScreenUpdating = False
  Range("A2:C10000").ClearContents
  For Each Sh In Worksheets
    If Sh.Name <> "Tonghop" Then
      With Sh.Range("A1").CurrentRegion.Offset(1, 1)
        With .Resize(.Rows.Count - 1, .Columns.Count - 1)
          Range("B65536").End(xlUp)(2).Resize(.Rows.Count, .Columns.Count).Value = .Value
        End With
      End With
    End If
  Next Sh
  Range("A1").SpecialCells(4).Value = Evaluate("=Row(R1:R1000)")
  Application.ScreenUpdating = True
End Sub

Nhờ các bác giúp em hiểu về nó
Em xin cảm ơn
 
Upvote 0
Em chưa hiểu được dòng lệnh With .Resize(.Rows.Count - 1, .Columns.Count - 1) trong Code
Nhờ các bác giúp em hiểu về nó
Em xin cảm ơn

Resize nó giống như bạn dùng phím shift với các phím mũi tên lên xuống trái phải vậy đó bạn muốn kéo bao nhiêu cột, dòng thì nhấn phím lên xuống trái phải theo ý muốn, bạn tìm mấy bài của chú SA có nói kỹ về đó lắm Thuộc tính Resize của đối tượng Range trong VBA
 
Upvote 0
Cám ơn bác nmhung49, về thuộc tính Resize thì em có biết nhưng em thắc mắc là tại sao nó mở rộng ra số dòng và số cột With .Resize(.Rows.Count - 1, .Columns.Count - 1) , tức là đoạn em bôi đen đấy ah.

Bởi em thấy dòng ngay trên nó
PHP:
With Sh.Range("A1").CurrentRegion.Offset(1, 1)
đã là toàn bộ vùng cần Copy sang rồi, sao còn mở rộng thêm làm gì nữa nhỉ?
 
Upvote 0
Bạn phải căn cứ vào đoạn code này mới đúng
PHP:
With .Resize(.Rows.Count - 1, .Columns.Count - 1) 
      Range("B65536").End(xlUp)(2).Resize(.Rows.Count, .Columns.Count).Value = .Value 
End With

Tức là vùng bạn muốn paste giá trị copy phải bằng vùng bạn copy nếu bạn không resize bằng vùng bạn copy thì khi paste sẽ thiếu

Bạn có thể thí nghiệm đoạn code này bạn hiểu rõ
PHP:
Sub Rest()
     Range("E4:F10").Value = Range("A4:C10").Value
End Sub

Mà cái Topic này thắc mắc về mảng bạn nên post vào topic những thắc mắc về code nhen. Thân chào!!!
 
Upvote 0
Xin hỏi mảng Gom trong Code sau có ý nghĩa thế nào

Em xem ví dụ đính kèm mà vẫn chưa hiểu Mảng Gom nhằm để làm gì, xin được giải thích giúp

PHP:
Public Sub SapXep()
    Dim Vung, I, Gom, Mg(), K, d
    Set d = CreateObject("scripting.dictionary")
    Vung = Range([A2], [A50000].End(xlUp)).Resize(, 3)
    ReDim Mg(1 To UBound(Vung) * 3, 1 To 1)
        For I = 1 To UBound(Vung)
            Gom = Vung(I, 1) & Vung(I, 2)
                If Not d.exists(Vung(I, 1)) And Not d.exists(Gom) Then
                    K = K + 1
                    d.Add Vung(I, 1), K
                    Mg(K, 1) = Vung(I, 1)
                    K = K + 1
                    d.Add Gom, K
                    Mg(K, 1) = Vung(I, 2)
                    K = K + 1
                    Mg(K, 1) = Vung(I, 3)
                ElseIf d.exists(Vung(I, 1)) And Not d.exists(Gom) Then
                    K = K + 1
                    d.Add Gom, K
                    Mg(K, 1) = Vung(I, 2)
                    K = K + 1
                    Mg(K, 1) = Vung(I, 3)
                Else
                    K = K + 1
                    Mg(K, 1) = Vung(I, 3)
                End If
        Next I
    [F2:F10000].ClearContents
    [F2].Resize(K) = Mg
End Sub
 

File đính kèm

Upvote 0
Tại sao mảng 1 chiều không chứa được biến?

Tôi có thủ tục sau:

Mã:
Sub FillArray()
    Dim MyRng As Range, n As Long, i As Long
    Set MyRng = Range(Source.[A2], Source.[A100].End(xlUp))
    n = MyRng.Rows.Count - 1
    [SIZE=3][COLOR=#0000cd][B]Dim ArrKhoiLuong([/B][/COLOR][COLOR=#ff0000][B]n[/B][/COLOR][COLOR=#0000CD][B]) As String[/B][/COLOR][/SIZE]
    For i = 0 To n
        ArrKhoiLuong(i) = MyRng(i + 1).Value
    Next
End Sub

Nếu như n = 3 và ghi là Dim ArrKhoiLuong(3) As String thì được, còn để vào n thì báo lỗi.
 
Upvote 0
Em xem ví dụ đính kèm mà vẫn chưa hiểu Mảng Gom nhằm để làm gì, xin được giải thích giúp

Nhìn thấy thủ tục của bạn, theo tôi, GOM không phải là mảng, mà là giá trị được ghép với nhau để tạo thành Key mà thôi.
 
Upvote 0
Tại sao mảng 1 chiều không chứa được biến?

Tôi có thủ tục sau:

Mã:
Sub FillArray()
    Dim MyRng As Range, n As Long, i As Long
    Set MyRng = Range(Source.[A2], Source.[A100].End(xlUp))
    n = MyRng.Rows.Count - 1
    [SIZE=3][COLOR=#0000cd][B]Dim ArrKhoiLuong([/B][/COLOR][COLOR=#ff0000][B]n[/B][/COLOR][COLOR=#0000CD][B]) As String[/B][/COLOR][/SIZE]
    For i = 0 To n
        ArrKhoiLuong(i) = MyRng(i + 1).Value
    Next
End Sub

Nếu như n = 3 và ghi là Dim ArrKhoiLuong(3) As String thì được, còn để vào n thì báo lỗi.
Trời!
Cái này nói nhiều lần rồi còn gì
Mảng không thể khai báo kiểu đó được! Muốn gì thì cứ Dim trước, xong sẽ ReDim (hoặc ReDim Preserve) sau đó theo biến
Ví dụ
Mã:
Dim ArrKhoiLuong()
ReDim ArrKhoiLuong(n)
 
Upvote 0
Trời!
Cái này nói nhiều lần rồi còn gì
Mảng không thể khai báo kiểu đó được! Muốn gì thì cứ Dim trước, xong sẽ ReDim (hoặc ReDim Preserve) sau đó theo biến
Ví dụ
Mã:
Dim ArrKhoiLuong()
ReDim ArrKhoiLuong(n)

Uh hen, lâu lâu bị "tẩu hỏa nhập ma", lập đi lập lại thành thói quen, giờ cái cơ bản lại không nhớ! Cám ơn Thầy nha.
 
Upvote 0
Cuối ngày rồi mình có 1 câu hỏi muốn hỏi các bạn ham thích về mảng Array cũng để các bạn hiểu rõ hơn về mảng Array
PHP:
Sub ArrinArr()
Dim Arr As Variant
Arr = Array(Array(Array(4, 5, 6), Array(7, 8, 9), Array(10, 11, 12)), Array(4, Array(13, 14, 15), 6))
'Debug.Print Arr(1)(1)(1)
End Sub
Bạn suy nghĩ trường hợp không dùng Option Base 1 thì truy xuất phần tử trong Array với kiểu truy xuất như dạng này Arr(1)(1)(1) thì giá trị là bao nhiêu, rồi dùng Option Base 1 thì giá trị là bao nhiêu suy nghĩ rồi thì bạn hãy dùng Debug.Print nhen! Các bạn cứ phát triển thêm phần tử trong mảng để hiểu rõ hơn

Anh Hùng ơi
Tại sao khi em paste code này và F5 nó ra giá trị = 14 tại Immediate window
Anh giải thích giúp em nhé
 
Upvote 0
Anh Hùng ơi
Tại sao khi em paste code này và F5 nó ra giá trị = 14 tại Immediate window
Anh giải thích giúp em nhé

Thì 14 đúng rồi!
Arr(0) = Array(Array(4, 5, 6), Array(7, 8, 9), Array(10, 11, 12))
Arr(1) = Array(4, Array(13, 14, 15), 6)
===>
Arr(1)(0) = 4
Arr(1)(1) = Array(13, 14, 15)
Arr(1)(2) = 6
===>
Arr(1)(1)(0) = 13
Arr(1)(1)(1) = 14
Arr(1)(1)(2) = 15
-------------
Đương nhiên kết quả trên dựa trên Option Base 0. Nếu là Option Base 1 thì kết quả sẽ khác
 
Lần chỉnh sửa cuối:
Upvote 0
Nhưng anh Ndu đã giải thích có chỗ này bị lỗi anh Ndu sửa lại dùng em chỗ Arr(1)(1)(0) = 15 thành Arr(1)(1)(2) = 15 nhen. Còn dùng Option Base 1 thì sẽ khác rồi bạn cứ nghiên cứu từ từ nhen
 
Upvote 0
nho giup do

Nhờ các anh chị giúp em giải quyết bài toán này ( em có kèm file)
Em có dùng hàm if(and( nhưng chỉ dùng được có 7 lần….. vì em là thanh viên mới nên không biết tìm bài giải của các anh chị ở đâu trên diễn đàn nữa, vui lòng gửi bài giúp em qua mail :quachcongluanadong@gmail.com ( và chỉ giúp em cách tìm bài được đăng ở đâu luôn các anh chị nhé…..để lần sau tự em tìm. Thanks!

Nếu A6> 0 thì AG6=4 nếu A6<1 thì AG6=5
Nếu A6>0, B6<1thì AH6=5, nếu A6<1,B6<1 thì AH6=7, nếu B6>0 thì AH6=4
Nếu A6<1,B6<1,C6<1 thì AI6=10, nếu A6>0,B6<1,C6<1 thì AI6=7, nếu B6>0,C6<1 thì AI6=5, nếu C6>0 thi AI6=4
Tương tự ……
Nếu A6<1,B6<1,C6<1……..AD6<1 thì Bj6=3000, nếu A6>0,B6<1,C6<1……..AD6<1 thì BJ6=2900, nếu B6>0,C6<1,D6<1……..AD6<1 thì BJ6=2700,nếu C6>0,D6<1,E6<1,F6<1……..AD6<1 thì BJ6=2500,
neu D6>0,E6<1,F6<1G6<1……..AD6<1 thì BJ6=2000, điều kiện tương tự như vậy đến khi AD>0 thì BJ6=4.
Nếu từ A6 đến AE6 đều <1 thì AG6=4 và lập lại điều kiện như trên









 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Nhờ các anh chị giúp em giải quyết bài toán này ( em có kèm file)
Em có dùng hàm if(and( nhưng chỉ dùng được có 7 lần….. vì em là thanh viên mới nên không biết tìm bài giải của các anh chị ở đâu trên diễn đàn nữa, vui lòng gửi bài giúp em qua mail :quachcongluanadong@gmail.com ( và chỉ giúp em cách tìm bài được đăng ở đâu luôn các anh chị nhé…..để lần sau tự em tìm. Thanks!

Nếu A6> 0 thì AG6=4 nếu A6<1 thì AG6=5
Nếu A6>0, B6<1thì AH6=5, nếu A6<1,B6<1 thì AH6=7, nếu B6>0 thì AH6=4
Nếu A6<1,B6<1,C6<1 thì AI6=10, nếu A6>0,B6<1,C6<1 thì AI6=7, nếu B6>0,C6<1 thì AI6=5, nếu C6>0 thi AI6=4
Tương tự ……
Nếu A6<1,B6<1,C6<1……..AD6<1 thì Bj6=3000, nếu A6>0,B6<1,C6<1……..AD6<1 thì BJ6=2900, nếu B6>0,C6<1,D6<1……..AD6<1 thì BJ6=2700,nếu C6>0,D6<1,E6<1,F6<1……..AD6<1 thì BJ6=2500,
neu D6>0,E6<1,F6<1G6<1……..AD6<1 thì BJ6=2000, điều kiện tương tự như vậy đến khi AD>0 thì BJ6=4.
Nếu từ A6 đến AE6 đều <1 thì AG6=4 và lập lại điều kiện như trên
Đây là box lập trình, bộ bạn muốn giải quyết bài toán bằng phương pháp lập trình sao mà gửi bài vào đây
 
Upvote 0
Uh hen, lâu lâu bị "tẩu hỏa nhập ma", lập đi lập lại thành thói quen, giờ cái cơ bản lại không nhớ! Cám ơn Thầy nha.

Hoặc Dim sau đó ReDim hoặc

Mã:
Sub FillArray()
    Dim MyRng As Range, n As Long, i As Long
    Set MyRng = Range(Source.[A2], Source.[A100].End(xlUp))
    n = MyRng.Rows.Count - 1
    [COLOR=#ff0000]Re[/COLOR]Dim ArrKhoiLuong(n) As String
    For i = 0 To n
        ArrKhoiLuong(i) = MyRng(i + 1).Value
    Next
End Sub
 
Upvote 0
Thì 14 đúng rồi!
Arr(0) = Array(Array(4, 5, 6), Array(7, 8, 9), Array(10, 11, 12))
Arr(1) = Array(4, Array(13, 14, 15), 6)
===>
Arr(1)(0) = 4
Arr(1)(1) = Array(13, 14, 15)
Arr(1)(2) = 6
===>
Arr(1)(1)(0) = 13
Arr(1)(1)(1) = 14
Arr(1)(1)(2) = 15
-------------
Đương nhiên kết quả trên dựa trên Option Base 0. Nếu là Option Base 1 thì kết quả sẽ khác

He he...
Trong mảng lại có mảng, Hay quá...e hiểu rồi, lại hiểu thêm một tí tẹo về mảng rồi
 
Upvote 0
Hàm kết nối/phân tách mảng chuỗi

Với mục đích tìm hiểu, học hỏi về dữ liệu kiểu Array, tôi có xây dựng 2 hàm:

1. Function JointStr(ar As Variant, Optional jS As String = " ") As String

Hàm này cho phép nối chuỗi có trong 1 Range (1 vùng), trong một Array (2 chiều, 1 chiều: dọc/ngang) thành một chuỗi với chuỗi phân tách tùy chọn:
Ví dụ: = JoinStr({1, 2, 3}, "->") sẽ cho kết quả là: 1->2->3
hoặc các dạng vùng = JointStr("A1:C5"); JointStr("A1:A5"); JointStr("A1:C1") ... chuỗi phân cách tuỳ chọn.
PHP:
Function JointStr(ar As Variant, Optional jS As String = " ") As String
Dim vStr As String, Item
    Application.Volatile
    For Each Item In ar
        vStr = vStr & jS & Item
    Next
    JointStr = Replace(vStr, jS, "", 1, 1)
End Function

2. Function SplitStr(str As String, Optional jS As String = " ") As Variant

Hàm này ngược với hàm trên.
Cho phép trả giá trị theo 1 hàng ngang hoặc 1 hàng dọc tuỳ người sử dụng.
PHP:
Function SplitStr(str As String, Optional jS As String = " ") As Variant
Dim c As Range, iR As Long, vkq(), hkq, j As Long
    Application.Volatile
    On Error Resume Next
    Set c = Application.Caller
    iR = c.Rows.Count
    On Error GoTo 0
    hkq = Split(str, jS)
    If (iR > 1) Then
        ReDim vkq(1 To iR, 1 To 1)
        For j = 1 To iR
            vkq(j, 1) = hkq(j - 1)
        Next
        SplitStr = vkq
    Else
        SplitStr = hkq
    End If
End Function

3. Cuối cùng là một ứng dụng nhỏ kết hợp 2 hàm này với hàm REPT của Excel để giải bài toán:
Cho 2 cột dữ liệu, cột đầu là các giá trị thường, cột sau là tần suất tương ứng. Viết ra một cột chứa giá trị lặp lại của cột dữ liệu đầu với số dòng bằng tần suất của nó.

(Xem file đính kèm)
<> Là bài tập với mục đích học hỏi, rất mong ACE trên Giải Pháp E góp ý kiến!
 

File đính kèm

Upvote 0
Là bài tập với mục đích học hỏi, rất mong ACE trên Giải Pháp E góp ý kiến!
Tôi xin góp ý với bạn một chút.
1. Thông thường khi viết hàm nối chuỗi người ta sẽ viết để sao cho hàm có thể nối được từ nhiều vùng dữ liệu khác nhau. Hàm JointStr của bạn chỉ cho phép nối từ một vùng hoặc một mảng. Và, thường sẽ bỏ qua ô không có dữ liệu. Ví dụ, JoinStr({1, "", 3}, "->") kết quả 1->3
sẽ hay hơn kết quả 1->->3
2. Hàm SplitStr của bạn chỉ đúng khi số ô trong vùng công thức đúng bằng số phần tử của kết quả. Nếu ít hơn kết quả sẽ thiếu và nếu nhiều hơn sẽ bị lỗi.
3. Về bài toán mà bạn áp dụng, tôi thấy nếu dùng code thì chỉ cần một thủ tục đơn giản với hai vòng lặp là đủ. Hoặc dùng công thức cũng được.
 
Upvote 0
Tôi xin góp ý với bạn một chút.
1. Thông thường khi viết hàm nối chuỗi người ta sẽ viết để sao cho hàm có thể nối được từ nhiều vùng dữ liệu khác nhau. Hàm JointStr của bạn chỉ cho phép nối từ một vùng hoặc một mảng. Và, thường sẽ bỏ qua ô không có dữ liệu. Ví dụ, JoinStr({1, "", 3}, "->") kết quả 1->3
sẽ hay hơn kết quả 1->->3

Rất cảm ơn bạn đã góp ý.

Hàm JointStr có thể được cải tiến theo gợi ý của bạn như sau:
PHP:
Function JointStr(jS As String, ParamArray ar() As Variant) As String
 Dim vStr As String, Item, iAr As Variant
     Application.Volatile
     For Each iAr In ar
     For Each Item In iAr
        If Item <> "" Then vStr = vStr & jS & Item
     Next
     Next
     JointStr = Replace(vStr, jS, "", 1, 1)
End Function
 
Upvote 0
Tôi xin góp ý với bạn một chút.
2. Hàm SplitStr của bạn chỉ đúng khi số ô trong vùng công thức đúng bằng số phần tử của kết quả. Nếu ít hơn kết quả sẽ thiếu và nếu nhiều hơn sẽ bị lỗi.

Bạn kiểm tra giúp hàm SplitStr sau khi sửa lỗi:
PHP:
Function SplitStr(str As String, Optional jS As String = " ") As Variant
Dim c As Range, iR As Long, iC As Long, vkq(), hkq, j As Long, m As Long
    Application.Volatile
    On Error Resume Next
    Set c = Application.Caller
    iR = c.Rows.Count
    iC = c.Columns.Count
    On Error GoTo 0
    j = InStr(str, jS & jS)
    Do While j > 0
        str = Replace(str, jS & jS, jS)
        j = InStr(str, jS & jS)
    Loop
    hkq = Split(str, jS)
    m = UBound(hkq)
    If (iR > 1) Then
        ReDim vkq(1 To m + 1, 1 To 1)
        For j = 1 To m + 1
            vkq(j, 1) = hkq(j - 1)
        Next
    Else
        ReDim vkq(1 To 1, 1 To m + 1)
        For j = 1 To m + 1
            vkq(1, j) = hkq(j - 1)
        Next
    End If
    SplitStr = vkq
End Function
 
Upvote 0
Rất cảm ơn bạn đã góp ý.

Hàm JointStr có thể được cải tiến theo gợi ý của bạn như sau:
PHP:
Function JointStr(jS As String, ParamArray ar() As Variant) As String
 Dim vStr As String, Item, iAr As Variant
     Application.Volatile
     For Each iAr In ar
     For Each Item In iAr
        If Item <> "" Then vStr = vStr & jS & Item
     Next
     Next
     JointStr = Replace(vStr, jS, "", 1, 1)
End Function
Hàm dạng này tôi viết cũng khá lâu... Nó như vầy:
PHP:
Function JoinText(ByVal Sep As String, ByVal IgnoreBlanks As Boolean, ParamArray sArray()) As String
  Dim tmpArr, SubArr, Arr(), Item, n As Long
  On Error Resume Next
  For Each SubArr In sArray
    tmpArr = SubArr
    If TypeName(tmpArr) <> "Variant()" Then
      If IgnoreBlanks = False Or Len(Trim(CStr(tmpArr))) > 0 Then
        n = n + 1
        ReDim Preserve Arr(1 To n)
        Arr(n) = CStr(tmpArr)
      End If
    Else
      For Each Item In tmpArr
        If IgnoreBlanks = False Or Len(Trim(CStr(Item))) > 0 Then
          n = n + 1
          ReDim Preserve Arr(1 To n)
          Arr(n) = CStr(Item)
        End If
      Next
    End If
  Next
  If n Then JoinText = Join(Arr, Sep)
End Function
- Nối chuổi từ mảng hoặc range (nhiều vùng hoặc 1 vùng)
- Bỏ qua chuổi rổng hay không là do người dùng quyết định
Bạn kiểm tra giúp với
--------------
Hàm của bạn vẫn còn vấn đề nếu dữ liệu đầu vào chỉ là 1 cell duy nhất
 
Upvote 0
PHP:
Function JoinText(ByVal Sep As String, ByVal IgnoreBlanks As Boolean, ParamArray sArray()) As String
'...'
End Function

Hàm của anh ndu rất tốt, tôi đã kiểm tra với nhiều trường hợp nhưng không phát hiện lỗi.
Cảm ơn đã reply!

(không hiểu sao với hàm JointStr thực hiện trên máy tính của tôi vẫn cho đúng kết quả khi đầu vào chỉ 1 ô duy nhất!)
 
Upvote 0
(không hiểu sao với hàm JointStr thực hiện trên máy tính của tôi vẫn cho đúng kết quả khi đầu vào chỉ 1 ô duy nhất!)
Sorry! Lúc nảy tôi test nhầm. Không phải lỗi xuất hiện khi dữ liệu đầu vào là 1 cell mà lỗi khi dữ liệu là 1 chuổi. Chẳng hạn =JointStr("-","a")
----------------

Xin hỏi về hàm SplitStr 1 tí: Sao phải cần đến hàm này trong khi VBA đã có sẵn hàm Split? Hay bạn muốn chuyển mảng 1 chiều thành 2 chiều chăng? (ngang thành dọc)
 
Lần chỉnh sửa cuối:
Upvote 0
Sorry! Lúc nảy tôi test nhầm. Không phải lỗi xuất hiện khi dữ liệu đầu vào là 1 cell mà lỗi khi dữ liệu là 1 chuổi. Chẳng hạn =JointStr("-","a")
----------------

Xin hỏi về hàm SplitStr 1 tí: Sao phải cần đến hàm này trong khi VBA đã có sẵn hàm Split? Hay bạn muốn chuyển mảng 1 chiều thành 2 chiều chăng? (ngang thành dọc)

Vâng, thì cũng có 1 vài lý do để viết lại hàm Split. Quan trọng nhất là để mở rộng kiến thức. Vì theo tôi phương pháp tìm hiểu tốt nhất là cố gắng viết lại, xây dựng lại một số chức năng/ hàm mà ngôn ngữ lập trình đã có. Ngoài ra, lập trình cũng là một thú vui (mà cũng vì nó mà tôi "khổ sở" đến tận bây giờ!).

Thay đổi hàm khắc phục lỗi anh ndu đã phát hiện (thật là đi 1 ngày học được bao điều!):
PHP:
Function JointStr(jS As String, ParamArray ar() As Variant) As String
 Dim vStr As String, Item, iAr As Variant
     Application.Volatile
     For Each iAr In ar
     If (TypeName(iAr) = "Variant()") Or (TypeName(iAr) = "Range") Or (TypeName(iAr) = "Array") Then
     For Each Item In iAr
        If Item <> "" Then vStr = vStr & jS & Item
     Next
     Else
        vStr = vStr & jS & iAr
     End If
     Next
     JointStr = Replace(vStr, jS, "", 1, 1)
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
dùng công thức mảng để so sánh 2 vùng dữ liệu???

Em đang học mảng và thử tìm hiểu cách dùng mảng để so sánh 2 vùng dữ liệu (so sánh sự khác nhau về số tiền hoặc ko tồn tại)

Anh, Chị giúp em nhé
 

File đính kèm

Upvote 0
Em đang học mảng và thử tìm hiểu cách dùng mảng để so sánh 2 vùng dữ liệu (so sánh sự khác nhau về số tiền hoặc ko tồn tại)

Anh, Chị giúp em nhé

Cứ nói đến TỒN TẠI hoặc KHÔNG TỒN TẠI, ta nghĩ ngay đến Dictionary
Loại bài toán này đã nói nhiều lần rồi, chẳng hạn là ở đây:
http://www.giaiphapexcel.com/forum/showthread.php?48469-Tạo-hàm-so-sánh-2-danh-sách
Hàm ấy chỉ so sánh 1 điều kiện, giờ so sánh 2 điều kiện thì thuật toán cũng thế thôi (chỉnh lại 1 chút... Có thể nối chuổi 2 điều kiện lại với nhau rồi mới so sánh cũng là 1 cách)
 
Upvote 0
Các sư phụ ơi! chủ đề này mình thấy rất bổ ích nhưng nếu được thì chắc các sư phụ có thể tổng hợp lại thành một chuyên đề về mãng một cách xúc tích và cô đọng hơn đc ko ah! Vì hiện giờ mình cũng đang tập tành ứng dụng VBA (đặc biệt là chủ đề mãng này) để giải quyết cho công việc của mình sao cho code chạy lẹ và chính xác! Nếu được thì mình rất cám ơn các sư phụ nhiều lắm!
 
Upvote 0
Em thử một đoạn code mảng này để làm công việc sau
Sheet có 11 cột và hơn 60.000 dòng dữ liệu
- Cột 5 : email
- Cột 7 : mobile
- Cột 10: City

Yêu cầu của Lãnh đạo theo thứ tự sau
1. Sort dữ liệu : Theo City
Sau đó
2. Sort dữ liệu : cùng city, vừa có email, vừa có di động
sau đó
3. Sort dữ liệu: Cùng city, chỉ có email, không có di động
sau đó
4. Sort dữ liệu: Cùng city, không email, có di động
cuối cùng
5. Sort dữ liệu: Cùng city, ko email, không di động

E đã tiến hành sort theo cột city trước (cột 10) rồi chạy đoạn code sau, nhưng nó bị lỗi
Nếu code chạy ok, em sẽ sort theo cột 11 là ổn
Chỉ giúp em

PHP:
Sub Locthutu()
Dim Arr
Dim SArr
SArr = Sheet1.Range("A6:K60005").Value
ReDim Preserve Arr(1 To UBound(SArr, 1), 1 To 1)
For i = 2 To UBound(Arr)
    Arr(i, 1) = IIf(SArr(i, 10) = SArr(i - 1, 10), trim(SArr(i - 1, 10)), trim(SArr(i, 10)))
        
        If SArr(i, 5) <> "" And SArr(i, 7) <> "" Then ' have email & mobile
            Arr(i, 1) = Arr(i, 1) & "A" ' rank A
            If SArr(i, 5) <> "" And SArr(i, 7) = "" Then ' Just email only, No Mobile
                Arr(i, 1) = Arr(i, 1) & "B" ' rank B
                If SArr(i, 5) = "" And SArr(i, 7) <> "" Then ' No email, just Mobile
                      Arr(i, 1) = Arr(i, 1) & "C"
                      If SArr(i, 5) = "" And SArr(i, 7) = "" Then ' No email, No Mobile
                      Arr(i, 1) = Arr(i, 1) & "D"
                      End If
                End If
            End If
        End If
Next i
Sheet1.Range("K6:K60005").Value = Arr


End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Em làm được rồi, bỏ Preserve đi là chạy (không hiểu sao lại thế nhỉ?)

Và Code sửa lại thành
phân cấp như sau
CityA: Có mail & di động
CityB: Có mail, ko di động
CityC: Ko mail, có di động
CityD: Ko mail, ko di động

PHP:
Sub Locthutu()
Dim Arr
Dim SArr
SArr = Sheet1.Range("A6:K60005").Value
ReDim Preserve Arr(1 To UBound(SArr, 1), 1 To 1)
For i = 2 To UBound(Arr)
    Arr(i, 1) = IIf(SArr(i, 10) = SArr(i - 1, 10), trim(SArr(i - 1, 10)), trim(SArr(i, 10)))
        
        If SArr(i, 5) <> "" And SArr(i, 7) <> "" Then ' have email & mobile
            Arr(i, 1) = Arr(i, 1) & "A" ' rank A
            If SArr(i, 5) <> "" And SArr(i, 7) = "" Then ' Just email only, No Mobile
                Arr(i, 1) = Arr(i, 1) & "B" ' rank B
                If SArr(i, 5) = "" And SArr(i, 7) <> "" Then ' No email, just Mobile
                      Arr(i, 1) = Arr(i, 1) & "C"
                      If SArr(i, 5) = "" And SArr(i, 7) = "" Then ' No email, No Mobile
                      Arr(i, 1) = Arr(i, 1) & "D"
                      End If
                End If
            End If
        End If
Next i
Sheet1.Range("K6:K60005").Value = Arr


End Sub

Cuối cùng, sort cột thứ 11
 
Lần chỉnh sửa cuối:
Upvote 0
Từ bài viết [URL="http://www.giaiphapexcel.com/forum/showthread.php?27719-Ch%C6%B0%C6%A1ng-tr%C3%ACnh-ch%E1%BB%8Dn-th%C3%A9p-theo-di%E1%BB%87n-t%C3%ADch"]Chương trình chọn thép theo diện tích [/URL]nhưng chỉ tra được từng diện tích một, thông thường người ta có bảng tính diện tích cốt thép cho nhiều mặt cắt với nhiều cấu kiện khác nhau thì trường hợp này rất mất thời gian. Để khắc phục đều này tôi nghĩ ra phương án là tạo Validation gồm các phương án cho từng diện tích cốt thép để người sử dụng lựa chọn nhưng đang vướng mắc một điều mong các anh chị giúp đỡ:
Giả sử tôi có mãng (Array) là Arr(). Vậy code nào chuyển các phần tử của mãng Arr() thành list của Validation của một cell trên bảng tính
Xin cảm ơn các anh chị
 
Upvote 0
Từ bài viết Chương trình chọn thép theo diện tích nhưng chỉ tra được từng diện tích một, thông thường người ta có bảng tính diện tích cốt thép cho nhiều mặt cắt với nhiều cấu kiện khác nhau thì trường hợp này rất mất thời gian. Để khắc phục đều này tôi nghĩ ra phương án là tạo Validation gồm các phương án cho từng diện tích cốt thép để người sử dụng lựa chọn nhưng đang vướng mắc một điều mong các anh chị giúp đỡ:
Giả sử tôi có mãng (Array) là Arr(). Vậy code nào chuyển các phần tử của mãng Arr() thành list của Validation của một cell trên bảng tính
Xin cảm ơn các anh chị

Với Validation thì có 2 cách Add List:
1> Gán Arr xuống 1 cột trên sheet rồi dùng cột này làm list cho Validation ---> Cái này chắc khỏi nói bạn cũng biết
2> Nối chuổi trong Arr theo kiểu Join(Arr, ",") rồi cho vào Validation (kiểu như gõ bằng tay trong validation vậy)... ví dụ:
Mã:
Sub Test()
  Dim Arr
  Arr = Array("A", "B", "C")
  With Range("A1").Validation
    .Delete
    .Add 3, , , Join(Arr, ",")
  End With
End Sub
 
Upvote 0
Với Validation thì có 2 cách Add List:
1> Gán Arr xuống 1 cột trên sheet rồi dùng cột này làm list cho Validation ---> Cái này chắc khỏi nói bạn cũng biết
2> Nối chuổi trong Arr theo kiểu Join(Arr, ",") rồi cho vào Validation (kiểu như gõ bằng tay trong validation vậy)... ví dụ:
Mã:
Sub Test()
  Dim Arr
  Arr = Array("A", "B", "C")
  With Range("A1").Validation
    .Delete
    .Add [COLOR=#ff0000]3[/COLOR], , , Join(Arr, ",")
  End With
End Sub
Em xin cảm ơn. Em đã giải quyết được vấn đề
 
Lần chỉnh sửa cuối:
Upvote 0
Tôi test đoạn này bị lỗi. Các bạn sửa giúp tôi với
Mục đích:
- Các format ngày trong cột B đang ở dạng Text
- Dùng code mảng chuyển nó về formate date

PHP:
Sub test()
Dim Arr
[B2:B1000].Value = Arr
For i = 1 To UBound(Arr(), 1)
Arr = DateSerial(Year(Arr), Month(Arr), Day(Arr))
Next i
[B2:B1000].Value = Arr

End Sub
Cám ơn
 
Upvote 0
Tôi test đoạn này bị lỗi. Các bạn sửa giúp tôi với
Mục đích:
- Các format ngày trong cột B đang ở dạng Text
- Dùng code mảng chuyển nó về formate date

PHP:
Sub test()
Dim Arr
[B2:B1000].Value = Arr
For i = 1 To UBound(Arr(), 1)
Arr = DateSerial(Year(Arr), Month(Arr), Day(Arr))
Next i
[B2:B1000].Value = Arr

End Sub
Cám ơn
Bạn đưa code lên cũng chẳng giúp ích được gì đâu. Cái điều quan trọng mà mọi người cần biết là Text trong cột B đang được sắp xếp kiểu gi
 
Upvote 0
Bạn đưa code lên cũng chẳng giúp ích được gì đâu. Cái điều quan trọng mà mọi người cần biết là Text trong cột B đang được sắp xếp kiểu gi

Cám ơn NDU
Ngày có định dạng như sau

yyyy/mm/dd hh:mm


PHP:
Sub testdate()
' text to column -> get date
    Columns("B:B").Select
    Selection.TextToColumns Destination:=Range("B1"), DataType:=xlFixedWidth, _
        FieldInfo:=Array(Array(0, 4), Array(10, 1)), TrailingMinusNumbers:=True

End Sub

Tạm thời Tôi record mảrco, dùng Text Column ra rồi, nhưng chửa hiểu số 4 và số 10 trong Array có nghĩa gì?
Thanks
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Cám ơn NDU
Ngày có định dạng như sau

yyyy/mm/dd hh:mm


PHP:
Sub testdate()
' text to column -> get date
    Columns("B:B").Select
    Selection.TextToColumns Destination:=Range("B1"), DataType:=xlFixedWidth, _
        FieldInfo:=Array(Array(0, 4), Array(10, 1)), TrailingMinusNumbers:=True

End Sub

Tạm thời Tôi record mảrco, dùng Text Column ra rồi, nhưng chửa hiểu số 4 và số 10 trong Array có nghĩa gì?
Thanks

Định dạng yyyy/mm/dd là quá ngon rồi còn gì. Với định dạng này, bạn chỉ cần copy 1 ô trống, xong, paste special\Value + Add vào dữ liệu là ra ngay kết quả
 
Upvote 0
Các Bác chỉ giúp Code dưới này sai ở đâu? (tôi muốn thử làm với mảng nhưng chưa quen)
Tks
PHP:
Function SumAll(RngCur As Range, dk1, RngDate As Range, dk2, RngMethod As Range, dk3) As Long '
  Dim i As Long
  Dim ArrCur
  Dim ArrDate
  Dim ArrMethod
  ArrCur = RngCur.Value
  ArrDate = RngDate.Value
  ArrMethod = RngMethod.Value
  ArrAmt = RngCur.Offset(, 3).Value
 For i = 1 To UBound(ArrCur())
    If UCase$(ArrCur(i, 1)) = dk1 And _
       UCase$(ArrDate(i, 1)) = dk2 And _
       UCase$(ArrMethod(i, 1)) = dk3 Then
       SumAll = SumAll + ArrAmt(i, 1)
    End If
 Next

End Function
 

File đính kèm

Upvote 0
Các Bác chỉ giúp Code dưới này sai ở đâu? (tôi muốn thử làm với mảng nhưng chưa quen)
Tks
PHP:
Function SumAll(RngCur As Range, dk1, RngDate As Range, dk2, RngMethod As Range, dk3) As Long '
  Dim i As Long
  Dim ArrCur
  Dim ArrDate
  Dim ArrMethod
  ArrCur = RngCur.Value
  ArrDate = RngDate.Value
  ArrMethod = RngMethod.Value
  ArrAmt = RngCur.Offset(, 3).Value
 For i = 1 To UBound(ArrCur())
    If UCase$(ArrCur(i, 1)) = dk1 And _
       UCase$(ArrDate(i, 1)) = dk2 And _
       UCase$(ArrMethod(i, 1)) = dk3 Then
       SumAll = SumAll + ArrAmt(i, 1)
    End If
 Next

End Function

Làm được hay không ta chưa nói đến, chỉ xét bài này thì thấy nó tương đương với công thức
=SUMPRODUCT(($A$2:$A$7=$G$1)*($B$2:$B$7=$F3)*($C$2:$C$7=G$2)*($D$2:$D$7))
Vậy nên dù bạn viết thế nào thì tốc độ tính toán của nó cũng sẽ không hơn SUMPRODUCT đâu
Đang thắc mắc: Tại sao bạn không dùng PivotTable để tổng hợp?
 
Upvote 0
Làm được hay không ta chưa nói đến, chỉ xét bài này thì thấy nó tương đương với công thức
=SUMPRODUCT(($A$2:$A$7=$G$1)*($B$2:$B$7=$F3)*($C$2:$C$7=G$2)*($D$2:$D$7))
Vậy nên dù bạn viết thế nào thì tốc độ tính toán của nó cũng sẽ không hơn SUMPRODUCT đâu
Đang thắc mắc: Tại sao bạn không dùng PivotTable để tổng hợp?

Cám ơn bác NDU
1. Tôi đang học mảng và thử trên nội dung này, (thấy Bác có hàm diengiai hay quá, định lò mò làm theo)
2. Lý do thứ 2 là Sumproduct, tôi thấy đưa vào VBA hơi khó. Đang cố thử làm lại (theo gợi ý của Bác )
3. PIVOT 2007 dữ liệu tổng hợp từ 2 sheet, tôi đã dùng multiple range (ALT + D + P) nhưng vẫn chưa thể làm ra được theo 3 điều kiện, đặc biệt điều kiện Date là từ một khoảng đến 1 khoảng

Link này tôi đã hỏi tại đây.
http://www.giaiphapexcel.com/forum/...heo-ngày-(From-To-)-từ-2-sheet-với-excel-2007
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
3. PIVOT 2007 dữ liệu tổng hợp từ 2 sheet, tôi đã dùng multiple range (ALT + D + P) nhưng vẫn chưa thể làm ra được theo 3 điều kiện, đặc biệt điều kiện Date là từ một khoảng đến 1 khoảng

Link này tôi đã hỏi tại đây.
http://www.giaiphapexcel.com/forum/showthread.php?73311-Nh%E1%BB%9D-h%C6%B0%E1%BB%9Bng-d%E1%BA%ABn-l%C3%A0m-PIVOT-theo-ng%C3%A0y-%28From-To-%29-t%E1%BB%AB-2-sheet-v%E1%BB%9Bi-excel-2007

PivotTable tôi không rành lắm, nhưng tôi nghĩ rằng: Nếu dùng multiple range không được thì sao ta không gộp 2 sheet lại thành một, xong dùng PivotTable chỉ là chuyện nhỏ
 
Upvote 0
PivotTable tôi không rành lắm, nhưng tôi nghĩ rằng: Nếu dùng multiple range không được thì sao ta không gộp 2 sheet lại thành một, xong dùng PivotTable chỉ là chuyện nhỏ
Cám ơn Bác NDU
tôi định quay ra cho vào 1 sheet (nhưng trường hợp file share dùng chung giữa 2 người, ngại trường hợp dữ liệu bị đè lên nhau)

Cám ơn Bác, PIVOT rất hay nhưng tôi cũng không khoái lắm, định mày mò học mà khó quá
 
Upvote 0
Mong các anh chị giúp đở em, em có viết một cái hàm nội suy 1 chiều nhưng giờ em mở lên chạy thì lại bị vô hiệu hoá không chạy được, Mong các bác giúp em sơm để còn kip làm đồ án!
 
Upvote 0
Bi Bô đang tập mảng và thử ghép 2 cột lại với nhau, dán nó vào cột khác
Nghịch một code như sau nhưng nó báo lỗi

Các Bác sửa lại giúp Bi Bô
PHP:
Sub ghep()


Dim SArr
SArr = Range("A3:J" & [J65000].End(xlUp).Row).Value
ReDim Arr(1 To UBound(SArr()), 1 To 1)
For i = 1 To UBound(SArr(), 1)
SArr(i, 3) = SArr(i, 3) & SArr(i, 4) ' cot 3 = cot 3 & cot 4
SArr(i, 1) = SArr(i, 9) & SArr(i, 3) ' cot 1 = cot 9  & cot 3
Arr(i, 1) = SArr(i, 1)
Next i
Range("A3:A" & [J65000].End(xlUp).Row).Value = Arr

End Sub
 
Upvote 0
Bi Bô đang tập mảng và thử ghép 2 cột lại với nhau, dán nó vào cột khác
Nghịch một code như sau nhưng nó báo lỗi

Các Bác sửa lại giúp Bi Bô
PHP:
Sub ghep()


Dim SArr
SArr = Range("A3:J" & [J65000].End(xlUp).Row).Value
ReDim Arr(1 To UBound(SArr()), 1 To 1)
For i = 1 To UBound(SArr(), 1)
SArr(i, 3) = SArr(i, 3) & SArr(i, 4) ' cot 3 = cot 3 & cot 4
SArr(i, 1) = SArr(i, 9) & SArr(i, 3) ' cot 1 = cot 9  & cot 3
Arr(i, 1) = SArr(i, 1)
Next i
Range("A3:A" & [J65000].End(xlUp).Row).Value = Arr

End Sub
1. Bạn đã dim Arr() đâu mà ReDim?
2. Bạn chỉ muốn xuất Arr thôi thì thêm lệnh: SArr(i, 3) = SArr(i, 3) & SArr(i, 4) làm gì?
3. Sao không gán Arr(i, 1) = SArr(i, 9) & SArr(i, 3) mà gán SArr(i, 1) = SArr(i, 9) & SArr(i, 3) để rồi phải thêm lệnh Arr(i, 1) = SArr(i, 1)
4. Range("A3:A" & [J65000].End(xlUp).Row).Value = Arr nên sửa lại Range("A3").Resize (UBound(arr)).Value = Arr
 
Lần chỉnh sửa cuối:
Upvote 0
Bi Bô đang tập mảng và thử ghép 2 cột lại với nhau, dán nó vào cột khác
Nghịch một code như sau nhưng nó báo lỗi

Các Bác sửa lại giúp Bi Bô
PHP:
Sub ghep()


Dim SArr
SArr = Range("A3:J" & [J65000].End(xlUp).Row).Value
ReDim Arr(1 To UBound(SArr()), 1 To 1)
For i = 1 To UBound(SArr(), 1)
SArr(i, 3) = SArr(i, 3) & SArr(i, 4) ' cot 3 = cot 3 & cot 4
SArr(i, 1) = SArr(i, 9) & SArr(i, 3) ' cot 1 = cot 9  & cot 3
Arr(i, 1) = SArr(i, 1)
Next i
Range("A3:A" & [J65000].End(xlUp).Row).Value = Arr

End Sub

Sửa chổ này
Mã:
ReDim Arr(1 To UBound(SArr[COLOR=#ff0000]()[/COLOR]), 1 To 1)
For i = 1 To UBound(SArr[COLOR=#ff0000]()[/COLOR], 1)
Thành
Mã:
ReDim Arr(1 To UBound(SArr), 1 To 1)
For i = 1 To UBound(SArr, 1)
Còn tôi thì sẽ viết thế này:
Mã:
Sub ghep()
  Dim Arr, i As Long
  With Range([A3], [J65000].End(xlUp))
    Arr = .Value
    For i = 1 To UBound(Arr, 1)
      Arr(i, 1) = Arr(i, 9) & Arr(i, 3) & Arr(i, 4)
    Next i
    .Resize(, 1).Value = Arr
  End With
End Sub
-----------------------------------------
1. Bạn đã dim Arr() đâu mà ReDim?
Cái này được à nghen ---> Khỏi Dim cũng ReDim được đấy
 
Lần chỉnh sửa cuối:
Upvote 0
Sửa chổ này
Mã:
ReDim Arr(1 To UBound(SArr[COLOR=#ff0000]()[/COLOR]), 1 To 1)
For i = 1 To UBound(SArr[COLOR=#ff0000]()[/COLOR], 1)
Thành
Mã:
ReDim Arr(1 To UBound(SArr), 1 To 1)
For i = 1 To UBound(SArr, 1)
Còn tôi thì sẽ viết thế này:
Mã:
Sub ghep()
  Dim Arr, i As Long
  With Range([A3], [J65000].End(xlUp))
    Arr = .Value
    For i = 1 To UBound(Arr, 1)
      Arr(i, 1) = Arr(i, 9) & Arr(i, 3) & Arr(i, 4)
    Next i
    .Resize(, 1).Value = Arr
  End With
End Sub
-----------------------------------------

Cái này được à nghen ---> Khỏi Dim cũng ReDim được đấy

Hay quá...Bi Bô làm được rồi
Cám ơn Viêt Hoài & NDU nhiều
 
Upvote 0
Trong hàm diengiai của Tác Giả NDU,
PHP:
Function diengiai(FVal, FindRng As Range, RestRng As Range) As String
  Dim i As Long, j As Long, Temp, Arr(), Dic1, Dic2
  Set Dic1 = CreateObject("Scripting.Dictionary")
  Set Dic2 = CreateObject("Scripting.Dictionary")
  For i = 1 To FindRng.Rows.Count
   If FindRng(i, 1) = FVal Then  ' neu thoa man
      Temp = RestRng(i, 1)       ' gan gia tri tu RestRng vao Temp
      If Not Dic1.Exists(Temp) Then  ' neu gia tri temp la duy nhat
        j = j + 1
        Dic1.Add Temp, 1    ' Dong nay nen dich hieu nhu nao? co phai add Item dau tien vao Temp
        Dic2.Add Temp, j    '??? add item thu J vao Temp
      Else
        Dic1.Item(Temp) = Dic1.Item(Temp) + 1 ' bo qua mot item neu ton tai???
      End If
      ReDim Preserve Arr(1 To j)
      Arr(Dic2.Item(Temp)) = Temp '& "(" & Dic1.Item(Temp) & ")"
    End If
  Next
  diengiai = Join(Arr, ", ")
End Function

Nhờ Các Bác giúp đỡ giải thích, chỉ dạy cho tôi một số dòng code, câu hỏi còn thắc mắc chưa hiểu
PHP:
1  Dic1.Add Temp, 1    
2  Dic2.Add Temp, j
Dòng code 1: có phải add item đầu tiên vào key Temp ?
Dỏng code 2: có phải add item thứ j vào Key Temp?
Nếu vậy? tại sao dòng 2 mình không khai là
PHP:
1  Dic1.Add Temp, 1    
2  Dic1.Add Temp, j

đoạn code dưới này có phải là bỏ qua một item trong RestRng (nếu đã có)
PHP:
Else
        Dic1.Item(Temp) = Dic1.Item(Temp) + 1

Và tại sao mình lại phải ReDim Preserve Arr(1 To j)
Trong khi từ đầu mình chưa dùng gì đến Arr ???


Ngồi nghĩ cả buổi chiều mà ko hiểu thuât toán như nào? Các bác giúp tôi nhé
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Hỏi về mảng- Array !!!

Em có bài toán đơn giản về mảng như thế này :
Tìm kiếm giá trị mà thỏa điều kiện đề ra thì ta táng vào 1 mảng. Và đọan code em viết như thế này : (ví dụ kèm theo )
Tuy nhiên cảm thấy chỉ có mỗi việc như thế mà chế đến đọan code dài dòng văn tự như thế này thì lãng phí quá.
Các cụ có cái thủ thuật nào hay và ngắn gọn, hoặc cái hàm nào ngắn gọn có thể trả về kết quả tương tự xin chỉ bảo hộ cho em với ...Em xin chân thành cám ơn các cụ ạ...!

Sub tt()
Dim i, k, count As Integer
Dim mang()
count = 0
i = 1
Do Until Cells(i, 1) = "END"
If Cells(i, 1) <> "" Then
count = count + 1
End If
i = i + 1
Loop
ReDim mang(1 To count, 2)
i = 1
k = 1
Do Until Cells(i, 1) = "END"
If Cells(i, 1) <> "" Then
mang(k, 1) = k
mang(k, 2) = Cells(i, 1)
k = k + 1
Else
k = k
End If
i = i + 1
Loop
For k = 1 To UBound(mang)
Cells(k + 2, 4) = mang(k, 1)
Cells(k + 2, 5) = mang(k, 2)
Next
End Sub
 

File đính kèm

Upvote 0
Em có bài toán đơn giản về mảng như thế này :
Tìm kiếm giá trị mà thỏa điều kiện đề ra thì ta táng vào 1 mảng. Và đọan code em viết như thế này : (ví dụ kèm theo )
Tuy nhiên cảm thấy chỉ có mỗi việc như thế mà chế đến đọan code dài dòng văn tự như thế này thì lãng phí quá.
Các cụ có cái thủ thuật nào hay và ngắn gọn, hoặc cái hàm nào ngắn gọn có thể trả về kết quả tương tự xin chỉ bảo hộ cho em với ...Em xin chân thành cám ơn các cụ ạ...!

Sub tt()
Dim i, k, count As Integer
Dim mang()
count = 0
i = 1
Do Until Cells(i, 1) = "END"
If Cells(i, 1) <> "" Then
count = count + 1
End If
i = i + 1
Loop
ReDim mang(1 To count, 2)
i = 1
k = 1
Do Until Cells(i, 1) = "END"
If Cells(i, 1) <> "" Then
mang(k, 1) = k
mang(k, 2) = Cells(i, 1)
k = k + 1
Else
k = k
End If
i = i + 1
Loop
For k = 1 To UBound(mang)
Cells(k + 2, 4) = mang(k, 1)
Cells(k + 2, 5) = mang(k, 2)
Next
End Sub
Mảng mà chạy trực tiếp trên Cell thì cũng bằng không! Cái này là "mảng nửa vời"
Tôi thì làm vầy:
Mã:
Sub Test()
   Dim aSrc, Arr(), tmp As String
   Dim i As Long, n As Long
   aSrc = Range(Cells(1, 1), Cells(10000, 1)).Value
   ReDim Arr(1 To UBound(aSrc, 1), 1 To 2)
   For i = 1 To UBound(aSrc, 1)
     tmp = CStr(aSrc(i, 1))
     If tmp = "END" Then GoTo Finish
     If Len(tmp) Then
       n = n + 1
       Arr(n, 1) = n
       Arr(n, 2) = tmp
     End If
   Next
Finish:
   If n Then Cells(3, 4).Resize(n, 2).Value = Arr
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Cám ơn thầy ndu nhé..biết ngay kiểu gì cũng có sự chỉ dẫn của thấy.. Ngắn gọn súc tích hơn , pờ rồ hơn nhưng nhiều cái phải tìm hiểu thêm...tìm hiểu kỹ thì mới nhớ lâu được..
Dùng máy công ty nó cổ lỗ sĩ quá, phần Help nó ít quá chả tham khảo được hàm nào cả...Em sẽ nghiên cứu thêm, mà không hiểu cái hàm Cstr của thầy nó có công dụng gì nhỉ ?

PS..Em đang săn cái thằng đối diện..để lồng vào cái Avatar của thầy, khi nào tìm được thằng ưng ý, em gửi cho thầy nhá....hè hè
 
Upvote 0
mà không hiểu cái hàm Cstr của thầy nó có công dụng gì nhỉ ?
Hàm CStr ấy mà ---> Biến mọi thứ thành kiểu dữ liệu String thôi
Trong code của bạn, nếu không có CStr cũng không sao, tại tôi quen tay rồi (nhằm tăng tốc)


PS..Em đang săn cái thằng đối diện..để lồng vào cái Avatar của thầy, khi nào tìm được thằng ưng ý, em gửi cho thầy nhá....hè hè
Nói gì hổng hiểu gì hết trơn
 
Upvote 0
Thực ra thấy cái Avatar của thầy giống như đang...chuẩn bị đánh ai thì phải...đoán như thế nên kiếm cái thằng đối diện cái avatar đó thêm vào cho đủ bộ ..ấy mà...
 
Upvote 0
...
Tuy nhiên cảm thấy chỉ có mỗi việc như thế mà chế đến đọan code dài dòng văn tự như thế này thì lãng phí quá.
Các cụ có cái thủ thuật nào hay và ngắn gọn, hoặc cái hàm nào ngắn gọn có thể trả về kết quả tương tự xin chỉ bảo hộ cho em với ...

Mục đích lập trình của bạn là gì?
Từ "lãng phí" ở trên muốn nói về lãng phí loại tài nguyên (resource) nào? bộ nhớ trong khi chạy code, thời gian chiếm hữu CPU/ổ cứng, thời gian chạy code, công sức viết code, hay số bytes cần thiết để trữ code (tức là số dòng code)?

Bạn phải xác định mục đích "tránh lãng phí" của mình rồi mới nói chuyện chỉnh sửa code cho hiệu quả được.

Ví dụ với những array lớn thì dùng array càng nhiều càng tốn bộ nhớ.

Nếu chỉ tự nhận thấy code của mình luộm thuộm thì nên hỏi người ta xem luộm thuộm chỗ nào và có thể sửa được ra sao.

Code của bạn gồm có 3 phần:
1. đếm trong vùng dữ liệu xem có bao nhiêu dòng và lập mảng với độ lớn ấy
2. ghi nhưng dòng dữ liệu không trống vào mảng
3. ghi mảng vào vùng kết quả

Cái lãng phí của code này là:
- mỗi công việc trên lại phải dùng một vòng lặp, trong khi chỉ cần một vòng lặp là làm được hết rồi.
- mảng 2 chiều, nhưng cột thứ nhất chỉ là số thứ tự từ 1 đến n, thế thì có thể hiểu ngầm chứ chứa làm quái gì?

Lưu ý: những lời tôi nói trên dùng để chỉ dẫn cách cải tiến trình độ lập trình. Nếu chỉ muốn giải uyết vấn đề của đề bài một cách gọn đẹp thì code sủa ndu96081531 là có thể coi như tối ưu rồi.
 
Upvote 0
Mục đích lập trình của bạn là gì?
Từ "lãng phí" ở trên muốn nói về lãng phí loại tài nguyên (resource) nào? bộ nhớ trong khi chạy code, thời gian chiếm hữu CPU/ổ cứng, thời gian chạy code, công sức viết code, hay số bytes cần thiết để trữ code (tức là số dòng code)?

Bạn phải xác định mục đích "tránh lãng phí" của mình rồi mới nói chuyện chỉnh sửa code cho hiệu quả được.

Ví dụ với những array lớn thì dùng array càng nhiều càng tốn bộ nhớ.

Nếu chỉ tự nhận thấy code của mình luộm thuộm thì nên hỏi người ta xem luộm thuộm chỗ nào và có thể sửa được ra sao.

Code của bạn gồm có 3 phần:
1. đếm trong vùng dữ liệu xem có bao nhiêu dòng và lập mảng với độ lớn ấy
2. ghi nhưng dòng dữ liệu không trống vào mảng
3. ghi mảng vào vùng kết quả

Cái lãng phí của code này là:
- mỗi công việc trên lại phải dùng một vòng lặp, trong khi chỉ cần một vòng lặp là làm được hết rồi.
- mảng 2 chiều, nhưng cột thứ nhất chỉ là số thứ tự từ 1 đến n, thế thì có thể hiểu ngầm chứ chứa làm quái gì?

Lưu ý: những lời tôi nói trên dùng để chỉ dẫn cách cải tiến trình độ lập trình. Nếu chỉ muốn giải uyết vấn đề của đề bài một cách gọn đẹp thì code sủa ndu96081531 là có thể coi như tối ưu rồi.


Thực sự là em là dân làm việc văn phòng, chưa qua trường lớp nào về lập trình cả. Toàn tự mày mò mà đọc rồi ứng dụng vào trong công việc thôi. Vì khi làm như thế này, em vẫn thấy cái code nó có đến 2 cái vòng lặp nên mới thấy mình ngu ngu nên mới mạo muội hỏi các thầy xem có cách khác hay không mà còn học hỏi thêm.
Ứng dụng thực sự là mảng 1 chiều thôi, làm cái 2 chiều để cho cái ví dụ cho các thầy dễ hiểu mà trả lời chính xác nội dung em cần hỏi thôi.
 
Upvote 0
Bạn phải xác định mục đích "tránh lãng phí" của mình rồi mới nói chuyện chỉnh sửa code cho hiệu quả được.

Những người mới học, mục đích của họ là: LÀM SAO TIẾP CẬN ĐƯỢC GIẢI THUẬT
Không bàn chuyện code đúng hay sai, hay hay dở... chỉ riêng chuyện code dài dòng cũng đủ gây khó khăn cho họ rồi (mù mù mờ mờ chẳng biết đâu mà lần)
Chỉ thế thôi
 
Upvote 0
Mục đích lập trình của bạn là gì?
Từ "lãng phí" ở trên muốn nói về lãng phí loại tài nguyên (resource) nào? bộ nhớ trong khi chạy code, thời gian chiếm hữu CPU/ổ cứng, thời gian chạy code, công sức viết code, hay số bytes cần thiết để trữ code (tức là số dòng code)?

Bạn phải xác định mục đích "tránh lãng phí" của mình rồi mới nói chuyện chỉnh sửa code cho hiệu quả được.

Ví dụ với những array lớn thì dùng array càng nhiều càng tốn bộ nhớ.

Nếu chỉ tự nhận thấy code của mình luộm thuộm thì nên hỏi người ta xem luộm thuộm chỗ nào và có thể sửa được ra sao.

Code của bạn gồm có 3 phần:
1. đếm trong vùng dữ liệu xem có bao nhiêu dòng và lập mảng với độ lớn ấy
2. ghi nhưng dòng dữ liệu không trống vào mảng
3. ghi mảng vào vùng kết quả

Cái lãng phí của code này là:
- mỗi công việc trên lại phải dùng một vòng lặp, trong khi chỉ cần một vòng lặp là làm được hết rồi.
- mảng 2 chiều, nhưng cột thứ nhất chỉ là số thứ tự từ 1 đến n, thế thì có thể hiểu ngầm chứ chứa làm quái gì?

Lưu ý: những lời tôi nói trên dùng để chỉ dẫn cách cải tiến trình độ lập trình. Nếu chỉ muốn giải uyết vấn đề của đề bài một cách gọn đẹp thì code sủa ndu96081531 là có thể coi như tối ưu rồi.

Thầy bảo : - mỗi công việc trên lại phải dùng một vòng lặp, trong khi chỉ cần một vòng lặp là làm được hết rồi.
-> Nếu mà dùng theo cách của em như ban đầu, chỉ mỗi một vòng lặp thì làm thế nào thầy có thể khai báo được chính xác thành phần của mảng hả thầy ?
 
Upvote 0
Thực ra cách giải giản dị (giản dị chứ không phải nhanh) nhất chả cần phải dùng mảng. Cứ đọc đến đâu ghi đến đấy.

Nếu bắt buộc phải dùng mảng thì dùng kỹ thuật chặp thêm mảng, ví dụ đặt mỗi khúc chặp thêm là 100 phần tử:

- Đặt một constant CHUNK = 100
- Đặt một biến đếm số phần tử n và một biến đếm cỡ mảng nmx
- Khởi mảng với CHUNK phần tử
- Khởi n=1, nmx = 100
- cứ mỗi lần truớc khi tăng n (+1) thì xét xem n đã đạt tới nmx chưa. Nếu đã đạt thì Redim Preserve mảng thêm CHUNK phần tử nữa.

Cuối cùng, ta được một mảng có thể dài hơn số phần tử nhưng chẳng sao cả, vì ta có số phần tử thật là n rồi.
 
Upvote 0
Thầy bảo : - mỗi công việc trên lại phải dùng một vòng lặp, trong khi chỉ cần một vòng lặp là làm được hết rồi.
-> Nếu mà dùng theo cách của em như ban đầu, chỉ mỗi một vòng lặp thì làm thế nào thầy có thể khai báo được chính xác thành phần của mảng hả thầy ?
Nếu mảng rồi thì xài mảng luôn khỏi phải duyệt từng cell.
Thử cái "Cùi bắp" này xem kết quả có giống của bạn không.
PHP:
Public Sub CuiBap()
Dim sArr(), dArr(), I As Long, K As Long
sArr = Range([A1], [A65000].End(xlUp)).Value
ReDim dArr(1 To UBound(sArr, 1), 1 To 2)
For I = 1 To UBound(sArr, 1)
    If sArr(I, 1) <> "" And sArr(I, 1) <> "END" Then
        K = K + 1
        dArr(K, 1) = K
        dArr(K, 2) = sArr(I, 1)
    End If
Next
[D3].Resize(K, 2).Value = dArr
End Sub
 
Upvote 0
Cám ơn các thầy...đó, hỏi ra mình mới học được rất nhiều..Các thầy quả là pờ rồ...
 
Upvote 0
em có 1 câu hỏi như thế này:
ta có 1 file có 3 sheet :
sheet1 chưa mảng arr1
sheet2 chứa mảng arr2
sheet3 chứa mảng arr3
3 mảng trên đều cùng chiều ngang, nhưng chiều dài khác nhau

Bây giờ e muốn nối 3 mảng đó thành 1 mảng arr thôi ( mảng arr này là mảng tạm )Mục đích của e là chỉ dùng 1 vòng lập trên 1 mảng tổng arr này .
E có gửi file đính kèm, mong các a chị và các thầy hướng dẫn em ah !
 

File đính kèm

Upvote 0
em có 1 câu hỏi như thế này:
ta có 1 file có 3 sheet :
sheet1 chưa mảng arr1
sheet2 chứa mảng arr2
sheet3 chứa mảng arr3
3 mảng trên đều cùng chiều ngang, nhưng chiều dài khác nhau

Bây giờ e muốn nối 3 mảng đó thành 1 mảng arr thôi ( mảng arr này là mảng tạm )Mục đích của e là chỉ dùng 1 vòng lập trên 1 mảng tổng arr này .
E có gửi file đính kèm, mong các a chị và các thầy hướng dẫn em ah !

- Nếu chỉ đáp ứng vừa đủ nhu cầu của bạn (nối 3 mảng thành 1) thì đây là bài toán dễ
- Nếu viết ở mức tổng quát (nối bao nhiêu mảng 2 chiều tùy ý) thì cũng hơi.. khó 1 chút
Tôi thử xem:
Mã:
Function Join2DArray(ParamArray arrays())
  Dim arr(), aSub, tmp
  Dim lRs As Long, lCs As Long, lR As Long, lC As Long
  Dim n As Long, m As Long, i As Long, bChk As Boolean
  On Error Resume Next

  For i = 0 To UBound(arrays)
    aSub = arrays(i)
    n = UBound(aSub, 1) - LBound(aSub, 1) + 1
    lRs = lRs + n
    m = UBound(aSub, 2) - LBound(aSub, 2) + 1
    If lCs < m Then lCs = m
  Next
  
  ReDim arr(1 To lCs, 1 To lRs)
  n = 0: m = 0
  For i = 0 To UBound(arrays)
    aSub = arrays(i)
    For lR = LBound(aSub, 1) To UBound(aSub, 1)
      bChk = False
      n = n + 1
      For lC = LBound(aSub, 2) To UBound(aSub, 2)
        tmp = aSub(lR, lC)
        Select Case VarType(tmp)
          Case 0 To 1: arr(lC, n) = vbNullString
          Case 2 To 7: arr(lC, n) = tmp
          Case 8
            If IsNumeric(tmp) Then
              arr(lC, n) = "'" & tmp
            Else
              arr(lC, n) = tmp
            End If
        End Select
        If Len(CStr(tmp)) Then bChk = True
      Next
      If bChk = False Then n = n - 1
    Next
  Next
  If n Then
    ReDim Preserve arr(1 To lCs, 1 To n)
    Join2DArray = Transpose2DArray(arr)
  End If
End Function
Mã:
Function Transpose2DArray(ByVal arr2D)
  Dim arr(), aTemp
  Dim lR As Long, lC As Long
  On Error Resume Next
  aTemp = arr2D
  ReDim arr(LBound(aTemp, 2) To UBound(aTemp, 2), LBound(aTemp, 1) To UBound(aTemp, 1))
  For lR = LBound(aTemp, 1) To UBound(aTemp, 1)
    For lC = LBound(aTemp, 2) To UBound(aTemp, 2)
      arr(lC, lR) = aTemp(lR, lC)
    Next
  Next
  Transpose2DArray = arr
End Function
Giờ đến phần ứng dụng ta viết thế này:
Mã:
Sub Main()
  Dim [COLOR=#ff0000][B]aRes[/B][/COLOR]
  [COLOR=#ff0000][B]aRes[/B][/COLOR] = Join2DArray(Sheet1.Range("D4:O1000"), Sheet2.Range("D4:O1000"), Sheet3.Range("D4:O1000"))
End Sub
aRes chính mà mảng tạm mà bạn cần. Ví dụ có thể gán mảng tạm aRes xuống sheet như thế này:
Mã:
Sub Main()
  Dim aRes
  aRes = Join2DArray(Sheet1.Range("D4:O1000"), Sheet2.Range("D4:O1000"), Sheet3.Range("D4:O1000"))
  Sheet4.Range("D4").Resize(UBound(aRes, 1), UBound(aRes, 2)).Value = aRes
End Sub
Áp dụng thử xem còn chổ nào trục trặc không nha!
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Em cám ơn thầy, code chạy ok . nhưng xin thầy vui lòng giải thích giùm e đoạn code này được không ah ! nhất là hàm vartype

PHP:
Select Case VarType(tmp)
          Case 0 To 1: arr(lC, n) = vbNullString
          Case 2 To 7: arr(lC, n) = tmp
          Case 8
            If IsNumeric(tmp) Then
              arr(lC, n) = "'" & tmp
            Else
              arr(lC, n) = tmp
            End If
 End Select
 
Lần chỉnh sửa cuối:
Upvote 0
Em cám ơn thầy, code chạy ok . nhưng xin thầy vui lòng giải thích giùm e đoạn code này được không ah ! nhất là hàm vartype

PHP:
Select Case VarType(tmp)
          Case 0 To 1: arr(lC, n) = vbNullString
          Case 2 To 7: arr(lC, n) = tmp
          Case 8
            If IsNumeric(tmp) Then
              arr(lC, n) = "'" & tmp
            Else
              arr(lC, n) = tmp
            End If
 End Select

VarType để kiểm tra dữ liệu của bạn thuộc dạng Text hay là Number

Syntax||

VarType(varname) ||

The required varname argument is a Variant containing any variable except a variable of a user-defined type.||

Return Values||

Constant|Value|Description

vbEmpty|0|Empty (uninitialized)

vbNull|1|Null (no valid data)

vbInteger|2|Integer

vbLong|3|Long integer

vbSingle|4|Single-precision floating-point number

vbDouble|5|Double-precision floating-point number

vbCurrency|6|Currency value

vbDate|7|Date value

vbString|8|String

vbObject|9|Object

vbError|10|Error value

vbBoolean|11|Boolean value

vbVariant|12|Variant (used only with arrays of variants)

vbDataObject|13|A data access object

vbDecimal|14|Decimal value

vbByte|17|Byte value

vbLongLong|20|LongLong integer (Valid on 64-bit platforms only.)

vbUserDefinedType|36|Variants that contain user-defined types

vbArray|8192|Array


Tôi phân các trường hợp trong Select Case để phòng trường hợp dữ liệu dạng Text nhưng chứa number, ví dụ là 0331... Trường hợp này nếu không có đoạn Select Case như trên thì chắc chắn kết quả nhận được sẽ là 331 (mất số 0 ở đầu)
------------
Ví dụ thêm trường hợp cột dữ liệu của bạn chứa số điện thoại chẳng hạn, sẽ luôn có số 0 ở đầu. Vậy phải bảo đảm kết quả xuất ra cũng y chang vậy (có số 0 ở đầu)
 
Lần chỉnh sửa cuối:
Upvote 0
Các thầy ơi cho em hỏi :
Trong VBA có cái hàm nào dùng để so sánh 2 mảng đồng cấp không hả các thầy ? Hay bắt buộc mình phải tự sướng mà chế code ?
Ví dụ :
Em có cái mảng EX1(1 to 3, 2) làm chuẩn.
Mảng EX2(1 To 3)
Lấy EX2 vác đi so sánh với từng trị trong mảng EX1, nếu trùng nhau hoàn toàn thì OK, không thì NG

Chằng hạn EX1(1 to 3,1 ) = {A,B,C}
EX1 (1 to 3,2) = {D,E,F}
EX2(1 to 3) = { D,E,F}
-> EX1(1 to 3, 1) trả về NG
EX1(1 to 3, 2) trả về OK

Cám ơn các thầy trước nhé...
 
Upvote 0
Các thầy ơi cho em hỏi :
Trong VBA có cái hàm nào dùng để so sánh 2 mảng đồng cấp không hả các thầy ? Hay bắt buộc mình phải tự sướng mà chế code ?
Ví dụ :
Em có cái mảng EX1(1 to 3, 2) làm chuẩn.
Mảng EX2(1 To 3)
Lấy EX2 vác đi so sánh với từng trị trong mảng EX1, nếu trùng nhau hoàn toàn thì OK, không thì NG

Chằng hạn EX1(1 to 3,1 ) = {A,B,C}
EX1 (1 to 3,2) = {D,E,F}
EX2(1 to 3) = { D,E,F}
-> EX1(1 to 3, 1) trả về NG
EX1(1 to 3, 2) trả về OK

Cám ơn các thầy trước nhé...
cái này có lẽ phải tự viết hàm thôi bạn ah !
 
Upvote 0
Các thầy chỉ cho em giải bài tóan này với, em so sánh mãi mà không được. ( file đính kèm)
1-Ta lấy giá trị mảng ở Mảng so sánh.
2-Lấy giá trị mảng đa chiều bắt đầu từ hàng 2, cột 1
3-So sánh nếu chỉ cần 1 trị của mảng so sánh khác với vùng so sánh thì ta điền cả mảng vào cột kế tiếp

Em viết như code như thế này mà không hiểu nó sai chỗ nào mà nó chả có ý kiến gì

Sub MangKiemta()
Dim i, j, k, t, r As Integer
Dim Mang()
Dim MangA(1 To 14)
i = 1
Do Until IsEmpty(Cells(2, i))
j = j + 1
i = i + 1
Loop
ReDim Mang(1 To 14, j)
For k = 1 To j
For i = 1 To 14
Mang(i, k) = Cells(i + 1, k)
Next
Next

For t = 1 To UBound(MangA)
MangA(t) = Cells(19 + t, 1)
Next

For r = 1 To 14
For k = 1 To j
If MangA(r) <> Mang(r, k) Then
Cells(r + 1, j) = MangA(r)
End If
Next
Next

End Sub

Nhờ các thầy chỉ bảo em với ! Em cám ơn%#^#$
 

File đính kèm

Upvote 0
Các anh chị cho em hỏi, tìm trên google mãi mà không ra
Ý của em hỏi là làm sao giống như trong file đính kèm, hàm bdttct2ltcxdvn có 21 hàng và 2 cột, các giá trị của hàm này được gán cho ô B17 đến ô C37 mà chỉ sử dụng duy nhất lệnh =bdttct2ltcxdvn(B3,B4,B7,B8,B9,B5,B6,B10,B11,B12) cho tất cả các ô . Muốn làm như vậy thì phải làm sao, cách tạo 1 sub thì em cũng biết nhưng em muốn làm giống như trong file. Mong các anh chị giúp đỡ
 

File đính kèm

Upvote 0
Nhờ chỉnh dùm code xử lý mảng lấy từ mảng sẳn có
Mình có thắc mắc như thế này: mình lấy dử liệu từ ADO gán vào Array1 sau đó gán tiếp xuống Sheet Range, sau đó gán Array2 = Range để xử lý tạo ra Array3 gán xuống sheet kết quả thì đươc. Nhưng khi mình lấy trực tiếp từ Array1 để xử lý tạo ra Array3 thì không được. Xin mọi người chỉ giáo. Mình cám ơn rất nhiều. (Mình có ghi chú trong code.)
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
trich lọc nhiều điều kiện

chuc moi nguoi vui vẻ
 
Lần chỉnh sửa cuối:
Upvote 0
Cho em hỏi về copy có điều kiện một chút ah.
- thứ nhất em có một danh sách ở sheet2 gồm 5 cột (họ tên , mã số , tháng 1, tháng 2, tháng 3) nếu trong cột tháng 2, tháng 3 >0 thì lấy đươa vào sheet3 em dùng đoạn code nhứ sau
Sub copy()
On Error Resume Next
Dim vung(), Arr(), HC As Long
With Sheet2
HC = .Range("A65536").End(xlUp).Row
vung = .Range("A2:M" & HC).Value
ReDim Arr(1 To UBound(vung, 1), 1 To 13)
For i = 1 To UBound(vung, 1)
If vung(i, 4) > 0 Or vung(i, 5) > 0 Then
k = k + 1
For y = 1 To 13
Arr(k, y) = vung(i, y)
Next y
End If
Next i
Sheet3.Range("A2").Resize(k, 13).Value = Arr
End With
End Sub

đoạn code chạy được nhưng vấn đề là ở cột mã KH thì mã số KH lại biến thành số xin các Bro giải thich giúp e chỗ này với ah.
- Thứ hai là bây giờ em muốn chọn tiếp ở sheet1 cột tháng 2 nếu > 0 thì lấy sang sheet4, ở sheet2 nếu cột tháng 1 <0 thì lấy sang sheet4 thì đoạn code trên phải sửa lại như thế nào ah, em cũng mới học về mảng nên còn mơ hồ lắm ah @_@.
em gửi file VD đính kèm ở dưới
 

File đính kèm

Upvote 0
Cho em hỏi về copy có điều kiện một chút ah.
- thứ nhất em có một danh sách ở sheet2 gồm 5 cột (họ tên , mã số , tháng 1, tháng 2, tháng 3) nếu trong cột tháng 2, tháng 3 >0 thì lấy đươa vào sheet3 em dùng đoạn code nhứ sau
Sub copy()
On Error Resume Next
Dim vung(), Arr(), HC As Long
With Sheet2
HC = .Range("A65536").End(xlUp).Row
vung = .Range("A2:M" & HC).Value
ReDim Arr(1 To UBound(vung, 1), 1 To 13)
For i = 1 To UBound(vung, 1)
If vung(i, 4) > 0 Or vung(i, 5) > 0 Then
k = k + 1
For y = 1 To 13
Arr(k, y) = vung(i, y)
Next y
End If
Next i
Sheet3.Range("A2").Resize(k, 13).Value = Arr
End With
End Sub

đoạn code chạy được nhưng vấn đề là ở cột mã KH thì mã số KH lại biến thành số xin các Bro giải thich giúp e chỗ này với ah.
- Thứ hai là bây giờ em muốn chọn tiếp ở sheet1 cột tháng 2 nếu > 0 thì lấy sang sheet4, ở sheet2 nếu cột tháng 1 <0 thì lấy sang sheet4 thì đoạn code trên phải sửa lại như thế nào ah, em cũng mới học về mảng nên còn mơ hồ lắm ah @_@.
em gửi file VD đính kèm ở dưới
1/ Bạn format cột B sheet3 thành Text rồi chạy code lại thử xem.
2/ Đã lấy dữ liệu được 1 sheet thì lặp lại như vậy cho 1 sheet nữa rồi gán vào sheet 4, cách nào tùy bạn.
 
Upvote 0
lấy dư lệu từng sheet thì em làm được rồi cách làm thế này, cũng đoạn code trên em lấy dữ liệu sheet2 cột tháng 1 xong đưa sang sheet4, sau đó sang sheet1 lấy dữ liệu và đưa sang sheet 4, em muốn là lấy dữ liệu sheet1, sheet 2 xong mói đưa dữ liệu sang sheet4 một lúc cơ
 
Upvote 0
lấy dư lệu từng sheet thì em làm được rồi cách làm thế này, cũng đoạn code trên em lấy dữ liệu sheet2 cột tháng 1 xong đưa sang sheet4, sau đó sang sheet1 lấy dữ liệu và đưa sang sheet 4, em muốn là lấy dữ liệu sheet1, sheet 2 xong mói đưa dữ liệu sang sheet4 một lúc cơ
Thì cứ dùng mảng Arr() đó, gán sheet1 vào rồi, gán tiếp sheet2 vào với k=k+1 tiếp tục, xong rồi hãy gán vào sheet4 1 lần.
 
Upvote 0
Chào các Thầy trên GPE,

Mình có chút vấn đền nhỏ không biết như thế nào... làm mãi vẫn không đúng.
Vui lòng xem file đính kèm.
[GPECODE=VB]
Sub ShowResult_OR()
Dim rngCellData1, rngCellData2, rngList1, rngList2 As Range
Dim wksTemp As Worksheet
Dim iLastRow1, iLastRow2, iLastRowResult, i As Long
Dim Dic, arrResult_OR
Set wksTemp = Worksheets("Temp")
iLastRow1 = LastRow(wksTemp, 3)
iLastRow2 = LastRow(wksTemp, 5)
iLastRowResult = LastRow(wksTemp, 7)
wksTemp.Range("G4:G" & iLastRowResult).Select
Selection.Clear
wksTemp.Range("G4").Select
Set rngList1 = wksTemp.Range("C4:C" & iLastRow1)
Set rngList2 = wksTemp.Range("E4:E" & iLastRow2)
On Error Resume Next
Set Dic = CreateObject("Scripting.Dictionary")
For Each rngCellData1 In rngList1
If Not IsEmpty(rngCellData1) Then Dic.Add rngCellData1.Value, ""
Next rngCellData1
For Each rngCellData2 In rngList2
If Not IsEmpty(rngCellData2) Then Dic.Add rngCellData2.Value, ""
Next rngCellData2

arrResult_OR = Dic.Keys

wksTemp.Range("G4").Resize(UBound(arrResult_OR, 1) + 1, 1) = arrResult_OR

'For i = 0 To UBound(arrResult_OR, 1)
'wksTemp.Range("G" & i + 4) = arrResult_OR(i)
'Next i

Set Dic = Nothing
'Sort
wksTemp.Sort.SortFields.Clear
wksTemp.Sort.SortFields.Add Key:=Range("G4:G3" & UBound(arrResult_OR, 1) + 4), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With wksTemp.Sort
.SetRange Range("G3:G3" & UBound(arrResult_OR, 1) + 4)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
TotalFile 7, "G3"

End Sub
[/GPECODE]

nếu chạy đoạn code tô màu đỏ thì ra kết quả sai!!!
wksTemp.Range("G4").Resize(UBound(arrResult_OR, 1) + 1, 1) = arrResult_OR --> kết quả sai

nếu chạy lại bẳng cách thay đoạn code màu đỏ bằng màu xanh thì ra kết quả đúng!!!!

For i = 0 To UBound(arrResult_OR, 1)
wksTemp.Range("G" & i + 4) = arrResult_OR(i)
Next i



[GPECODE=VB]

Sub ShowResult_OR()
Dim rngCellData1, rngCellData2, rngList1, rngList2 As Range
Dim wksTemp As Worksheet
Dim iLastRow1, iLastRow2, iLastRowResult, i As Long
Dim Dic, arrResult_OR
Set wksTemp = Worksheets("Temp")
iLastRow1 = LastRow(wksTemp, 3)
iLastRow2 = LastRow(wksTemp, 5)
iLastRowResult = LastRow(wksTemp, 7)
wksTemp.Range("G4:G" & iLastRowResult).Select
Selection.Clear
wksTemp.Range("G4").Select
Set rngList1 = wksTemp.Range("C4:C" & iLastRow1)
Set rngList2 = wksTemp.Range("E4:E" & iLastRow2)
On Error Resume Next
Set Dic = CreateObject("Scripting.Dictionary")
For Each rngCellData1 In rngList1
If Not IsEmpty(rngCellData1) Then Dic.Add rngCellData1.Value, ""
Next rngCellData1
For Each rngCellData2 In rngList2
If Not IsEmpty(rngCellData2) Then Dic.Add rngCellData2.Value, ""
Next rngCellData2

arrResult_OR = Dic.Keys

'wksTemp.Range("G4").Resize(UBound(arrResult_OR, 1) + 1, 1) = arrResult_OR

For i = 0 To UBound(arrResult_OR, 1)
wksTemp.Range("G" & i + 4) = arrResult_OR(i)
Next i


Set Dic = Nothing
'Sort
wksTemp.Sort.SortFields.Clear
wksTemp.Sort.SortFields.Add Key:=Range("G4:G3" & UBound(arrResult_OR, 1) + 4), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With wksTemp.Sort
.SetRange Range("G3:G3" & UBound(arrResult_OR, 1) + 4)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
TotalFile 7, "G3"

End Sub

[/GPECODE]

Mong các sư phụ chỉ giáo.

Xin Cám ơn rất nhiều.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Chào các Thầy trên GPE,

Mình có chút vấn đền nhỏ không biết như thế nào... làm mãi vẫn không đúng.
Vui lòng xem file đính kèm.


Mong các sư phụ chỉ giáo.

Xin Cám ơn rất nhiều.

Mục đích của bạn là làm cái gì vậy bạn? Có phải bạn muốn tổng hợp 2 cột Data1 Data2 rồi lọc duy nhất và gán cho cột Kết quả OR hay không?
 
Upvote 0
Mục đích của bạn là làm cái gì vậy bạn? Có phải bạn muốn tổng hợp 2 cột Data1 Data2 rồi lọc duy nhất và gán cho cột Kết quả OR hay không?

Dạ đúng rùi ah...
nhưng cái mục đích này chỉ là "cái cớ" để nghiên cứu DICTIONARY , và MẢNG mà thôi.
Hiện tại mình "kẹt" vấn đề "GÁN GIÁ TRỊ Dic.Keys VÀO MẢNG, Và GHI MẢNG NÀY LÊN SHEET.
VIỆC GHI CỦA MÌNH KHÔNG THÀNH CÔNG (Code màu đó). nếu ghi bằng lệnh FOR thì OK nhưng thời gian làm rất là lâu!!!
vậy bạn có thể giúp mình ghi mảng được gán từ Dic.Keys lên Sheet không ah...
Cám ơn bạn nhiều.
 
Upvote 0
Dạ đúng rùi ah...
nhưng cái mục đích này chỉ là "cái cớ" để nghiên cứu DICTIONARY , và MẢNG mà thôi.
Hiện tại mình "kẹt" vấn đề "GÁN GIÁ TRỊ Dic.Keys VÀO MẢNG, Và GHI MẢNG NÀY LÊN SHEET.
VIỆC GHI CỦA MÌNH KHÔNG THÀNH CÔNG (Code màu đó). nếu ghi bằng lệnh FOR thì OK nhưng thời gian làm rất là lâu!!!
vậy bạn có thể giúp mình ghi mảng được gán từ Dic.Keys lên Sheet không ah...
Cám ơn bạn nhiều.

OK, chỉ vậy thôi thì quá dễ:

Mã:
Sub OneColumnUniqueArrays(ByRef UniqueArray(), _
                          ByRef RowCount As Long, _
                          ParamArray ManiOneColumnArrays())
                          
    Dim SubArray, EachItem, Dict As Object
    Set Dict = CreateObject("Scripting.Dictionary")
    
    For Each SubArray In ManiOneColumnArrays
        If Not IsArray(SubArray) Then SubArray = Array(SubArray)
        For Each EachItem In SubArray
            If Not IsEmpty(EachItem) And Not Dict.Exists(EachItem) Then
                Dict.Add EachItem, ""
            End If
        Next
    Next
    
    If Dict.Count Then
        UniqueArray = [COLOR=#ff0000][B]Application.WorksheetFunction.Transpose(Dict.Keys)[/B][/COLOR]
        RowCount = Dict.Count
    End If

    Set Dict = Nothing

End Sub


Sub Test()
    Dim UniqueArray(), RowCount As Long
    With Sheets("Temp")
        OneColumnUniqueArrays UniqueArray, RowCount, .Range("C4:C23"), .Range("E4:E25") 'Muon cot nao nua thi them vao
        .Range("G3:G65536").ClearContents
        .Range("G3") = RowCount & " pictures"
        .Range("G4").Resize(RowCount) = UniqueArray
    End With
End Sub

Bản thân Dict.Keys nó là mảng một chiều nên khi gán cho UniqueArray phải hoán vị cho nó.

Tất cả chỉ có vậy!
 
Lần chỉnh sửa cuối:
Upvote 0
Nếu bạn không muốn dùng dòng này:

UniqueArray = Application.WorksheetFunction.Transpose(Dict.Keys)

Tức không muốn dùng Hàm Application.WorksheetFunction.Transpose (hàm của Excel)

thì bạn có thể sửa lại như sau:

Mã:
Sub OneColumnUniqueArrays(ByRef UniqueArray(), _
                          ByRef RowCount As Long, _
                          ParamArray ManiOneColumnArrays())
                          
    Dim SubArray, EachItem, Dict As Object
    Set Dict = CreateObject("Scripting.Dictionary")
    
    For Each SubArray In ManiOneColumnArrays
        If Not IsArray(SubArray) Then SubArray = Array(SubArray)
        For Each EachItem In SubArray
            If Not IsEmpty(EachItem) And Not Dict.Exists(EachItem) Then
                Dict.Add EachItem, ""
            End If
        Next
    Next
    
[COLOR=#0000ff]    RowCount = Dict.Count[/COLOR]

[COLOR=#0000ff]    If RowCount Then[/COLOR]
[COLOR=#0000ff]        Dim r As Long, DictKeys()[/COLOR]
[COLOR=#0000ff]        DictKeys = Dict.Keys[/COLOR]
[COLOR=#0000ff]        ReDim UniqueArray(1 To RowCount, 1 To 1)[/COLOR]
[COLOR=#0000ff]        For r = 1 To RowCount[/COLOR]
[COLOR=#0000ff]            UniqueArray(r, 1) = DictKeys(r - 1)[/COLOR]
[COLOR=#0000ff]        Next[/COLOR]
[COLOR=#0000ff]    End If
[/COLOR]
    Set Dict = Nothing

End Sub

Những chỗ màu xanh là sửa lại.

Bạn cũng nên bẫy lỗi cho trường hợp không có mục nào được lọc (tức là mảng rỗng):

Mã:
Sub Test()
    Dim UniqueArray(), RowCount As Long
    With Sheets("Temp")
        OneColumnUniqueArrays UniqueArray, RowCount, .Range("C4:C23"), .Range("E4:E25") 'Muon cot nao nua thi them vao
        .Range("G3:G65536").ClearContents
[COLOR=#0000ff]        If RowCount > 0 Then[/COLOR]
[COLOR=#0000ff]            .Range("G3") = RowCount & " pictures"[/COLOR]
[COLOR=#0000ff]            .Range("G4").Resize(RowCount) = UniqueArray[/COLOR]
[COLOR=#0000ff]        End If[/COLOR]
    End With
End Sub
 
Upvote 0
Nếu bạn không muốn dùng dòng này:

UniqueArray = Application.WorksheetFunction.Transpose(Dict.Keys)

Tức không muốn dùng Hàm Application.WorksheetFunction.Transpose (hàm của Excel)

thì bạn có thể sửa lại như sau:

Mã:
Sub OneColumnUniqueArrays(ByRef UniqueArray(), _
                          ByRef RowCount As Long, _
                          ParamArray ManiOneColumnArrays())
                          
    Dim SubArray, EachItem, Dict As Object
    Set Dict = CreateObject("Scripting.Dictionary")
    
    For Each SubArray In ManiOneColumnArrays
        If Not IsArray(SubArray) Then SubArray = Array(SubArray)
        For Each EachItem In SubArray
            If Not IsEmpty(EachItem) And Not Dict.Exists(EachItem) Then
                Dict.Add EachItem, ""
            End If
        Next
    Next
    
[COLOR=#0000ff]    RowCount = Dict.Count[/COLOR]

[COLOR=#0000ff]    If RowCount Then[/COLOR]
[COLOR=#0000ff]        Dim r As Long, DictKeys()[/COLOR]
[COLOR=#0000ff]        DictKeys = Dict.Keys[/COLOR]
[COLOR=#0000ff]        ReDim UniqueArray(1 To RowCount, 1 To 1)[/COLOR]
[COLOR=#0000ff]        For r = 1 To RowCount[/COLOR]
[COLOR=#0000ff]            UniqueArray(r, 1) = DictKeys(r - 1)[/COLOR]
[COLOR=#0000ff]        Next[/COLOR]
[COLOR=#0000ff]    End If
[/COLOR]
    Set Dict = Nothing

End Sub

Những chỗ màu xanh là sửa lại.

Bạn cũng nên bẫy lỗi cho trường hợp không có mục nào được lọc (tức là mảng rỗng):

Mã:
Sub Test()
    Dim UniqueArray(), RowCount As Long
    With Sheets("Temp")
        OneColumnUniqueArrays UniqueArray, RowCount, .Range("C4:C23"), .Range("E4:E25") 'Muon cot nao nua thi them vao
        .Range("G3:G65536").ClearContents
[COLOR=#0000ff]        If RowCount > 0 Then[/COLOR]
[COLOR=#0000ff]            .Range("G3") = RowCount & " pictures"[/COLOR]
[COLOR=#0000ff]            .Range("G4").Resize(RowCount) = UniqueArray[/COLOR]
[COLOR=#0000ff]        End If[/COLOR]
    End With
End Sub

Cám Ơn Bạn rất nhiều, mình đã hiểu và làm được rùi. Vậy là biết thêm được là mảng của Dic.Keys là như thế nào...
 
Upvote 0
Thì cứ dùng mảng Arr() đó, gán sheet1 vào rồi, gán tiếp sheet2 vào với k=k+1 tiếp tục, xong rồi hãy gán vào sheet4 1 lần.

dạ vấn đề là ở chỗ này đó , em mới biết về mảng nên còn mơ hồ lắm, đoạn code trên em làm được là dựa vào các bài trước mọi người thảo luận đó ah, tuy làm ra kết quả nhưng mà vẫn chưa hiểu rõ lắm cho nên em không biết làm thế nào để chỉ dùng 1 Arr() mà gán sheet1 vào rồi lại gán tiếp sheet2 vào @_@ xong rồi mới gán vào sheet4 cùng một lúc, nếu được Mong Bro chỉ cho em chi tiết hơn một chút nữa không ah.
 
Upvote 0
dạ vấn đề là ở chỗ này đó , em mới biết về mảng nên còn mơ hồ lắm, đoạn code trên em làm được là dựa vào các bài trước mọi người thảo luận đó ah, tuy làm ra kết quả nhưng mà vẫn chưa hiểu rõ lắm cho nên em không biết làm thế nào để chỉ dùng 1 Arr() mà gán sheet1 vào rồi lại gán tiếp sheet2 vào @_@ xong rồi mới gán vào sheet4 cùng một lúc, nếu được Mong Bro chỉ cho em chi tiết hơn một chút nữa không ah.
Bạn chờ "Bro" đi.
Tui thì vừa già vừa dốt không biết "Bro" là cái gì. Nếu làm giúp bạn thì tui là "Bro" sao?
Híc. Tiếng Việt nhiều khi tui còn hổng hiểu.
 
Upvote 0
Bạn chờ "Bro" đi.
Tui thì vừa già vừa dốt không biết "Bro" là cái gì. Nếu làm giúp bạn thì tui là "Bro" sao?
Híc. Tiếng Việt nhiều khi tui còn hổng hiểu.
ui trời cái tội sử dụng tiếng lóng sửa mãi không chừa +-+-+-+ em thành thật xin lỗi , lâu nay ra tiệm net toàn chơi game nên mới bị nhiễm mấy thứ ngôn ngữ này +-+-+-+ Mong các thầy trên diễn đàn chỉ bảo thêm ạ ! em xin chân thành cảm ơn !
 
Lần chỉnh sửa cuối:
Upvote 0
Hi các a/c.
Giúp mình trường hợp sau:
có 1 mảng (range) là số có sắp xếp từ nhỏ tới lớn và không có giá trị trùng nhau, mình muốn dùng VBA để tìm giá trị trong mảng đó gần nhất với 1 giá trị cho trước (lớn hơn hoặc nhỏ hơn).
ví dụ mảng: 12,25,29,35,43,55,60
Giá trị cho trước: là 30 kết quả là 29, là 33 kết quả là 35.

Trân trọng cảm ơn.
 
Upvote 0
Hi các a/c.
Giúp mình trường hợp sau:
có 1 mảng (range) là số có sắp xếp từ nhỏ tới lớn và không có giá trị trùng nhau, mình muốn dùng VBA để tìm giá trị trong mảng đó gần nhất với 1 giá trị cho trước (lớn hơn hoặc nhỏ hơn).
ví dụ mảng: 12,25,29,35,43,55,60
Giá trị cho trước: là 30 kết quả là 29, là 33 kết quả là 35.

Trân trọng cảm ơn.
Tham khảo code này. Tuy nhiên để xài được chắc phải sửa lại nhiều
PHP:
Sub test()
Dim Sarr(), Dk, I
Sarr = Array(12, 25, 39, 43, 55, 60, 76, 85)
Dk = 30
Do
   If Sarr(I) > Dk Then
      MsgBox "So lon hon là: " & Sarr(I)
      If Sarr(I - 1) <> Dk Then
         MsgBox "So nho hon là: " & Sarr(I - 1)
      Else
         MsgBox "So nho hon là: " & Sarr(I - 2)
      End If
      Exit Do
   End If
   I = I + 1
Loop Until I > UBound(Sarr)
End Sub
 
Upvote 0
Hi các a/c.
Giúp mình trường hợp sau:
có 1 mảng (range) là số có sắp xếp từ nhỏ tới lớn và không có giá trị trùng nhau, mình muốn dùng VBA để tìm giá trị trong mảng đó gần nhất với 1 giá trị cho trước (lớn hơn hoặc nhỏ hơn).
ví dụ mảng: 12,25,29,35,43,55,60
Giá trị cho trước: là 30 kết quả là 29, là 33 kết quả là 35.

Trân trọng cảm ơn.

Đề bài dỏm. Nếu số nằm ngay giữa 2 phần tử của mảng thì chọn trị nào?

Thường thường tìm trong mảng có sắp xếp thì người ta dùng giải thuật tìm nhị phân (binary search), và dùng hàm đệ quy.

code sau đây giả định nếu nằm giữa 2 phần tử thì chọn phần tử trước

Mã:
Sub t()
Dim Sarr()
Sarr = Array(12, 25, 39, 43, 55, 60, 76, 85)
Debug.Print TriGanNhat(30, Sarr, LBound(Sarr), UBound(Sarr))
End Sub


Function TriGanNhat(ByVal tri As Integer, ByRef mang() As Variant, ByVal dau As Integer, ByVal duoi As Integer) As Integer
' hàm đệ quy tìm giá trị gần nhất trong một mảng
If dau + 1 >= duoi Then ' chỉ còn 2 điểm, như vậy 1 trong 2 phải là đáp số
If tri <= (mang(dau) + mang(duoi)) / 2 Then TriGanNhat = mang(dau) Else TriGanNhat = mang(duoi)
Exit Function
End If
Dim giua As Integer ' điểm giữa chia mảng thành 2 đoạn
giua = (dau + duoi) / 2
If tri = mang(giua) Then ' tìm được trị chính xác
TriGanNhat = mang(giua)
ElseIf tri > mang(giua) Then
TriGanNhat = TriGanNhat(tri, mang, giua, duoi) ' đáp số nằm ở đoạn 2, tiếp tục dò
Else
TriGanNhat = TriGanNhat(tri, mang, dau, giua) ' đáp số nằm ở đoạn 1, tiếp tục dò
End If
End Function
 
Upvote 0
Đề bài dỏm. Nếu số nằm ngay giữa 2 phần tử của mảng thì chọn trị nào?

Thường thường tìm trong mảng có sắp xếp thì người ta dùng giải thuật tìm nhị phân (binary search), và dùng hàm đệ quy.

code sau đây giả định nếu nằm giữa 2 phần tử thì chọn phần tử trước

Mã:
Sub t()
Dim Sarr()
Sarr = Array(12, 25, 39, 43, 55, 60, 76, 85)
Debug.Print TriGanNhat(30, Sarr, LBound(Sarr), UBound(Sarr))
End Sub


Function TriGanNhat(ByVal tri As Integer, ByRef mang() As Variant, ByVal dau As Integer, ByVal duoi As Integer) As Integer
' hàm đệ quy tìm giá trị gần nhất trong một mảng
If dau + 1 >= duoi Then ' chỉ còn 2 điểm, như vậy 1 trong 2 phải là đáp số
If tri <= (mang(dau) + mang(duoi)) / 2 Then TriGanNhat = mang(dau) Else TriGanNhat = mang(duoi)
Exit Function
End If
Dim giua As Integer ' điểm giữa chia mảng thành 2 đoạn
[B][COLOR=#ff0000]giua = (dau + duoi) / 2[/COLOR][/B]
If tri = mang(giua) Then ' tìm được trị chính xác
TriGanNhat = mang(giua)
ElseIf tri > mang(giua) Then
TriGanNhat = TriGanNhat(tri, mang, giua, duoi) ' đáp số nằm ở đoạn 2, tiếp tục dò
Else
TriGanNhat = TriGanNhat(tri, mang, dau, giua) ' đáp số nằm ở đoạn 1, tiếp tục dò
End If
End Function

Cần nhớ là việc thực hiện code đơn giản vd. k = (a + b) / 2 là quá trình tính từng bước. Bộ vi xử lý hay việc tính toán trên giấy bằng tay cũng thế, không thể đồng thời thực hiện phép cộng và chia được.
Trước hết phép cộng (a + b) được thực hiện và kết quả đó được nhớ tạm "ở đâu đó". Sau đó mới thực hiện phép chia giá trị "ở đâu đó" cho 2 và trả về kết quả. Phải rất thận trọng vì dễ quên và kết quả trung gian sẽ vượt quá giới hạn.

Khi tính vd. (a + b) thì kết quả trung gian sẽ được gán cho kiểu có giới hạn rộng nhất trong a và b. Tức nếu a as Integer và b As Long thì kết quả trung gian sẽ được gán cho kiểu Long. Nhưng nếu cũng có b As Integer thì kết quả trung gian sẽ được gán cho kiểu Integer.

Ta xét code

Mã:
Dim k as integer, a as Integer, b as Integer
a = 16000
b = 32000
k = (a + b) / 2
Msgbox k

Rõ ràng giá trị k = 24000 nằm trong giới hạn của Integer. a và b cũng thế.
Nhưng Run code sẽ có lỗi tại dòng k = (a + b) / 2. Vì sao? Vì khi tính (a + b) thì kết quả trung gian này sẽ được gán cho kiểu Integer do a và b đều là kiểu Integer. Nhưng kết quả trung gian này lại có giá trị 48000, tức vượt quá giới hạn của kiểu Integer. Do vậy có lỗi Overflow

Phải rất chú ý vì nhiều khi mọi biến "tham gia" trong phép toán (ở trên là a và b) đều có giá trị không vượt quá giới hạn của kiểu của chúng nhưng phép toán lại có lỗi Overflow

Như vậy chỗ đỏ đỏ sẽ có lỗi overflow một khi nào đó.

Vd. sẽ có lỗi overflow ở dòng đỏ đỏ (ở lần gọi hàm lần thứ hai, tức khi dau = 16000 và duoi = 32000) nếu có code

Mã:
Sub t()
Dim Sarr()
    ReDim Sarr(1 To 32000)
    For k = 1 To 32000
        Sarr(k) = k
    Next
    Debug.Print TriGanNhat(16001, Sarr, LBound(Sarr), UBound(Sarr))
End Sub

---------------
Ngoài ra với kiểu của trị là Integer mà chủ chủ đề có mảng 12, 25, 139, 2343, 1055, 32234, 36789, 40085 và muốn tìm giá trị 35000 thì không dùng hàm trên được rồi. Cái mảng và giá trị cần tìm mà chủ chủ đề đưa ra chỉ là ví dụ thôi

ví dụ mảng: 12,25,29,35,43,55,60
Giá trị cho trước: là 30

chứ có chỗ nào nói là Integer đâu.

Nếu sửa thành Byval tri As Long thì khi chạy code sẽ có lỗi overflow. Vì chắc chắn giá trị 36789 sẽ được tìm thấy nhưng TriGanNhat lại chỉ có kiểu Integer.

---------------

Tôi thử không dùng đệ quy. Vì đệ quy luôn là tốn thêm bộ nhớ - do các địa chỉ trở về, giá trị các biến phải được ghi vào bộ nhớ (stack) và được "lấy lại" khi hàm trở về. Đặc biệt tốn bộ nhớ khi "độ sâu" đệ quy càng lớn.

Mã:
Sub test()
Dim Sarr()
    ReDim Sarr(1 To 32000)
    For k = 1 To 32000
        Sarr(k) = k
    Next
    Debug.Print NearestValue(16001.6, Sarr)
'    Sarr = Array(12, 25, 139, 2343, 1055, 32234, 36789, 40085)
'    Debug.Print NearestValue(35000, Sarr)
End Sub

Function NearestValue(ByVal find_value As Double, mang()) As Double
Dim index As Long, Lo As Long, Hi As Long
    Lo = LBound(mang)
    Hi = UBound(mang)
    If find_value < mang(Lo) Or find_value > mang(Hi) Then
        MsgBox "Khong tim thay gia tri!"
        Exit Function
    End If
    index = (Lo + Hi) \ 2
    Do While mang(index) <> find_value
        If index = Lo Then Exit Do
        If mang(index) < find_value Then
            Lo = index
        Else
            Hi = index
        End If
        index = (Lo + Hi) \ 2
    Loop
    If mang(index) = find_value Then
        NearestValue = find_value
    Else
        If 2 * find_value <= mang(Lo) + mang(Hi) Then
            NearestValue = mang(Lo)
        Else
            NearestValue = mang(Hi)
        End If
    End If
End Function

Nếu ai test thấy sai sót thì xin góp ý. Chuyện nhầm lẫn là chuyện thường, ai cũng có thể mắc phải. Chỉ có điều sự đời nó là thế này: "Cái lỗi của người khác nhìn cứ như con voi ấy, rõ mồn một. Nhưng cũng lỗi ấy của bản thân thì nhìn nó như con kiến ấy, tìm đi tìm lại mà chả thấy."
 
Lần chỉnh sửa cuối:
Upvote 0
1. Tuỳ theo ngôn ngữ mà chuyện tràn số tính khác nhau. Nếu là ngôn ngữ cấp dưới như C/C++ chẳng hạn thì tràn số cho kết quả sai (không nảy sinh error mà chỉ cắt bớt số bits của kết quả). Theo dòng họ BASIC thì tràn số sẽ bị error cho nên cũng không quan trọng lắm. Ở đây đâu có nói chuyện phóng phi thuyền lên vũ trụ. Cách tránh tràn số có hơi phức tạp.

2. Đệ quy tốn bộ nhớ và thời gian kết nối. Điều đó ai sử dụng đệ quy cũng phải biết. Tuỳ theo mức độ trầm trọng của vấn đề mà chúng ta có dùng nó hay không. (chú ý từ "trầm trọng" thay vì "quan trọng")
 
Upvote 0
Cảm ơn các bác đã giúp đỡ.
Mảng của mình khoảng 2000 giá trị và mình muốn viết thành là function để tìm kiếm. Không biết như thế thì có chậm không nhỉ

Cần nhớ là việc thực hiện code đơn giản vd. k = (a + b) / 2 là quá trình tính từng bước. Bộ vi xử lý hay việc tính toán trên giấy bằng tay cũng thế, không thể đồng thời thực hiện phép cộng và chia được.
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
...
Mảng của mình khoảng 2000 giá trị và mình muốn viết thành là function để tìm kiếm. Không biết như thế thì có chậm không nhỉ

Đỏ:
Xét lại yêu cầu: tìm một giá trị
Thực tế: Trả về một giá trị là nhiệm vụ của function. Nếu không thì nguời ta đã dùng sub cho khoẻ.
Suy ra: đề bài này dùng function là đúng rồi. Không có cách nào hay hơn nữa.
Tuy nhiên: như tôi đã nói. Chi tiết đề dỏm. Nếu trị dò tìm nằm chính giữa hai trị trong mảng thì lấy lớn hay nhỏ?

Xanh:
Chậm và nhanh không phải là ưu tiên của tôi. Cái này để người khác trả lời. Toi chỉ có thể nói là phương pháp nhị phân chính là để giúp tăng hiệu quả so với cách tìm tuần tự từ đầu mảng.
Khi lập trình ưu tiên của tôi nằm ở kết quả nhìn vào có dễ kiểm soát là đúng hay sai hay không.
Tôi làm việc với dữ liệu nhiều năm. Kinh nghiệm cho biết cái đáng sợ nhất là kết quả sai nhưng không hiện rõ, vài ba tháng/năm sau mới té ra mình dùng dữ liệu sai bét.
 
Upvote 0
For và For each trong đoạn này khác nhau ở đâu ?

xin giúp đỡ em giữa 2 đoạn code
Mã:
Private Type HocSinh
tuoi As Integer
ten As String
End Type
đoạn code này
Mã:
Dim t(1 To 6) As HocSinh
Dim i As Integer
For i = 1 To 6 Step 1
t(i).ten = "abc"
Next
được chấp nhận còn đoạn code này

Mã:
Dim hs As HocSinh
Dim t(1 To 6) As HocSinh
For Each hs In t
hs.ten = "abc"
Next
lại báo lỗi " for each control variable on arrays must be variant "
cái em cần là sử dụng For each vì em xài mảng động
xin cho em biết phải sửa lại ntn
và xin cho biết cách đếm số phần tử hiện tại của 1 mảng động. Cảm ơn
 
Lần chỉnh sửa cuối:
Upvote 0
xin giúp đỡ em giữa 2 đoạn code
Mã:
Private Type HocSinh
tuoi As Integer
ten As String
End Type
đoạn code này
Mã:
Dim t(1 To 6) As HocSinh
Dim i As Integer
For i = 1 To 6 Step 1
t(i).ten = "abc"
Next
được chấp nhận còn đoạn code này

Mã:
Dim hs As HocSinh
Dim t(1 To 6) As HocSinh
For Each hs In t
hs.ten = "abc"
Next
lại báo lỗi " for each control variable on arrays must be variant "
cái em cần là sử dụng For each vì em xài mảng động
xin cho em biết phải sửa lại ntn
và xin cho biết cách đếm số phần tử hiện tại của 1 mảng động. Cảm ơn

For Each có thể không được sử dụng trên mảng của Type người dùng định nghĩa hoặc các chuỗi dài cố định (For Each may not be used on array of user-defined type or fixed-length strings). Vì thế trong trường hợp này bạn không nên dùng nó.

Cách tính cận trên (Ubound) và cận dưới (Lbound) của mảng sau đó lấy cận trên trừ cho cận dưới cộng thêm 1 là ra số phần tử trong mảng.

Số phần tử = Ubound(YourArray) - Lbound(YourArray) + 1
 
Upvote 0
Các anh cho e hỏi. E có 1 mãng từ A1:A10. Em muốn tìm giá trị của cell B1 trong mãng nói trên nếu có thì xuất giá trị đó vào cell C1. Em phải code như thế nào vậy các anh
 
Upvote 0

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

Back
Top Bottom