- Tham gia
- 13/6/06
- Bài viết
- 4,810
- Được thích
- 10,312
- Giới tính
- Nam
- Nghề nghiệp
- Giáo viên, CEO tại Bluesofts
Chúng ta đã biết lập trình VBA trong Excel với việc xử lý dữ liệu lớn rồi ghi lên bảng tính, bình thường chạy bị chậm. Phương pháp làm tăng tốc độ là xử lý trong mảng rồi điền cả mảng vào bảng tính. Thông thường khi làm với mảng, các công việc như xoá các phần tử trong mảng, chèn thêm dữ liệu vào mảng, chúng ta sẽ dùng vòng lặp để làm và tốc độ ứng dụng chạy vẫn bị chậm nếu mảng dữ liệu lớn. Từ nhu cầu thực tế và qua trao đổi trong chủ để "Array: Có thể remove một hay vài hàng bất kỳ mà không dùng vòng lặp được không?" của anh Hoàng Trọng Nghĩa tôi xây dựng một module tên "modFastArray" cung cấp các hàm xử lý mảng với giải thuật không dùng vòng lặp mà xử lý việc dịch chuyển các byte (dữ liệu) của mảng trong bộ nhớ nên tốc độ chạy rất nhanh!
Phiên bản 1.0->1.1 cung cấp các hàm mảng sau:
1. DeleteElementArray1D - Cho phép xoá một hay nhiều phần tử mảng (1 chiều - 1D) liên tiếp
2. DeleteElementArray2D - Cho phép xoá một hay nhiều phần tử mảng (2 chiều - 2D) liên tiếp
3. InsertElementArray1D - Cho phép chèn một mảng dữ liệu vào một mảng đã có vào vị trí bất kỳ. Hàm này làm việc với mảng 1 chiều chiều
4. InsertElementArray2D - Cho phép chèn một mảng dữ liệu vào một mảng đã có vào vị trí bất kỳ. Hàm này làm việc với mảng 2 chiều
5. ConvertArray1DTo2D - Cho phép chuyển đổi từ mảng 1 chiều sang mảng 2 chiều. Hàm này hữu dụng khi ta cần đưa mảng vào bảng tính. Mảng đưa vào muốn trình bày trong một cột thì phải đưa về mảng hai chiều. Đặc biệt nó tốt hơn hàm Excel Application.WorksheetFunction.Transpose() rất nhiều khi làm việc với mảng 1 chiều và số phần tử mảng lớn (lên đến trên 100.000 phần tử).
6. FillToRange - Cho phép điền mảng vào bảng tính tại ô bất kỳ
7. NumberOfDimensions - Đếm số chiều của mảng
8 DeleteColumnArray2D - Xóa cac cột trong mảng 2 chiều
9 InsertColumnArray2D - Chèn thêm các cột từ mảng khác vào mảng 2 chiều
Để biết cách sử dụng các bạn hãy download tập tin "FastArray_vx.x.xls"đính kèm.
(*) Khi sử dụng cần lưu ý:
+ Các phần tử của mảng phải là kiểu VARIANT
+ Đọc kỹ các comment trong mỗi hàm để nắm được quy tắc cũng như mục đích sử dụng hàm và của từng tham số.
Mã nguồn các hàm dưới đây:
[GPECODE=vb]
Function DeleteElementArray1D(ByRef arrDest() As Variant, ByRef arrSource As Variant, ByVal lIndexBegin As Long, ByVal lIndexEnd As Long) As Boolean
'Programming by: Nguyen Duy Tuan - www.bluesofts.net
'arrSource: is array 1D. Elements of array with VARIANT type
'arrDest: an array 1D after deleting element from lIndexBegin to lIndexEnd. Elements of array with VARIANT type
Dim I As Long, lLowSource As Long
Erase arrDest 'Free all elements
lLowSource = LBound(arrSource)
'Check the validity of the parameters
If (lIndexEnd < lLowSource) Or (lIndexEnd > UBound(arrSource)) Then
lIndexEnd = UBound(arrSource)
End If
If lIndexBegin < lLowSource Then
Err.Raise 10000, "DeleteElementArray1D", "Parameter lIndexBegin is invalid."
End If
If (lIndexBegin > lIndexEnd) Then
Err.Raise 10001, "DeleteElementArray1D", "You must ensure that lIndexBegin <= lIndexEnd."
End If
If (lIndexEnd - lIndexBegin) = (UBound(arrSource) - lLowSource) Then '<==> Clear all elements of array
ReDim arrDest(lLowSource To lLowSource)
DeleteElementArray1D = True
Exit Function
End If
ReDim arrDest(lLowSource To UBound(arrSource) - (lIndexEnd - lIndexBegin + 1)) As Variant
CopyMemory ByVal VarPtr(arrDest(lLowSource)), _
ByVal VarPtr(arrSource(lLowSource)), _
SZ_VARIANT * ((lIndexBegin - lLowSource))
If UBound(arrSource) > lIndexEnd Then 'the rest
CopyMemory ByVal VarPtr(arrDest(lIndexBegin)), _
ByVal VarPtr(arrSource(lIndexEnd + 1)), _
SZ_VARIANT * (UBound(arrSource) - lIndexEnd)
End If
'Erase Source array in memory
'Must move bytes should be deleted from arrSource(lIndexBegin to lIndexEnd) into arrDelSource to free them in memory
ReDim arrDelSource(lIndexBegin To lIndexEnd) As Variant
CopyMemory ByVal VarPtr(arrDelSource(lIndexBegin)), _
ByVal VarPtr(arrSource(lIndexBegin)), _
SZ_VARIANT * (lIndexEnd - lIndexBegin + 1)
Erase arrDelSource
ZeroMemory ByVal VarPtr(arrSource(lLowSource)), SZ_VARIANT * (UBound(arrSource) - lLowSource + 1)
Erase arrSource
DeleteElementArray1D = True
End Function
Function DeleteElementArray2D(ByRef arrDest() As Variant, ByRef arrSource As Variant, ByVal lIndexBegin As Long, ByVal lIndexEnd As Long) As Boolean
'Programming by: Nguyen Duy Tuan - www.bluesofts.net
'arrSource: is array 2D. Elements of array with VARIANT type
'arrDest: an array after deleting element from lIndexBegin to lIndexEnd. Elements of array with VARIANT type
Dim I As Long, lLowSourceD1 As Long, lLowSourceD2 As Long
Erase arrDest 'Free all elements
lLowSourceD1 = LBound(arrSource, 1)
lLowSourceD2 = LBound(arrSource, 2)
'Check the validity of the parameters
If (lIndexEnd < lLowSourceD1) Or (lIndexEnd > UBound(arrSource, 1)) Then
lIndexEnd = UBound(arrSource, 1)
End If
If lIndexBegin < lLowSourceD1 Then
Err.Raise 10000, "DeleteElementArray2D", "Parameter lIndexBegin is invalid."
End If
If lIndexBegin > lIndexEnd Then
Err.Raise 10001, "DeleteElementArray2D", "You must ensure that lIndexBegin <= lIndexEnd."
End If
ReDim arrDest(lLowSourceD1 To UBound(arrSource, 1) - (lIndexEnd - lIndexBegin + 1), _
lLowSourceD2 To UBound(arrSource, 2)) As Variant
For I = LBound(arrSource, 2) To UBound(arrSource, 2) 'Copy columns
CopyMemory ByVal VarPtr(arrDest(lLowSourceD1, I)), _
ByVal VarPtr(arrSource(lLowSourceD1, I)), _
SZ_VARIANT * (lIndexBegin - lLowSourceD1)
Next I
If UBound(arrSource) > lIndexEnd Then
For I = LBound(arrSource, 2) To UBound(arrSource, 2)
CopyMemory ByVal VarPtr(arrDest(lIndexBegin, I)), _
ByVal VarPtr(arrSource(lIndexEnd + 1, I)), _
SZ_VARIANT * (UBound(arrSource) - lIndexEnd)
Next I
End If
'Erase Source array in memory
ReDim arrDelSource(lIndexBegin To lIndexEnd, lLowSourceD2 To UBound(arrSource, 2)) As Variant
For I = LBound(arrSource, 2) To UBound(arrSource, 2)
'Must move bytes should be deleted from arrSource(lIndexBegin to lIndexEnd) into arrDelSource to free them in memory
CopyMemory ByVal VarPtr(arrDelSource(lIndexBegin, I)), _
ByVal VarPtr(arrSource(lIndexBegin, I)), _
SZ_VARIANT * (lIndexEnd - lIndexBegin + 1)
ZeroMemory ByVal VarPtr(arrSource(lLowSourceD1, I)), SZ_VARIANT * (UBound(arrSource) - lLowSourceD1 + 1)
Next I
Erase arrDelSource
Erase arrSource
DeleteElementArray2D = True
End Function
Function DeleteColumnArray2D(ByRef arrDest() As Variant, ByRef arrSource As Variant, ByVal lIndexBegin As Long, ByVal lIndexEnd As Long) As Boolean
'Programming by: Nguyen Duy Tuan - www.bluesofts.net
'arrSource: is array 2D. Elements of array with VARIANT type
'arrDest: an array2D after deleting columns of data from lIndexBegin to lIndexEnd. Elements of array with VARIANT type
Dim I As Long, lLowSourceD1 As Long, lHighSourceD1 As Long, lLowSourceD2 As Long
Erase arrDest 'Free all elements
lLowSourceD1 = LBound(arrSource, 1)
lHighSourceD1 = UBound(arrSource, 1)
lLowSourceD2 = LBound(arrSource, 2)
'Check the validity of the parameters
If (lIndexEnd < lLowSourceD2) Or (lIndexEnd > UBound(arrSource, 2)) Then
lIndexEnd = UBound(arrSource, 2)
End If
If lIndexBegin < lLowSourceD1 Then
Err.Raise 10000, "DeleteElementArray2D", "Parameter lIndexBegin is invalid."
End If
If lIndexBegin > lIndexEnd Then
Err.Raise 10001, "DeleteElementArray2D", "You must ensure that lIndexBegin <= lIndexEnd."
End If
ReDim arrDest(lLowSourceD1 To UBound(arrSource, 1), _
lLowSourceD2 To UBound(arrSource, 2) - (lIndexEnd - lIndexBegin + 1)) As Variant
Dim lColIndex As Long
lColIndex = lLowSourceD2 - 1
For I = lLowSourceD2 To UBound(arrSource, 2) 'Copy columns
If I < lIndexBegin Or I > lIndexEnd Then
lColIndex = lColIndex + 1
CopyMemory ByVal VarPtr(arrDest(lLowSourceD1, lColIndex)), _
ByVal VarPtr(arrSource(lLowSourceD1, I)), _
SZ_VARIANT * ((lHighSourceD1 - lLowSourceD1 + 1))
End If
Next I
DeleteColumnArray2D = True
'Erase Source array in memory
ReDim arrDelSource(lLowSourceD1 To lHighSourceD1, _
lIndexBegin To lIndexEnd) As Variant
lColIndex = lIndexBegin - 1
For I = LBound(arrSource, 2) To UBound(arrSource, 2)
'Must move bytes should be deleted from arrSource(lIndexBegin to lIndexEnd) into arrDelSource to free them in memory
If I >= lIndexBegin And I <= lIndexEnd Then
lColIndex = lColIndex + 1
CopyMemory ByVal VarPtr(arrDelSource(lLowSourceD1, lColIndex)), _
ByVal VarPtr(arrSource(lLowSourceD1, I)), _
SZ_VARIANT * ((lHighSourceD1 - lLowSourceD1 + 1))
End If
ZeroMemory ByVal VarPtr(arrSource(lLowSourceD1, I)), SZ_VARIANT * (lHighSourceD1 - lLowSourceD1 + 1)
Next I
Erase arrDelSource
Erase arrSource
End Function
Function InsertElementArray1D(ByRef arrDest() As Variant, ByRef arrSource1 As Variant, ByVal lIndex As Long, ByRef arrSource2 As Variant) As Boolean
'Programming by: Nguyen Duy Tuan - www.bluesofts.net
'arrSource1: is array 1D. Elements of array with VARIANT type
'arrSource2: is array 1D. Elements of array with VARIANT type, it is inserted into arrSource1 at position lIndex
'arrDest: an array 1D contents arrSource1 and arrSource2
Dim I As Long, lLowSource1 As Long, lLowSource2 As Long, lHighSource2 As Long
Erase arrDest 'Free all elements
lLowSource1 = LBound(arrSource1)
'Check the validity of the parameters
If (lIndex < lLowSource1) Or (lIndex > UBound(arrSource1)) Then
lIndex = UBound(arrSource1) + 1 'insert array at the end of arrSource1 array
End If
lLowSource2 = LBound(arrSource2)
lHighSource2 = UBound(arrSource2)
ReDim arrDest(lLowSource1 To UBound(arrSource1) + (lHighSource2 - lLowSource2 + 1)) As Variant
CopyMemory ByVal VarPtr(arrDest(lLowSource1)), _
ByVal VarPtr(arrSource1(lLowSource1)), _
SZ_VARIANT * ((lIndex - lLowSource1))
'Insert arrSource2 into arrSource1 at position lIndex of arrSource1
CopyMemory ByVal VarPtr(arrDest(lIndex)), _
ByVal VarPtr(arrSource2(LBound(arrSource2))), _
SZ_VARIANT * (lHighSource2 - lLowSource2 + 1)
If UBound(arrSource1) >= lIndex Then 'the rest
CopyMemory ByVal VarPtr(arrDest(lIndex + (lHighSource2 - lLowSource2 + 1))), _
ByVal VarPtr(arrSource1(lIndex)), _
SZ_VARIANT * (UBound(arrSource1) - lIndex + 1)
End If
'Erase Source array in memory
ZeroMemory ByVal VarPtr(arrSource1(lLowSource1)), SZ_VARIANT * (UBound(arrSource1) - lLowSource1 + 1)
Erase arrSource1
ZeroMemory ByVal VarPtr(arrSource2(lLowSource2)), SZ_VARIANT * (UBound(arrSource2) - lLowSource2 + 1)
Erase arrSource2
InsertElementArray1D = True
End Function
Function InsertElementArray2D(ByRef arrDest() As Variant, ByRef arrSource1 As Variant, ByVal lIndex As Long, ByRef arrSource2 As Variant) As Boolean
'Programming by: Nguyen Duy Tuan - www.bluesofts.net
'arrSource1: is array 2D. Elements of array with VARIANT type
'arrSource2: is array 2D. Elements of array with VARIANT type, it is inserted into arrSource1 at position lIndex
'arrDest: an array 2D contents arrSource1 and arrSource2
Dim I As Long
Dim lLowSource1D1 As Long, lLowSource1D2 As Long
Dim lLowSource2D1 As Long, lHighSource2D1 As Long
Erase arrDest 'Free all elements
lLowSource1D1 = LBound(arrSource1, 1)
lLowSource1D2 = LBound(arrSource1, 2)
lLowSource2D1 = LBound(arrSource2, 1)
lHighSource2D1 = UBound(arrSource2, 1)
'Check the validity of the parameters
If lIndex < lLowSource1D1 Or lIndex > UBound(arrSource1) Then
lIndex = UBound(arrSource1) + 1 'insert array at the end of arrSource1 array
End If
If (UBound(arrSource1, 2) - LBound(arrSource1, 2)) <> (UBound(arrSource2, 2) - LBound(arrSource2, 2)) Or _
UBound(arrSource1, 2) <> UBound(arrSource2, 2) Then
Err.Raise 10002, "InsertElementArray2D", "arrSource1 and arrSource2 have different structures."
End If
ReDim arrDest(lLowSource1D1 To UBound(arrSource1, 1) + (lHighSource2D1 - lLowSource2D1 + 1), _
lLowSource1D2 To UBound(arrSource1, 2)) As Variant
For I = LBound(arrSource1, 2) To UBound(arrSource1, 2) 'Copy columns
CopyMemory ByVal VarPtr(arrDest(lLowSource1D1, I)), _
ByVal VarPtr(arrSource1(lLowSource1D1, I)), _
SZ_VARIANT * ((lIndex - lLowSource1D1))
Next I
'Insert arrSource2 into arrSource1 at position lIndex of arrSource1
For I = LBound(arrSource1, 2) To UBound(arrSource1, 2) 'Copy columns
CopyMemory ByVal VarPtr(arrDest(lIndex, I)), _
ByVal VarPtr(arrSource2(LBound(arrSource2), I)), _
SZ_VARIANT * (lHighSource2D1 - lLowSource2D1 + 1)
Next I
If UBound(arrSource1, 1) >= lIndex Then 'the rest
For I = LBound(arrSource1, 2) To UBound(arrSource1, 2) 'Copy columns
CopyMemory ByVal VarPtr(arrDest(lIndex + (lHighSource2D1 - lLowSource2D1 + 1), I)), _
ByVal VarPtr(arrSource1(lIndex, I)), _
SZ_VARIANT * (UBound(arrSource1) - lIndex + 1)
Next I
End If
'Erase Source array in memory
For I = LBound(arrSource1, 2) To UBound(arrSource1, 2)
ZeroMemory ByVal VarPtr(arrSource1(lLowSource1D1, I)), _
SZ_VARIANT * (UBound(arrSource1) - lLowSource1D1 + 1)
Next I
Erase arrSource1
For I = LBound(arrSource2, 2) To UBound(arrSource2, 2)
ZeroMemory ByVal VarPtr(arrSource2(lLowSource1D1, I)), _
SZ_VARIANT * (UBound(arrSource2) - lLowSource2D1 + 1)
Next I
Erase arrSource2
InsertElementArray2D = True
End Function
[/GPECODE]
Bộ hàm trên tương thích với các môi trường Windows , Office 32 và 64-bit.
Hy vọng bộ hàm này giúp ích được các bạn khi xây dựng ứng dụng với tốc độ chạy nhanh. Rất mong các bạn góp ý thêm để bộ hàm được hoàn thiện hơn.
Phiên bản mới nhất là FastArray_v1.1
Phiên bản 1.0->1.1 cung cấp các hàm mảng sau:
1. DeleteElementArray1D - Cho phép xoá một hay nhiều phần tử mảng (1 chiều - 1D) liên tiếp
2. DeleteElementArray2D - Cho phép xoá một hay nhiều phần tử mảng (2 chiều - 2D) liên tiếp
3. InsertElementArray1D - Cho phép chèn một mảng dữ liệu vào một mảng đã có vào vị trí bất kỳ. Hàm này làm việc với mảng 1 chiều chiều
4. InsertElementArray2D - Cho phép chèn một mảng dữ liệu vào một mảng đã có vào vị trí bất kỳ. Hàm này làm việc với mảng 2 chiều
5. ConvertArray1DTo2D - Cho phép chuyển đổi từ mảng 1 chiều sang mảng 2 chiều. Hàm này hữu dụng khi ta cần đưa mảng vào bảng tính. Mảng đưa vào muốn trình bày trong một cột thì phải đưa về mảng hai chiều. Đặc biệt nó tốt hơn hàm Excel Application.WorksheetFunction.Transpose() rất nhiều khi làm việc với mảng 1 chiều và số phần tử mảng lớn (lên đến trên 100.000 phần tử).
6. FillToRange - Cho phép điền mảng vào bảng tính tại ô bất kỳ
7. NumberOfDimensions - Đếm số chiều của mảng
8 DeleteColumnArray2D - Xóa cac cột trong mảng 2 chiều
9 InsertColumnArray2D - Chèn thêm các cột từ mảng khác vào mảng 2 chiều
Để biết cách sử dụng các bạn hãy download tập tin "FastArray_vx.x.xls"đính kèm.
(*) Khi sử dụng cần lưu ý:
+ Các phần tử của mảng phải là kiểu VARIANT
+ Đọc kỹ các comment trong mỗi hàm để nắm được quy tắc cũng như mục đích sử dụng hàm và của từng tham số.
Mã nguồn các hàm dưới đây:
[GPECODE=vb]
Function DeleteElementArray1D(ByRef arrDest() As Variant, ByRef arrSource As Variant, ByVal lIndexBegin As Long, ByVal lIndexEnd As Long) As Boolean
'Programming by: Nguyen Duy Tuan - www.bluesofts.net
'arrSource: is array 1D. Elements of array with VARIANT type
'arrDest: an array 1D after deleting element from lIndexBegin to lIndexEnd. Elements of array with VARIANT type
Dim I As Long, lLowSource As Long
Erase arrDest 'Free all elements
lLowSource = LBound(arrSource)
'Check the validity of the parameters
If (lIndexEnd < lLowSource) Or (lIndexEnd > UBound(arrSource)) Then
lIndexEnd = UBound(arrSource)
End If
If lIndexBegin < lLowSource Then
Err.Raise 10000, "DeleteElementArray1D", "Parameter lIndexBegin is invalid."
End If
If (lIndexBegin > lIndexEnd) Then
Err.Raise 10001, "DeleteElementArray1D", "You must ensure that lIndexBegin <= lIndexEnd."
End If
If (lIndexEnd - lIndexBegin) = (UBound(arrSource) - lLowSource) Then '<==> Clear all elements of array
ReDim arrDest(lLowSource To lLowSource)
DeleteElementArray1D = True
Exit Function
End If
ReDim arrDest(lLowSource To UBound(arrSource) - (lIndexEnd - lIndexBegin + 1)) As Variant
CopyMemory ByVal VarPtr(arrDest(lLowSource)), _
ByVal VarPtr(arrSource(lLowSource)), _
SZ_VARIANT * ((lIndexBegin - lLowSource))
If UBound(arrSource) > lIndexEnd Then 'the rest
CopyMemory ByVal VarPtr(arrDest(lIndexBegin)), _
ByVal VarPtr(arrSource(lIndexEnd + 1)), _
SZ_VARIANT * (UBound(arrSource) - lIndexEnd)
End If
'Erase Source array in memory
'Must move bytes should be deleted from arrSource(lIndexBegin to lIndexEnd) into arrDelSource to free them in memory
ReDim arrDelSource(lIndexBegin To lIndexEnd) As Variant
CopyMemory ByVal VarPtr(arrDelSource(lIndexBegin)), _
ByVal VarPtr(arrSource(lIndexBegin)), _
SZ_VARIANT * (lIndexEnd - lIndexBegin + 1)
Erase arrDelSource
ZeroMemory ByVal VarPtr(arrSource(lLowSource)), SZ_VARIANT * (UBound(arrSource) - lLowSource + 1)
Erase arrSource
DeleteElementArray1D = True
End Function
Function DeleteElementArray2D(ByRef arrDest() As Variant, ByRef arrSource As Variant, ByVal lIndexBegin As Long, ByVal lIndexEnd As Long) As Boolean
'Programming by: Nguyen Duy Tuan - www.bluesofts.net
'arrSource: is array 2D. Elements of array with VARIANT type
'arrDest: an array after deleting element from lIndexBegin to lIndexEnd. Elements of array with VARIANT type
Dim I As Long, lLowSourceD1 As Long, lLowSourceD2 As Long
Erase arrDest 'Free all elements
lLowSourceD1 = LBound(arrSource, 1)
lLowSourceD2 = LBound(arrSource, 2)
'Check the validity of the parameters
If (lIndexEnd < lLowSourceD1) Or (lIndexEnd > UBound(arrSource, 1)) Then
lIndexEnd = UBound(arrSource, 1)
End If
If lIndexBegin < lLowSourceD1 Then
Err.Raise 10000, "DeleteElementArray2D", "Parameter lIndexBegin is invalid."
End If
If lIndexBegin > lIndexEnd Then
Err.Raise 10001, "DeleteElementArray2D", "You must ensure that lIndexBegin <= lIndexEnd."
End If
ReDim arrDest(lLowSourceD1 To UBound(arrSource, 1) - (lIndexEnd - lIndexBegin + 1), _
lLowSourceD2 To UBound(arrSource, 2)) As Variant
For I = LBound(arrSource, 2) To UBound(arrSource, 2) 'Copy columns
CopyMemory ByVal VarPtr(arrDest(lLowSourceD1, I)), _
ByVal VarPtr(arrSource(lLowSourceD1, I)), _
SZ_VARIANT * (lIndexBegin - lLowSourceD1)
Next I
If UBound(arrSource) > lIndexEnd Then
For I = LBound(arrSource, 2) To UBound(arrSource, 2)
CopyMemory ByVal VarPtr(arrDest(lIndexBegin, I)), _
ByVal VarPtr(arrSource(lIndexEnd + 1, I)), _
SZ_VARIANT * (UBound(arrSource) - lIndexEnd)
Next I
End If
'Erase Source array in memory
ReDim arrDelSource(lIndexBegin To lIndexEnd, lLowSourceD2 To UBound(arrSource, 2)) As Variant
For I = LBound(arrSource, 2) To UBound(arrSource, 2)
'Must move bytes should be deleted from arrSource(lIndexBegin to lIndexEnd) into arrDelSource to free them in memory
CopyMemory ByVal VarPtr(arrDelSource(lIndexBegin, I)), _
ByVal VarPtr(arrSource(lIndexBegin, I)), _
SZ_VARIANT * (lIndexEnd - lIndexBegin + 1)
ZeroMemory ByVal VarPtr(arrSource(lLowSourceD1, I)), SZ_VARIANT * (UBound(arrSource) - lLowSourceD1 + 1)
Next I
Erase arrDelSource
Erase arrSource
DeleteElementArray2D = True
End Function
Function DeleteColumnArray2D(ByRef arrDest() As Variant, ByRef arrSource As Variant, ByVal lIndexBegin As Long, ByVal lIndexEnd As Long) As Boolean
'Programming by: Nguyen Duy Tuan - www.bluesofts.net
'arrSource: is array 2D. Elements of array with VARIANT type
'arrDest: an array2D after deleting columns of data from lIndexBegin to lIndexEnd. Elements of array with VARIANT type
Dim I As Long, lLowSourceD1 As Long, lHighSourceD1 As Long, lLowSourceD2 As Long
Erase arrDest 'Free all elements
lLowSourceD1 = LBound(arrSource, 1)
lHighSourceD1 = UBound(arrSource, 1)
lLowSourceD2 = LBound(arrSource, 2)
'Check the validity of the parameters
If (lIndexEnd < lLowSourceD2) Or (lIndexEnd > UBound(arrSource, 2)) Then
lIndexEnd = UBound(arrSource, 2)
End If
If lIndexBegin < lLowSourceD1 Then
Err.Raise 10000, "DeleteElementArray2D", "Parameter lIndexBegin is invalid."
End If
If lIndexBegin > lIndexEnd Then
Err.Raise 10001, "DeleteElementArray2D", "You must ensure that lIndexBegin <= lIndexEnd."
End If
ReDim arrDest(lLowSourceD1 To UBound(arrSource, 1), _
lLowSourceD2 To UBound(arrSource, 2) - (lIndexEnd - lIndexBegin + 1)) As Variant
Dim lColIndex As Long
lColIndex = lLowSourceD2 - 1
For I = lLowSourceD2 To UBound(arrSource, 2) 'Copy columns
If I < lIndexBegin Or I > lIndexEnd Then
lColIndex = lColIndex + 1
CopyMemory ByVal VarPtr(arrDest(lLowSourceD1, lColIndex)), _
ByVal VarPtr(arrSource(lLowSourceD1, I)), _
SZ_VARIANT * ((lHighSourceD1 - lLowSourceD1 + 1))
End If
Next I
DeleteColumnArray2D = True
'Erase Source array in memory
ReDim arrDelSource(lLowSourceD1 To lHighSourceD1, _
lIndexBegin To lIndexEnd) As Variant
lColIndex = lIndexBegin - 1
For I = LBound(arrSource, 2) To UBound(arrSource, 2)
'Must move bytes should be deleted from arrSource(lIndexBegin to lIndexEnd) into arrDelSource to free them in memory
If I >= lIndexBegin And I <= lIndexEnd Then
lColIndex = lColIndex + 1
CopyMemory ByVal VarPtr(arrDelSource(lLowSourceD1, lColIndex)), _
ByVal VarPtr(arrSource(lLowSourceD1, I)), _
SZ_VARIANT * ((lHighSourceD1 - lLowSourceD1 + 1))
End If
ZeroMemory ByVal VarPtr(arrSource(lLowSourceD1, I)), SZ_VARIANT * (lHighSourceD1 - lLowSourceD1 + 1)
Next I
Erase arrDelSource
Erase arrSource
End Function
Function InsertElementArray1D(ByRef arrDest() As Variant, ByRef arrSource1 As Variant, ByVal lIndex As Long, ByRef arrSource2 As Variant) As Boolean
'Programming by: Nguyen Duy Tuan - www.bluesofts.net
'arrSource1: is array 1D. Elements of array with VARIANT type
'arrSource2: is array 1D. Elements of array with VARIANT type, it is inserted into arrSource1 at position lIndex
'arrDest: an array 1D contents arrSource1 and arrSource2
Dim I As Long, lLowSource1 As Long, lLowSource2 As Long, lHighSource2 As Long
Erase arrDest 'Free all elements
lLowSource1 = LBound(arrSource1)
'Check the validity of the parameters
If (lIndex < lLowSource1) Or (lIndex > UBound(arrSource1)) Then
lIndex = UBound(arrSource1) + 1 'insert array at the end of arrSource1 array
End If
lLowSource2 = LBound(arrSource2)
lHighSource2 = UBound(arrSource2)
ReDim arrDest(lLowSource1 To UBound(arrSource1) + (lHighSource2 - lLowSource2 + 1)) As Variant
CopyMemory ByVal VarPtr(arrDest(lLowSource1)), _
ByVal VarPtr(arrSource1(lLowSource1)), _
SZ_VARIANT * ((lIndex - lLowSource1))
'Insert arrSource2 into arrSource1 at position lIndex of arrSource1
CopyMemory ByVal VarPtr(arrDest(lIndex)), _
ByVal VarPtr(arrSource2(LBound(arrSource2))), _
SZ_VARIANT * (lHighSource2 - lLowSource2 + 1)
If UBound(arrSource1) >= lIndex Then 'the rest
CopyMemory ByVal VarPtr(arrDest(lIndex + (lHighSource2 - lLowSource2 + 1))), _
ByVal VarPtr(arrSource1(lIndex)), _
SZ_VARIANT * (UBound(arrSource1) - lIndex + 1)
End If
'Erase Source array in memory
ZeroMemory ByVal VarPtr(arrSource1(lLowSource1)), SZ_VARIANT * (UBound(arrSource1) - lLowSource1 + 1)
Erase arrSource1
ZeroMemory ByVal VarPtr(arrSource2(lLowSource2)), SZ_VARIANT * (UBound(arrSource2) - lLowSource2 + 1)
Erase arrSource2
InsertElementArray1D = True
End Function
Function InsertElementArray2D(ByRef arrDest() As Variant, ByRef arrSource1 As Variant, ByVal lIndex As Long, ByRef arrSource2 As Variant) As Boolean
'Programming by: Nguyen Duy Tuan - www.bluesofts.net
'arrSource1: is array 2D. Elements of array with VARIANT type
'arrSource2: is array 2D. Elements of array with VARIANT type, it is inserted into arrSource1 at position lIndex
'arrDest: an array 2D contents arrSource1 and arrSource2
Dim I As Long
Dim lLowSource1D1 As Long, lLowSource1D2 As Long
Dim lLowSource2D1 As Long, lHighSource2D1 As Long
Erase arrDest 'Free all elements
lLowSource1D1 = LBound(arrSource1, 1)
lLowSource1D2 = LBound(arrSource1, 2)
lLowSource2D1 = LBound(arrSource2, 1)
lHighSource2D1 = UBound(arrSource2, 1)
'Check the validity of the parameters
If lIndex < lLowSource1D1 Or lIndex > UBound(arrSource1) Then
lIndex = UBound(arrSource1) + 1 'insert array at the end of arrSource1 array
End If
If (UBound(arrSource1, 2) - LBound(arrSource1, 2)) <> (UBound(arrSource2, 2) - LBound(arrSource2, 2)) Or _
UBound(arrSource1, 2) <> UBound(arrSource2, 2) Then
Err.Raise 10002, "InsertElementArray2D", "arrSource1 and arrSource2 have different structures."
End If
ReDim arrDest(lLowSource1D1 To UBound(arrSource1, 1) + (lHighSource2D1 - lLowSource2D1 + 1), _
lLowSource1D2 To UBound(arrSource1, 2)) As Variant
For I = LBound(arrSource1, 2) To UBound(arrSource1, 2) 'Copy columns
CopyMemory ByVal VarPtr(arrDest(lLowSource1D1, I)), _
ByVal VarPtr(arrSource1(lLowSource1D1, I)), _
SZ_VARIANT * ((lIndex - lLowSource1D1))
Next I
'Insert arrSource2 into arrSource1 at position lIndex of arrSource1
For I = LBound(arrSource1, 2) To UBound(arrSource1, 2) 'Copy columns
CopyMemory ByVal VarPtr(arrDest(lIndex, I)), _
ByVal VarPtr(arrSource2(LBound(arrSource2), I)), _
SZ_VARIANT * (lHighSource2D1 - lLowSource2D1 + 1)
Next I
If UBound(arrSource1, 1) >= lIndex Then 'the rest
For I = LBound(arrSource1, 2) To UBound(arrSource1, 2) 'Copy columns
CopyMemory ByVal VarPtr(arrDest(lIndex + (lHighSource2D1 - lLowSource2D1 + 1), I)), _
ByVal VarPtr(arrSource1(lIndex, I)), _
SZ_VARIANT * (UBound(arrSource1) - lIndex + 1)
Next I
End If
'Erase Source array in memory
For I = LBound(arrSource1, 2) To UBound(arrSource1, 2)
ZeroMemory ByVal VarPtr(arrSource1(lLowSource1D1, I)), _
SZ_VARIANT * (UBound(arrSource1) - lLowSource1D1 + 1)
Next I
Erase arrSource1
For I = LBound(arrSource2, 2) To UBound(arrSource2, 2)
ZeroMemory ByVal VarPtr(arrSource2(lLowSource1D1, I)), _
SZ_VARIANT * (UBound(arrSource2) - lLowSource2D1 + 1)
Next I
Erase arrSource2
InsertElementArray2D = True
End Function
[/GPECODE]
Bộ hàm trên tương thích với các môi trường Windows , Office 32 và 64-bit.
Hy vọng bộ hàm này giúp ích được các bạn khi xây dựng ứng dụng với tốc độ chạy nhanh. Rất mong các bạn góp ý thêm để bộ hàm được hoàn thiện hơn.
Phiên bản mới nhất là FastArray_v1.1
File đính kèm
Lần chỉnh sửa cuối: