قرار دادن یک فایل تکست در ماتریس در ویژوال بیسیک

zhm

New Member
سلام.یک فایل تکست دارم که چندتا ستون و سطر از اعداد داره.میخوام این فایل رو تو ویژوال بخونم و داخل یک ماتریس(هر عدد در یک درایه)قرار بدم.طوریکه برای ماتریس( mat(i,jبه هر space رسید به شمارنده i یک واحد و به انتهای سطر رسید به شمارنده j یک واحد اضافه کنه.
اگر بتونین کمکم کنین خیلی ممنون میشم
 

the_king

مدیرکل انجمن
سلام.یک فایل تکست دارم که چندتا ستون و سطر از اعداد داره.میخوام این فایل رو تو ویژوال بخونم و داخل یک ماتریس(هر عدد در یک درایه)قرار بدم.طوریکه برای ماتریس( mat(i,jبه هر space رسید به شمارنده i یک واحد و به انتهای سطر رسید به شمارنده j یک واحد اضافه کنه.
اگر بتونین کمکم کنین خیلی ممنون میشم

من یک ماژول (Module) با نام ModuleArray ساختم که شامل دو تابع است :

تابع ReadFile محتویات یک فایل را بصورت یک آرایه دو بعدی برمی گرداند و دو پارامتر ورودی دارد :
پارامتر اول آن مسیر (Path) فایلی است که می خواهید بخوانید و پارامتر دوم تعداد ستون های آرایه است.
اگر تعداد ستون های درون فایل کمتر از مقدار مورد نظر باشد، بقیه ستونها با رشته تهی "" پر می شوند،
و اگر تعداد ستونهای داخل فایل بیشتر از مقدار تعیین شده باشد ستونهای اضافی دور ریخته می شوند.

اگر فایل مورد نظر تهی باشد، آرایه شامل یک سطر شامل مقادیر رشته تهی "" خواهد بود.
تابع ReadFile می تواند بجای عدد کلمات را هم در آرایه قرار دهد.

اندیس های آرایه چه در سطر و چه در ستون از مقدار 1 آغاز خواهند شد، به عبارتی دیگر (A(1,1 اولین سطر و ستون
آرایه A می باشد.

مثلا کد زیر محتویات فایل test.txt را در آرایه دو بعدی A می خواند، آرایه A به تعداد 2 ستون خواهد داشت :
کد:
    Dim A() As Variant
    A = [B]ReadFile[/B]("test.txt", 2)

برای آنکه تعداد سطر های آرایه را تشخیص دهید از تابع اصلی زبان ویژوال بیسیک به نام UBound استفاده کنید.
کد زیر تعداد سطر های آرایه A را در متغیر Count قرار می دهد (پارامتر دوم را برابر 2 قرار خواهید داد زیرا اگر مقدار
پارامتر دوم را تعیین نکنید یا برابر 1 قرار دهید، بجای تعداد سطر های آرایه، تعداد ستون های آنرا دریافت می کنید) :
کد:
    Dim A() As Variant
    Dim Count As Long
    Count = [B]UBound[/B](A, [B]2[/B])

همچنین یک تابع ShowArray ساختم که محتویات یک آرایه دو بعدی را نمایش دهد.
این تابع تنها یک پارامتر ورودی دارد که همان آرایه خواهد بود. مثلا کد زیر محتویات آرایه A را نمایش می دهد :

کد:
    [B]ShowArray[/B] A

فرض کنیم که یک فایل متنی با نام Input.txt داریم که محتویات آن چنین است :
کد:
1	2	3
4	5	6
7	8	9
10	11	12
13	14	15

یعنی 5 سطر که در هر کدام 3 ستون عدد وجود دارد.

کد زیر محتویات این فایل را که در فایل "Input.txt" قرار دارد از مسیر فعلی برنامه خواهد خواند و نمایش می دهد :

کد:
    Dim Path As String
    Dim A() As Variant
    Path = App.Path & IIf(Right(Path, 1) = "\", "", "\") & "Input.txt"
    A = [B]ReadFile[/B](Path, 3)
    [B]ShowArray[/B] A

کد کامل ماژول ModuleArray به همراه یک پروژه نمونه و فایل اجرایی exe ضمیمه این پست می باشد.
 

پیوست ها

  • Read Array.zip
    6.6 کیلوبایت · بازدیدها: 29

zhm

New Member
ممنون خیلی خیلی لطف کردین!فقط یه سوال: اگه تعداد ستونها رو ندونم باید چکار کنم؟ در مورد این خط هم میشه یه توضیح بدین؟
("\",'"","\"=(IIf(Right(Path
البته تا همین جا هم خیلی خیلی کمکم کردین!خیلی ممنون
 

the_king

مدیرکل انجمن
ممنون خیلی خیلی لطف کردین!فقط یه سوال: اگه تعداد ستونها رو ندونم باید چکار کنم؟

طبیعیه که شما آرایه ای نخواهید داشت مگر آنکه بدانید به چه طولی آنرا بسازید، پیشنهاد می کنم حداکثر طول ستون
ممکن را در نظر بگیرید، مثلا 20 ستون. ستونهای خالی با مقدار "" پر می شوند.

در مورد این خط هم میشه یه توضیح بدین؟

کد:
IIf(Right(Path, 1) = "\", "", "\")

البته تا همین جا هم خیلی خیلی کمکم کردین!خیلی ممنون
فرض کنید که مسیر اجرا برنامه شاخه C:\MyProg باشه، آنوقت برای آنکه مسیر C:\MyProg\Input.txt بسازید
علاوه بر نام فایل Input.txt بایستی یک کاراکتر \ را به آن اضافه کنید.
اما نکته اینجا است که این یک حالت استثنا دارد، در مسیر ریشه درایو ها مثلا \:C این کاراکتر \ به خودی خود وجود دارد
و نباید کاراکتر \ دیگری اضافه شود.

در کدی که نوشته بودم تابع IIf دو حالت را بررسی می کند، اگر اولین کاراکتر سمت راست رشته یعنی (Right(Path, 1
برابر با \ بود رشته تهی "" و در غیر اینصورت کاراکتر \ را به آن اضافه می کند.
این کد تضمین می کند که هنگامی که رشته Path به نام فایل اضافه می شود، همواره یک و فقط یک کاراکتر \ مابین آنها
باشد.
 

zhm

New Member
بازم خیلی ممنون!واقعا لطف بزرگی در حق من کردین.
 

zhm

New Member
خیلی خیلی شرمنده اما بازم یه مشکل دیگه!تعداد ستونها که زیاد میشه(20تا) همه سطر ها رو چاپ نمیکنه!مشکل از کجاست؟:(
 

the_king

مدیرکل انجمن
خیلی خیلی شرمنده اما بازم یه مشکل دیگه!تعداد ستونها که زیاد میشه(20تا) همه سطر ها رو چاپ نمیکنه!مشکل از کجاست؟:(

من اون تابع ShowArray را به عنوان یک مثال مطرح کردم تا صحت کار برنامه و نحوه نمایش اطلاعات رو نشون بدم، وگرنه
تابع MessageBox از نظر حداکثر طول رشته ای که می تونه نمایش بده محدودیت داره، و از اون مهمتر اینکه برای ScrollBar
و تعداد سطر و ستون های زیاد هم قابلیتی در نظر گرفته نشده.

اگر قصد دارید محتویات داده ای زیادی را نمایش دهید می بایستی مقادیر را در داخل یک فروم و درون یک کنترل Table درج کنید.
من یک تابع ()ShowArrayOnTable را به برنامه اضافه کردم که محتویات یک آرایه دو بعدی (پارامتر اول تابع) را در یک MSFlexGrid
نمایش می دهد.

مثلا کد زیر محتویات آرایه دوبعدی A را در درون کنترل MSFlexGrid1 نمایش می دهد :

کد:
    [B]ShowArrayOnTable[/B] A, MSFlexGrid1

کد کامل ویرایش جدید ماژول ModuleArray به همراه یک پروژه نمونه و فایل اجرایی exe ضمیمه این پست می باشد.
 

پیوست ها

  • Read Array.zip
    8 کیلوبایت · بازدیدها: 22
آخرین ویرایش توسط مدیر:
  • Like
Reactions: zhm

zhm

New Member
واقعاً شرمنده ام که بازم برای مشکلم مزاحم شما میشم.خیلی سعی کردم خودم مشکلمو حل کنم و مزاحم شما نشم اما نتونستم.کاش میتونستم لطفتونو جبران کنم.
این error چه زمانی اتفاق میافته و چطور میشه رفع کرد؟
subscript out of range
علت اینکه این سؤالو اینجا پرسیدم اینه که در ادامه همین برنامه میخوام ستون اول آرایه A را در یک ماتریس دیگه بریزم.دستور زیر تا i=11 اجرا میشه و در i=11 این error رو میده

dim xmat(100) as single
(countline=ubound(A,2
for i=1 to countline
if isnumeric(A(i,1) then
(xmat(i)=A(i,1
end if
next i
در ضمن آرایه A 25 سطر داره.بازم ممنون
 

the_king

مدیرکل انجمن
واقعاً شرمنده ام که بازم برای مشکلم مزاحم شما میشم.خیلی سعی کردم خودم مشکلمو حل کنم و مزاحم شما نشم اما نتونستم.کاش میتونستم لطفتونو جبران کنم.
این error چه زمانی اتفاق میافته و چطور میشه رفع کرد؟
subscript out of range
علت اینکه این سؤالو اینجا پرسیدم اینه که در ادامه همین برنامه میخوام ستون اول آرایه A را در یک ماتریس دیگه بریزم.دستور زیر تا i=11 اجرا میشه و در i=11 این error رو میده

dim xmat(100) as single
(countline=ubound(A,2
for i=1 to countline
if isnumeric(A(i,1) then
(xmat(i)=A(i,1
end if
next i
در ضمن آرایه A 25 سطر داره.بازم ممنون

خواهش می کنم، مزاحمتی نیست.
من داخل کد شما سه اشکال می بینم :

اولین مشکل مربوط به حلقه i است، شما CountLine را برابر تعداد سطرهای آرایه A قرار داده اید، یعنی (UBound(A,2 که
اندیس دوم آرایه A است، اما در هنگام انتقال دادن محتویات یک خانه از آرایه A متغیر i را در اندیس اول (ستون ها) قرار داده اید.
طبیعی است که تعداد سطر ها (CountLine) با تعداد ستون های آرایه A برابر نیست و خطا می دهد.
اگر منظور شما از i تعداد ستون های آرایه A است، بجای (UBound(A,2 از (UBound(A,1 استفاده کنید.


مساله دوم آن شرط ((IsNumeric(A(i,1 است، اگر این شرط برقرار نباشد، اندیس i افزایش می یابد ولی چیزی داخل
xmat نوشته نمی شود، در واقع شما داخل xmat خانه های خالی بدون مقدار تعیین شده (در این کد مقدار آن خانه ها 0 است)
خواهید داشت. اگر می خواهید خانه های خالی در درون xmat ایجاد نشوند، یک متغیر جدید با نام Count تعریف کنید که
پیش از اجرای حلقه i مقدارش صفر باشد (Count = 0)
هر زمانی که شرط ((IsNumeric(A(i,1 برقرار بود، مقدار Count را یک واحد افزایش دهید (Count = Count + 1) و بجای
اندیس i در xmat از اندیس Count استفاده کنید ( (xmat(Count) = A(i,1 )

این تغییر تضمین می کند که در xmat خانه خالی نخواهید داشت، البته الزاما تعداد خانه های xmat با تعداد ستون های A
برابر نخواهد بود و Count تعداد ستون های xmat را نشان می دهد.

مساله سوم، تعریف کردن آرایه xmat است، شما آرایه xmas را به شیوه (xmat(100 تعریف کردید، بصورت پیشفرض اندیس
اول این آرایه 0 خواهد بود و نه 1 ، در واقع شما یک خانه اضافی در اندیس 0 دارید که بکار برده نمی شود.
اگر می خواهید مطابق حلقه i اولین خانه آرایه اندیس 1 باشد، آرایه xmas را به شیوه (xmat(1 To 100 تعریف کنید.
 

zhm

New Member
من که نمیتونم محبت شما رو جبران کنم،از خدا میخوام خودش لطفتونو در حق من جبران کنه!
 

zhm

New Member
اونقد پاسخهاتون کامله که با وجود اینکه هیچی از ویژوال بیسیک نمیدونم کاملاً متوجه میشم .سؤالایی که اینجا پرسیدم بعضی هاشو جاهای دیگه هم پرسیدم اما جوابای خوب و کاملتون باعث میشه بازم مزاحمتون بشم .واقعاً شرمنده ام.اما مشکل این دفعه ام:فایل تکست من هیچ سطر خالی ای نداره ، وقتی برنامه میخونش و در msflrxgrid هم نشونس میده درست نشون میده، اما وقتی تو یه ماتریس دیگه میریزم یک عالمه سطر اضافه میشه که همه درایه هاشون صفرن!این سطرهای صفر از کجا ایجاد میشن؟همونطور که قسمت قبل گفتین متغیر count هم تعریف کردم(یکی برای شمارنده سطرها (که کنترل میکنه اگر همه درایه های سطر عدد باشن به countline یک واحد اضافه میشه و یکی هم برای شمارش ستونها) این بار مشکل چیه؟!!
Dim countline As Single
Dim countcolumn As Single
Dim temp As Boolean
countline= 0
( For i = 1 To UBound(A, 2
(For j = 1 To UBound(A, 1
If IsNumeric(A(j, i)) Then temp = True
Next j
If temp = True Then
countline= countline + 1
( For j = 2 To UBound(A, 1
If IsNumeric(A(j, i)) Then
countcolumn = countcolumn + 1
( zmat(countcolumn, countline) = A(j, i
End If
Next j
End If
countc = 0
temp = False
Next i
برای نشون دادن ماتریس zmat هم از کدی که قبلاً خودتون نوشته بودین استفاده کردم!
(For RowIndex = LBound(zmat, 2) To UBound(zmat, 2
( For ColumnIndex = LBound(zmat, 1) To UBound(zmat, 1
Text = Text & zmat(ColumnIndex, RowIndex) & IIf(ColumnIndex < UBound(zmat, 1), vbTab,"") Next
If RowIndex < UBound(zmat, 2) Then Text = Text & vbNewLine
Next
MsgBox Text
 
آخرین ویرایش:

the_king

مدیرکل انجمن
قصدتون رو از اینکه محتویات آرایه رو در یک آرایه دیگه کپی می کنید نمی دونم، ولی به هر حال اگه آرایه شما همچنان
دو بعدی باشه و الگوریتم درستی هم اجرا کنید (نه این کدی که شما نوشتید ناقصه) خانه های خالی آرایه
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 یک آرایه دو بعدی است که اجبار تعداد ستون های هر سطر آن یکسان است.
 
  • Like
Reactions: zhm

zhm

New Member
بازم ممنون!باورم نمیشه آدمایی مثله شما باشن که بدون اینکه حتی کسی رو بشناسین اینقد کمکش کنین! با کمکاتون شرمندم کردین.
دلیل اینکه میخوام درایه های ماتریس aرا بریززم تو ماتریس z اینه که: ستون اول ماتریس a مقادیر(x(i و سطر اول مقادیر (y(j و بقیه ی سطرها و ستونها مقادیر( z(i,j هستن، که نهایتاً باید تصویری که این ماتریسها میدن کشیده بشه!برای من که نه رشته ام کامپیوتره و نه از برنامه نویسی چیزی میدونم خیی کار سختیه!! تا اینجا با لطف شما پیش اومدم.امیدوارم بتونم بقیه کار رو خودم انجام بدم و مزاحمتون نشم.بازم یه دنیا ممنونم...
 
مربوط به سوالم از the_king عزیز...

مربوط به سوالم از the_king عزیز...
 

پیوست ها

  • topo-ascii.rar
    64.6 کیلوبایت · بازدیدها: 6

zhm

New Member
سوال visual basic

سلام به همه ! بازم یه سوال:sad:
چطور یه ماتریس رو بدون اینکه نظمش بهم بخوره و بین سطرهاش سطر اضافه ایجاد نشه بریزم تو یه فایل تکست؟
قبلاً برعکس این رو پرسیده بودم(خوندن ماتریس از فایل تکست).این دفعه هم ممنون میشم جوابمو بدین.
:rose:
 

the_king

مدیرکل انجمن
سلام به همه ! بازم یه سوال:sad:
چطور یه ماتریس رو بدون اینکه نظمش بهم بخوره و بین سطرهاش سطر اضافه ایجاد نشه بریزم تو یه فایل تکست؟
قبلاً برعکس این رو پرسیده بودم(خوندن ماتریس از فایل تکست).این دفعه هم ممنون میشم جوابمو بدین.
:rose:

از تابع SaveArray زیر استفاده کنید :

کد:
Private Sub [B]SaveArray[/B](ByVal Path As String, ByRef VarArray As Variant)
    Dim Col As Long, Row As Long, FileNo As Integer
    FileNo = FreeFile
    Open Path For Output As FileNo
    For Row = LBound(VarArray, 1) To UBound(VarArray, 1)
        For Col = LBound(VarArray, 2) To UBound(VarArray, 2) - 1
            Print #FileNo, VarArray(Row, Col); ",";
        Next
        Print #FileNo, VarArray(Row, Col)
    Next
    Close FileNo
End Sub

مثلا در کد زیر محتویات آرایه 4 سطر و 8 ستونی A را در داخل فایل C:\array.txt ذخیره می کند :
کد:
    Dim A(1 To 4, 1 To 8) As Long
    [B]SaveArray[/B] "C:\array.txt", A
 
  • Like
Reactions: zhm

the_king

مدیرکل انجمن
مربوط به سوالم از the_king عزیز...
فایل های پیوستی :
topo-ascii.rar

دو مساله در مورد ساختار فایل متنی ضمیمه شده وجود داشت :
مورد اول اینکه تعداد سطر و ستون های ماتریس در داخل فایل مشخص شده بود و پیش از گشودن فایل از مقدار آنها اطلاعی
نداشتیم، در نتیجه استفاده از تابع ReadFile برای این منظور مناسب نبود.
مورد دوم محتویات چندین سطر اول فایل بود که ارتباطی با مقادیر خود ماتریس اعداد نداشت و بایستی نادیده گرفته می شد.

تابع ReadFileEx زیر یک نمونه تکمیلی از ReadFile است که با ساختار آن فایل متنی پیوستی مطابقت دارد.
برخلاف ReadFile نیازی به مشخص کردن تعداد ستون های ماتریس نیست، در داخل تابع بصورت خودکار ابعاد ماتریس
بر اساس مقدار ncols مشخص شده در فایل و یا حداکثر تعداد ستون های موجود در فایل مشخص می گردد.
فرضا اگر در یک سطر 5 ستون و در سطر بعدی 15 ستون داده داشته باشیم، خروجی این تابع 15 ستونی خواهد بود.

سطرهایی که با مقادیر ncols یا nrows یا xllcorner یا yllcorner یا cellsize یا NODATA_value شروع شوند، نادیده گرفته خواهند شد
و در آرایه خروجی درج نمی شوند.

کد:
Public Function [B]ReadFileEx[/B](ByVal Path As String) As Variant
    Dim FileNo As Integer
    Dim ArrayData() As Variant
    Dim Count As Long
    Dim LineText As String
    Dim LineData() As String
    Dim ColumnIndex As Long
    Dim RowIndex As Long
    Dim VarChar As Byte
    Dim Columns As Long
    Dim NewColumns As Long
    Dim TempArray() As Variant
    FileNo = FreeFile
    ReDim ArrayData(1 To 1, 1 To 100)
    Open Path For Binary Access Read Lock Write As FileNo
    Columns = 1
    NewColumns = 1
    Do
        If Loc(FileNo) <= LOF(FileNo) Then
            Get #FileNo, , VarChar
        Else
            VarChar = 1
        End If
        Select Case VarChar
        Case 9
            LineText = LineText & " "
        Case 13, 10, 1
            LineText = Trim(LineText)
            Do Until InStr(LineText, "  ") = 0
                LineText = Replace(LineText, "  ", " ")
            Loop
            If Len(LineText) > 0 Then
                LineData = Split(LineText, " ")
                Select Case Trim(LCase(LineData(0)))
                Case "ncols"
                    If UBound(LineData) > 0 Then
                        NewColumns = Val(LineData(1))
                    End If
                Case "nrows", "xllcorner", "yllcorner", "cellsize", "nodata_value"
                Case Else
                    If NewColumns < UBound(LineData) + 1 Then
                        NewColumns = UBound(LineData) + 1
                    End If
                    If NewColumns > Columns Then
                        TempArray = ArrayData
                        ReDim ArrayData(1 To NewColumns, 1 To Count + 100)
                        For RowIndex = 1 To Count
                            For ColumnIndex = 1 To Columns
                                ArrayData(ColumnIndex, RowIndex) = TempArray(ColumnIndex, RowIndex)
                            Next
                        Next
                        Columns = NewColumns
                    End If
                    ReDim Preserve LineData(0 To Columns - 1)
                    Count = Count + 1
                    If Count > UBound(ArrayData, 2) Then
                        ReDim Preserve ArrayData(1 To Columns, 1 To Count + 100)
                    End If
                    For ColumnIndex = 1 To Columns
                        If IsNumeric(LineData(ColumnIndex - 1)) Then
                            ArrayData(ColumnIndex, Count) = CDbl(LineData(ColumnIndex - 1))
                        Else
                            ArrayData(ColumnIndex, Count) = LineData(ColumnIndex - 1)
                        End If
                    Next
                End Select
                LineText = ""
            End If
        Case Else
            LineText = LineText & Chr(VarChar)
        End Select
    Loop While VarChar <> 1
    Close FileNo
    If Count = 0 Then Count = 1
    ReDim Preserve ArrayData(1 To Columns, 1 To Count)
    ReadFileEx = ArrayData
End Function

به عنوان مثال کد زیر مقادیر موجود در فایل C:\Input.txt را در آرایه VarArray می خواند :
کد:
    Dim VarArray() As Variant
    VarArray = ReadFileEx("C:\test.txt)

توابع ShowArray و ShowArrayOnTable ای که قبلا معرفی کرده بودم، با این تابع ReadFileEx قابل استفاده اند.
 
آخرین ویرایش توسط مدیر:
درخواست رفع خطای "out of memory" در ShowArrayOnTable

سلام به the_king عزیز و ممنون از پاسخهای خوبت...
از این کدها استفاده کردم و خیلی خوب جواب دادن; همه ستونهای عددی فایل متنی در MSFlexgrid قرار گرفتند و ردیفهایی که تعداد کمی عدد داشتند هم ایجاد مشکل نکردند.
اما وقتی 6 ردیف توضیحات رو به ابتدای فایل اضافه می کنیم برنامه پیغام خطای"out of memory" میده,اگر ممکنه در رفع این مشکل هم کمکم کنید.

6 ردیف توضیحات فایل متنی عبارتند از:
ncols 4111
nrows 3601
xllcorner 213950
yllcorner 3289950
cellsize 100
NODATA_value -9999


برنامه در خط قرمز زیر متوقف میشه:
Public Sub ShowArrayOnTable(ByRef ArrayData() As Variant, ByRef Table As MSFlexGrid)
Dim ColumnIndex As Long
Dim RowIndex As Long
Dim Text As String
With Table
.Rows = 2
.Clear
.FixedCols = 0
.FixedRows = 1
.Cols = UBound(ArrayData, 1) - LBound(ArrayData, 1) + 1
For ColumnIndex = 0 To .Cols - 1
.ColAlignment(ColumnIndex) = flexAlignCenterCenter
Next
For RowIndex = LBound(ArrayData, 2) To UBound(ArrayData, 2)
Text = ArrayData(LBound(ArrayData, 1), RowIndex)
For ColumnIndex = LBound(ArrayData, 1) + 1 To UBound(ArrayData, 1)
Text = Text & vbTab & ArrayData(ColumnIndex, RowIndex)
Next

.AddItem Text, RowIndex - LBound(ArrayData, 2) + 1
Next
If .Rows > 2 Then .RemoveItem .Rows - 1
End With
End Sub
با تشکر فراوان...
 

the_king

مدیرکل انجمن
خطای کمبود حافظه مربوط به کنترل MSFlexGrid است که امکان دسترسی و تصحیح آن وجود ندارد، اما به هر حال مشکل
مربوط به میزان حافظه آزاد کامپیوتر شما است، وگرنه بروز این پیغام خطا عادی نیست.

شخصا برنامه را با همین فایل ورودی (شامل 6 سطر ابتدایی) بدون مشکل اجرا می کنم و میزان مصرف حافظه در فایل اجرایی
آن (Project1.exe) حدود 9.4 مگابایت است که مقدار زیاد و مشکل سازی نیست.
 

جدیدترین ارسال ها

بالا