روال در VBA | تعریف روال و انواع آن در ویژوال بیسیک

روال‌ها (Procedures) در VBA مجموعه‌ای از دستورات هستند که برای انجام کاری خاص طراحی می‌شوند. هدف از ایجاد روال، سازمان‌دهی بهتر کدها، خوانایی بیشتر و امکان استفادهٔ مجدد از بخش‌های تکراری برنامه است.

📑 فهرست مطالب

تعریف روال

روال‌ها در VBA به سه دستهٔ اصلی تقسیم می‌شوند: Sub، Function و Property. هرکدام کاربرد خاصی دارند، ولی در ساختار کلی شباهت زیادی به هم دارند.

آیا می‌دانید:

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

روال Sub

روال Sub برای اجرای مجموعه‌ای از دستورات استفاده می‌شود، اما هیچ مقداری را بازنمی‌گرداند. معمولاً برای انجام کارهایی مانند نمایش پیام، محاسبه، یا تغییر مقدار سلول‌ها استفاده می‌شود.

ساختار کامل یک روال Sub به صورت زیر است:

[ Private | Public | Friend ] [ Static ] Sub name [ ( arglist ) ]
    [ statements ]
    [ Exit Sub ]
    [ statements ]
End Sub
بخشتوضیح
Private | Public | Friendمحدوده دسترسی: Public (پیش‌فرض) از همه ماژول‌ها، Private فقط از ماژول جاری، Friend در سطح پروژه
Staticدر صورت استفاده، مقادیر متغیرهای محلی بین فراخوانی‌ها حفظ می‌شود
Sub nameکلمه کلیدی Sub و سپس نام روال
[ ( arglist ) ]لیست اختیاری آرگومان‌های ورودی
[ statements ]بدنه روال – دستورات اجرایی
[ Exit Sub ]خروج شرطی از روال
End Subپایان روال

مثال پایه از روال Sub

مثال زیر جمع دو عدد را محاسبه و نمایش می‌دهد:

Public Sub SumNumbers(a As Integer, b As Integer)
    MsgBox "جمع اعداد برابر است با: " & (a + b)
End Sub

'فراخوانی:
Call SumNumbers(5, 7)

خروج سریع از روال Sub

برای خروج زودتر از اجرای روال می‌توان از دستور Exit Sub استفاده کرد. مثلاً اگر مقدار ورودی معتبر نباشد:

Sub CheckValue(x As Integer)
    If x < 0 Then
        MsgBox "عدد منفی مجاز نیست!"
        Exit Sub
    End If
    MsgBox "عدد وارد شده: " & x
End Sub

مدیریت خطا در روال Sub

در روال‌های Sub نیز می‌توان با استفاده از دستور On Error GoTo و یک برچسب، خطاهای زمان اجرا را مدیریت کرد. این روش باعث می‌شود برنامه در مواجهه با خطا متوقف نشود و پیام مناسب به کاربر نمایش داده شود.

به مثال زیر توجه کنید:

در این مثال، دستور ThisWorkbook.Sheets(sheetName).Activate تلاش می‌کند تا شیت مشخص‌شده در کاربرگ فعلی (ThisWorkbook) را فعال کند. اگر شیت وجود نداشته باشد، خطای زمان اجرا رخ می‌دهد و با استفاده از مدیریت خطا، برنامه به‌صورت کنترل‌شده واکنش نشان می‌دهد و از توقف ناگهانی جلوگیری می‌شود.

Sub OpenWorksheet(sheetName As String)
    On Error GoTo errHandler   ' فعال‌سازی مدیریت خطا

    ' تلاش برای فعال کردن شیت مورد نظر
    ThisWorkbook.Sheets(sheetName).Activate
    Exit Sub                   ' خروج موفقیت‌آمیز از Sub

errHandler:                     ' برچسب مدیریت خطا
    If Err.Number = 9 Then
        MsgBox "صفحه '" & sheetName & "' در این کاربرگ وجود ندارد."
    Else
        MsgBox "خطای شماره " & Err.Number & ": " & Err.Description
    End If
End Sub

