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

Liên hệ QC

viehoai

Thành viên gắn bó
Tham gia
22/5/09
Bài viết
2,600
Được thích
2,907
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ị
 
Lại là cái tâm á sư phụ Vẹt nhỏ, tại hôm trước xem trên youtube mấy anh bảo là anh Kiều Phong này có rút gọn một số chiêu thức trong Giáng Long Thập Bát Chưởng.


Nghĩa là anh ta hết mục đích sống, sống không biết để làm gì.

Cháu đoán bác gái không có nick trên gpe này, ahihi.
Cả ba đều lạc lối.
1. Cần hiểu rõ thế nào là "rút gọn". Triết lý "một bao mười" mãi đến tập sau này là "Tiếu Ngạo Giang Hồ" mới ra. Độc Cô Cửu Kiếm chỉ có 9 chiêu, bao hết luôn thập bát ban võ nghệ, và diễn ra liên miên bất tuyệt.
Nhưng nên nhớ, Lệnh Hồ Xung đã lúng túng khi phải đối phó với Tịch Tà Kiếm Pháp. Suy ra khi đối phó ma đạo ở điểm quái dị cần bình tâm.
Điếu này KD đã mở trước trong Cô Gái Đồ Long. Trương Giáo Chủ thần công vô địch (*), lại thêm tuyệt tác Thái Cực Quyền và lời dạy "quên sạch" của Trương Tam Phong nhưng vẫn lúng túng khi đối diện với lói đánh quái dị của Càn Khôn Đại Nã Di Thức Pháp.

2. Chỉ có phim mới diễn tả là anh ta hết ý sống. Cần câu nước mắt khán giả mà. Nếu y thực thế thì chưa xứng đáng được tôi gọi là "tâm".
Con người của y cao hơn mức ấy. Y đem cái chết của mình ra để mua lại yên lành cho dân Tống. Y hăm doạ Liêu Vương phải lui binh. Và vì phạm lỗi "quân thần" đối với nước Liêu nên y không thể sống. Tam cương ngũ thường mà.

3. tôi cũng theo đạo "phu vi phụ cương". Chỉ là tôi xem từ "cương" là cái đạo lý mà người chủ gia đình phải làm gương. Bà xã tôi không có nít niếc gì hết. Nhưng bà ấy biết rõ tôi làm gì.

Xin lỗi quý vị khác trên diễn đàn, và đặc biệt thớt này. Tôi diễn triết đạo chuyện kiếm hiệp Hồng Kông hơi dài do tôi thực sự thấy nó có sự liên hệ giữa "triết lý võ học" của Kim Dung với lý thuyết và ứng dụng cấu trúc mảng (và các cấu trúc khác như Collection, Dictionary, ...) trong VBA.
 
Upvote 0
Xin lỗi quý vị khác trên diễn đàn, và đặc biệt thớt này. Tôi diễn triết đạo chuyện kiếm hiệp Hồng Kông hơi dài do tôi thực sự thấy nó có sự liên hệ giữa "triết lý võ học" của Kim Dung với lý thuyết và ứng dụng cấu trúc mảng (và các cấu trúc khác như Collection, Dictionary, ...) trong VBA.
Cám ơn anh. Tuy nhiên cũng nên cắt ngang ở đây
 
Upvote 0
Em muốn check cái báo cáo tình hình sử dụng HĐ của hệ thống, em đã tự viếtt code "Dic" nhưng chỉ đúng khi số HĐ của các dải không trùng nhau. Khi trùng nhau thì đang bị trả kết quả sai.
Em là member mới, chỉ học vẹt code. Kính nhờ các thầy GPE hỗ trợ với ạ. em gửi file đính kèm.
Cám ơn GPE!!!
Kết quả mong muốn--->
- Hiện ra số dải: cố ký hiệu
- Hiện ra số đầu dải: số đầu tiên của mỗi dải ( dấu x)
- Hiện ra số cuối dải: Số kết thúc dải
- Hiện ra số hủy: Số không xuất hiện trong mỗi dải
Note: HĐ đã tự sắp xếp theo thứ tự liên tục rồi, dữ liệu khá nhiều dải và lớn
 

