مدرسه اکسل ! 
چگونه میتوان در اکسل تابعی جدید تعریف کرد؟
چکیده :
در اکسل کاربر میتواند توابعی را تعریف کند که User Defined Function یا به اختصار UDF نامیده میشوند، در این مقاله نحوه تعریف این توابع و بکار گیری آن توضیح داده شده است.
مطالب به صورت خود آموز و قدم به قدم توضیح داده شده است .
مقدمه
دقیقا یادم است که روزی قرار ملاقاتی با یکی از اساتید اکسل داشتم ، ایشان استاد دانشگاه بودند و گویا دوتا هم مدرک دکتری . تقریبا یادم نیست که چه صحبتهایی شد اما این را خوب یادم است که بعد از آن ملاقات بود که میخواستم خودم در اکسل یک تابع بنویسم ، خوب از کجا میدانستم که میشود اینکار را کرد ؟
فکر کنم که روزی فایلی را از اینترنت گرفته بودم و بعد از نصب آن وقتی به Insert à function رفته بودم گزینهای به نام User Function را دیدم و همان موقع شصتم خبر دار شد که بله میشود خودمان توابع دلخواهمان را در اکسل بنویسیم . اما چطوری ؟
تابع چیست ؟ در دبیرستان ساعتها وقت ما را همین کلمه گرفت و انصافاٌ من با کامپیوتر بود که تازه فهمیدم تابع چیست. در واقع تابع یک عملگری است که چیزی را میگیرد و روی آن کاری را انجام میدهد و بعد چیز دیگری که خروجی میگوییم را به ما میدهد. مثلا همین تابع SUM را در نظر بگیرید ، چند تا عدد میگیرد و جمع آنها را به ما میدهد. اکسل بیش از 300 تابع دارد که اکثر کارهایی که ممکن است بخواهیم انجام دهیم با این توابع قابل انجام است ، در ضمن ترکیب این توابع نیز برای ما امکانات فراوانی را بهمراه دارد و این را هم مد نظر داشته باشیم که شرکتی به عظمت ماکروسافت و تجربه چندین سالهاش مطمئنا نیازهای تمامی کاربران در سطح دنیا را در نظر داشته و تا آنجایی که امکان داشته توابع مختلف را پیش بینی کرده است . توابع جدید به چه کاری میآیند البته این سوال ممکن است به ذهن شما متبادر شود که چرا باید تابع جدیدی اضافه کرد. شاید دلایل زیر بتواند گوشهای از ارزش تابع را برای ما بیان کند: جلوگیری از کارهای تکراری در اکسل انجام محاسبات پیچیده دسترسی به کلیه امکانات یک زبان برنامه نویسی مانند ویژوال بیسیک به اشتراک گذاشتن توابع با سایر کاربران استفاده سریعتر از نرم افزار جلوگیری از اشتباهات کاربران آشنایی با ویژوال بیسیک برای شروع بهتر است کمی در خصوص ویژوال بیسیک بدانیم . VB یک زبان برنامه نویسی بسیار متداول است. برای اینکه یک تابع جدید نوشته شود لازم است که کمی با برنامه نویسی با این زبان آشنا باشیم. برای این منظور پیشنهاد میکنم که نرم افزار VB را تهیه کنید و بعد از آن هم چند CD آموزشی و یک کتاب . با کمی تمرین با اصول ابتدایی این زبان آشنا خواهید شد و قول میدهم کار بسیار ساده تر از آنچه فکر میکنید باشد. لازم به ذکر است که نسخه جدید نرم افزار VB به نام VB.NET نیز وجود دارد که امکان استفاده آن در OFFICE 12 که نسخه بعدی آفیس است گنجانده شده و بد نیست بدانیم که VB.NET در واقع قابلیتهای زبان برنامه نویسی C# را دارد. شما برای استفاده از VB در اکسل نیاز ندارید که نرم افزار VISUAL BASIC را نصب کنید ، همراه با نصب آفیس خود این نرم افزار نیز نصب میشود. گام اول ورود به محیط ویژوال بیسیک ابتدا بایستی وارد محیط VB شویم. برای اینکار چندین راه وجود دارد که عبارتند از: · زدن کلید ALT+F11 · از منوها : Tools à Macro à Visual Basic Editor · از Toolbar :
محیط ویژوال بیسک
گام دوم ایجاد یک ماژول
شما باید دستورات تابع خود را در یک Module (ماژول) بنویسید ، از منوی Insert گزینه Module را بزنید . و اگر به project explorer نگاه کنید متوجه خواهید شد که یک ماژول جدید ایجاد شده است.