📌 توضیح:

  • On Error GoTo errHandler: اگر خطایی رخ دهد، اجرای Sub به بخش errHandler منتقل می‌شود.
  • Exit Sub: بعد از اجرای موفق دستورات، از Sub خارج می‌شویم تا بخش مدیریت خطا اجرا نشود.
  • در بخش errHandler، می‌توان خطاهای مشخص را مدیریت کرد یا پیام عمومی برای سایر خطاها نمایش داد.

این روش باعث می‌شود برنامه شما قابل اعتمادتر و پایدارتر باشد و از توقف ناگهانی به دلیل خطا جلوگیری شود.

روال Function

روال Function مشابه Sub است، با این تفاوت که می‌تواند یک مقدار را برگرداند. یعنی می‌توان از آن مانند یک متغیر در سایر قسمت‌های برنامه استفاده کرد.

ساختار کامل یک روال Function به صورت زیر است:

[Public | Private | Friend] [ Static ] Function name [ ( arglist ) ] [ As type ]
    [ statements ]
    [ name = expression ]
    [ Exit Function ]
    [ statements ]
    [ name = expression ]
End Function
بخشتوضیح
Public | Private | Friendمحدوده دسترسی (مشابه Sub)
Staticحفظ مقادیر متغیرهای محلی بین فراخوانی‌ها
Function nameکلمه کلیدی Function و نام تابع
[ ( arglist ) ]لیست اختیاری آرگومان‌های ورودی
[ As type ]نوع داده مقدار بازگشتی
[ name = expression ]تخصیص مقدار بازگشتی به نام تابع
[ Exit Function ]خروج شرطی از تابع
End Functionپایان تابع

مثال پایه از روال Function

Function Multiply(x As Double, y As Double) As Double
    Multiply = x * y
End Function

' استفاده از تابع:
Dim result As Double
result = Multiply(5, 3.5)
MsgBox "حاصل ضرب: " & result

مقدار بازگشتی در تابع (Function) در VBA

مقدار بازگشتی در یک روال Function باید متناسب با نوع داده‌ای باشد که برای آن تابع تعریف شده است. به بیان دیگر، اگر تابع به‌صورت صریح با نوع داده‌ای مانند Integer، Double، String یا هر نوع دیگر تعریف شده باشد، مقدار بازگشتی نیز باید از همان نوع یا نوعی قابل تبدیل به آن باشد.

برای مشخص کردن مقدار بازگشتی، مقدار مورد نظر به نام تابع با استفاده از عملگر = انتساب داده می‌شود. این کار به کامپایلر VBA اعلام می‌کند که این مقدار، نتیجه نهایی تابع است.

به‌طور معمول مقدار بازگشتی یک تابع در انتهای روال، قبل از End Function تعیین می‌شود. اما اگر به هر دلیلی بخواهید مقدار تابع را میان بدنه تابع مشخص کنید، فراموش نکنید که پس از انتساب، دستور Exit Function را به‌کار ببرید تا اجرای تابع بلافاصله متوقف شود.

به مثال زیر توجه کنید:

Function CalcJalaliMonthDays(monthNum As Byte) As Byte
    If monthNum = 0 Or monthNum > 12 Then
        MsgBox "عدد ماه بدرستی وارد نشده است."
    End If
    If monthNum < 7 Then
        CalcJalaliMonthDays = 31
    End If
    CalcJalaliMonthDays = 30
End Function

📌 نکته:
در این حالت، صرف‌نظر از مقدار ورودی monthNum، مقدار بازگشتی همیشه 30 خواهد بود. تنها تفاوت این است که اگر monthNum برابر 0 یا بزرگ‌تر از 12 باشد، پیام هشدار نمایش داده می‌شود، اما مقدار تابع همچنان 30 است.

کد صحیح و استاندارد با استفاده از Exit Function به شکل زیر است:

Function CalcJalaliMonthDays(monthNum As Byte) As Byte
    If monthNum = 0 Or monthNum > 12 Then
        MsgBox "عدد ماه بدرستی وارد نشده است."
        Exit Function
    End If
    
    If monthNum < 7 Then
        CalcJalaliMonthDays = 31
        Exit Function
    End If
    
    CalcJalaliMonthDays = 30
    Exit Function
End Function

📌 توضیح:
در نسخه اصلاح‌شده:

  • اگر ورودی نامعتبر باشد، پیام نمایش داده شده و تابع بلافاصله خاتمه می‌یابد.
  • برای ماه‌های 1 تا 6 مقدار بازگشتی 31 است و پس از تعیین مقدار، تابع خاتمه می‌یابد.
  • در غیر این صورت مقدار 30 برای ماه‌های 7 تا 12 بازگردانده می‌شود.