File đính kèm

  • BCHD.xlsm
    20.2 KB · Đọc: 25
Upvote 0
Em muốn check cái báo cáo tình hình sử dụng HĐ của hệ thống, em đã tự viếtt code "Dic" nhưng chỉ đúng khi số HĐ của các dải không trùng nhau. Khi trùng nhau thì đang bị trả kết quả sai.
Em là member mới, chỉ học vẹt code. Kính nhờ các thầy GPE hỗ trợ với ạ. em gửi file đính kèm.
Cám ơn GPE!!!
Kết quả mong muốn--->
- Hiện ra số dải: cố ký hiệu
- Hiện ra số đầu dải: số đầu tiên của mỗi dải ( dấu x)
- Hiện ra số cuối dải: Số kết thúc dải
- Hiện ra số hủy: Số không xuất hiện trong mỗi dải
Note: HĐ đã tự sắp xếp theo thứ tự liên tục rồi, dữ liệu khá nhiều dải và lớn
Dữ liệu được sort theo ký hiệu và số hóa đơn
Mã:
Public Sub XYZ()
  Dim sArr(), Res()
  Dim i As Long, sRow As Long, k As Long, KyHieu As String

  With Sheet2
    i = .Range("A" & Rows.Count).End(xlUp).Row
    If i < 2 Then MsgBox ("Khong co du lieu"): Exit Sub
    sArr = .Range("A2:B" & i + 1).Value 'Lay du 1 dong
  End With
  sRow = UBound(sArr, 1) - 1
  ReDim Res(1 To sRow, 1 To 4)
  For i = 1 To sRow
    If KyHieu <> sArr(i, 1) Then
      KyHieu = sArr(i, 1)
      k = k + 1
      Res(k, 1) = sArr(i, 1)
      Res(k, 2) = sArr(i, 2)
    ElseIf sArr(i, 2) > sArr(i - 1, 2) + 1 Then
      For r = sArr(i - 1, 2) + 1 To sArr(i, 2) - 1
        Res(k, 4) = Res(k, 4) & ";" & r
      Next r
    End If
    If KyHieu <> sArr(i + 1, 1) Then
      Res(k, 3) = sArr(i, 2)
      If Res(k, 4) <> Empty Then Res(k, 4) = Mid(Res(k, 4), 2, Len(Res(k, 4)))
    End If
  Next i
  With Sheet2
    .Range("F2:I1000").ClearContents
    .Range("F2").Resize(k, 4) = Res
    MsgBox ("Chuc mung ban")
  End With
End Sub
 
Upvote 0
Em muốn check cái báo cáo tình hình sử dụng HĐ của hệ thống, em đã tự viếtt code "Dic" nhưng chỉ đúng khi số HĐ của các dải không trùng nhau. Khi trùng nhau thì đang bị trả kết quả sai.
Em là member mới, chỉ học vẹt code. Kính nhờ các thầy GPE hỗ trợ với ạ. em gửi file đính kèm.
Cám ơn GPE!!!
Kết quả mong muốn--->
- Hiện ra số dải: cố ký hiệu
- Hiện ra số đầu dải: số đầu tiên của mỗi dải ( dấu x)
- Hiện ra số cuối dải: Số kết thúc dải
- Hiện ra số hủy: Số không xuất hiện trong mỗi dải
Note: HĐ đã tự sắp xếp theo thứ tự liên tục rồi, dữ liệu khá nhiều dải và lớn
Bạn thử.
Mã:
Sub laydulieu()
   Dim i As Long, lr As Long, a As Long, b As Long, arr, kq, dk As String, j As Long
   With Sheets("baocao")
        lr = .Range("A" & Rows.Count).End(xlUp).Row
        arr = .Range("A2:C" & lr).Value
        ReDim kq(1 To UBound(arr), 1 To 4)
        For i = 1 To UBound(arr)
            If dk <> arr(i, 1) Then
               If a Then
                 If Len(kq(a, 4)) > 0 Then kq(a, 4) = Right(kq(a, 4), Len(kq(a, 4)) - 1)
               End If
               dk = arr(i, 1)
               a = a + 1
               kq(a, 1) = arr(i, 1)
               kq(a, 2) = arr(i, 2)
               kq(a, 3) = arr(i, 2)
               b = arr(i, 2)
            Else
               For j = b + 1 To arr(i, 2) - 1
                   kq(a, 4) = kq(a, 4) & "," & j
               Next j
               b = arr(i, 2)
               kq(a, 3) = arr(i, 2)
            End If
        Next i
        .Range("E2:H100").ClearContents
        If Len(kq(a, 4)) > 0 Then kq(a, 4) = Right(kq(a, 4), Len(kq(a, 4)) - 1)
        If a Then .Range("E2:H2").Resize(a).Value = kq
   End With
