Luyện tập Code VBA: Các bạn đã biết lập trình mảng động nâng cao trong VBA?

Liên hệ QC

HeSanbi

Nam Nhân✨Hiếu Lễ Nghĩa Trí Tín✨
Tham gia
24/2/13
Bài viết
2,382
Được thích
3,536
Giới tính
Nam
(*Đọc xong bài viết và các bạn hãy thử viết một hàm đăng lên chủ đề này!)

Các bạn đã biết lập trình mảng động trong VBA là gì hay chưa? Các bạn sẽ biết ngay sau khi bỏ ra vài phút để đọc bài viết này.

Định nghĩa "mảng động": hiểu đơn giản là dữ liệu hoặc mảng dữ liệu gốc trong bảng tính thay đổi thì mảng trả kết quả cũng thay đổi theo.

Có hai kiểu lập trình xử lý mảng động, lập trình mảng động cơ bản và lập trình mảng động phụ thuộc WinAPI.


A. Lập trình Mảng động căn bản:
Các bạn đã từng vận dụng các Hàm mảng động Excel như UNIQUE , SORT, SORTBY, FILTER, SEQUENCE, RANDARRAY, SINGLE, tùy vào phiên bản, tùy vào hàm nhưng thường thì áp dụng các hàm trên vào bảng tính Excel là sự kết hợp của tổ hợp phím "Ctrl+Shift+Enter".
Và với Lập trình Mảng động căn bản cũng vận dụng tổ hợp phím như vậy để áp dụng hàm.
1. Cách viết hàm mảng động:
+ Viết một hàm trả về kết quả mảng bình thường.
+ Khởi tạo hàm nhận trả kết quả có cặp ngoặc tròn () đằng sau kiểu khởi tạo. Hoặc đằng sau mảng khi trả kết quả.
+ Có hoặc không đặt Application.Volatile vào hàm: Buộc tính toán lại khi giá trị của một ô trong bảng tính thay đổi, nếu có nhiều hàm có Application.Volatile sẽ khiến độ trễ của việc tính toán Excel càng lúc càng lớn.
Ví dụ 1:
PHP:
'Cách 1:'
Function CopyRangeValue(ByVal oRange As Object) As Variant()
  Application.Volatile
  CopyRangeValue = oRange.Value
End Function

'Cách 2:'
Function CopyRangeValue(ByVal oRange As Object)
  Dim Arr()
  Application.Volatile
  Arr = oRange.Value
  CopyRangeValue = Arr()
End Function
----------------
Ví dụ 2:​
PHP:
Function RandomNumbers(ByVal Number As Long, _
                       ByVal Row As Integer, _
                       ByVal Column As Integer, _
              Optional ByVal optVolatile As Boolean) As Variant()
  If optVolatile Then Application.Volatile
  Dim Arr(), R As Integer, C As Integer
  ReDim Arr(1 To Row, 1 To Column)
  Randomize
  For R = 1 To Row
    For C = 1 To Column
      Arr(R, C) = R + Rnd
    Next C
  Next R
  RandomNumbers = Arr()
End Function
----------------​
2. Hàm được hiển thị trong Cell như thế nào?

{=RandomNumbers(2, 10, 2, True)}
3. Cách áp dụng:
Kéo chuột Chọn một vùng Range để áp dụng​
Với =RandomNumbers(2, 10, 2, True) thì vùng chọn là A1:B10, sau khi chọn xong gõ hàm vào thanh công thức, và ấn tổ hợp Ctrl+Shift+Enter.
4. Ưu điểm và nhược điểm:
+ Nhược điểm: Khi đã tạo Mảng động, không thể chèn xóa hàng cột thuộc mảng động. Phải sử dụng tổ hợp phím Ctrl+Shift+Enter để hoàn thành. Phải chọn vùng trước khi nhập hàm.