استفاده از Exit Function در چنین شرایطی باعث می‌شود مقدار بازگشتی دقیقاً مطابق انتظار باشد و دستورات بعدی بدون اثر اجرا نشوند.

انتساب مقدار به تابع به معنای خروج از آن نیست. اگر پس از انتساب مقدار، دستورات دیگری در بدنه‌ی تابع وجود داشته باشد، آن دستورات نیز اجرا خواهند شد. در صورتی که بخواهید اجرای تابع در همان نقطه متوقف شود، باید از دستور Exit Function استفاده کنید.

🔹 مثال ۱: تابع بدون استفاده از Exit Function

در این مثال مقدار بازگشتی تعیین می‌شود، اما چون از Exit Function استفاده نشده، بقیهٔ کد نیز اجرا می‌شود.

Function SquareNum(x As Double) As Double
    SquareNum = x * x           ' تعیین مقدار بازگشتی
    MsgBox "این پیام پس از تعیین مقدار بازگشتی نیز اجرا می‌شود."
End Function

📘 توضیح:
اگر تابع SquareNum(4) فراخوانی شود، مقدار بازگشتی برابر ۱۶ خواهد بود، ولی پنجرهٔ پیام نیز نمایش داده می‌شود، زیرا هنوز از تابع خارج نشده‌ایم.

🔹 مثال ۲: تابع با استفاده از Exit Function

در این مثال، بلافاصله پس از تعیین مقدار بازگشتی، تابع خاتمه می‌یابد.

Function SquareNumSafe(x As Double) As Double
    If x < 0 Then
        MsgBox "ورودی منفی مجاز نیست!"
        Exit Function             ' خروج زودهنگام از تابع
    End If
    
    SquareNumSafe = x * x
    Exit Function                 ' خروج پس از تعیین مقدار بازگشتی
End Function

📘 توضیح:
در این حالت، اگر عدد ورودی منفی باشد، پیام هشدار نمایش داده شده و تابع بدون بازگرداندن مقدار ادامه نمی‌دهد.
در غیر این صورت، مقدار مربع عدد محاسبه و بلافاصله بازگردانده می‌شود.

بازگرداندن شیء با تابع (Function) در VBA

گاهی اوقات مقدار بازگشتی یک تابع نوع داده‌ای ساده نیست و به جای آن یک شیء (Object)، مانند Worksheet یا Workbook، بازگردانده می‌شود. در چنین مواردی، برای تعیین مقدار بازگشتی تابع، باید مرجع شیء با استفاده از دستور Set به نام تابع انتساب داده شود.

به مثال زیر توجه کنید:

Function GetWorksheet(name As String) As Worksheet
    Set GetWorksheet = ThisWorkbook.Sheets(name)
End Function

📌 توضیح:

  • تابع GetWorksheet یک شیء از نوع Worksheet بازمی‌گرداند.
  • خط Set GetWorksheet = ThisWorkbook.Sheets(name)، مرجع شیء صفحه‌ای با نام name در کاربرگ جاری (ThisWorkbook) را به تابع اختصاص می‌دهد.
  • استفاده از Set برای انتساب شیء الزامی است؛ اگر بدون Set مقداردهی شود، کد با خطای زمان اجرا روبه‌رو خواهد شد.

نکته: برای سایر اشیاء مانند Workbook، Range یا Collection نیز همین روش استفاده می‌شود؛ همیشه هنگام بازگرداندن شیء از Set استفاده کنید.

خروج سریع از روال Function

در صورت نیاز به پایان سریع تابع، می‌توان از دستور Exit Function استفاده کرد:

Function SafeDivide(a As Double, b As Double) As Variant
    If b = 0 Then
        SafeDivide = "تقسیم بر صفر مجاز نیست!"
        Exit Function
    End If
    SafeDivide = a / b
End Function

مدیریت خطا در روال Function

برای مدیریت خطا در یک روال Function در VBA، معمولاً از دستور On Error GoTo همراه با یک برچسب (Label) استفاده می‌کنیم. این روش به شما امکان می‌دهد تا در صورت رخداد خطا، اجرای تابع را کنترل کرده و پیام مناسب نمایش دهید، بدون اینکه برنامه متوقف شود.