گام سوم ایجاد یک تابع در ماژول
یک تابع در ویژوال بیسیک قواعد استانداردی دارد که شما باید از این قواعد اطاعت کنید .
اولین قانون آن این است که یک تابع با دستورات استانداردی شروع و به پایان میرسد.
قانون دوم این است که هر تابع یک نوع دارد و ورودیهای یک تابع در داخل پرانتز مشخص میشوند.
قانون سوم ، نوع داده ورودیها (و خود تابع) باید مشخص شود.
این دستورات عبارتند از :
Private Function Test(Num As Integer) as Double
End Function
نام تابع ما test است و عبارت داخل پرانتز میگوید که این تابع یک ورودی دارد که نام آن ورودی Num است و integer بیانگر آن است که این ورودی عددی صحیح است . (-32,768 تا 32,767 )
خروجی تابع از نوع double است و البته گذاشتن آن در همه موارد الزامی نیست ، گرچه بهتر است که مشخص شود. (برای اطلاع بیشتر به کتابهای برنامه نویسی مراجعه کنید.)
عبارت Private Function نشانگر شروع تابع و End Function برای پایان تابع است.
گام چهارم – نوشتن تابع
فرض کنید میخواهیم تابعی بنویسیم که یک عدد را بگیرد و آنرا در 10 ضرب کند!
اول باید تصمیم بگیریم که اسم این تابع را چه بگذاریم ، در حقیقت این اسم همان کلمهای است که در اکسل برای استفاده از این تابع استفاده خواهیم کرد.
خوب اسم آنرا Test میگذاریم و میدانیم که این تابع باید یک ورودی داشته باشد و خوب چون به تازگی با نوع عدد Integer آشنا شدیم (عدد صحیح) نوع این ورودی را هم Integer میگذاریم.
باید نامی برای این ورودی در نظر بگیریم ، این نام نباید یک نام آشنا ! برای VB باشد و بهتر است نامی با مسما در نظر بگیریم ، اینجا اسم این ورودی را Num میگذاریم.
پس در ماژول خود خواهیم نوشت :
Private Function Test(Num As Integer)
Test = Num * 10
End Function

حال از ویژوال بیسیک خارج میشویم ( Alt + Q) و به اکسل بر میگردیم .
گام پنجم - استفاده از تابع
مثل توابع استاندارد اکسل میتوان از این تابع هم استفاده کرد مثلا بنویسید :
= test(8)
= test(A1)
اگر به جای کلمه Private ، Public بنویسیم، میتوانیم نام تابع جدیدمان را در UserFunction ببینیم.

