Các câu hỏi về mảng trong VBA (Array) (4 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ị
 
Tôi không nghĩ vấn đề chỉ theo một hướng đó. Nếu biêt tại sao thì bác cứ giải thích tại sao là tại sao đi? Tôi "gà mờ" nên chịu thôi.
Dạ ý em đúng là hỏi vì sao thao tác trên combo Box lại k đc ghi lại trên Macro đó ạ. E cũng tìm hỉu gg rùi mà k ra đc :(
 
Upvote 0
Dạ ý em đúng là hỏi vì sao thao tác trên combo Box lại k đc ghi lại trên Macro đó ạ. E cũng tìm hỉu gg rùi mà k ra đc :(
Không phải lúc nào cũng ghi macro được đâu. Những thao tác trên các Controls càng không ghi được. Vì thế phải học VBA để thao tác.
 
Upvote 0
cho em hỏi ngu cái ạ ví dụ:
dim Arr, Arr1()
- thì Arr là mảng các variant, còn Arr1 là mảng
vậy tại sao ta cho: Arr=range("A1","C5") được mà không làm được như vậy với Arr1, xin các bạn chỉ giáo
 
Upvote 0
cho em hỏi ngu cái ạ ví dụ:
dim Arr, Arr1()
- thì Arr là mảng các variant, còn Arr1 là mảng
vậy tại sao ta cho: Arr=range("A1","C5") được mà không làm được như vậy với Arr1, xin các bạn chỉ giáo

vậy nó báo lổi gì??? tôi thấy nó nhận giá trị tuốt luốt mà???
 
Upvote 0
cho em hỏi ngu cái ạ ví dụ:
dim Arr, Arr1()
- thì Arr là mảng các variant, còn Arr1 là mảng
vậy tại sao ta cho: Arr=range("A1","C5") được mà không làm được như vậy với Arr1, xin các bạn chỉ giáo
Làm gì mà không gán được!

Mã:
Sub test()
    Dim Arr, Arr1()
    Arr1 = Range("A1", "C5")
    MsgBox UBound(Arr1, 1)
End Sub
 
Upvote 0
do mình chọn vị trí ra ngoài kích thước mảng, nhưng nhờ các bạn giải thích Arr và Arr1() khác nhau chỗ nào nhỉ, và khai báo cái nào code chạy nhanh hơn
 
Lần chỉnh sửa cuối:
Upvote 0
mình viết kiểu này nó báo lỗi
Mã:
Sub xuly()
    Dim arr, arr1()
    With Sheet1
        arr1 = .Range("a1", Range("b65000").End(xlUp))
    End With
    MsgBox arr1(2, 3)
End Sub
Nếu cột B không có dữ liệu, thì Arr1=Range("A1:B1"), tức chỉ 1 hàng, 2 cột, vậy làm sao có thể có Arr1(2, 3) được? Đó là nói về hàng, nói về cột thì A và B chỉ 2 cột, lấy ở đâu ra cột thứ 3?
 
Upvote 0
Nếu cột B không có dữ liệu, thì Arr1=Range("A1:B1"), tức chỉ 1 hàng, 2 cột, vậy làm sao có thể có Arr1(2, 3) được? Đó là nói về hàng, nói về cột thì A và B chỉ 2 cột, lấy ở đâu ra cột thứ 3?
thank bạn mình đã sửa lại bài bên trên và có 1 câu hỏi mong bạn giải đáp
 
Upvote 0
do mình chọn vị trí ra ngoài kích thước mảng, nhưng nhờ các bạn giải thích Arr và Arr1() khác nhau chỗ nào nhỉ, và khai báo cái nào code chạy nhanh hơn
Xem và so với cái này coi có chỗ nào khác nhau không:
With Sheet1
arr1 = .Range("a1", Range("b65000").End(xlUp))
End With
With Sheet1
arr1 = .Range("a1", .Range("b65000").End(xlUp)).Value
End With
Cái mảng arr1() chỉ có cột A và B
MsgBox arr1(2, 3), cái số 3 này từ đâu ra?
 
Lần chỉnh sửa cuối:
Upvote 0
a em thấy rồi cái dưới có .Value cái trên hổng có . hihi
 
Upvote 0
do mình chọn vị trí ra ngoài kích thước mảng, nhưng nhờ các bạn giải thích Arr và Arr1() khác nhau chỗ nào nhỉ, và khai báo cái nào code chạy nhanh hơn
Khác hẳn, Với Arr là một biến Variant, tức ta có thể gán bất cứ thứ gì cho nó cũng được, dạng chuỗi, dạng số, dạng mảng v.v..., nhưng Arr1() là biến mảng, ta chỉ được gán dữ liệu dạng mảng cho nó mà thôi.

Một thử nghiệm nho nhỏ:

Mã:
Sub Test()
    Dim Arr, Arr1()
    Arr = Range("A1")
    MsgBox "OK"
    Arr1 = Range("A1")
    MsgBox "OK"
End Sub

Với lần chạy cho Arr thì OK, nhưng Arr1 thì lỗi.
 
Upvote 0
Em chào các Thầy và các anh ! Sau khi thêm bớt hoặc chỉnh sửa tên trong danh sách, để tự động đánh dấu(tô màu) những tên trong danh sách Cột B không có trong danh sách cột O em dùng code này.

Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 2 Then
   Dim CompareRange1 As Range, CompareRange2 As Range, x As Range
   Dim DongCuoiB As Integer, DongCuoiO As Integer
    DongCuoiB = [B65000].End(xlUp).Row
    DongCuoiO = [O65000].End(xlUp).Row
    Set CompareRange1 = Range("B2").Resize(DongCuoiB - 1, 1)
    Set CompareRange2 = Range("O2").Resize(DongCuoiO, 1)
    If Not Intersect(Target, CompareRange1) Is Nothing Then
        CompareRange1.Interior.ColorIndex = xlNone
        For Each x In CompareRange1
            If Application.WorksheetFunction.CountIf(CompareRange2, x) < 1 Then
                If x.Value Like " *" Then
                    x.Interior.ColorIndex = 15
                    Else: x.Interior.ColorIndex = 34
                End If
            End If
        Next x
    End If
End If
End Sub

Nhưng khi dùng cho danh sách có đến 2500 dòng thì code chạy nặng chậm. Em thấy đề tài này có nói đến dùng mảng Array để tăng tốc độ xử lý, nay em xin các Thầy cùng các bạn giúp em cải thiện tốc độ chạy code trên nhé ? Em rất cám ơn ạ.

Nếu bài hỏi này không đúng chổ em xin mọi người góp ý để em chuyển bài đến đúng chủ đề nhé em xin cám ơn.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Nhưng khi dùng cho danh sách có đến 2500 dòng thì code chạy nặng chậm. Em thấy đề tài này có nói đến dùng mảng Array để tăng tốc độ xử lý, nay em xin các Thầy cùng các bạn giúp em cải thiện tốc độ chạy code trên nhé ? Em rất cám ơn ạ.

Nếu bài hỏi này không đúng chổ em xin mọi người góp ý để em chuyển bài đến đúng chủ đề nhé em xin cám ơn.

Thử code vầy xem tốc độ thế nào:
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
  Dim x As Range, rngFind As Range, rng As Range
  If Not Intersect(Range("B2:B10000"), Target) Is Nothing Then
    Set rng = Intersect(Range("B2:B10000"), Target)
    For Each x In rng
      If Len(x.Value) Then
        If Left(x.Value, 1) = Space(1) Then
          x.Interior.ColorIndex = 15
        Else
          Set rngFind = Range("O2:O10000").Find(x.Value, , xlValues, xlWhole)
          If rngFind Is Nothing Then
            x.Interior.ColorIndex = 34
          Else
            x.Interior.ColorIndex = xlNone
          End If
        End If
      End If
    Next
  End If
End Sub
 
Upvote 0
Thử code vầy xem tốc độ thế nào:
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
  Dim x As Range, rngFind As Range, rng As Range
  If Not Intersect(Range("B2:B10000"), Target) Is Nothing Then
    Set rng = Intersect(Range("B2:B10000"), Target)
    For Each x In rng
      If Len(x.Value) Then
        If Left(x.Value, 1) = Space(1) Then
          x.Interior.ColorIndex = 15
        Else
          Set rngFind = Range("O2:O10000").Find(x.Value, , xlValues, xlWhole)
          If rngFind Is Nothing Then
            x.Interior.ColorIndex = 34
          Else
            x.Interior.ColorIndex = xlNone
          End If
        End If
      End If
    Next
  End If
End Sub

Wao... Tốc độ nhanh hơn gấp đôi rồi Thầy ơi. Em cám ơn Thầy nhiều nhiều. À Thầy ơi em muốn thêm đoạn code này nhưng em không biết phải thêm như thế nào cho tốc độ vẫn nhanh.

Mã:
' [COLOR=#ff8c00]Khi xóa tên --> màu và các dử liệu cùng dòng cũng xóa theo[/COLOR]
On Error Resume Next
    If Target = "" Then 
        With Target.Offset(, -1).Resize(, 7)
            .ClearContents
            .Interior.ColorIndex = xlNone
        End With
    End If

Em xin Thầy ghép vào giúp nhé.
 
Lần chỉnh sửa cuối:
Upvote 0
Wao... Tốc độ nhanh hơn gấp đôi rồi Thầy ơi. Em cám ơn Thầy nhiều nhiều. À Thầy ơi em muốn thêm đoạn code này nhưng em không biết phải thêm như thế nào cho tốc độ vẫn nhanh.

Mã:
' [COLOR=#ff8c00]Khi xóa tên --> màu và các dử liệu cùng dòng cũng xóa theo[/COLOR]
On Error Resume Next
    If Target = "" Then 
        With Target.Offset(, -1).Resize(, 7)
            .ClearContents
            .Interior.ColorIndex = xlNone
        End With
    End If

Em xin Thầy ghép vào giúp nhé.
Có thể là vầy chăng
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
  Dim x As Range, rngFind As Range, rng As Range
  If Not Intersect(Range("B2:B10000"), Target) Is Nothing Then
    Set rng = Intersect(Range("B2:B10000"), Target)
    For Each x In rng
      If Len(x.Value) Then
        If Left(x.Value, 1) = Space(1) Then
          x.Interior.ColorIndex = 15
        Else
          Set rngFind = Range("O2:O10000").Find(x.Value, , xlValues, xlWhole)
          If rngFind Is Nothing Then
            x.Interior.ColorIndex = 34
          Else
            x.Interior.ColorIndex = xlNone
          End If
        End If
      [COLOR=#ff0000]Else
        x.Offset(, -1).ClearContents
        x.Offset(, 1).Resize(, 5).ClearContents
        x.Offset(, -1).Resize(, 7).Interior.ColorIndex = xlNone
      End If[/COLOR]
    Next
  End If
End Sub
 
Upvote 0
Em chào các Thầy và các anh ! Sau khi thêm bớt hoặc chỉnh sửa tên trong danh sách, để tự động đánh dấu(tô màu) những tên trong danh sách Cột B không có trong danh sách cột O em dùng code này.

Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 2 Then
   Dim CompareRange1 As Range, CompareRange2 As Range, x As Range
   Dim DongCuoiB As Integer, DongCuoiO As Integer
    DongCuoiB = [B65000].End(xlUp).Row
    DongCuoiO = [O65000].End(xlUp).Row
    Set CompareRange1 = Range("B2").Resize(DongCuoiB - 1, 1)
    Set CompareRange2 = Range("O2").Resize(DongCuoiO, 1)
    If Not Intersect(Target, CompareRange1) Is Nothing Then
        CompareRange1.Interior.ColorIndex = xlNone
        For Each x In CompareRange1
            If Application.WorksheetFunction.CountIf(CompareRange2, x) < 1 Then
                If x.Value Like " *" Then
                    x.Interior.ColorIndex = 15
                    Else: x.Interior.ColorIndex = 34
                End If
            End If
        Next x
    End If
End If
End Sub

Nhưng khi dùng cho danh sách có đến 2500 dòng thì code chạy nặng chậm. Em thấy đề tài này có nói đến dùng mảng Array để tăng tốc độ xử lý, nay em xin các Thầy cùng các bạn giúp em cải thiện tốc độ chạy code trên nhé ? Em rất cám ơn ạ.

Nếu bài hỏi này không đúng chổ em xin mọi người góp ý để em chuyển bài đến đúng chủ đề nhé em xin cám ơn.

ngồi nhổ râu riết trụi lũi rồi..........hihihihi
góp tí cho vui
Mã:
Sub hello()
Dim Cot_O, Cot_B As Variant, i, j, k As Long, dic As Object, st_1, st_2 As String
Cot_O = [o2:o20]
Cot_B = Range([B2], [B2].End(4)).Value
Range([B2], [B2].End(4)).Interior.ColorIndex = xlNone
Set dic = CreateObject("Scripting.Dictionary")
For i = 1 To UBound(Cot_O)
    If Not dic.exists(Cot_O(i, 1)) Then dic.Add (Cot_O(i, 1)), ""
Next
For i = 1 To UBound(Cot_B)
j = i + 1
    If Left(Cot_B(i, 1), 1) = Space(1) Then
        If Len(st_1) Then st_1 = st_1 & "," & "B" & j Else st_1 = "B" & j
    Else
        If Not dic.exists(Cot_B(i, 1)) Then
            If Len(st_2) Then st_2 = st_2 & "," & "B" & j Else st_2 = "B" & j
       End If
    End If
Next
Range(st_1).Interior.ColorIndex = 15
Range(st_2).Interior.ColorIndex = 34

End Sub
 
Upvote 0
Có thể là vầy chăng
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
  Dim x As Range, rngFind As Range, rng As Range
  If Not Intersect(Range("B2:B10000"), Target) Is Nothing Then
    Set rng = Intersect(Range("B2:B10000"), Target)
    For Each x In rng
      If Len(x.Value) Then
        If Left(x.Value, 1) = Space(1) Then
          x.Interior.ColorIndex = 15
        Else
          Set rngFind = Range("O2:O10000").Find(x.Value, , xlValues, xlWhole)
          If rngFind Is Nothing Then
            x.Interior.ColorIndex = 34
          Else
            x.Interior.ColorIndex = xlNone
          End If
        End If
      [COLOR=#ff0000]Else
        x.Offset(, -1).ClearContents
        x.Offset(, 1).Resize(, 5).ClearContents
        x.Offset(, -1).Resize(, 7).Interior.ColorIndex = xlNone
      End If[/COLOR]
    Next
  End If
End Sub

Em cám ơn Thầy đã giúp, Em test rồi tốc độ vẫn đảm bảo. Em cũng test code 2, nếu chỉ xóa 1 tên tốc độ vẫn tương đương với code của Thầy.

code 2
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim x As Range, rngFind As Range, rng As Range
  If Not Intersect(Range("B2:B10000"), Target) Is Nothing Then
    Set rng = Intersect(Range("B2:B10000"), Target)
    For Each x In rng
      If Len(x.Value) Then
        If Left(x.Value, 1) = Space(1) Then
          x.Interior.ColorIndex = 15
        Else
          Set rngFind = Range("O2:O10000").Find(x.Value, , xlValues, xlWhole)
          If rngFind Is Nothing Then
            x.Interior.ColorIndex = 34
          Else
            x.Interior.ColorIndex = xlNone
          End If
        End If
      End If
    Next
    [COLOR=#ff8c00]On Error Resume Next
    If Target = "" Then
        Target.Offset(, -1).ClearContents
        Target.Offset(, 1).Resize(, 5).ClearContents
        Target.Offset(, -1).Resize(, 7).Interior.ColorIndex = xlNone
    End If[/COLOR]
End If
End Sub

Nhưng nếu quét khối xóa một lược nhiều tên (khoảng 3 tên trở lên) --> code 2 nhanh hơn, em đoán nguyên nhân do phần code màu cam không nằm trong vòng lặp, có phải vậy không Thầy ?
 
Upvote 0
ngồi nhổ râu riết trụi lũi rồi..........hihihihi
góp tí cho vui
Mã:
Sub hello()
Dim Cot_O, Cot_B As Variant, i, j, k As Long, dic As Object, st_1, st_2 As String
Cot_O = [o2:o20]
Cot_B = Range([B2], [B2].End(4)).Value
Range([B2], [B2].End(4)).Interior.ColorIndex = xlNone
Set dic = CreateObject("Scripting.Dictionary")
For i = 1 To UBound(Cot_O)
    If Not dic.exists(Cot_O(i, 1)) Then dic.Add (Cot_O(i, 1)), ""
Next
For i = 1 To UBound(Cot_B)
j = i + 1
    If Left(Cot_B(i, 1), 1) = Space(1) Then
        If Len(st_1) Then st_1 = st_1 & "," & "B" & j Else st_1 = "B" & j
    Else
        If Not dic.exists(Cot_B(i, 1)) Then
            If Len(st_2) Then st_2 = st_2 & "," & "B" & j Else st_2 = "B" & j
       End If
    End If
Next
Range(st_1).Interior.ColorIndex = 15
Range(st_2).Interior.ColorIndex = 34

End Sub
Cám ơn anh Let'GâuGâu giúp em, anh xem code anh viết hình như còn thiếu cái gì đó, chạy code báo lổi này.
ảnh lổi.png
 
Upvote 0
Em cám ơn Thầy đã giúp, Em test rồi tốc độ vẫn đảm bảo. Em cũng test code 2, nếu chỉ xóa 1 tên tốc độ vẫn tương đương với code của Thầy.

code 2
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim x As Range, rngFind As Range, rng As Range
  If Not Intersect(Range("B2:B10000"), Target) Is Nothing Then
    Set rng = Intersect(Range("B2:B10000"), Target)
    For Each x In rng
      If Len(x.Value) Then
        If Left(x.Value, 1) = Space(1) Then
          x.Interior.ColorIndex = 15
        Else
          Set rngFind = Range("O2:O10000").Find(x.Value, , xlValues, xlWhole)
          If rngFind Is Nothing Then
            x.Interior.ColorIndex = 34
          Else
            x.Interior.ColorIndex = xlNone
          End If
        End If
      End If
    Next
    [COLOR=#ff8c00]On Error Resume Next
    If Target = "" Then
        Target.Offset(, -1).ClearContents
        Target.Offset(, 1).Resize(, 5).ClearContents
        Target.Offset(, -1).Resize(, 7).Interior.ColorIndex = xlNone
    End If[/COLOR]
End If
End Sub

Nhưng nếu quét khối xóa một lược nhiều tên (khoảng 3 tên trở lên) --> code 2 nhanh hơn, em đoán nguyên nhân do phần code màu cam không nằm trong vòng lặp, có phải vậy không Thầy ?

nhanh hơn là đúng rồi vì code 2 tào lao quá mà
Nếu bạn không hiểu bản chất thì nên làm theo code anh NDU viết sẵn , đừng chế lung tung
Tôi nói thí dụ đơn giản dòng này là trật lất
Mã:
[COLOR=#FF8C00][I]If Target = "" Then[/I][/COLOR]
vì Target đâu có chắc nó là 1 ô đơn đâu mà được xét như thế
 
Upvote 0
Cám ơn anh Let'GâuGâu giúp em, anh xem code anh viết hình như còn thiếu cái gì đó, chạy code báo lổi này.
View attachment 149769

bạn ấy có chút nhầm lẫn ấy mà . Nhưng nói chung thì không nên sử dụng cách giải ấy . Vì address String nhét vô .Range(address)
nó chỉ nhận có vài trăm kí tự , address String mà dài hơn nữa là nó tự cắt cho cụt luôn nên sẽ báo lỗi
 
Upvote 0
nhanh hơn là đúng rồi vì code 2 tào lao quá mà
Nếu bạn không hiểu bản chất thì nên làm theo code anh NDU viết sẵn , đừng chế lung tung
Tôi nói thí dụ đơn giản dòng này là trật lất
Mã:
[COLOR=#FF8C00][I]If Target = "" Then[/I][/COLOR]
vì Target đâu có chắc nó là 1 ô đơn đâu mà được xét như thế

Em cám ơn Thầy (Cô) doveandrose chỉ dạy, nhưng xin Thầy doveandrose chỉ dạy nhẹ tay thôi vì em còn rất " nai tơ " với VBA lắm. Để chạy được 1 lệnh VBA mà em mong muốn, em phải lùng sụt khắp Google xem cái nào na ná giống cái em cần là em lắp vô, may mắn code chạy được đúng ý là vui mừng không kể siết, cho nên không thể tránh khỏi tào lao, lung tung, trật lất....,mặc dù em biết viết
Mã:
[COLOR=#FF8C00][I]If Target = "" Then[/I][/COLOR]
là quá chung chung không phù hợp với code của Thầy NDU, nhưng em đâu biết phải làm thế nào mới đúng, em chỉ biết lắp vào như thế nó chạy nhanh hơn và em muốn nhờ các Thầy, các thành viên trong ngôi nhà GPE giúp đỡ để code chạy đúng và nhanh hơn.

Nếu em có lời nào không phải xin các Thầy cùng các bạn hiểu cho nỗi khổ của em , cảm thông cho em , từ từ chỉ dạy em nhé. Em xin cảm ơn tất cả mọi người.
 
Lần chỉnh sửa cuối:
Upvote 0
Có thể là vầy chăng
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
  Dim x As Range, rngFind As Range, rng As Range
  If Not Intersect(Range("B2:B10000"), Target) Is Nothing Then
    Set rng = Intersect(Range("B2:B10000"), Target)
    For Each x In rng
      If Len(x.Value) Then
        If Left(x.Value, 1) = Space(1) Then
          x.Interior.ColorIndex = 15
        Else
          Set rngFind = Range("O2:O10000").Find(x.Value, , xlValues, xlWhole)
          If rngFind Is Nothing Then
            x.Interior.ColorIndex = 34
          Else
            x.Interior.ColorIndex = xlNone
          End If
        End If
      [COLOR=#ff0000]Else
        x.Offset(, -1).ClearContents
        x.Offset(, 1).Resize(, 5).ClearContents
        x.Offset(, -1).Resize(, 7).Interior.ColorIndex = xlNone
      End If[/COLOR]
    Next
  End If
End Sub

Em xin chào các Thầy! Sau nhiều lần thử tới thử lui em phát hiện nguyên nhân code chạy chậm là do file excel của em có quá nhiều công thức vlookup, ngoài sheet DANH SACH file còn có 20 sheet TRUC DEM, mổi sheet TRUC DEM có cấu trúc giống nhau 55 dòng tên chứa Vlookup ở cột C,D,H và I .Chính khối Vlookup khổng lồ này làm chậm tốc độ, bằng chứng là em copy / past value cho tất cã 20 sheet TRUC DEM lập tức code của Thầy NDU chạy nhanh vù vù luôn.

Để tống khứ đống Vlookup đó đi em viết code này

Mã:
Sub ThayTheVlookup()
    Dim DuLieuTam
    Dim LastRow As Long, DongCuoiB As Long, DongCuoiG As Long, i As Integer
    Const SoDongCuoi = 50
For i = 1 To 2 'file thuc tê' có den 20 sheet
    With Sheets(i)
        DongCuoiB = Cells(SoDongCuoi, 2).End(xlUp).Row
        DongCuoiG = Cells(SoDongCuoi, 7).End(xlUp).Row
                If DongCuoiB > DongCuoiG Then
                    LastRow = DongCuoiB
                    Else: LastRow = DongCuoiG
                End If
        If LastRow < 3 Then Exit Sub
        Dim VungKetQua As Range
        Set VungKetQua = .Range("A3:I" & LastRow)
        DuLieuTam = VungKetQua
    End With
    With DanhSach
        LastRow = .Range("B" & Rows.Count).End(xlUp).Row
        If LastRow < 2 Then Exit Sub
        Dim x As Long, y As Long
        Dim rngData As Range, rngFind As Range
        Set rngData = .Range("A1:D" & LastRow)
    End With
    For x = 1 To UBound(DuLieuTam)
        Set rngFind = rngData.Find(What:=DuLieuTam(x, 2), LookIn:=xlFormulas, LookAt:=xlWhole)
        DuLieuTam(x, 1) = x
        DuLieuTam(x, 3) = rngFind.Offset(, 1)
        DuLieuTam(x, 4) = rngFind.Offset(, 2)
    Next x
    For y = 1 To UBound(DuLieuTam)
        Set rngFind = rngData.Find(What:=DuLieuTam(y, 7), LookIn:=xlFormulas, LookAt:=xlWhole)
        DuLieuTam(y, 6) = y
        DuLieuTam(y, 8) = rngFind.Offset(, 1)
        DuLieuTam(y, 9) = rngFind.Offset(, 2)
    Next y
    VungKetQua = DuLieuTam
Next i
End Sub

Nhưng nó không chạy được. Em gửi kèm file chỉ chừa lại 2 sheet TRUC DEM , sheet DANH SACH và bớt số dòng để tiện gửi file.
Kính mong các Thầy xem và sữa chửa giúp em nhé, nhân đây cho em nói lời xin lổi với Thầy NDU: " Thầy NDU ơi cho em xin lổi, Thầy đừng buồn đừng giận em nhé ".
 

File đính kèm

Upvote 0
Em cám ơn Thầy hpkhuong nhé, Thầy đoán đúng code trên là code chắp ghép chế lại ạ, Vlookup hay vlookup do em gỏ vội chỉ muốn nói đến hàm VLOOKUP.

Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim fRng As Range, Clls As Range, Ds As Worksheet
Set Ds = Sheets("DANH SACH")
If Target.Row > 2 And (Target.Column = 2 Or Target.Column = 7) Then
    For Each Clls In Target
        If Clls.Value = Empty Then Clls.Offset(, 1).Resize(, 2) = Empty
    Set fRng = Ds.Range(Ds.[B2], Ds.[B10000].End(3)).Find(Clls.Value, , xlValues, xlWhole)
        If Not fRng Is Nothing Then Clls.Offset(, 1).Resize(, 2) = fRng.Offset(, 1).Resize(, 2).Value
    Next Clls
End If
End Sub

Code này chạy tốt lắm ạ.
Nếu ta chỉnh sửa dử liệu ở cột C,D của Sheets("DANH SACH") muốn các sheet TRUC DEM tự động cập nhật theo thì phải làm thế nào ạ ?
 
Upvote 0
Sub ThayTheVlookup() em viết dùng đến Mảng Array (biến là DuLieuTam) với 4 mong muốn:

1. Loại bỏ hàm VLOOKUP cho nhẹ file.
2. Sau khi chỉnh sửa dử liệu cột C,D (TLƯƠNG,HỆ SỐ)ở sheet DANH SACH xong --> click nút --> tự động cập nhật vào các sheet TRUC DEM
3. Khi chỉnh sửa bớt thêm tên ở cột B,G của các sheet TRUC DEM ( thêm tên: có nghĩa là gõ tên từng ô hoặc copy một lược nhiều tên ở sheet DANH SACH past vào) xong --> cột TLƯƠNG,HỆ SỐ tự động cập nhật từ sheet DANH SACH (giống y như hàm VLOOKUP tự cập nhật vậy).
4.Tốc độ xử lí dử liệu nhanh.

Nhưng nay các mong muốn trên đành hỏi lại ở chủ đề khác để không phạm qui, em cám ơn Thầy hpkhuong nhắc nhở.
 
Upvote 0
Bạn phải kéo sheet Danh Mục của bạn ra đằng trước 2 sheet TRUCDIEM thì mới chạy code đúng được.

Chú ý chỗ màu đỏ tôi tô bên dưới:
Các sheet cần update tự động thì phải để sau cùng. Vì mục đích ta duyệt qua 'Sheet.Count (bắt đầu từ sheet thứ 2, vì sheet thứ 1 là DanhSach rồi.) Nếu có nhiều sheet khác ngoài danh sách thì bạn cứ Move tới phía trước, các sheet TrucDiem cần chạy code. Sau đó xác định Sheet cần chạy code đầu tiên nằm ở số thứ tự bao 'nhiêu thì thay đổi số 2 trên vòng lặp thành số thứ tự đó....Hiểu chứ...

Mã:
For i = [COLOR=#ff0000][B]2 To Sheets.Count 'chú ý chỗ này.[/B][/COLOR]

Em đã làm theo nhưng sao click nút nó vẫn đơ ra, code chỉ chạy trong cửa sổ Microsoft Visual Basic và với điều kiện Activesheet phải là các sheet TRUC DEM, em không rỏ nguyên nhân.
 

File đính kèm

  • mota1.jpg
    mota1.jpg
    24.8 KB · Đọc: 7
  • mota2.jpg
    mota2.jpg
    34.1 KB · Đọc: 7
Upvote 0
Bạn kèm file lên đây, sao không chạy cơ chứ....

Dạ em gửi file anh xem giúp nhé, em dùng Excel 2003 có liên quang đến việc chạy code không anh ?

Em xin bổ xung : nếu cái nút gán ở sheet TRUC DEM code lại chạy được sao vậy ta ?
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Gì vậy đồng chí. Code vậy thì bạn đứng tại bất cứ sheet nào chạy cũng có tác dụng hết.
Bạn thử xóa dữ liệu đi, đứng ở bất kỳ sheet nào chạy code nó cũng có tác dụng cả...
Các anh đã test rồi vẫn chạy bình thường à ? thế thì em chết mất, từ lúc dùng Excel đến nay em chỉ gặp code chạy báo lỗi chạy không đúng yêu cầu chứ chưa từng gặp trường hợp này bao giờ.
 
Upvote 0
Các anh đã test rồi vẫn chạy bình thường à ? thế thì em chết mất, từ lúc dùng Excel đến nay em chỉ gặp code chạy báo lỗi chạy không đúng yêu cầu chứ chưa từng gặp trường hợp này bao giờ.

A host application may disable or enable macros. This error has the following causes and solutions:


  • You opened the document with Macros Disabled. Close the document, and then reopen it with Enable Macros.
For additional information, select the item in question and press F1 (in Windows) or HELP (on the Macintosh).
ofm
=========
tôi cũng bị lổi, hãy thử với phần help
 
Upvote 0
A host application may disable or enable macros. This error has the following causes and solutions:


  • You opened the document with Macros Disabled. Close the document, and then reopen it with Enable Macros.
For additional information, select the item in question and press F1 (in Windows) or HELP (on the Macintosh).
ofm
=========
tôi cũng bị lổi, hãy thử với phần help
Cái này có nghĩa là gì hở bác ^^
 
Upvote 0
Em đang đọc về mảng qua Topic này. Em có đoạn CODE sau để đánh số thứ tự từ 1 đến 100 :
PHP:
Option Explicit
Sub STT2()
Dim i As Long, Arr(1 To 100) As Double 
For i = 1 To 100    
   Arr(i) = i  
Next i  
Range("A1:A100").Value = Arr() 
End Sub
Tuy nhiên nó lại toàn ra số 1. Nhờ mọi người kiểm tra giúp em sao lại bị như vậy.
 
Upvote 0
Em đang đọc về mảng qua Topic này. Em có đoạn CODE sau để đánh số thứ tự từ 1 đến 100 :
PHP:
Option Explicit
Sub STT2()
Dim i As Long, Arr(1 To 100) As Double 
For i = 1 To 100    
   Arr(i) = i  
Next i  
Range("A1:A100").Value = Arr() 
End Sub
Tuy nhiên nó lại toàn ra số 1. Nhờ mọi người kiểm tra giúp em sao lại bị như vậy.

ủa Option Explicit là gì vẩy bạn ? có tác dụng gì ta ?
mình vớ được cái này ở đâu đó
Range("A1:A100").Value = WorksheetFunction.Transpose(Arr)
 
Upvote 0
Em đang đọc về mảng qua Topic này. Em có đoạn CODE sau để đánh số thứ tự từ 1 đến 100 :
PHP:
Option Explicit
Sub STT2()
Dim i As Long, Arr(1 To 100) As Double 
For i = 1 To 100    
   Arr(i) = i  
Next i  
Range("A1:A100").Value = Arr() 
End Sub
Tuy nhiên nó lại toàn ra số 1. Nhờ mọi người kiểm tra giúp em sao lại bị như vậy.
Sửa thế này thì ok
Mã:
Sub tong()
Dim i As Long, Arr(1 To 100, 1 To 1) As Double
For i = 1 To 100
      Arr(i, 1) = i
Next i
Range("A1:A100").Value = Arr()
End Sub
 
Upvote 0
Cảm ơn anh DoveandRose và bạn doatmenhhon nhiều. Tức là khi gán từ mảng xuống Range thì bắt buộc mảng phải là mảng 2 chiều có đúng không ạ.
ủa Option Explicit là gì vẩy bạn ? có tác dụng gì ta ?
Cái này có thật là anh hổng bít không hay lại tính chọt em đây ??

Cái bạn sửa với cái của Phong nó khác hoàn toàn nhé. 1 Cái là mảng 1 chiều, cái 2 chiều...
Ku Phong đang làm theo 1 chiều, thì Transpose mới là giái pháp đúng...
Nhờ các anh làm rõ thêm tại sao của em lại toàn ra số 1 vậy
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn thử đổi thành Range("A1:Z1").Value = Arr() sẽ thấy rõ. Arr(i) là mảng theo hàng là mảng ngang . Mảng (“A1:A100”) là mảng theo cột là mảng dọc nên gán (“A1:A100”) = Arr thì chỉ nhận được đúng kết quả Arr(1)=1
 
Lần chỉnh sửa cuối:
Upvote 0
Nhờ các anh làm rõ thêm tại sao của em lại toàn ra số 1 vậy
Chạy code này thì biết ngay tấp lự thôi!
PHP:
Option Explicit
Sub STT2()
Dim I As Long, Arr(1 To 100) As Double
For I = 1 To 100
   Arr(I) = I
Next I
Range("A1").Resize(, 100).Value = Arr()
End Sub
 
Upvote 0
Em xin cảm ơn. Em xin trình bày ý hiểu của mình, nếu có chổ nào sai xót mọi người chỉnh giúp em hé:

Mảng Arr(1 to 100) là mảng 1 chiều do mình tạo ra vì thế nó luôn là mảng ngang. Vì vậy nếu ta muốn gán các phần tử của mảng xuống Range thì bắt buộc Range đó phải theo chiều ngang. Như ở trên có 2 cách để thực hiện việc này:
1. Là thực hiện theo cách của anh DoveandRose tức là dùng hàm Transpose để chuyển mảng ngang do mình tạo ra thành mảng dọc rồi sau đó gán các pt của mảng xuống Sheet có Range là chiều đứng.
2. Thực hiện theo cách của bạn doatmenhhon và tác giả HYến là gán luôn mảng đó xuống sheet nhưng sheet phải có Range là theo chiều ngang.

Như vầy em đã hiểu đúng bản chất của vấn đề chưa ạ.
 
Lần chỉnh sửa cuối:
Upvote 0
em xin cảm ơn. Em hiểu như vầy không biết đã đúng chưa, nếu có chổ nào sai xót mọi người chỉnh giúp em hé:
Mảng arr(1 to 100) là mảng 1 chiều do mình tạo ra vì thế nó luôn là mảng ngang. Vì thế nếu ta muốn gán các phần tử của mảng xuống range thì bắt buộc range đó phải theo chiều ngang. Như ở trên có 2 cách để thực hiện việc này:
1. Là cách của anh doveandrose tức là dùng hàm transpose để chuyển mảng ngang thành mảng dọc rồi sau đó gán xuống sheet chứa range là chiều đứng.
2. Thực hiện theo cách của bạn doatmenhhon và tác giả hyến là gán luôn mảng đó xuống sheet nhưng sheet phải chứa range là theo chiều ngang.
Như vầy đã đúng chưa ạ.
"u" "ngờ" "ung", "đờ ung đung sắc"...... Rồi +-+-+-++-+-+-++-+-+-+
 
Upvote 0
Hi hi, em hi vọng trong dấu ba chấm kia là Đúng. Nếu mà vẫn chưa đúng thật thì xin tác giả góp ý cho em với ạ...

muốn biết đúng hay không thì bạn thử là biết, muốn hỏi mình hiểu chưa, thì bạn phải giải thích tại sao nó thế, tại sao thế, còn chỉ nhắc lại việc ng ta đã làm thì là đúng thôi.
 
Upvote 0
Em xin cảm ơn. Em xin trình bày ý hiểu của mình, nếu có chổ nào sai xót mọi người chỉnh giúp em hé:

Mảng Arr(1 to 100) là mảng 1 chiều do mình tạo ra vì thế nó luôn là mảng ngang. Vì vậy nếu ta muốn gán các phần tử của mảng xuống Range thì bắt buộc Range đó phải theo chiều ngang. Như ở trên có 2 cách để thực hiện việc này:
1. Là thực hiện theo cách của anh DoveandRose tức là dùng hàm Transpose để chuyển mảng ngang do mình tạo ra thành mảng dọc rồi sau đó gán các pt của mảng xuống Sheet có Range là chiều đứng.
2. Thực hiện theo cách của bạn doatmenhhon và tác giả HYến là gán luôn mảng đó xuống sheet nhưng sheet phải có Range là theo chiều ngang.

Như vầy em đã hiểu đúng bản chất của vấn đề chưa ạ.

Chỉ đúng đến khoảng 75%. Chỗ còn lại hơi khó chứng minh.
Thật ra, hàm application.transpose tự động chuyển mảng của bạn thành 2 chiều.

muốn biết đúng hay không thì bạn thử là biết, muốn hỏi mình hiểu chưa, thì bạn phải giải thích tại sao nó thế, tại sao thế, còn chỉ nhắc lại việc ng ta đã làm thì là đúng thôi.

Bình thường thì lý luận này đúng. Nhưng riêng trường hợp này phải biết lý thuyết mới biết cách thử.
Nếu không biết lý thuyết, bạn chỉ thử đến mức làm ra kết quả hay không thôi, chứ lý do tại sao thì hơi khó nghiệm ra.
 
Upvote 0
Bình thường thì lý luận này đúng. Nhưng riêng trường hợp này phải biết lý thuyết mới biết cách thử.
Nếu không biết lý thuyết, bạn chỉ thử đến mức làm ra kết quả hay không thôi, chứ lý do tại sao thì hơi khó nghiệm ra.

Không nghiệm ra thì là chưa hiểu, vì thế mới nói bạn ta là cần phải nói tại sao, thì mới người mới hiểu là bạn ta hiểu hay chưa. Còn suốt ngày nói chung, nói chung thế này thì biết còn cụ thể thì tắc tịt thì là chưa hiểu.
 
Upvote 0
Em xin cảm ơn. Em xin trình bày ý hiểu của mình, nếu có chổ nào sai xót mọi người chỉnh giúp em hé:

Mảng Arr(1 to 100) là mảng 1 chiều do mình tạo ra vì thế nó luôn là mảng ngang
Mảng một chiều là 1 vector mà vector thì có thể nằm đứng, nằm ngang hay nằm gì gì đó tùy ý, miễn sao là thẳng đường. do trong excel người ta quy ước sẳn khi dán mảng một chiều xuống range thì nó nằm ngang, chứ không phải mảng một chiều là mảng ngang
 
Upvote 0
Em có 2 câu hỏi nhờ mọi người tư vấn giùm ạ:
1. Vẫn là bài tập bên trên nhưng giờ em chuyển qua mảng 2 chiều (CODE này em lấy trên diễn đàn) viết như sau:
PHP:
Sub STT1()  Dim i As Long, Arr()  
ReDim Arr(1 To 100, 1 To 1)  
For i = 1 To 100   
  Arr(i, 1) = i  
Next  
Range("A1:A100").Value = Arr
End Sub
Sau khi đọc xong em sửa lại theo ý của em thành thế này :
PHP:
Sub STT2()  Dim i As Long, Arr(1 To 100, 1 To 1) 
 For i = 1 To 100    
   Arr(i, 1) = i  
 Next  
Range("A1:A100").Value = Arr
End Sub
thấy CODE vẫn chạy mà không có gì thay đổi. Vậy xin mọi người cho em hỏi giữa 2 đoạn CODE trên có điểm gì khác nhau ạ.

2.Tại sao CODE đầu tiên lại phải thên Redim vào làm gì vậy. Em có đọc và thấy mọi người nói là Redim dùng khi kích thước của mảng bị thay đổi nhưng với bài này em chưa hiểu được công dụng của nó : tức là trong TH này thì tại sao kích thước của mảng lại bị thay đổi (em có thấy bị thay đổi gì đâu) và nếu nó có thay đổi đi chăng nữa thì cũng phải qua 1 số bước bên dưới nữa thì mới bị thay đổi chớ ...sao chưa gì đã Redim ngay từ đầu CODE là vì sao vậy.
Em xin cảm ơn ạ !
 
Lần chỉnh sửa cuối:
Upvote 0
Em có 2 câu hỏi nhờ mọi người tư vấn giùm ạ:
1. Vẫn là bài tập bên trên nhưng giờ em chuyển qua mảng 2 chiều (CODE này em lấy trên diễn đàn) viết như sau:
PHP:
Sub STT1()  Dim i As Long, Arr()  
ReDim Arr(1 To 100, 1 To 1)  
For i = 1 To 100   
  Arr(i, 1) = i  
Next  
Range("A1:A100").Value = Arr
End Sub
Sau khi đọc xong em sửa lại theo ý của em thành thế này :
PHP:
Sub STT2()  Dim i As Long, Arr(1 To 100, 1 To 1) 
 For i = 1 To 100    
   Arr(i, 1) = i  
 Next  
Range("A1:A100").Value = Arr
End Sub
thấy CODE vẫn chạy mà không có gì thay đổi. Vậy xin mọi người cho em hỏi giữa 2 đoạn CODE trên có điểm gì khác nhau ạ.

2.Tại sao CODE đầu tiên lại phải thên Redim vào làm gì vậy. Em có đọc và thấy mọi người nói là Redim dùng khi kích thước của mảng bị thay đổi nhưng với bài này em chưa hiểu được công dụng của nó : tức là trong TH này thì tại sao kích thước của mảng lại bị thay đổi (em có thấy bị thay đổi gì đâu) và nếu nó có thay đổi đi chăng nữa thì cũng phải qua 1 số bước bên dưới nữa thì mới bị thay đổi chớ ...sao chưa gì đã Redim ngay từ đầu CODE là vì sao vậy.
Em xin cảm ơn ạ !

thì lúc đâu bạn chỉ khai báo nó là mảng thôi, bạn có cho nó kích thướt là bao nhiêu đâu
Mã:
dim Arr()

vậy thì bước tiếp theo bạn phải khai báo nó
Mã:
[COLOR=#000000][COLOR=#0000BB]ReDim Arr[/COLOR][COLOR=#007700]([/COLOR][COLOR=#0000BB]1 To 100[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]1 To 1[/COLOR][COLOR=#007700])

chứ ngay từ đâu bạn khai báo nó vậy luôn đi
Mã:
dim [COLOR=#000000][COLOR=#0000BB]Arr[/COLOR][COLOR=#007700]([/COLOR][COLOR=#0000BB]1 To 100[/COLOR][COLOR=#007700], [/COLOR][COLOR=#0000BB]1 To 1[/COLOR][COLOR=#007700])
thì có sao đâu
bạn phải khai báo kích thướt thì tiếp theo bạn mới nhét số liệu vô được chứ
[/COLOR][/COLOR][/COLOR][/COLOR]
 
Upvote 0
Tại vì cái code redim bạn lấy của ai đó chỉ dùng để ví dụ cái gì đó chứ không phải để giải thích nhiệm vụ của redim.
Nếu bạn chịu khó tìm ký hơn, sẽ thấy bài nói về Redim.

Đại khái khai báo Dim a(1 to 100, 1 to 1) là cách khai báo mảng cứng. VBA sẽ giành ra đúng 100 dòng và 1 cột trong bộ nhớ chủa nó (vì không có kiểu phần tử cho nên nó chỉ là địa chỉ variant). Việc ginahf bộ nhớ này xảy ra lúc compile, khong phải lúc chạy.
Trong khí đó, khai báo a() và sau đó Redim a(...) là cách khai báo động, thường thường Redim a(lb to ub, ...) với lb là ub là biến chứ không phải hằng như code của bạn. VBA chỉ giành ra một địa chỉ cho a, đến khi code chạy đến chỗ redim mới biết mảng cần như thế nào và giành ra một khoảng bộ nhớ.
Không cần phải lý luận nhiều, ai cũng có thể thấy rằng cách đông linh hoạt hơn cách cứng, nhưng ngược lại, cách cứng nhanh hơn cách động.
 
Upvote 0
Như vậy là với bài tập trên của em ta không nhất thiết phải sử dụng Redim . Tuy nhiên em vẫn chưa thấy được tầm quan trọng của nó. Bây giờ mọi người có thể cho em 1 ví dụ nào đơn giản mà bắt buộc phải dùng đến Redim được không ạ để em thực sự thấy được sự cần thiết -phải có nó
 
Upvote 0
Như vậy là với bài tập trên của em ta không nhất thiết phải sử dụng Redim . Tuy nhiên em vẫn chưa thấy được tầm quan trọng của nó. Bây giờ mọi người có thể cho em 1 ví dụ nào đơn giản mà bắt buộc phải dùng đến Redim được không ạ để em thực sự thấy được sự cần thiết -phải có nó

Ví dụ:
ReDim arr(1 to n)
Với n là một biến mà bằng cách nào đó bạn phải tính toán mới có được (chẳng hạn n = rng.Rows.Count)
Vậy theo nguyên tắc thì bạn không thể Dim arr(1 to n) được mà BUỘC phải ReDim
Bởi quy định:
- Nếu n là con số "chết" cụ thể nào đó, chẳng hạn là 100 thì bạn được quyền Dim arr(1 to 100)
- Nếu n là biến mà bạn cố tình Dim arr(1 to n) thì Excel sẽ báo lỗi ngay lập tức
Anh Bill nói vậy!
 
Upvote 0
Ví dụ đơn giản:
Tôi cần một mảng để chứa n trị integer. Tôi chưa biết n là bao nhiêu.
Tôi có 2 cách code:
1. Mảng tĩnh: Tôi khai báo một mảng rất lớn - để chắc ăn là số phần tử nhiều hơn n. Và tôi phải luôn ghi nhớ rằng những phần tử sau n không dùng đến.
2. Mảng động: tôi khai báo tên mảng. Cần đến bao nhiêu, tôi lại redim đến đó.

Nhắc lại bài trước đây:
Dim a(1 to 100) là mảng tĩnh. Khai báo xong là xài được rồi. Kích cỡ (100 phần tử) và hình dáng (mảng 1 chiều) đã được cố định.
Dim a() là mảng động, chỉ có cái tên chứ chưa xài được. Chỉ sau khi Redim(...) thì mảng mới có thực chất. Lúc Redim là lúc bạn cho nó kích cỡ và hình dáng.

Chú thêm:
Dim là lệnh khai báo. Bạn dùng nó để khai báo cho trình dịch VBA biết rằng bạn sẽ sử dụng một biến như thế. Lúc khai báo bạn có quyền chọn là tĩnh hay động.
Redim là lệnh thi hành. Bạn dùng nó để ra lệnh VBA chuyển kích cỡ và hình dạng của mảng như bạn cần. Dĩ nhiên, VBA chỉ có thể chuyển dạng được mảng động.
 
Lần chỉnh sửa cuối:
Upvote 0
Nhờ các thầy/cô/anh/chị và bạn giải thích giúp em trong CODE này tại sao er lại phải cộng thêm 1 trong khi vùng dữ liệu chỉ là từ A2:F21

(trong phần chú thích CODE em có ghi rõ câu hỏi rồi đó ạ. CODE này để tính tổng cho từng bộ phận). Em xin cám ơn !
 

File đính kèm

Upvote 0
Nhờ các thầy/cô/anh/chị và bạn giải thích giúp em trong CODE này tại sao er lại phải cộng thêm 1 trong khi vùng dữ liệu chỉ là từ A2:F21

(trong phần chú thích CODE em có ghi rõ câu hỏi rồi đó ạ. CODE này để tính tổng cho từng bộ phận). Em xin cám ơn !
bạn không nên hỏi tại sao er lại phải cộng thêm 1 ? vì mỗi người có 1 cách suy nghĩ khác nhau nên mỗi người có một cách viết khác nhau theo lối suy nghĩ của người ta. Bạn nên hỏi là từ đầu vào này làm sao có được đầu ra thì mọi người sẽ tư duy giúp bạn, chứ bạn hỏi như vậy, tôi cá rằng rất rất ít người đọc lại đống code của bạn rồi trả lời cho bạn, làm biếng hiểu ý của người khác lắm.
 
Upvote 0
bạn không nên hỏi tại sao er lại phải cộng thêm 1 ? vì mỗi người có 1 cách suy nghĩ khác nhau nên mỗi người có một cách viết khác nhau theo lối suy nghĩ của người ta. Bạn nên hỏi là từ đầu vào này làm sao có được đầu ra thì mọi người sẽ tư duy giúp bạn, chứ bạn hỏi như vậy, tôi cá rằng rất rất ít người đọc lại đống code của bạn rồi trả lời cho bạn, làm biếng hiểu ý của người khác lắm.

Em cũng không biết phải diễn đạt bằng cách nào để mọi người dễ hiểu hơn nữa. Tuy nhiên để hiểu đc thắc mắc của em cũng không cần phải đọc hết CODE đâu anh. Dễ hiểu lắm mà anh. Vùng chứa dữ liệu chỉ là từ A2:F21 thôi thế mà trong đoạn CODE er đã bằng 21 rồi tại sao lại phải cộng thêm 1 thế hóa ra mảng arr1 gồm các giá trị trong vùng A2:F22 --->bị thừa ra 1 dòng là sao ạ ??? Mong anh và mọi người hiểu đc khúc mắc của em và giải thích dùm em với...
 
Lần chỉnh sửa cuối:
Upvote 0
Em cũng không biết phải diễn đạt bằng cách nào để mọi người dễ hiểu hơn nữa. Tuy nhiên để hiểu đc thắc mắc của em cũng không cần phải đọc hết CODE đâu anh. Dễ hiểu lắm mà anh. Vùng chứa dữ liệu chỉ là từ A2:F21 thôi thế mà trong đoạn CODE er đã bằng 21 rồi tại sao lại phải cộng thêm 1 thế hóa ra mảng arr1 gồm các giá trị trong vùng A2:F22 --->bị thừa ra 1 dòng là sao ạ ??? Mong anh và mọi người hiểu đc khúc mắc của em và giải thích dùm em với...

thử lại er+1 thành er+0 xem có sao không, khôgn sao cả, nên đó lệnh viết thừa

Nhưng toàn bộ code đó có thể bỏ đi, vì excel có chức năng subtotal rồi: Data / subtotal...
 
Upvote 0
Em cũng không biết phải diễn đạt bằng cách nào để mọi người dễ hiểu hơn nữa. Tuy nhiên để hiểu đc thắc mắc của em cũng không cần phải đọc hết CODE đâu anh. Dễ hiểu lắm mà anh. Vùng chứa dữ liệu chỉ là từ A2:F21 thôi thế mà trong đoạn CODE er đã bằng 21 rồi tại sao lại phải cộng thêm 1 thế hóa ra mảng arr1 gồm các giá trị trong vùng A2:F22 --->bị thừa ra 1 dòng là sao ạ ??? Mong anh và mọi người hiểu đc khúc mắc của em và giải thích dùm em với...

à mấy cái này cứ để chuyên gia ba xàm trả lời nè
là vì có dòng này
Mã:
If arr1(i, 4) <> arr1(i + 1, 4) Then
đây không phải là chuyện thích hay không thích mà là với cách viết IF như này thì bắt buộc phải lấy dư 1 dòng
bạn xóa thử +1 chỗ er + 1 thử xem sao ?
 
Upvote 0
Để bạn ấy tự bỏ cho hiểu hơn, lúc đó thì mới à à ... ra thế.
bạn đừng lảng sang chuyện của người khác . tôi nhắc lại
bạn nói rằng

thử lại er+1 thành er+0 xem có sao không, khôgn sao cả, nên đó lệnh viết thừa

Nhưng toàn bộ code đó có thể bỏ đi, vì excel có chức năng subtotal rồi: Data / subtotal...

xin bạn giải thích ý nghĩa dòng màu đỏ
 
Upvote 0
bạn đừng lảng sang chuyện của người khác . tôi nhắc lại
bạn nói rằng



xin bạn giải thích ý nghĩa dòng màu đỏ

Tôi trả lời cho người hỏi, không trả lời cho bạn,
Nếu bỏ đi có cách sửa , vì thực chất là nó thừa, Arr1 không chứa dữ liệu nào ở dòng 22 đó.
 
Upvote 0
Tôi trả lời cho người hỏi, không trả lời cho bạn,
Nếu bỏ đi có cách sửa , vì thực chất là nó thừa, Arr1 không chứa dữ liệu nào ở dòng 22 đó.
bạn trả lời cho người khác , nhưng đây là diễn đàn chung , bạn trả lời tầm bậy thì người khác phải lên tiếng
bạn nói rằng bỏ chỗ + 1 của er + 1 đi có sao không ? không sao cả , lệnh đó viết thừa
nhưng sau đó không hề nêu hướng sửa => 1000 người vào đọc thì bao nhiêu người hiểu là chỉ cần xóa chỗ + 1 thì code vẫn chạy đúng ? bạn trả lời xem ?
đây là đang thắc mắc về mảng trong VBA mà lại nêu sang hướng Data/subtotal ?
 
Upvote 0
bạn trả lời cho người khác , nhưng đây là diễn đàn chung , bạn trả lời tầm bậy thì người khác phải lên tiếng
bạn nói rằng bỏ chỗ + 1 của er + 1 đi có sao không ? không sao cả , lệnh đó viết thừa
nhưng sau đó không hề nêu hướng sửa => 1000 người vào đọc thì bao nhiêu người hiểu là chỉ cần xóa chỗ + 1 thì code vẫn chạy đúng ? bạn trả lời xem ?
đây là đang thắc mắc về mảng trong VBA mà lại nêu sang hướng Data/subtotal ?

Bạn đang spam quá nhiều đó, hãy để chủ nhân câu hỏi trả lời, khi người ta ngộ ra điều sai thì người ta mới thấy là sao nó cần và dễ nhớ hơn....

Còn thừa thì là thừa vì nó không cần thiết,... Toàn bộ đoạn code cũng không cần lắm, lời khuyên là dùng công cụ sẵn của Excel thì hay hơn.. ngay cả code thì nếu có công cụ thì code dụng công cụ excel luôn cũng hay hơn nhiều.
 
Upvote 0
Bạn đang spam quá nhiều đó, hãy để chủ nhân câu hỏi trả lời, khi người ta ngộ ra điều sai thì người ta mới thấy là sao nó cần và dễ nhớ hơn....

Còn thừa thì là thừa vì nó không cần thiết,... Toàn bộ đoạn code cũng không cần lắm, lời khuyên là dùng công cụ sẵn của Excel thì hay hơn.. ngay cả code thì nếu có công cụ thì code dụng công cụ excel luôn cũng hay hơn nhiều.
Spam ??? tôi đang nói về những điều nằm ngoài câu hỏi của KhuongVietPhong ????
trả lời tầm bậy rồi nói là đợi người hỏi ngộ ra cái sai ? chết cười với độ chơi lầy của vị "tiên sinh" này
ở đây là đang trau dồi kiến thức về mảng VBA thì lại lái sang vấn đề công cụ Excel ? tôi lại phải tiếp tục chào thua cái độ chơi lầy của vị "tiên sinh" này lần nữa ? =))
 
Upvote 0
Spam ??? tôi đang nói về những điều nằm ngoài câu hỏi của KhuongVietPhong ????
trả lời tầm bậy rồi nói là đợi người hỏi ngộ ra cái sai ? chết cười với độ chơi lầy của vị "tiên sinh" này
ở đây là đang trau dồi kiến thức về mảng VBA thì lại lái sang vấn đề công cụ Excel ? tôi lại phải tiếp tục chào thua cái độ chơi lầy của vị "tiên sinh" này lần nữa ? =))

Rõ là thừa vì không chứa dữ liệu, còn vẫn thích kiểu thừa thì cứ để thôi. Còn phán bài người khác là tầm bậy, thì bạn là trên cả tầm đó rôi - khỏi định nghĩa...
 
Upvote 0
à mấy cái này cứ để chuyên gia ba xàm trả lời nè
là vì có dòng này
Mã:
If arr1(i, 4) <> arr1(i + 1, 4) Then
đây không phải là chuyện thích hay không thích mà là với cách viết IF như này thì bắt buộc phải lấy dư 1 dòng
bạn xóa thử +1 chỗ er + 1 thử xem sao ?
Ý chà chà . Hóa ra nguyên nhân nó nằm tại chổ này If arr1(i, 4) <> arr1(i + 1, 4)...Anh DoveangRose siêu quá. Cảm ơn anh nhiều nghen :-=:-=
 
Upvote 0
thử lại er+1 thành er+0 xem có sao không, khôgn sao cả, nên đó lệnh viết thừa
Tất nhiên là mình đã thử rồi và không được thì mình mới hỏi diễn đàn bạn ạ vì thế chắc không phải thừa như bạn nói đâu.
Tuy nhiên nếu bạn vẫn bảo vệ ý kiến của bạn thì bạn phải chứng minh được cho mọi người thấy rằng nó đúng. Hiện tại mình vẫn chưa thấy bạn làm được điều này. Còn nếu chẳng may đã nhầm rồi thì ta nhận ta sai thôi chứ có gì to tát đâu.... bởi trong cuộc sống nhầm lẫn là chuyện hết sức bình thường mà bạn ....có nhầm lẫn thì bữa sau mới ngộ ra được nhiều điều :-=:-=
Nhưng toàn bộ code đó có thể bỏ đi, vì excel có chức năng subtotal rồi: Data / subtotal...
Mình biết, nhưng ở đây mình đang học về CODE nên muốn dùng CODE để giải quết vấn đề nếu không mình đã chẳng đăng vào box Lập trình với Excel

 
Lần chỉnh sửa cuối:
Upvote 0
Mình có ví dụ, có thể là vừa tầm với bạn đây:

Như vậy là với BT trên ta không nhất thiết phải sử dụng Redim.
Tuy nhiên em vẫn chưa thấy được tầm quan trọng của nó.
Bây giờ mọi người có thể cho em 1 ví dụ nào đơn giản mà bắt buộc phải dùng đến Redim được không ạ để em thực sự thấy được sự cần thiết -phải có nó

Giả dụ chúng ta có bảng đơn giá của các nhà cung cấp cho các mã mặt hàng như hình (Bảng dữ liệu có màu nền trong hình)
Giờ đây ta muốn lập bảng dữ liệu khác hơn, chỉ gồm 3 cột
Để làm việc này, mình đã viết 2 hàm người dùng như sau:

PHP:
Option Explicit
Dim Arr(), Dg As Long
Dim rDL As Range, rNCC As Range
Function XoayBang(DuLieu As Range, NCC As Range)
 Dim Cot As Byte, W As Byte, Tmp As Byte, J As Byte
  
 Dg = DuLieu.Rows.Count:                            Cot = NCC.Cells.Count
3 ReDim Arr(1 To Dg * Cot, 1 To 3)
 Set rDL = DuLieu:                                  Set rNCC = NCC
 For J = 1 To Cot
    Tmp = GPE((J - 1) * Dg + 1, J * Dg, J)
 Next J
8 XoayBang = Arr()
 Erase Arr():                                       Set rDL = Nothing
End Function
Mã:
[b]
Function GPE(BD As Byte, KT As Byte, STT As Byte)[/b]
 Dim J As Integer, Tmp As Long
 
 Tmp = Dg * (STT - 1)
 For J = BD To KT
4    Arr(J, 1) = rDL(1).Offset(J - BD).Value
    Arr(J, 2) = rDL(2).Offset(J - BD).Value
6    Arr(J, 3) = rNCC(STT).Value
 Next J
 GPE = J
[b]End Function [/b]

Ở đây mình fải khai báo biến mảng dùng chung Arr() (cho 2 hàm người dùng)
Bạn chỉ cần chú í các dòng lệnh có đánh số sẽ có thể rõ vấn đề hơn.

Những mong ít nhiều hỗ trợ được bạn fần nào & chúc vui!
 

File đính kèm

  • ChuyenVi.JPG
    ChuyenVi.JPG
    53.9 KB · Đọc: 65
Upvote 0
Tất nhiên là mình đã thử rồi và không được thì mình mới hỏi diễn đàn bạn ạ vì thế chắc không phải thừa như bạn nói đâu.
Tuy nhiên nếu bạn vẫn bảo vệ ý kiến của bạn thì bạn phải chứng minh được cho mọi người thấy rằng nó đúng. Hiện tại mình vẫn chưa thấy bạn làm được điều này. Còn nếu chẳng may đã nhầm rồi thì ta nhận ta sai thôi chứ có gì to tát đâu.... bởi trong cuộc sống nhầm lẫn là chuyện hết sức bình thường mà bạn ....có nhầm lẫn thì bữa sau mới ngộ ra được nhiều điều :-=:-=

Mình biết, nhưng ở đây mình đang học về CODE nên muốn dùng CODE để giải quết vấn đề nếu không mình đã chẳng đăng vào box Lập trình với Excel


vậy thì xem đi, chỉ sửa theo code của bạn thui (còn code này còn nhiều điểm cần gọn hơn)

Mã:
Sub TaoTotal01()

Dim er&, i&, k&, ir&
Dim arr1, arr2

With Sheets("Data")
  er = .Cells(65000, 1).End(3).Row ' er = 21
  arr1 = .Range("A2:F" & er).Value  ' tai sao phai cong them 1 moi duoc ??????
End With

ReDim arr2(1 To UBound(arr1) * 2, 1 To 6) 'co the thay bang: arr2(1 to 26, 1 to 6)

Dim n&
Dim bo As Boolean
n = UBound(arr1)
s = 0: ir = 0 ' gan s =0 va ir = 0
For i = 1 To n  ' i chay tu 1 den 20
  s = s + 1
  ir = ir + 1
  arr2(s, 1) = ir ' phan tu dong s cot 1 cua mang 2 = ir
  
  For k = 2 To 6
    arr2(s, k) = arr1(i, k) 'phan tu dong s cot k cua mang 2 = pt dong i cot k mang 1
  Next k
  
  
  If i < n Then
        bo = arr1(i, 4) <> arr1(i + 1, 4)
  Else: bo = True:  End If
  
  If bo Then ' Neu pt dong i cot 4 <> pt dong i+1 cot 4
    s = s + 1
    arr2(s, 6) = "=SUbtotal(9,R[-1]C:R[-" & ir & "]C)"
    arr2(s, 3) = "Cong"
    ir = 0
  End If
  
Next i
arr2(s + 1, 3) = "Tong cong"
arr2(s + 1, 6) = "=SUbtotal(9,R[-" & s & "]C:R[-1]C)"

With Sheets("TH")
  .[A2].Resize(s + 1, 6).Value = arr2
End With

End Sub
 
Upvote 0
vậy thì xem đi, chỉ sửa theo code của bạn thui (còn code này còn nhiều điểm cần gọn hơn)

Mã:
Sub TaoTotal01()

Dim er&, i&, k&, ir&
Dim arr1, arr2

With Sheets("Data")
  er = .Cells(65000, 1).End(3).Row ' er = 21
  arr1 = .Range("A2:F" & er).Value  ' tai sao phai cong them 1 moi duoc ??????
End With

ReDim arr2(1 To UBound(arr1) * 2, 1 To 6) 'co the thay bang: arr2(1 to 26, 1 to 6)

[COLOR=#ff0000][B]Dim n&
Dim bo As Boolean[/B][/COLOR]
n = UBound(arr1)
s = 0: ir = 0 ' gan s =0 va ir = 0
For i = 1 To n  ' i chay tu 1 den 20
  s = s + 1
  ir = ir + 1
  arr2(s, 1) = ir ' phan tu dong s cot 1 cua mang 2 = ir
  
  For k = 2 To 6
    arr2(s, k) = arr1(i, k) 'phan tu dong s cot k cua mang 2 = pt dong i cot k mang 1
  Next k
  
  
  [COLOR=#ff0000][B]If i < n Then
        bo = arr1(i, 4) <> arr1(i + 1, 4)
  Else: bo = True:  End If
  
  If bo Then[/B][/COLOR] ' Neu pt dong i cot 4 <> pt dong i+1 cot 4
    s = s + 1
    arr2(s, 6) = "=SUbtotal(9,R[-1]C:R[-" & ir & "]C)"
    arr2(s, 3) = "Cong"
    ir = 0
  End If
  
Next i
arr2(s + 1, 3) = "Tong cong"
arr2(s + 1, 6) = "=SUbtotal(9,R[-" & s & "]C:R[-1]C)"

With Sheets("TH")
  .[A2].Resize(s + 1, 6).Value = arr2
End With

End Sub

OK. Trước tiên rất cám ơn bạn vì đã tham gia tranh luận rất nhiệt tình. Tuy nhiên, đọc CODE của bạn mình cũng hiểu được thực chất bạn đã dùng thêm hàm IF để ngăn cho câu lệnh If arr1(i, 4) <> arr1(i + 1, 4) - khi i đạt đến giá trị 20 không xảy ra được nên CODE chạy ngon lành mà không báo lỗi gì. Nhưng như vậy mình thấy có khi cứ làm như ban đầu CODE của mình thì sẽ ngắn gọn hơn chút tất nhiên cách của bạn cũng là 1 ý tưởng hay và qua đó cũng thể hiện bạn có hiểu vấn đề rắc rối của mình.

Tuy nhiên ban đầu bạn lại nói là đoạn "er +1 trong CODE của mình thì +1 là thừa, có thể bỏ đi" (mình dẫn y nguyên câu nói của bạn không thêm không bớt) như vậy là vẫn SAI. Bởi nếu đã là thừa thì ta có quền vứt quách nó đi và không phải thêm bất cứ gì nữa mà vẫn chẳng ảnh hưởng gì đến CODE --> đó thì đó mới gọi là THỪA. Nhưng ở đây của bạn, bạn vứt bỏ nó đi tuy nhiên bạn lại phải viết thêm 1 đoạn CODE khác vào cho nó (đoạn bôi đỏ trong CODE của bạn) thì nó mới chạy được thì đó không gọi là THỪA được.Bởi bạn đã tác động vào nó làm cho nó không còn bản chất như ban đầu nữa...đúng không ?? Như vậy làm sao gọi là thừa được...đúng chưa bạn ??? Bạn phải công nhận điều này nhé.:-=:-=

Cảm ơn các anh/bạn đã tham gia trả lời vào câu hỏi này. Hi vọng anh em không vì 1 bài tập nhỏ này mà bất đồng quan điểm. Cuối cùng chúc mọi người vui vẻ :-=:-=
 
Lần chỉnh sửa cuối:
Upvote 0
Tuy nhiên ban đầu bạn lại nói là đoạn "er +1 trong CODE của mình thì +1 là thừa, có thể bỏ đi" (mình dẫn y nguyên câu nói của bạn không thêm không bớt) như vậy là vẫn SAI.

Cứ xem như cách hiểu vấn đề mỗi người mỗi khác. Đa số chúng ta nói THỪA đồng nghĩa là CÓ THỂ BỎ ĐI nhưng người khác hiểu THỪA là thứ gì đó... ai mà biết được
Nói chung cuối cùng bạn hiểu ra vấn đề là đủ rồi
--------------------------------
(Ba ông cộng lại, ai mà chịu nỗi --=0)
 
Upvote 0
Bài của bạn không hẳn là bài toán mảng thuần tuý. Có thể nói nó thuộc về bài "thuật toán tính tổng theo nhóm".

Lô gic của bài toán tính tổng là duyệt mảng, thấy hết nhóm thì tính tổng và bắt đầu nhóm mới. Vấn đề căn bản của bài toán này xoay quanh việc làm thế nào để nhận ra là đã đến cuối nhóm và bắt đầu nhóm mới.

Để thực hiện việc "nhận thức hết nhóm" bài của bạn dùng thuật toán "nhìn trước". Vì thuật toán này nhìn trước sử dụng phân tử i+1 cho nên sẽ bị error khi i là phần tử cuối mảng. Lý do đơn giản là phần tử cuối mảng không có phần tử kế tiếp nó.
Để khắc phục lỗi này, bạn đã dùng phương pháp giản dị là cộng thêm 1 phần tử giả, đi sau phần tử cuối cùng. Lưu ý tôi dùng từ "giản dị".

Cách của bạn không sai, và tôi có nhấn mạnh là nó rất đơn giản. Tuy nhiên, theo bình diện lập trình lý thuyết (lưu ý ở đây tôi dùng từ "lý thuyết") thì tạo phần tử giả là chuyện bất đắc dĩ mới phải dùng tới. Tôi nghĩ lý do bạn kia nói "thừa" là chỗ đó.

Tôi chỉ giải thích nghĩa của từ "thừa" thôi, không chủ ý bàn thêm về thuật toán tính tổng nhóm. Bởi vì ưu khuyết điểm của các thuật toán còn tuỳ thuuộc vào tình huống.

Chú: bạn có cách đặt tên biến hơi khó hiểu.
1. tên er thường thường giành cho lỗi. Đọc thấy er, tôi chới với không hiểu bạn muốn bắt lỗi chỗ nào.
2. trong trường hợp chạy 2 mảng song song như thế, bạn dùng chỉ số s và ir nó hơi khó hiểu và khó kiểm soát. Nếu bạn đã dùng arr1 và arr2 thì tại sao khong dùng i1 và i2, hay rw1 và rw2
3. thường thường k dùng để làm số đếm. Nếu cần chỉ số cột thì người ta dùng j hoặc cot, col
Tôi chỉ nói theo kinh nghiệm lập trình thôi. Đặt tên biến là quyền của bạn, cái nào VBA không giành làm từ khoá riêng thì bạn có quyền dùng. Bạn có quyền cọi cột là dòng và range là sh VBA cũng hiểu tuốt.
 
Upvote 0
Em xin cảm ơn và tiếp thu những góp ý của tác giả Vetmini, bài toán này thực chất em đã làm được bằng cách dùng For-Next nhưng vì em đang học về mảng nên muốn chuyển nó sang Array để thực hành luôn. Xin nói thêm, file trên và CODE trên là do em lượm được của tác giả ThuNghi về mổ xẻ ra để ngâm cứu. Thú thật là em cũng thấy không "hào hứng" lắm với cách đặt tên biến của tác giả nhưng vì CODE khá dài nên em chỉ đổi tên lại 2 biến sarr rarr của tác giả tương ứng thành arr1arr2 cho dễ hiểu còn mấy cái er, ir ,,.. thì thôi em ngại quá chẳng buồn chuyển nữa..Tóm lại là em cũng hổng quen với kiểu gọi tên biến thế này đâu.
 
Lần chỉnh sửa cuối:
Upvote 0
OK. Trước tiên rất cám ơn bạn vì đã tham gia tranh luận rất nhiệt tình. Tuy nhiên, đọc CODE của bạn mình cũng hiểu được thực chất bạn đã dùng thêm hàm IF để ngăn cho câu lệnh If arr1(i, 4) <> arr1(i + 1, 4) - khi i đạt đến giá trị 20 không xảy ra được nên CODE chạy ngon lành mà không báo lỗi gì. Nhưng như vậy mình thấy có khi cứ làm như ban đầu CODE của mình thì sẽ ngắn gọn hơn chút tất nhiên cách của bạn cũng là 1 ý tưởng hay và qua đó cũng thể hiện bạn có hiểu vấn đề rắc rối của mình.

Tuy nhiên ban đầu bạn lại nói là đoạn "er +1 trong CODE của mình thì +1 là thừa, có thể bỏ đi" (mình dẫn y nguyên câu nói của bạn không thêm không bớt) như vậy là vẫn SAI. Bởi nếu đã là thừa thì ta có quền vứt quách nó đi và không phải thêm bất cứ gì nữa mà vẫn chẳng ảnh hưởng gì đến CODE --> đó thì đó mới gọi là THỪA. Nhưng ở đây của bạn, bạn vứt bỏ nó đi tuy nhiên bạn lại phải viết thêm 1 đoạn CODE khác vào cho nó (đoạn bôi đỏ trong CODE của bạn) thì nó mới chạy được thì đó không gọi là THỪA được.Bởi bạn đã tác động vào nó làm cho nó không còn bản chất như ban đầu nữa...đúng không ?? Như vậy làm sao gọi là thừa được...đúng chưa bạn ??? Bạn phải công nhận điều này nhé.:-=:-=

Cảm ơn các anh/bạn đã tham gia trả lời vào câu hỏi này. Hi vọng anh em không vì 1 bài tập nhỏ này mà bất đồng quan điểm. Cuối cùng chúc mọi người vui vẻ :-=:-=

Tóm lại thừa là thừa , bạn không cần lý luận nhiều đừng theo kiểu các trẻ trâu ngoài đời kia; nâng tầm mình lên, tôi giúp người khác là cho họ cần câu không phải con cá đã rán. E rằng bạn còn cần tìm hiểu thêm nữa mới ngộ ra.

P/S: lần sau bạn trích code của ai thì cần ghi rõ nguồn và tên của tác giả đó, không phải 1 hồi rồi nói code của người khác còn nói không thích.
 
Lần chỉnh sửa cuối:
Upvote 0
Tóm lại thừa là thừa , bạn không cần lý luận nhiều đừng theo kiểu các trẻ trâu ngoài đời kia; nâng tầm mình lên, tôi giúp người khác là cho họ cần câu không phải con cá đã rán. E rằng bạn còn cần tìm hiểu thêm nữa mới ngộ ra.
Chỉ sợ là cần câu của bạn không có lưỡi câu, cho người ta người ta câu hoài không có cá thì thôi cho con cá còn tốt hơn.
 
Upvote 0
Chỉ sợ là cần câu của bạn không có lưỡi câu, cho người ta người ta câu hoài không có cá thì thôi cho con cá còn tốt hơn.

Cám ơn bạn. CÒn tùy thuộc người câu thế nào, và từ từ đầu tiên phải vót cần trước đừng nghĩ đến lưỡi vội. Như kiêu người bệnh phải uống thuốc từ từ, tránh sốc.
 
Upvote 0
Qua 1 số bài viết ở trên. Tôi e rằng bạn mới là ngừoi có lối trẻ trâu ấy. Mới cần tìm hiểu thêm...
thôi đừng nói về những chuyện không liên quan đến topic
cuộc sống muôn màu mà , trên trường lớp cũng đâu thiếu các giáo viên giảng bài vớ vẩn cho học trò về áp dụng vô làm bài tập ra kết quả sai bét , phụ huynh hỏi tại sao thì giáo viên giải thích đơn giản : tôi cố tình giảng sai để giúp các em nó tự ngộ ra chỗ sai , giúp nhớ bài lâu . Diễn đàn cũng vậy . Không nên phí thời gian tranh cãi đúng sai với những người này . Để tự có công luận phán xét
Đi giúp người khác mà trong lòng họ tự hứa với lòng lần sau thà không biết làm chứ không muốn nghe thêm lời nào của vị "chuyên gia" này thì đó cũng là cách sống , bạn không cấm được các "chuyên gia" này
 
Upvote 0
/-)ừng có bề trên, bố thí kiến thức theo kiểu bố thí nhỏ giọt cho kẻ ăn mày!

Chuyện này cũng có thể coi cho cần câu để câu cá ngừ đại dương trên biển hồ!
 
Upvote 0
Đây là diễn đàn học hỏi. Bàn chuyện đúng sai thì nên nói rõ. Nói kiểu cộc lốc chả ai học được gì cả.

Tôi lập lại lời tôi đã nói ở bài trước: nếu nói theo quan niệm lập trình lý thuyết thì tạo thêm 1 dòng cho mảng để tránh lỗi cuối mảng là phương pháp gượng ép.

Với hầu hết các ngôn ngữ dạng "thấp" hơn, ngưởi ta có thể test cuối mảng và đọc dòng kế trong cùng một câu lô gic.
IF (cuối mảng HOẶC khác dòng kế tiếp)
Lô gic được đặt theo kiểu thông minh, nếu điều kiện cuối mảng thoả rồi thì nó không tiếp tục tính điều kiện kế. Vì vậy tránh được lỗi quá chỉ số.

Nhưng VBA không cho phép làm như vậy. Đối với VBA, tất cả các biểu thức con nằm trong biểu thức lô gic chính đều được tính. Vì vậy, cách thêm 1 dòng giả tuy hơi "nghịch đạo" 1 chút, nhưng lại là cách giản dị nhất.
 
Upvote 0
Chào mọi người ! Em có bài tập này cần tư vấn. Em đã giải được bằng đoạn CODE sau:
PHP:
Option Explicit
Sub dic2()
Dim dic, i, j, k, mang(1 To 6, 1 To 6)
Set dic = CreateObject("Scripting.Dictionary")
For i = 2 To 21
If Not dic.exists(Cells(i, 2).Value) Then
   j = j + 1
   mang(j, 1) = j
   dic.Add Cells(i, 2).Value, ""
   For k = 2 To 6
      mang(j, k) = Cells(i, k).Value
   Next k
End If
Next i
  Range("J9").Resize(dic.Count, 6) = mang
End Sub
Khi khai báo mảng , nếu thay vì viết như trên nếu em chỉ viết là : mang thì sẽ bị báo lỗi. Tuy nhiên cái khó nằm ở con số 6 kia nếu như ta không biết trước kết quả thì làm sao biết là viết số nào vào chổ ấy, với chiều cột thì mình còn đếm được là 6 chứ với chiều hàng thì mình biết đếm sao ???, hổng lẽ lại khai báo là mang( 1 to 21, 1 to 6) .

Vậy xin hỏi mọi người có cách nào để giải quyết được vấn đề trên không ạ. Em xin cảm ơn !
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Chào mọi người ! Em có bài tập này cần tư vấn. Em đã giải được bằng đoạn CODE sau:
PHP:
Option Explicit
Sub dic2()
Dim dic, i, j, k, mang(1 To 6, 1 To 6)
Set dic = CreateObject("Scripting.Dictionary")
For i = 2 To 21
If Not dic.exists(Cells(i, 2).Value) Then
   j = j + 1
   mang(j, 1) = j
   dic.Add Cells(i, 2).Value, ""
   For k = 2 To 6
      mang(j, k) = Cells(i, k).Value
   Next k
End If
Next i
  Range("J9").Resize(dic.Count, 6) = mang
End Sub
Khi khai báo mảng , nếu thay vì viết như trên nếu em chỉ viết là : mang thì sẽ bị báo lỗi. Tuy nhiên cái khó nằm ở con số 6 kia nếu như ta không biết trước kết quả thì làm sao biết là viết số nào vào chổ ấy, với chiều cột thì mình còn đếm được là 6 chứ với chiều hàng thì mình biết đếm sao ???, hổng lẽ lại khai báo là mang( 1 to 21, 1 to 6) .

Vậy xin hỏi mọi người có cách nào để giải quyết được vấn đề trên không ạ. Em xin cảm ơn !

Đi tìm bài về mảng động, sẽ thấy cách giải quyết. mangr động là loại mảng có số phần tử thay đổi được.

Đại khái là khi khai báo thì dùng hai dấu ngoặc trống, và khi cho kích thước thì dùng lệnh Redim:

Dim mang() ' dấu ngoặc trống, không có tham số, báo cho VBA biết biến này là loại mảng động
...
Dim lb1 As Long, ub1 As Long, lb2 As Long, ub2 As Long
lb1 = 1: ub1 = 21: lb2 = 1: ub2 = 6 ' có thể dùng biểu thức để gán trị cho các biến này
ReDim mang(lb1 To ub1, lb2 To ub2) ' kích thước mảng được định ở đây
 
Upvote 0
Dim lb1 As Long, ub1 As Long, lb2 As Long, ub2 As Long
lb1 = 1: ub1 = 21: lb2 = 1: ub2 = 6 ' có thể dùng biểu thức để gán trị cho các biến này
ReDim mang(lb1 To ub1, lb2 To ub2) ' kích thước mảng được định ở đây

Vấn đề của em là làm cách nào để biết được chiều dọc của mảng có 6 hàng mà không phải dùng đến số 21 í

hổng lẽ lại khai báo là mang( 1 to 21, 1 to 6) .

!

Và cho em xin hỏi thêm , em viết lại như vầy mà cũng không đúng là sao ạ:
PHP:
Option Explicit
Sub dic2()
Dim dic, i, j, k, mang()
Set dic = CreateObject("Scripting.Dictionary")
For i = 2 To 21
If Not dic.exists(Cells(i, 2).Value) Then
   j = j + 1
   mang(j, 1) = j
   dic.Add Cells(i, 2).Value, ""
   For k = 2 To 6
      mang(j, k) = Cells(i, k).Value
   Next k
End If
Next i
  ReDim mang(1 To dic.Count, 1 To 6)
  Range("J9").Resize(dic.Count, 6) = mang()
End Sub
 
Upvote 0
Vấn đề của em là làm cách nào để biết được chiều dọc của mảng có 6 hàng mà không phải dùng đến số 21 í



Và cho em xin hỏi thêm , em viết lại như vầy mà cũng không đúng là sao ạ:

1/ Để biết được có 6 hàng thì bạn có thể làm như sau:

- B1: Add tất cả các phần tử vào Dic
- B2: ngay sau khi add Redim lại mảng theo số hàng là dic.Count


2/ Code của bạn sai vì bạn chưa khai báo ubound của mảng mà bạn đã add dữ liệu vào mảng. Bạn hãy làm như (1) để có kết quả đúng
 
Upvote 0
Bạn chưa biết số dòng dữ liệu của mảng sẽ là bao nhiêu. Như vậy bạn có 2 cách làm.

1. Như bài #696, nạp dic trước, Redim mang theo dic.count

2. Cứ làm theo code của bạn. Lúc ghi xuống thì dùng dic.count và resize để giới hạn vùng ghi.
Vì bạn không biết trước dic bao lớn trước khi xong vòng lặp cho nên dùng UBound tối đa là đúng rồi.
Để chỉnh code của bạn, chỉ cần nhét thêm dòng
Redim mang(1 to 21, 1 to 6) ngay trước khi bắt đầu sử dụng mảng, trong trường hợp này tức là trước vòng lặp.
Con số 21 có lẽ là giới hạn vùng dữ liệu input của bạn. Như vậy với trường hợp tổng quát, câu Redim bạn áp dụng vào lúc đã tính ra con số vùng dữ liệu.
vd
dim dongCuoi as Long
dongCuoi = công_thức_tính_dòng_cuối
Redim mang(1 to dongCuoi, 1 to 6)
hoặc là
Redim mang(1 to công_thức_tính_dòng_cuối, 1 to 6)
Con số 6 cũng vậy, bạn có thể thay nó bằng công thức tính cột cuối dữ liệu
 
Upvote 0
Vấn đề của em là làm cách nào để biết được chiều dọc của mảng có 6 hàng mà không phải dùng đến số 21 í
bạn có thể khai báo tới mảng tối đa có thể chứa được dữ liệu, trong bài này là 21, nó không chiếm bộ nhớ của bạn là bao.
nếu không thích cách này thì bạn lại tốn thêm thời gian nạp vào DIC và đếm, sau đó mới redim, tính ra thì cũng không lợi bao nhiêu, mà sau này muốn xem lại code phải đọc thêm phần DIC nữa, rất mất thời gian và mất công
 
Upvote 0
Em viết như vầy:
PHP:
Option Explicit
Sub dic2()
Dim dic, i, j, k, mang()
Set dic = CreateObject("Scripting.Dictionary")
For i = 2 To 21
If Not dic.exists(Cells(i, 2).Value) Then
   j = j + 1
   dic.Add Cells(i, 2).Value, ""
   ReDim mang(1 To dic.Count, 1 To 6)
   mang(j, 1) = j
   For k = 2 To 6
      mang(j, k) = Cells(i, k).Value
   Next k
End If
Next i
    Range("J9").Resize(dic.Count, 6) = mang()
End Sub

Thì nó chỉ ra kết quả hàng cuối cùng, khi em thêm từ khóa Preserve vào sau Redim thì lại bị bắt lỗi. Mọi người giúp em thêm lần nữa với ạ. :.,:.,
 
Upvote 0
Em viết như vầy:
PHP:
Option Explicit
Sub dic2()
Dim dic, i, j, k, mang()
Set dic = CreateObject("Scripting.Dictionary")
For i = 2 To 21
If Not dic.exists(Cells(i, 2).Value) Then
   j = j + 1
   dic.Add Cells(i, 2).Value, ""
   ReDim mang(1 To dic.Count, 1 To 6)
   mang(j, 1) = j
   For k = 2 To 6
      mang(j, k) = Cells(i, k).Value
   Next k
End If
Next i
    Range("J9").Resize(dic.Count, 6) = mang()
End Sub

Thì nó chỉ ra kết quả hàng cuối cùng, khi em thêm từ khóa Preserve vào sau Redim thì lại bị bắt lỗi. Mọi người giúp em thêm lần nữa với ạ. :.,:.,
Bạn làm như thế này
Mã:
Option Explicit
Sub dic2()
Dim dic, dicTMP, i, j, k, mang()
Set dic = CreateObject("Scripting.Dictionary")
'===============================================
Set dicTMP = CreateObject("Scripting.Dictionary")
For i = 2 To 21
    'Add du lieu vao Dic
    If Not dicTMP.exists(Cells(i, 2).Value) Then
        dicTMP.Add Cells(i, 2).Value, ""
    End If
Next
'Khai bao mang
ReDim mang(1 To dicTMP.Count, 1 To 6)
'================================================
'Dua du lieu vao mang - Code cua ban
For i = 2 To 21
    If Not dic.exists(Cells(i, 2).Value) Then
        j = j + 1
        mang(j, 1) = j
        dic.Add Cells(i, 2).Value, ""
        For k = 2 To 6
            mang(j, k) = Cells(i, k).Value
        Next k
    End If
Next i
Range("J9").Resize(UBound(mang, 1), 6) = mang()
End Sub
 
Upvote 0
Em viết như vầy:
PHP:
Option Explicit
Sub dic2()
Dim dic, i, j, k, mang()
Set dic = CreateObject("Scripting.Dictionary")
For i = 2 To 21
If Not dic.exists(Cells(i, 2).Value) Then
   j = j + 1
   dic.Add Cells(i, 2).Value, ""
   ReDim mang(1 To dic.Count, 1 To 6)
   mang(j, 1) = j
   For k = 2 To 6
      mang(j, k) = Cells(i, k).Value
   Next k
End If
Next i
    Range("J9").Resize(dic.Count, 6) = mang()
End Sub

Thì nó chỉ ra kết quả hàng cuối cùng, khi em thêm từ khóa Preserve vào sau Redim thì lại bị bắt lỗi. Mọi người giúp em thêm lần nữa với ạ. :.,:.,

1/ Bạn khai báo mang(), nghĩa là khai báo mảng 2 chiều
2/ Mảng 2 chiều khi Redim thì nó tạo lại 1 mảng "trống trơn".
3/ Mảng 2 chiều không thể Preserve.
4/ Bạn muốn thử dùng mảng thì chơi luôn mảng, sao xài Cells() cho "nửa nạc nửa mỡ"?
5/ Mới bước vào "con đường đau khổ" thì phải tập khai báo tường minh các biến, đừng "làm biếng" thành thói quen, dù là code vẫn chạy.
6/ Trường hợp của bạn, dữ liệu có lẽ từ B2 đến F21? Xác định được mảng Data thì dựa vào chiều dọc ngang của mảng Data mà khai báo mang(), dùng mảng thì dù bạn khai bào "dư chút đỉnh" cũng chẳng "bựa" chút nào khi chạy code đâu mà sợ.
6/ Đọc code của bạn có thể xài cái này:
PHP:
Sub dic2()
Dim Dic As Object, i As Long, j As Long, k As Long, sArr(), Mang()
Set Dic = CreateObject("Scripting.Dictionary")
sArr = Range("B2:F21").Value               '<-----------Bằng cách nào đó bạn phải xác định được Range() này'
ReDim Mang(1 To UBound(sArr, 1), 1 To UBound(sArr, 2) + 1)
For i = 1 To UBound(sArr, 1)
    If Not Dic.Exists(sArr(i, 1)) Then
        k = k + 1
        Dic.Add sArr(i, 1), ""
        Mang(k, 1) = k
        For j = 1 To UBound(sArr, 2)
            Mang(k, j + 1) = sArr(i, j)
        Next j
    End If
Next i
Range("J9").Resize(k, UBound(Mang, 2)) = Mang
Set Dic=Nothing
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
...
Thì nó chỉ ra kết quả hàng cuối cùng, khi em thêm từ khóa Preserve vào sau Redim thì lại bị bắt lỗi. Mọi người giúp em thêm lần nữa với ạ

Khi Redim, dữ liệu trong mảng sẽ bị xóa. Vì vậy các dòng trước đó sẽ trống trơn.
Khi bạn biết thêm từ khóa Preserve vào thì có lẽ bạn đã biết tại sao nó chỉ cho ra dòng cuối cùng.

Tuy nhiên, cái bạn quên để ý là Redim Preserve chỉ cho phép đổi chiều cuối cùng. Mảng của bạn 2 chiều cho nên nó chỉ cho đổi chiều thứ 2. Điều này đã có nhiều bài bàn cãi qua, và tôi cũng có từng giải thích tại sao VBA lại đặt ta luật như vậy.

Trong bài trước đó, tôi có đề nghị là bạn Redim trước khi bắt đầu vòng lặp. Không phải là không có lý do.

Theo lô gic bài toán, vòng lặp của bạn biết trước là nó sẽ chạy 21 lần, không có lý do gì mảng của bạn không thể redim trước là 21 dòng. Nếu bạn thay đổi số cuối vòng lặp bằng bất cứ cái gì thì cũng có thể thay redim mảng của bạn bằng cái ấy.
 
Upvote 0
quote_icon.png
Nguyên văn bởi Ba Tê

3/ Mảng 2 chiều không thể Preserve.

mình xin phép nghi ngờ điều này

Bạn kia chỉ nói vắn tắt thôi. Bắt bẻ làm gì.
Cần bổ xung thì nói thẳng ra. Úp mở chỉ mất công tranh cãi.
 
Upvote 0
Hình như vẫn Preserve được nhưng chỉ có tác dụng với chiều thứ nhất thì phải

mảng một chiều thì có thể preverse tăng thêm dòng
mảng 2 chiều chỉ có thể preverse tăng thêm cột
(tôi xài từ "dòng", "cột", không biết chính xác trong mảng người ta gọi nó là cái gi.....hihiih)
 
Upvote 0
Đầu xuân, năm mới. Tôi xin được kính chúc các anh chị biên tập viên và các thầy giáo của diễn đàn GPE lời chúc sức khỏe hạnh phúc và thành công. Tôi có một vấn đề này mong các anh chị giúp đỡ viết cho code của nút NHAP. Các yêu cầu đã ghi rõ trong file đính kèm.
Xin trân trọng cảm ơn!

Tôi không biết đăng ở đâu. Nếu có gì sai xin được sự cảm thông của Anh chị em và các thầy nhé!
 

File đính kèm

Upvote 0
Đầu xuân, năm mới. Tôi xin được kính chúc các anh chị biên tập viên và các thầy giáo của diễn đàn GPE lời chúc sức khỏe hạnh phúc và thành công. Tôi có một vấn đề này mong các anh chị giúp đỡ viết cho code của nút NHAP. Các yêu cầu đã ghi rõ trong file đính kèm.
Xin trân trọng cảm ơn!

Tôi không biết đăng ở đâu. Nếu có gì sai xin được sự cảm thông của Anh chị em và các thầy nhé!

Thứ nhất: Bài của bạn thuộc diện xen ngang; Nó có thể bị xóa cùng với bài này của mình.

Bài này iêu cầu làm bằng macro; Nên nó fải ở trong mục "lập trình"

Điều nữa: Thiết kế trang tính CSDL của bạn sẽ có vấn đề không tốt khi vận hành sau này;
Nếu là mình thì mình tách ra làm 2 bảng dữ liệu như sau:
Trang chính có tên là "Chung" gồm các trường/cột sau:
[STT] Dùng để ghi STT các fiếu
[Mã khóa] - Mã này để liên hệ với trang tính "chi tiết"
[Số fiếu] - Là số fiếu nhập của bạn
[Người giao]
[Người nhận]
[Ghi chú]

Trang thứ hai là có tên là "Chi tiết", gồm các trường
[STT] như trên
[Mã khóa] - Như trên
[Mã hàng]
[Tên hàng]
[Đơn vị tính]
[Đơn giá]
[Số lượng]
[Thành tiền]
Ở trang chi tiết này ta ghi mỗi loại hàng của từng hóa đơn 1 dòng;
Như vậy 2 trang tính này có mối quan hệ 1 - nhiều với nhau
 
Upvote 0
Cảm ơn bác SA_DQ nhiều!. về cấu trúc dữ liệu thị đây chỉ là file ví dụ. Tôi đã làm file có cả mã hàng, tên hàng hóa...
Mong các bác viết hộ phần code để nhập vào sheet tổng hợp.
Cảm ơn!
 
Upvote 0
Tôi dự định chỉ phân quyền cho những user có tên trong danh sách và tại các máy được chỉ định (việc này sẽ được kiểm tra khi file được mở) tôi nghĩ nên dùng mảng và for để tìm trong mảng (nếu tìm không thấy thì đóng file lại), nhưng không biết phải khai báo như thế nào và tìm ra làm sao... Mong các anh chị chỉ giáo.
 

File đính kèm

Upvote 0

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

Back
Top Bottom