End Sub
 
Upvote 0
Cảm ơn 2 thầy HieuCD và snow25 ạ, em thử 2 code của bác đều ra kết quả đúng và rất nhanh, Code của 2 bác với trình độ học vẹt của em thì chưa hiểu được hết. Em xin phép copy về dùng và ngâm cứu thêm mới hiểu rõ đường đi nước bước được. Có gì vướng mắc kinh mong các thầy hỗ trợ ạ.
Cám ơn GPE rất nhiều! :)
 
Upvote 0
Em muốn lọc dữ liệu ra từng khách hàng (từ ngày đến ngày), do em sưu tầm và chỉnh sửa lại thôi.
Tình hình là nó như vậy, Em cho lọc dữ liệu từ cột 1 -> 10, nhưng chỉ chạy đến cột thứ 9,
không biết chỉnh lại như thế nào (Cột 10_PHIẾU phân biệt phiếu PN hoặc PX)
Kính nhờ các thầy GPE hỗ trợ với ạ. Em gửi file đính kèm.
Cám ơn GPE !
 

File đính kèm

  • Trich loc bao cao.xlsb
    133.1 KB · Đọc: 10
Upvote 0
Em muốn lọc dữ liệu ra từng khách hàng (từ ngày đến ngày), do em sưu tầm và chỉnh sửa lại thôi.
Tình hình là nó như vậy, Em cho lọc dữ liệu từ cột 1 -> 10, nhưng chỉ chạy đến cột thứ 9,
không biết chỉnh lại như thế nào (Cột 10_PHIẾU phân biệt phiếu PN hoặc PX)
Kính nhờ các thầy GPE hỗ trợ với ạ. Em gửi file đính kèm.
Cám ơn GPE !
Theo yêu cầu của bạn, Bạn tìm 2 dòng này và sửa lại. Các chuyện khác tôi không biết
PHP:
Sheet2.Range("B15:J" & Dcuoi).Clear 'Sửa J thành K'
.......................................
Sheet2.Range("B15").Resize(k, 9) = ArrD 'Sửa 9 thành 10'

Nên dùng With cho trường hợp này:
With Sheet2
    .Range("B15:K" & Dcuoi).Clear
    ....
    .Range("B15").Resize(k, 10) = ArrD
    ....
End With
 
Upvote 0
Em có tập làm form tìm kiếm khách hàng, do em sưu tầm và chỉnh sửa lại thôi.
- Khi nhấn đúp vào ô tìm kiếm (sheet DCCN ô K2, tắt tự động tích vào dòng tiêu đề + mã khách hàng, chỉ được phép chọn 1 mã khách hàng - khi tích chọn khách hàng sau, tích trước tự xóa đi).
- Khi tích chọn mã khách hàng xong, mã khách hàng lại không hiển thị xuống bảng tính (Sheet DCCN ô K2).
Kính nhờ các thầy GPE hỗ trợ với ạ. Em gửi file đính kèm.
Cám ơn GPE !
 

File đính kèm

  • tim ma khac hang.xlsb
    95.1 KB · Đọc: 12
