قصدتون رو از اینکه محتویات آرایه رو در یک آرایه دیگه کپی می کنید نمی دونم، ولی به هر حال اگه آرایه شما همچنان
دو بعدی باشه و الگوریتم درستی هم اجرا کنید (نه این کدی که شما نوشتید ناقصه) خانه های خالی آرایه
zmat همچنان وجود خواهند داشت، تنها تفاوت در اینه که خانه های خالی zmat به انتهای ستون ها انتقال می یابند.
برای انتقال کامل و بدون تغییر محتویات یک آرایه کد B = A کافیست :
کد:
Private Sub Form_Load()
Dim A(1 To 10, 1 To 5) As Variant
Dim B() As Variant
A(3, 4) = "my name"
[B]B = A[/B]
MsgBox B(3, 4)
End Sub
اگر می خواهید تعداد ستون های آرایه در هر سطر با سطر های دیگر فرق کنه، بایستی یک آرایه یک بعدی از نوع
Variant بسازید، یک متغیر Variant خودش می تواند یک آرایه چند بعدی را در خود جای بدهد.
برای همین هر عنصر از آرایه یک بعدی ما می تواند خودش یک آرایه با هر طول دلخواه و متفاوتی باشد.
یک مثال می زنم، در کد زیر ما یک آرایه تک بعدی دو عضوی A داریم که هر عضو از آن خودش یک آرایه است.
ترکیب این سه آرایه A و a1 و a2 یک آرایه دوبعدی است که دو سطر دارد و سطر اولش 3 عنصر و سطر دومش 5 عنصر دارد.
مثلا برای دسترسی به عنصر ستون پنجم در سطر دوم بایستی از کد (5)(2)A استفاده کرد و نه (2,5)A
کد:
Private Sub Form_Load()
Dim A(1 To 2) As Variant
Dim a1(1 To 3) As Variant
Dim a2(1 To 5) As Variant
A(1) = a1
A(2) = a2
A(1)(3) = "my name"
A(2)(5) = "my family"
MsgBox A(1)(3)
MsgBox A(2)(5)
End Sub
کدی که شما نوشتید ناقص است، بدین دلیل که شما ابتدا بایستی یک طول مشخص و اضافی برای zmat در نظر بگیرید،
سپس محتویات آرایه را به داخل zmat انتقال دهید، و در انتها طول دقیق آرایه zmat را تعیین کنید.
استفاده از واژه کلیدی Preserve در هنگام استفاده از دستور Redim مانع از بین رفتن محتویات آرایه در هنگام
تغییر طول آن می شود. اگر از Preserve استفاده نشود، محتویات آرایه پاک می شوند.
دقت کنید که Redim صرفا می تواند طول آخرین اندیس آرایه را تغییر دهد و طول اندیس های قبلی
(در آرایه های دو بعدی و بیشتر) غیر قابل تغییر است.
در ضمن دقت کنید که متغیر های حلقه حتما نوع صحیح بدون اعشار (اصولا Long) باشند و نه Single
شمارش اعداد در متغیر های اعشاری مثل Single قابل اعتماد نیستند و خطای گرد کردن اعشاری در آنها دردسر آفرین است.
تابع FilterNumbers را بر اساس کد شما ساختم، محتویات آرایه zmat توسط این تابع برگردانده می شود و سطر های
اضافی حذف می گردند. اگر آرایه حاصل به هر دلیل تهی باشد یک آرایه دوبعدی برگردانده می شود که یک سطر و
یک ستون (یک عضو) دارد. دلیل این امر اینست که اگر آرایه را تهی کنیم و بخواهید از UBound یا LBound
استفاده کنید، پیغام خطا دریافت خواهید کرد. برای جلوگیری از بروز خطا یک آرایه دو بعدی تک عنصری برمی گرداند.
کد:
Public Function [B]FilterNumbers[/B](ByRef A() As Variant) As Variant
Dim CountLine As Long
Dim CountColumn As Long
Dim zmat() As Variant
Dim i As Long
Dim j As Long
CountLine = 0
ReDim zmat(1 To UBound(A, 1), 1 To UBound(A, 2))
For i = 1 To UBound(A, 2)
CountColumn = 0
For j = 1 To UBound(A, 1)
If IsNumeric(A(j, i)) Then
If CountColumn = 0 Then CountLine = CountLine + 1
CountColumn = CountColumn + 1
zmat(CountColumn, CountLine) = A(j, i)
End If
Next j
Next i
If CountLine = 0 Then
ReDim zmat(1 To 1, 1 To 1)
zmat(1, 1) = ""
Else
ReDim Preserve zmat(1 To UBound(A, 1), 1 To CountLine)
End If
FilterNumbers = zmat
End Function
نحوه استفاده از تابع اینچنین است :
کد:
Dim zmat() As Variant
zmat = [B]FilterNumbers[/B](A)
ShowArray zmat
اکنون zmat دیگر سطر خالی نخواهد داشت، اما همانطور که گفتم اگر در یک سطر از آرایه zmat مقادیر غیر عددی
وجود داشته باشند، به تعداد آن عناصر غیر عددی، در ستون های آخر همان سطر خانه خالی وجود خواهد داشت.
دلیل این امر این است که همچنان zmat یک آرایه دو بعدی است که اجبار تعداد ستون های هر سطر آن یکسان است.