به عنوان مثال، در تابع GetWorksheet، اگر صفحه‌ای با نام name در کاربرگ ThisWorkbook وجود نداشته باشد، خطای زمان اجرا ۹ (Run-time error 9) (Subscript out of range) (تصویر زیر) رخ می‌دهد.

پیام خطای Run-time error 9 در محیط VBA
این تصویر پیام خطای شماره ۹ را در VBA نشان می‌دهد که هنگام فراخوانی یک شیء یا صفحه ناموجود رخ می‌دهد.

می‌توانیم این خطا را به شکل زیر مدیریت کنیم:

Function GetWorksheet(name As String) As Worksheet
    On Error GoTo errHandler   ' فعال‌سازی مدیریت خطا

    Set GetWorksheet = ThisWorkbook.Sheets(name)
    Exit Function             ' خروج موفقیت‌آمیز از تابع

errHandler:                     ' برچسب مدیریت خطا
    If Err.Number = 9 Then
        MsgBox "صفحه '" & name & "' در این کاربرگ وجود ندارد."
    Else
        MsgBox "خطای شماره " & Err.Number & ": " & Err.Description
    End If
End Function

📌 توضیح:

  • On Error GoTo errHandler: اجرای تابع در صورت وقوع خطا به بخش errHandler منتقل می‌شود.
  • Exit Function: بعد از اجرای موفقیت‌آمیز کد، تابع را ترک می‌کنیم تا بخش مدیریت خطا اجرا نشود.
  • در بخش errHandler، می‌توان خطاهای مشخص را مدیریت کرد یا پیام عمومی برای سایر خطاها نمایش داد.

این روش باعث می‌شود تابع شما قابل اعتماد و بدون توقف ناگهانی اجرا شود و خطاها به شکل کنترل‌شده مدیریت شوند.

تعریف آرگومان یا پارامتر

پارامترها (Parameters) متغیرهای نام‌گذاری شده‌ای هستند که در تعریف تابع لیست می‌شوند. آنها به عنوان placeholders برای مقادیری عمل می‌کنند که هنگام فراخوانی تابع به آن ارسال می‌شوند. پارامترها نوع و تعداد ورودی‌های مورد انتظار یک تابع را تعریف می‌کنند.

آرگومان‌ها (Arguments) مقادیر یا عبارت‌های واقعی هستند که هنگام فراخوانی تابع به آن ارسال می‌شوند. این مقادیر به پارامترهای متناظر در تعریف تابع اختصاص داده می‌شوند و به تابع اجازه می‌دهند روی داده‌های خاصی عمل کند.

ساختار کامل تعریف یک پارامتر در VBA به صورت زیر است:

[ Optional ] [ ByVal | ByRef ] [ ParamArray ] varname [ ( ) ] [ As type ] [ = defaultvalue ]
بخشتوضیحمثال
Optionalپارامتر اختیاری – می‌تواند ارسال نشودOptional x As Integer
ByVal | ByRefنحوه ارسال: ByVal (بر اساس مقدار) یا ByRef (بر اساس مرجع – پیش‌فرض)ByVal name As String
ParamArrayآرایه پارامترهای متغیر – فقط برای آخرین پارامترParamArray args() As Variant
varnameنام متغیر پارامترusername
[ ( ) ]برای پارامترهای آرایه‌ایscores() As Integer
[ As type ]نوع داده پارامترAs String
[ = defaultvalue ]مقدار پیش‌فرض برای پارامترهای اختیاری= 0

مثال‌های کاربردی از پارامترها

پارامترهای اختیاری با مقدار پیش‌فرض:

Sub GreetUser(name As String, Optional title As String = "کاربر")
    MsgBox "سلام " & title & " " & name
End Sub

' فراخوانی:
GreetUser "علی" ' بدون عنوان
GreetUser "علی", "آقای" ' با عنوان

تفاوت ByVal و ByRef:

Sub TestByValByRef()
    Dim x As Integer, y As Integer
    x = 5: y = 5
    
    IncrementByVal x
    IncrementByRef y
    
    MsgBox "x (ByVal) = " & x & ", y (ByRef) = " & y ' x=5, y=6
End Sub