B. Lập trình Mảng động phụ thuộc WinAPI:
Lập trình Mảng động phụ thuộc WinAPI sẽ tạo nên một sự phong phú và đa dạng trong lập trình VBA, giúp phát triển Hàm tốt hơn rất nhiều so với Mảng động căn bản.
1. Cơ chế hoạt động của quy trình sử dụng WinAPI:
Sau khi hàm đã được gõ vào Ô trong bảng tính. Hàm bắt đầu khởi tạo và gán các đối số vào các biến cục bộ như Vùng chọn, giá trị, ... . Sau đó đặt một lệnh để WinAPI sẽ thực hiện, và Hàm WinAPI sẽ tự động gọi một hàm trung gian sau khi Hàm chính tính toán xong.
2. Ứng dụng: Viết các hàm tương đương với các Hàm mảng động Excel như UNIQUE , SORT, SORTBY, FILTER, SEQUENCE, RANDARRAY, SINGLE. Và viết đa dạng kiểu hàm mảng động tùy vào "sức mạnh và tư duy lập trình của các bạn".
3. Hướng dẫn: (*Sẽ cập nhật sau)​
4. Ví dụ:
Copy Code dưới đây vào Module và thực hiện:
Gõ vào A1: =RandomNumbers(B1, 10, 5) (*Không cần đến tổ hợp phím để hoàn thành)
Gõ vào B1: một số ngẫu nhiên
JavaScript:
Option Explicit
#If VBA7 Then
  Private Declare PtrSafe Function SetTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr, ByVal uElapse As LongPtr, ByVal lpTimerFunc As LongPtr) As Long
  Private Declare PtrSafe Function KillTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