مثال 1) تابع بدست آوردن شماره رنگ یک سلول و رنگ قلم آن سلول
میخواهیم تابعی بنویسیم که شماره رنگ یک سلول (fill color) یا شماره رنگ قلم (font color) را مشخص کنیم.
(میدانیم که در اکسل از 56 رنگ میتوان استفاده کرد که هر رنگ یک کد دارد مثلا کد رنگ قرمز 3 و آبی 5 است.)
· نام تابع : CellColor
· ورودی : تابع دو ورودی دارد ، ورودی اول آدرس سلول است و ورودی دوم مشخص میکند که ما میخواهیم رنگ زمینه سلول را داشته باشیم یا رنگ قلم آنرا .
اگر ورودی دوم عبارت fill بود رنگ زمینه مد نظر است و اگر font بود رنگ قلم.
· نام ورودی اول MyRange و از نوع Range است
· نام ورودی دوم Mode و از نوع String است
· اگر ورودی دوم داده نشده بود و یا مقادیری غیر fill و font بود ، خروجی تابع یک خطا به شکل #Mistake باشد .
برای نوشتن این تابع از دستور شرطی IF به صورت زیر استفاده میکنیم :
Public Function Colorindex(MyRange As Range, Mode As String)
Application.Volatile True
If Mode = "font" Then
Colorindex = MyRange.Font.Colorindex
ElseIf Mode = "fill" Then
Colorindex = MyRange.Interior.Colorindex
Else
Colorindex = "#Mistake"
End If
End Function
عبارت As Range بیان میکند که ورودی اول یک خانه است.
عبارت String As بیان میکند که ورودی دوم یک رشته (متن – غیر عدد) است .
دستور Application.Volatile True به اکسل میگوید که هر وقت هر خانهای را مجدد محاسبه کرد، باید تابع ما را نیز مجدد محاسبه کند . ( این حالت مانند تابع now() خود اکسل است که زمان را مرتب محاسبه و نشان میدهد.) زدن کلید F9 نیز باعث میشود که این تابع مجدد محاسبه شود.
حال خانه A1 را به رنگ زرد و متن آنرا قرمز میکنیم و تابع را روی آن آزمایش میکنیم.
فرمولهای بکار رفته در خانه B1 و B2 را به ترتیب در D1 و D2 مشاهده میکنید.
|
|
A |
B |
C |
D |
|
1 |
far |
13 |
|
=colorindex(A1,"font") |
|
2 |
|
6 |
|
=colorindex(A1,"fill") |
مثال 2) سلولهایی را که رنگ آنها . . . را با هم جمع بزنید.
بهتر است از مثال قبل یک استفاده کاربردی کنیم. مثلا در یک محدوده میخواهیم سلولهای قرمز رنگ را با هم جمع بزنیم. (این سلولها میتوانند با Conditional Formationg قرمز شده باشند.)
Public Function SumByColor(InRange As Range, WhatColorIndex As Integer) As Double
Application.Volatile True
For Each C In InRange.Cells
If C.Interior.Colorindex = WhatColorIndex Then
SumByColor = SumByColor + C.Value
End If
Next C
End Function
· نام تابع : SumByColor و نوع آن را Double در نظر گرفتیم.
· ورودیها: محدوده که نام آنرا InRange و شماره رنگ که نام آنرا WhatColorIndex گذاشتیم و از نوع عدد صحیح است.
· عبارت For Each C InRange دارد میگوید که C یک سلول از سلولهای محدود InRange است .
مثال 4- تابعی ایجاد کنید که اختلاف بزرگترین و کوچکترین عدد یک محدوده را حساب کند.
البته اینکار با خود اکسل بسیار ساده است و کافی است که فرمول =max( ) – Min( ) را بکار ببریم ، اما هدف این مثال اینست که نشان دهد چطور میتوان در محیط ویژوال بیسیک از توابع استاندارد اکسل استفاده کرد.
Public Function max_min(InRange As Range) As Double
Application.Volatile True
MaxNum = Application.WorksheetFunction.Max(InRange)
MinNum = Application.WorksheetFunction.Min(InRange)
max_min = MaxNum - MinNum
End Function
همانطور که میبینید با دستور application.worksheetfunction.xxx که به جای xxx نام تابع استاندارد اکسل را مینویسیم.
مثال 4- میخواهیم تابعی بنویسیم که بتواند مقدار هزار، میلیون و میلیارد را در یک عدد تشخیص دهد و سپس کلمه "تومان" یا "ریال" را هم به آن عدد اضافه کند . در صورتی که عدد معتبر نبود پیغام خطای مناسبی را اعلام کند.
مثلا اگر عدد 15000 وارد شد بنویسید : 15 هزار ریال (یا 15 هزار تومان)
با این مثال قصد داریم ورودیهای Optional را مرور کنیم. مثلا اگر تابع Vlookup را در نظر بگیریم ، آخرین ورودی آن انتخابی (optional) است ، بدین معنی که اگر کاربر مقداری را وارد نکند به طور پیش فرض مقدار True را در نظر میگیرد و در ضمن اگر کاربر خواست میتواند ورودی را به تابع بدهد.
حالت ساده این کار در VB به این صورت است که مینویسیم :
Public Function Test(Num as Integer, optional Num as Integer = True)
تفسیر کد بالا به این صورت است که تابعی داریم به نام Test با دو ورودی.
ورودی اول آن مقداری است به نام Num و از نوع عدد صحیح است .
ورودی دوم آن مقداری است اختیاری ، یعنی کاربر میتواند ورودی دوم را ندهد و با تعریف بالا مقدار پیش فرض آن True در نظر گرفته شده که اگر کاربر مقداری را صریحاً به تابع اعلام نکند ، آنوقت مقدار دوم True در نظر گرفته خواهد شد و کار تابع با این مقدار شروع میشود.
اگر ورودی دوم داده نشود یا 1 یا True اعلام شود ، کلمه ریال در نظر گرفته خواهد شد.
اگر ورودی دوم False یا 0 داده شود ، کلمه تومان در نظر گرفته خواهد شد.
حال به نوشتن تابع مذکور میپردازیم :
Public Function PersianCurrency(MyNumber As String, Optional Mode As Boolean = True)
Application.Volatile True
If Val(MyNumber) >= 0 Then
Temp$ = MyNumber
Cur$ = ""
End If
If Val(MyNumber) >= 1000 Then
Temp$ = Mid(Trim(MyNumber), 1, Len(MyNumber) - 3)
Cur$ = "هزار"
End If
If Val(MyNumber) >= 1000000 Then
Temp$ = Mid(Trim(MyNumber), 1, Len(MyNumber) - 6)
Cur$ = "ميليون"
End If
If Val(MyNumber) >= 1000000000 Then
Temp$ = Mid(Trim(MyNumber), 1, Len(MyNumber) - 9)
Cur$ = "ميليارد"
End If
If Mode = True Then C$ = "ريال" Else C$ = "تومان"
PersianCurrency = Temp$ & Cur$ & " " & C$
If Val(MyNumber) = 0 Then
PersianCurrency = "مقدار يافت نشد"
End If
End Function
تست و خروجی این تابع را در مثال زیر مشاهد میکنید .
تذکر : مقدار True همان 1 است و مقدار False همان 0 است . (یعنی از هر کدام از این مقادیر میتوان استفاده کرد.)
|
|
A |
B |
C |
|
1 |
10000 |
10هزار ريال |
=Persiancurrency(A1,1) |
|
2 |
250000 |
250هزار تومان |
=Persiancurrency(A2,FALSE) |
|
3 |
15000000 |
15ميليون ريال |
=Persiancurrency(A3,1) |
|
4 |
15000001 |
15ميليون تومان |
=Persiancurrency(A4,FALSE) |
|
5 |
far |
مقدار يافت نشد |
=Persiancurrency(A5,1) |
این تابع جنبه تمرینی دارد و همه مقادیر اعداد را پوشش نمیدهد ، فقط ارقامی که با صفر همراه هستند را می شناسد.
استفاده از توابع در تمامی فایلهای اکسل
اما این سوال پیش میآید که چطور میشود این توابع را در همه جا – یعنی همه فایلهای اکسل – استفاده کنیم . وقتی شما یک تابع جدید را تعریف میکنید این تابع فقط در همان فایل (البته همه sheet های آن) قابل استفاده است و اگر بخواهید این تابع را در فایل دیگری فراخوانی کنید، با پیغام #Name مواجه خواهید شد. یک راه این است که این فایل را بعنوان یک فایل Template ذخیره و بعد استفاده کنیم. اما راه اصولی اضافه کردن تابع در اکسل استفاده از Add-In ها است. Add-In چیست؟ Add-In توابعی هستند که توسط کاربران نوشته میشود و سپس روی اکسل اضافه میگردند. هر بار که اکسل اجرا شود، تمامی این توابع نیز فراخوانی خواهند شد و در واقع Add-In ها امکان بسط نرم افزار را بدون محدودیت به کاربران میدهد. ایجاد یک Add-In قدم اول ایجاد یک Add-In است که کار بسیار سادهای است. فایلی که توابع در آن نوشته شده است را باز کنید. تمام Sheetهای اضافه آن را حذف کنید. (فقط یک sheet خالی داشته باشید.) از منوی File گزینه Save as را انتخاب کنید. یک نام برای فایل انتخاب کنید. در جلوی گزینه Save As type گزینه MicroSoft Office Excel Add-In را انتخاب کنید. دقت داشته باشید که فایل را در کجا Save میکنید. نصب یک Add-In بعد از ساختن یک Add-In شما میتوانید آنرا در هر کامپیوتری با هر نسخهای از Office نصب کنید.( مثلا Office2000) با نصب این فایل تمامیتوابعی که نوشتهاید به اکسل اضافه خواهد شد و تا وقتی که شما office را Uninstall یا Remove نکنید، این توابع همراه اکسل خواهند بود. برای نصب یک Add-In مراحل زیر را دنبال کنید. از منوی Tools گزینه Add-Ins… را انتخاب کنید. با زدن گزینه Brower فایل Add-In را انتخاب کنید. تا وقتی که CheckBox در حالت فعال قرار دارد ، این فایل با اکسل فراخوانی میشود و میتوان با تمامی توابع این فایل کار کرد و بازدن کلید Alt+F11 میتوانید وارد محیط ویژوال بیسیک شوید و فایل خود را با پسوند xla ببینید. از اینکه نظرات و تجربیات و ... را از طرف شما دریافت کنم خوشحال خواهم شد. فرشید میدانی / تابستان 85