Sub IncrementByVal(ByVal num As Integer)
    num = num + 1
End Sub

Sub IncrementByRef(ByRef num As Integer)
    num = num + 1
End Sub

استفاده از ParamArray برای پارامترهای متغیر:

Function SumAll(ParamArray numbers() As Variant) As Double
    Dim total As Double, i As Integer
    For i = LBound(numbers) To UBound(numbers)
        total = total + numbers(i)
    Next i
    SumAll = total
End Function

' فراخوانی:
Dim result As Double
result = SumAll(1, 2, 3, 4, 5) ' نتیجه: 15

روال Property

روال‌های Property معمولاً در کلاس‌ها استفاده می‌شوند و اجازه می‌دهند برای اشیاء، ویژگی‌های خواندنی و نوشتنی ایجاد کنیم. این روال‌ها کنترل کاملی بر روی نحوه دسترسی و تنظیم مقادیر خصوصی یک کلاس فراهم می‌کنند.

انواع روال‌های Property

نوع Propertyکاربردساختار
Property Getخواندن مقدار یک ویژگیProperty Get Name() As Type
Property Letتنظیم مقدار برای انواع داده‌ای سادهProperty Let Name(value As Type)
Property Setتنظیم مقدار برای انواع شیءProperty Set Name(obj As Object)

مثال کاربردی از روال Property

' در ماژول کلاس به نام Employee
Private pName As String
Private pSalary As Double

' Property Get برای خواندن نام
Property Get Name() As String
    Name = pName
End Property

' Property Let برای تنظیم نام
Property Let Name(value As String)
    If Len(value) > 0 Then
        pName = value
    Else
        Err.Raise 5, , "نام نمی‌تواند خالی باشد"
    End If
End Property

' Property Get برای خواندن حقوق
Property Get Salary() As Double
    Salary = pSalary
End Property

' Property Let برای تنظیم حقوق
Property Let Salary(value As Double)
    If value >= 0 Then
        pSalary = value
    Else
        Err.Raise 5, , "حقوق نمی‌تواند منفی باشد"
    End If
End Property

استفاده از کلاس در کد:

Sub TestEmployee()
    Dim emp As New Employee
    emp.Name = "علی رضایی" ' فراخوانی Property Let
    emp.Salary = 5000000 ' فراخوانی Property Let
    
    MsgBox "نام: " & emp.Name & vbCrLf & _
           "حقوق: " & Format(emp.Salary, "#,##0") ' فراخوانی Property Get
End Sub

Property Set برای اشیاء

' در ماژول کلاس به نام Department
Private pManager As Employee

Property Get Manager() As Employee
    Set Manager = pManager
End Property

Property Set Manager(emp As Employee)
    Set pManager = emp
End Property

جمع‌بندی

در این آموزش با مفهوم روال‌ها در VBA آشنا شدیم و تفاوت سه نوع اصلی آن را مرور کردیم:

  • Sub: مجموعه‌ای از دستورات که عملی انجام می‌دهد ولی مقداری برنمی‌گرداند.
  • Function: مانند Sub است اما می‌تواند مقدار محاسبه‌شده را برگرداند.
  • Property: برای تعریف ویژگی‌های سفارشی اشیاء در کلاس‌ها و فرم‌ها استفاده می‌شود.

همچنین با ساختار کامل پارامترها و نحوه استفاده از انواع مختلف آنها آشنا شدیم. درک تفاوت این سه نوع روال و تسلط بر نحوه تعریف پارامترها به شما کمک می‌کند تا کدهایی ساخت‌یافته‌تر، قابل نگهداری‌تر و انعطاف‌پذیرتر در VBA بنویسید.

سؤالات متداول درباره روال‌ها در VBA

روال (Procedure) در VBA چیست و چه کاربردی دارد؟

روال یا Procedure مجموعه‌ای از دستورات است که برای انجام یک کار مشخص نوشته می‌شود. هدف از ایجاد روال، سازمان‌دهی کد، جلوگیری از تکرار، افزایش خوانایی و امکان استفاده مجدد از دستورات است.

تفاوت Sub و Function در VBA چیست؟

Sub مجموعه‌ای از دستورات را اجرا می‌کند ولی مقداری بازنمی‌گرداند، در حالی که Function علاوه بر اجرای دستورات، می‌تواند یک مقدار یا شیء را به روال فراخواننده برگرداند. به طور ساده: Sub برای انجام عمل، Function برای محاسبه و بازگرداندن مقدار.