Lần chỉnh sửa cuối:
Upvote 0
Bạn thử với con macro xíu này xem có ích gì không:
PHP:
Option Explicit
Private sArray:                             Dim Dic As Object
Dim lbID As Integer

Private Sub LBDMKH_Click()
 lbID = LBDMKH.ListIndex
 MsgBox lbID, , Me!LBDMKH.List(lbID, 3)
End Sub
 
Upvote 0
Bạn thử với con macro xíu này xem có ích gì không:
PHP:
Option Explicit
Private sArray:                             Dim Dic As Object
Dim lbID As Integer

Private Sub LBDMKH_Click()
lbID = LBDMKH.ListIndex
MsgBox lbID, , Me!LBDMKH.List(lbID, 3)
End Sub

Em cám ơn anh nhiều nha, tiếc là chưa phải cái em cần ah.
MA KH.JPG
 
Upvote 0
(/ậy thì thế nào mới phải (đạo), bạn cho mình mục kỉnh bằng 1 ví dụ xem sao!
 
Upvote 0
(/ậy thì thế nào mới phải (đạo), bạn cho mình mục kỉnh bằng 1 ví dụ xem sao!
Mình có gửi file đính kèm ở trên, như thế này:
- Khi nhấn đúp vào ô K2 (sheet DCCN tìm kiếm DMKH).
- Hiện form tự động tích vào dòng tiêu đề + 1 mã khách hàng.
+ Em muốn tắt tích chọn tự động này (lúc hiện lên).
+ Khi tích chọn khách hàng mới, tích trước tự bỏ dấu tích đi (chỉ được chọn 1).
- Khi tích chọn mã khách hàng xong => CHỌN, mã khách hàng lại không hiển thị xuống bảng tính (Sheet DCCN ô K2).
Rất mong các bác GPE giúp đỡ ah, cám ơn rất nhiều !
 
Upvote 0
Thì bạn thử đổi thuộc tính MultiSelect => 0 (single)
Sau đó tiếp tục thử & thử . . . .
 
Upvote 0
Theo yêu cầu của bạn, Bạn tìm 2 dòng này và sửa lại. Các chuyện khác tôi không biết
PHP:
Sheet2.Range("B15:J" & Dcuoi).Clear 'Sửa J thành K'
.......................................
Sheet2.Range("B15").Resize(k, 9) = ArrD 'Sửa 9 thành 10'

Nên dùng With cho trường hợp này:
With Sheet2
    .Range("B15:K" & Dcuoi).Clear
    ....
    .Range("B15").Resize(k, 10) = ArrD
    ....
End With

Bác cho em hỏi, trường hợp này bẫy lỗi
Từ ngày ... đến ngày ... mà không có dữ liệu (phát sinh) thì cho hiện ra bảng thông báo "Chua phat sinh"
Nhờ bác hỗ trợ giúp em đoạn code. Em cám ơn bác rất nhiều, để hoàn thiện hơn ah !
Bài đã được tự động gộp:

Thì bạn thử đổi thuộc tính MultiSelect => 0 (single)
Sau đó tiếp tục thử & thử . . . .

Em đang cố tìm hiểu xem lỗi như thế nào, những vẫn chưa ra bác ah.
Cám ơn bác nha !
 
Upvote 0
Em đang cố tìm hiểu xem lỗi như thế nào, những vẫn chưa ra bác ah.
Chỉ mỗi MultiSelect = TRUE *** thì không giải quyết được đâu.

Có một điều ít người biết là nếu đúp chuột trên vd. CommandButton thì sẽ có 5 sự kiện được kích hoạt. Có thể làm thí nghiệm như sau: mở tập tin mới -> thêm UserForm1 -> đặt CommandButton1 trên UserForm -> viết code trong UserForm
Mã:
Option Explicit

Private k As Long

Private Sub CommandButton1_Click()
    k = k + 1
    Debug.Print "Click" & k
End Sub

Private Sub CommandButton1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
    k = k + 1
    Debug.Print "DblClick" & k
End Sub

Private Sub CommandButton1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    k = k + 1
    Debug.Print "Down" & k
End Sub

Private Sub CommandButton1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    k = k + 1
    Debug.Print "Up" & k
End Sub
-> hiển thị Form -> đúp chuột vào CommandButton1 -> sẽ có kết quả:
Down1
Up2
Click3
DblClick4
Up5

Như thế khi đúp chuột thì có 5 sự kiện được kích hoạt cho CommandButton1, thứ tự là: MouseDown -> MouseUp -> Click -> DblClick -> MouseUp.

Trong nhiều tình huống MouseUp thứ 2 được kích hoạt khi "dưới trỏ chột" đã là control hoàn toàn khác. Tức ta đúp chuột trên control1 và MouseUp thứ 2 không được kích hoạt cho control1 mà nó được kích hoạt cho control2, khi mà ở thời điểm sau khi thực hiện DblClick thì "dưới trỏ chuột" không phải là control1 mà là control2.

Cụ thể trong trường hợp của bạn như thế nào? Bạn hãy thiết lập MultiSelect = TRUE *** . Khi bạn đúp chuột trong K2 thì có thể KH0007 (đúp chuột gần mép trên của K2), KH0008 (đúp chuột quãng giữa của K2) hoặc KH0009 (đúp chuột gần mép dưới của K2) được chọn trong ListBox. Tại sao? Khi hiển thị Form thì mục KH0007, KH0008 và KH0009 đều nằm gọn trong dòng 2 của sheet so với màn hình. Trên máy bạn với độ phân giải khác thì rất có thể đó là 3 mục KH... khác nhưng bản chất là như nhau. Tức sau khi Form được hiển thị thì trỏ chuột đang ở vị trí của dòng KH0007, KH008 hoăc KH009 trong ListBox . Vì thế MouseUp thứ 2 được kích hoạt cho ListBox. Lúc đó code trong thư viện VBA sẽ chọn KH007, KH0008 hoặc KH0009 tùy theo vị trị chuột lúc đó ở trên dòng của mục KH0007, KH0008 hay KH0009 (dòng dưới trỏ chuột sẽ được chọn).
----------
Theo tôi bạn không dùng Worksheet_BeforeDoubleClick cho sheet DCCN. Bạn có thể đặt 1 Button1 trên sheet vả hiển thị Form từ Button1.
---------
***
: nhầm, phải là False, chính xác thì là fmMultiSelectSingle
 
Lần chỉnh sửa cuối:
Upvote 0
Chỉ mỗi MultiSelect = TRUE thì không giải quyết được đâu.

Có một điều ít người biết là nếu đúp chuột trên vd. CommandButton thì sẽ có 5 sự kiện được kích hoạt. Có thể làm thí nghiệm như sau: mở tập tin mới -> thêm UserForm1 -> đặt CommandButton1 trên UserForm -> viết code trong UserForm
Mã:
Option Explicit

Private k As Long

Private Sub CommandButton1_Click()
    k = k + 1
    Debug.Print "Click" & k
End Sub

Private Sub CommandButton1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
    k = k + 1
    Debug.Print "DblClick" & k
End Sub

Private Sub CommandButton1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    k = k + 1
    Debug.Print "Down" & k
End Sub

Private Sub CommandButton1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    k = k + 1
    Debug.Print "Up" & k
End Sub
-> hiển thị Form -> đúp chuột vào CommandButton1 -> sẽ có kết quả:
Down1
Up2
Click3
DblClick4
Up5

Như thế khi đúp chuột thì có 5 sự kiện được kích hoạt cho CommandButton1, thứ tự là: MouseDown -> MouseUp -> Click -> DblClick -> MouseUp.

Trong nhiều tình huống MouseUp thứ 2 được kích hoạt khi "dưới trỏ chột" đã là control hoàn toàn khác. Tức ta đúp chuột trên control1 và MouseUp thứ 2 không được kích hoạt cho control1 mà nó được kích hoạt cho control2, khi mà ở thời điểm sau khi thực hiện DblClick thì "dưới trỏ chuột" không phải là control1 mà là control2.

Cụ thể trong trường hợp của bạn như thế nào? Bạn hãy thiết lập MultiSelect = TRUE. Khi bạn đúp chuột trong K2 thì có thể KH0007 (đúp chuột gần mép trên của K2), KH0008 (đúp chuột quãng giữa của K2) hoặc KH0009 (đúp chuột gần mép dưới của K2) được chọn trong ListBox. Tại sao? Khi hiển thị Form thì mục KH0007, KH0008 và KH0009 đều nằm gọn trong dòng 2 của sheet so với màn hình. Trên máy bạn với độ phân giải khác thì rất có thể đó là 3 mục KH... khác nhưng bản chất là như nhau. Tức sau khi Form được hiển thị thì trỏ chuột đang ở vị trí của dòng KH0007, KH008 hoăc KH009 trong ListBox . Vì thế MouseUp thứ 2 được kích hoạt cho ListBox. Lúc đó code trong thư viện VBA sẽ chọn KH007, KH0008 hoặc KH0009 tùy theo vị trị chuột lúc đó ở trên dòng của mục KH0007, KH0008 hay KH0009 (dòng dưới trỏ chuột sẽ được chọn).
----------
Theo tôi bạn không dùng Worksheet_BeforeDoubleClick cho sheet DCCN. Bạn có thể đặt 1 Button1 trên sheet vả hiển thị Form từ Button1.
Cám ơn bác rất nhiều nhé, do em làm thiếu mất đoạn code, giờ thì okay rồi ah.

Hy vọng Bác giúp em bẫy lỗi trong trường hợp này ah:
Chọn kiểm tra Từ ngày ... đến ngày ... mà không có dữ liệu (phát sinh) thì cho hiện ra bảng thông báo "Chua phat sinh"
Nhờ bác hỗ trợ giúp em đoạn code. Em cám ơn bác rất nhiều, để hoàn thiện hơn ah !
Mã:
Private Sub LBDMKH_Change()
    Dim Id, i
    Id = LBDMKH.ListIndex
    With Me.LBDMKH
        On Error Resume Next
        If .Selected(Id) Then
            If Not Dic.exists(.List(Id, 0)) Then
                Dic.ADD .List(Id, 0), .List(Id, 0) & ";" & .List(Id, 1) & ";" & .List(Id, 2) & ";" & .List(Id, 3)
            End If
        Else
            Dic.Remove (.List(Id, 0))
        End If
    End With
End Sub
 

File đính kèm

  • Trich loc bao cao.xlsb
    130.6 KB · Đọc: 8
Upvote 0
Cám ơn bác rất nhiều nhé, do em làm thiếu mất đoạn code, giờ thì okay rồi ah.

Hy vọng Bác giúp em bẫy lỗi trong trường hợp này ah:
Chọn kiểm tra Từ ngày ... đến ngày ... mà không có dữ liệu (phát sinh) thì cho hiện ra bảng thông báo "Chua phat sinh"
Nhờ bác hỗ trợ giúp em đoạn code. Em cám ơn bác rất nhiều, để hoàn thiện hơn ah !
Mã:
Private Sub LBDMKH_Change()
    Dim Id, i
    Id = LBDMKH.ListIndex
    With Me.LBDMKH
        On Error Resume Next
        If .Selected(Id) Then
            If Not Dic.exists(.List(Id, 0)) Then
                Dic.ADD .List(Id, 0), .List(Id, 0) & ";" & .List(Id, 1) & ";" & .List(Id, 2) & ";" & .List(Id, 3)
            End If
        Else
            Dic.Remove (.List(Id, 0))
        End If
    End With
End Sub
Hãy mô tả cách thức hoạt động code trong Form cho người khác hiểu.

Tôi chưa tìm hiểu nhưng tôi có câu hỏi. Có thể chọn nhiều mục trong ListBox hay không? Đã có lúc có người đề nghị MultiSelect = TRUE nhưng không thấy bạn phản đối. Bây giờ tôi lại có cảm giác là bạn cho khả năng chọn nhiều trong ListBox.
 
Upvote 0
Web KT
Back
Top Bottom