#Else
  Private Declare Function SetTimer Lib "user32" (ByVal HWnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
  Private Declare Function KillTimer Lib "user32" (ByVal HWnd As Long, ByVal nIDEvent As Long) As Long
#End If

Private fRN_TimerID As Long, fRN_Number&, fRN_Row%, fRN_Column%, fRN_Range As Range

Function RandomNumbers(ByVal Number&, ByVal Row%, ByVal Column%)
  RandomNumbers = "RandomNumbers:"
  Set fRN_Range = Application.Caller
  fRN_Number = Number: fRN_Row = Row: fRN_Column = Column
  On Error Resume Next
  If fRN_TimerID <> 0 Then KillTimer 0&, fRN_TimerID
  fRN_TimerID = SetTimer(0&, 0&, 1, AddressOf printRandomNumbers)
End Function

Private Sub printRandomNumbers()
  On Error Resume Next
  KillTimer 0&, fRN_TimerID: fRN_TimerID = 0
  If fRN_Number = 0 Or fRN_Row = 0 Or fRN_Column = 0 Or fRN_Range Is Nothing Then GoTo Ends
  Dim SU As Boolean, AC As Long
  SU = Application.ScreenUpdating
  AC = Application.Calculation
  Application.Calculation = xlCalculationManual
  Application.ScreenUpdating = False
  Dim Arr(), R%, C%
  ReDim Arr(1 To fRN_Row, 1 To fRN_Column)
  Randomize
  For R = 1 To fRN_Row
    For C = 1 To fRN_Column
      Arr(R, C) = CLng((fRN_Number + 1) * Rnd + fRN_Number)
    Next C
  Next R
  fRN_Range(2, 1).Resize(fRN_Row, fRN_Column).value = Arr
  Application.ScreenUpdating = SU
  Application.Calculation = AC
  fRN_Number = 0: fRN_Row = 0: fRN_Column = 0
Ends:  Set fRN_Range = Nothing
End Sub
----------------
 
Lần chỉnh sửa cuối:
Mình đã giải quyết cho 1 bạn trong cộng đồng chúng ta bài toán như sau:


UDF Array.JPG

(https://www.giaiphapexcel.com/diendan/threads/lấy-danh-sách-nhân-viên-làm-thừa-hoặc-thiếu-đầu-công-việc.143543/#post-926458)
Xin hỏi chủ bài đăng: Đó có phải là hàm mảng động hay chưa?
Xin cảm ơn thiệt nhiều, nha.
PHP:
Function NamViec(Rng As Range)
ReDim Arr(1 To Rng.Rows.Count, 1 To 2) As String
Dim Cls As Range:                  Dim Ma As String
Dim W As Integer, Dm As Integer

For Each Cls In Rng
    If IsNumeric(Right(Cls.Value, 2)) Then
        If Dm = 0 And W = 0 Then
            W = W + 1
        End If
'        If (Dm < 5 And Dm > 0) Or Dm > 5 Then       '
        If Cls <> Rng(1) And Dm <> 5 Then
            Arr(W, 1) = Ma:            Arr(W, 2) = Dm
            Dm = 0:                       W = W + 1
       ElseIf Dm = 5 Then
            Dm = 0
       End If
       Ma = Cls.Value       '*'
    Else
       Dm = Dm + 1
       If Cls.Row = Rng.Rows.Count And Dm <> 5 Then
            Arr(W, 1) = Ma:       Arr(W, 2) = Dm
       End If
    End If
Next Cls
  NamViec = Arr()
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
Thì đưa trỏ chuột vào vùng C14: D25 xem nó có động đậy hay không thì biết liền.
Mình thử như bạn nói thì không chuyện gì diễn ra cả;
Nhưng tại vùng [A9:A14] mà nhập 1 mã nhân viên nào khác thì tại vùng [C14:D25] có biến chuyển theo trị nhập mới

Còn file dưới đây là cách hiện chi tiết nội dung khi chọn 1 trong các mã biên bản nghiệm thu:
 

File đính kèm

  • UDF.rar
    15.2 KB · Đọc: 23
Lần chỉnh sửa cuối:
Upvote 0
SA_DQ
Thưa Bác SA_DQ hàm của bác viết chính là hàm mảng động.

Để kiểm tra nó có phải mảng động hay không. Bác thử công thức sau

=INDEX(NamViec($A$1:$A$24),3)
 
Upvote 0
Vậy thì mình có file bài tập này, các bạn có thể tham khảo 1 vài trong chúng theo nhu cầu của từng người
 

File đính kèm

  • UDF.rar
    43.5 KB · Đọc: 21
Lần chỉnh sửa cuối:
Upvote 0
Mạnh tò mò mới bắt trước bài số 1 tập làm 1 cái không biết keo nó là chiArray.gif
 

File đính kèm

  • Array.rar
    461 KB · Đọc: 23
Lần chỉnh sửa cuối:
Upvote 0
Bài 8 của Mạnh @HeSanbi thấy sao và keo nó là chỉ được .... ý tưởng code bài 1 rất hay còn vận dụng được hay không thì phụ thuộc vào khả năng của từng bạn
 
Upvote 0
Bài 8 của Mạnh @HeSanbi thấy sao và keo nó là chỉ được .... ý tưởng code bài 1 rất hay còn vận dụng được hay không thì phụ thuộc vào khả năng của từng bạn
----------------------------


Hơi khó hiểu vì sao lại gọi là ý tưởng.

Cách trên gần như là một kỹ thuật duy nhất để gọi bất kì xử lý nào từ VBA với một hàm UDF tự tạo, không riêng gì mảng động.

Đa số bạn học VBA nhìn vào có thể không hiểu được ý nghĩa của kỹ thuật trên.

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

Còn đối với ví dụ của bác kieu manh thì cũng đơn giản.

bác thử áp dụng với ADODB xem cảm giác có hứng thú hơn không.
 
Upvote 0
bác thử áp dụng với ADODB xem cảm giác có hứng thú hơn không.
Sẻ làm lấy từ File Excel và Access lên Ok chỉ viết thêm hàm gán nó vào Mảng là xong à + thêm cái hàm chuyển mảng nửa cho nó dễ hình dung cái thuở ban đầu mò nó ... xong xóa nó luôn lấy lên tới đâu duyệt tới đó ( Bỏ 2 vòng For khi chuyển mảng he )
....
[a1]= Ham(Path,SQL) xong ngay và luôn đó ... chắc trong tầm tay

Keo kỹ thuật chính xác hơn ý tưởng đó ... ( đính chính lại ) :p
 
Lần chỉnh sửa cuối:
Upvote 0
Ngày chủ nhật mới làm xong phiên bản ADO lấy dữ liệu File Access & Excel lên .... lấy Server hay *.CSV, *.txt ... thì nó cũng thế thôi
Quan trọng tính toán +-*/ xong gán vào 1 cái Hàm chung nhất nó gán lên Sheet là Xong

Cơ bản kỹ thuật Hàm gán lên Sheet kiểu Office 365 Mạnh đã thực thi xong .... còn lại Fix lỗi + viết thêm các hàm khác thôi
Ai đam mê mò là tự viết được .... không khó lắm ... Copy Trên GPE 1 tí + Internet 1 tẹo + tư duy 1 téo là xong
 

File đính kèm

  • ADO_Access_Excel.rar
    3.3 MB · Đọc: 37
Upvote 0
(*Đọc xong bài viết và các bạn hãy thử viết một hàm đăng lên chủ đề này!)

Các bạn đã biết lập trình mảng động trong VBA là gì hay chưa? Các bạn sẽ biết ngay sau khi bỏ ra vài phút để đọc bài viết này.

Định nghĩa "mảng động": hiểu đơn giản là dữ liệu hoặc mảng dữ liệu gốc trong bảng tính thay đổi thì mảng trả kết quả cũng thay đổi theo.

Có hai kiểu lập trình xử lý mảng động, lập trình mảng động cơ bản và lập trình mảng động phụ thuộc WinAPI.


A. Lập trình Mảng động căn bản:
Các bạn đã từng vận dụng các Hàm mảng động Excel như UNIQUE , SORT, SORTBY, FILTER, SEQUENCE, RANDARRAY, SINGLE, tùy vào phiên bản, tùy vào hàm nhưng thường thì áp dụng các hàm trên vào bảng tính Excel là sự kết hợp của tổ hợp phím "Ctrl+Shift+Enter".
Và với Lập trình Mảng động căn bản cũng vận dụng tổ hợp phím như vậy để áp dụng hàm.
1. Cách viết hàm mảng động:
+ Viết một hàm trả về kết quả mảng bình thường.
+ Khởi tạo hàm nhận trả kết quả có cặp ngoặc tròn () đằng sau kiểu khởi tạo. Hoặc đằng sau mảng khi trả kết quả.
+ Có hoặc không đặt Application.Volatile vào hàm: Buộc tính toán lại khi giá trị của một ô trong bảng tính thay đổi, nếu có nhiều hàm có Application.Volatile sẽ khiến độ trễ của việc tính toán Excel càng lúc càng lớn.
Ví dụ 1:
PHP:
'Cách 1:'
Function CopyRangeValue(ByVal oRange As Object) As Variant()
  Application.Volatile
  CopyRangeValue = oRange.Value
End Function

'Cách 2:'
Function CopyRangeValue(ByVal oRange As Object)
  Dim Arr()
  Application.Volatile
  Arr = oRange.Value
  CopyRangeValue = Arr()
End Function
----------------
Ví dụ 2:​
PHP:
Function RandomNumbers(ByVal Number As Long, _
                       ByVal Row As Integer, _
                       ByVal Column As Integer, _
              Optional ByVal optVolatile As Boolean) As Variant()
  If optVolatile Then Application.Volatile
  Dim Arr(), R As Integer, C As Integer
  ReDim Arr(1 To Row, 1 To Column)
  Randomize
  For R = 1 To Row
    For C = 1 To Column
      Arr(R, C) = R + Rnd
    Next C
  Next R
  RandomNumbers = Arr()
End Function
----------------​
2. Hàm được hiển thị trong Cell như thế nào?

{=RandomNumbers(2, 10, 2, True)}
3. Cách áp dụng:
Kéo chuột Chọn một vùng Range để áp dụng​
Với =RandomNumbers(2, 10, 2, True) thì vùng chọn là A1:B10, sau khi chọn xong gõ hàm vào thanh công thức, và ấn tổ hợp Ctrl+Shift+Enter.
4. Ưu điểm và nhược điểm:
+ Nhược điểm: Khi đã tạo Mảng động, không thể chèn xóa hàng cột thuộc mảng động. Phải sử dụng tổ hợp phím Ctrl+Shift+Enter để hoàn thành. Phải chọn vùng trước khi nhập hàm.

B. Lập trình Mảng động phụ thuộc WinAPI:
Lập trình Mảng động phụ thuộc WinAPI sẽ tạo nên một sự phong phú và đa dạng trong lập trình VBA, giúp phát triển Hàm tốt hơn rất nhiều so với Mảng động căn bản.
1. Cơ chế hoạt động của quy trình sử dụng WinAPI:
Sau khi hàm đã được gõ vào Ô trong bảng tính. Hàm bắt đầu khởi tạo và gán các đối số vào các biến cục bộ như Vùng chọn, giá trị, ... . Sau đó đặt một lệnh để WinAPI sẽ thực hiện, và Hàm WinAPI sẽ tự động gọi một hàm trung gian sau khi Hàm chính tính toán xong.
2. Ứng dụng: Viết các hàm tương đương với các Hàm mảng động Excel như UNIQUE , SORT, SORTBY, FILTER, SEQUENCE, RANDARRAY, SINGLE. Và viết đa dạng kiểu hàm mảng động tùy vào "sức mạnh và tư duy lập trình của các bạn".
3. Hướng dẫn: (*Sẽ cập nhật sau)​
4. Ví dụ:
Copy Code dưới đây vào Module và thực hiện:
Gõ vào A1: =RandomNumbers(B1, 10, 5) (*Không cần đến tổ hợp phím để hoàn thành)
Gõ vào B1: một số ngẫu nhiên
JavaScript:
Option Explicit
#If VBA7 Then
  Private Declare PtrSafe Function SetTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr, ByVal uElapse As LongPtr, ByVal lpTimerFunc As LongPtr) As Long
  Private Declare PtrSafe Function KillTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
#Else
  Private Declare Function SetTimer Lib "user32" (ByVal HWnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
  Private Declare Function KillTimer Lib "user32" (ByVal HWnd As Long, ByVal nIDEvent As Long) As Long
#End If

Private fRN_TimerID As Long, fRN_Number&, fRN_Row%, fRN_Column%, fRN_Range As Range

Function RandomNumbers(ByVal Number&, ByVal Row%, ByVal Column%)
  RandomNumbers = "RandomNumbers:"
  Set fRN_Range = Application.Caller
  fRN_Number = Number: fRN_Row = Row: fRN_Column = Column
  On Error Resume Next
  If fRN_TimerID <> 0 Then KillTimer 0&, fRN_TimerID
  fRN_TimerID = SetTimer(0&, 0&, 1, AddressOf printRandomNumbers)
End Function

Private Sub printRandomNumbers()
  On Error Resume Next
  KillTimer 0&, fRN_TimerID: fRN_TimerID = 0
  If fRN_Number = 0 Or fRN_Row = 0 Or fRN_Column = 0 Or fRN_Range Is Nothing Then GoTo Ends
  Dim SU As Boolean, AC As Long
  SU = Application.ScreenUpdating
  AC = Application.Calculation
  Application.Calculation = xlCalculationManual
  Application.ScreenUpdating = False
  Dim Arr(), R%, C%
  ReDim Arr(1 To fRN_Row, 1 To fRN_Column)
  Randomize
  For R = 1 To fRN_Row
    For C = 1 To fRN_Column
      Arr(R, C) = CLng((fRN_Number + 1) * Rnd + fRN_Number)
    Next C
  Next R
  fRN_Range(2, 1).Resize(fRN_Row, fRN_Column).value = Arr
  Application.ScreenUpdating = SU
  Application.Calculation = AC
  fRN_Number = 0: fRN_Row = 0: fRN_Column = 0
Ends:  Set fRN_Range = Nothing
End Sub
----------------
Các anh chị cho em hỏi có cách nào để trên 1 sheet em sử dụng 2 hàm RandomNumbers thì chạy cả 2 ạ. (Hiện tại hàm chỉ chạy được 1 cái)
 

File đính kèm

  • Test Fun.xlsm
    16.6 KB · Đọc: 3
Upvote 0
Các anh chị cho em hỏi có cách nào để trên 1 sheet em sử dụng 2 hàm RandomNumbers thì chạy cả 2 ạ. (Hiện tại hàm chỉ chạy được 1 cái)


Code trên tôi chỉ ví dụ để các bạn học tập và viết code, bạn cần phải thực tập và mở rộng khả năng code của bạn thì hàm mảng động mới phát huy hết công dụng của nó

Bạn có thể tham khảo code dưới:

PHP:
'                    _,
' ___   _   _  _ ___(_)
'/ __| / \ | \| | _ | |
'\__ \/ \ \| \\ | _ \ |
'|___/_/ \_|_|\_|___/_|
'
Option Explicit
#If VBA7 Then
  Private Declare PtrSafe Function SetTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr, ByVal uElapse As LongPtr, ByVal lpTimerFunc As LongPtr) As Long
  Private Declare PtrSafe Function KillTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
#Else
  Private Declare Function SetTimer Lib "user32" (ByVal HWnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
  Private Declare Function KillTimer Lib "user32" (ByVal HWnd As Long, ByVal nIDEvent As Long) As Long
#End If
Private Type TypeArgs
  FromNumber As Long
  ToNumber As Long
  Row As Long
  Column As Long
  Caller As Excel.Range
  Action As Long
  Formula As String
  Unique As Object
  MakeUnique As Boolean
  MaxNumber As Long
End Type

#If VBA7 And Win64 Then
  Private gTimerID As LongPtr
#Else
  Private gTimerID As Long
#End If
Private Args() As TypeArgs, WorkIndex As Integer

Function S_Rand( _
                   ByVal FromNumber&, _
          Optional ByVal ToNumber&, _
          Optional ByVal Unique As Boolean, _
          Optional ByVal Row% = 1, _
          Optional ByVal Column% = 1) As Variant

  On Error Resume Next
  Dim k&, r, F$
  If ToNumber < FromNumber Then
    k = ToNumber: ToNumber = FromNumber: FromNumber = k
  End If
  Set r = Application.Caller
  F = r(1, 1).Formula
  k = UBound(Args)
  VBA.Randomize
  S_Rand = Int(FromNumber + VBA.Rnd * (ToNumber - FromNumber + 1))
  If Row * Column > 1 Then
    ReDim Preserve Args(1 To k + 1)
    With Args(k + 1)
      .FromNumber = FromNumber
      .ToNumber = ToNumber
      .Row = Row
      .Column = Column
      .Formula = F
      .MakeUnique = Unique
      .Action = 0
      .MaxNumber = ToNumber - FromNumber
      Set .Unique = VBA.CreateObject("Scripting.Dictionary")
      .Unique.Add S_Rand, S_Rand
      Set .Caller = r
    End With
    If gTimerID = 0 Then
      gTimerID = SetTimer(0&, 0&, 1, AddressOf S_Rand_callback)
    End If
  End If
End Function

Private Sub S_Rand_callback()
  On Error Resume Next
  Call KillTimer(0&, gTimerID): gTimerID = 0
  S_Rand_working
  On Error GoTo 0
End Sub

Private Sub S_Rand_working()
  Dim UA%, s$
  UA = UBound(Args)
  If UA > 0 Then
    WorkIndex = WorkIndex + 1
    Dim a As TypeArgs, AP As Object
    a = Args(WorkIndex)
    Set AP = a.Caller.Parent.Parent.Parent
    Debug.Print a.Action, a.Caller.Formula, a.Formula
    If a.Action <> 0 Or a.Caller.Formula <> a.Formula Then
      GoTo N
    End If
    a.Action = 1
    '//'//'//'//'//'//'//'//'//'//'//'//'//'//'//'//'//'//'//'//
    If a.ToNumber = 0 Or a.Row = 0 Or a.Column = 0 Then
      GoTo Ends
    End If
    Dim SU As Boolean, AC As Long
    SU = AP.ScreenUpdating
    AC = AP.Calculation
    If AC <> xlCalculationManual Then
      AP.Calculation = xlCalculationManual
    End If
    If SU Then
      AP.ScreenUpdating = False
    End If
   
    VBA.Randomize
    Dim Arr(), r&, C%, t&, k&
   
    If a.MakeUnique Then
      ReDim Arr(1 To 1, 1 To a.Column - 1)
      r = 1
      For C = 1 To UBound(Arr, 2)
        GoSub r
       
      Next C
      a.Caller(1, 2).Resize(1, UBound(Arr, 2)).Value = Arr
      ReDim Arr(1 To a.Row - 1, 1 To a.Column)
      For r = 1 To UBound(Arr)
        For C = 1 To a.Column
          GoSub r
        Next C
      Next r
      a.Caller(2, 1).Resize(UBound(Arr), a.Column).Value = Arr
    Else
      ReDim Arr(1 To a.Column - 1)
      For C = 1 To UBound(Arr, 2)
        Arr(C) = CLng((a.ToNumber + 1) * VBA.Rnd + a.ToNumber)
      Next C
      a.Caller(1, 2).Resize(1, UBound(Arr)).Value = Arr
      ReDim Arr(1 To a.Row - 1, 1 To a.Column)
      For r = 1 To UBound(Arr)
        For C = 1 To a.Column
          Arr(r, C) = CLng((a.ToNumber + 1) * VBA.Rnd + a.ToNumber)
        Next C
      Next r
      a.Caller(2, 1).Resize(UBound(Arr), a.Column).Value = Arr
    End If
    If SU <> AP.ScreenUpdating Then
      AP.ScreenUpdating = SU
    End If
    If AP.Calculation <> AC Then
      AP.Calculation = AC
    End If
    a.ToNumber = 0: a.Row = 0: a.Column = 0
Ends:
    '//'//'//'//'//'//'//'//'//'//'//'//'//'//'//'//'//'//'//'//
N:
    If WorkIndex >= UA Then
      Erase Args: WorkIndex = 0
    Else
      gTimerID = SetTimer(0&, 0&, 1, AddressOf S_Rand_callback)
    End If
  End If
  On Error GoTo 0
Exit Sub
r:
  If k >= a.MaxNumber Then
    t = 0
  Else
    t = Int(a.FromNumber + VBA.Rnd * (a.ToNumber - a.FromNumber + 1))
    s = t
    If Not a.Unique.exists(s) Then
      k = k + 1
      a.Unique.Add s, t
      Arr(r, C) = t
    Else
      GoSub r
    End If
  End If
Return
End Sub
 

File đính kèm

  • S_RandomNumbers.xlsm
    33.7 KB · Đọc: 19
Lần chỉnh sửa cuối:
Upvote 0
Web KT
Back
Top Bottom