چرا باید از Exit Sub و Exit Function استفاده کنیم؟

از Exit Sub و Exit Function برای پایان زودهنگام روال استفاده می‌شود. این دستورها باعث می‌شوند اجرای روال یا تابع قبل از رسیدن به انتهای آن متوقف شود، که در شرایطی مانند ورودی نامعتبر یا مدیریت خطا بسیار کاربردی است.

تفاوت ByVal و ByRef در پارامترهای VBA چیست؟

ByVal (ارسال بر اساس مقدار) یک کپی از مقدار را به روال ارسال می‌کند، بنابراین تغییرات در داخل روال روی متغیر اصلی تاثیری ندارد.
ByRef (ارسال بر اساس مرجع) آدرس متغیر را ارسال می‌کند و تغییرات در داخل روال مستقیماً روی متغیر اصلی اعمال می‌شود. این روش پیش‌فرض VBA است.

روال Property در VBA چه کاربردی دارد و انواع آن کدام است؟

روال‌های Property در کلاس‌ها برای ایجاد ویژگی‌های اشیاء استفاده می‌شوند. این روال‌ها امکان تعریف ویژگی‌های فقط‌خواندنی (Property Get)، فقط‌نوشتنی (Property Let/Set) و خواندنی/نوشتنی را فراهم می‌کنند و می‌توانند اعتبارسنجی و کنترل دسترسی روی داده‌ها اعمال کنند.

چه زمانی باید از Property Set به جای Property Let استفاده کنیم؟

زمانی که می‌خواهید یک شیء (Object) را به ویژگی اختصاص دهید، از Property Set استفاده می‌کنید. برای انواع داده‌ای ساده مانند Integer، String یا Double از Property Let استفاده می‌شود.

چگونه می‌توان یک روال را از داخل روال دیگر فراخوانی کرد؟

در VBA می‌توان هر روال (Sub یا Function) را از داخل روال دیگر فراخوانی کرد. این کار باعث کاهش تکرار کد، سازمان‌دهی بهتر و استفاده مجدد از روال‌ها می‌شود. برای مثال، یک Sub می‌تواند نتیجه یک Function را دریافت و نمایش دهد.

چگونه خطاها را در Sub و Function مدیریت کنیم؟

با استفاده از On Error GoTo Label و تعریف یک برچسب، می‌توان خطاهای زمان اجرا را مدیریت کرد. این روش باعث می‌شود برنامه بدون توقف ناگهانی ادامه یابد و پیام مناسب به کاربر نمایش داده شود. برای مثال، اگر شیتی وجود نداشته باشد، می‌توان با مدیریت خطا، پیام هشدار داد و از توقف برنامه جلوگیری کرد.

دستور Call در VBA چه کاربردی دارد؟

دستور Call برای فراخوانی یک روال (Sub یا Function) استفاده می‌شود، به‌ویژه زمانی که می‌خواهیم پارامترها را در پرانتز قرار دهیم. استفاده از Call اختیاری است و بیشتر برای وضوح یا سازگاری با کدهای قدیمی VBA کاربرد دارد. مثال: Call MySub(Arg1, Arg2) یا به صورت مستقیم MySub Arg1, Arg2.

چگونه باید مقدار بازگشتی تابع را دریافت کنیم؟

برای دریافت مقدار بازگشتی یک Function، باید نام تابع را در سمت راست انتساب قرار داده و آرگومان‌ها را در پرانتز بنویسید. مثال: result = MyFunction(x, y). اگر نام تابع بدون پرانتز در یک خط نوشته شود، مانند یک Sub اجرا می‌شود و مقدار بازگشتی استفاده نخواهد شد. بنابراین همیشه برای استفاده از نتیجه تابع، باید آن را به متغیری انتساب دهید و آرگومان‌ها را در پرانتز قرار دهید.

منابع:

📘 راهنمای جامع VBA در مایکروسافت آفیس
✳️ آموزش نوشتن رویه Sub در VBA
🔹 آموزش نوشتن تابع Function در VBA
🏷️ آموزش نوشتن ویژگی Property در VBA

دیدگاهتان را بنویسید