فصل ۵: رشتهها، توابع و کادرهای پیام
این فصل نحوهٔ کار با رشتههای متنی، استفاده از Functionهای داخلی VBA و طراحی Message Boxهای حرفهای را توضیح میدهد.
رشتهها
اگر زیاد با Access کار کرده باشید میدانید String در برنامهنویسی به معنی نخ واقعی نیست؛ بلکه دنبالهای از کاراکترهای پشتسرهم است. این کاراکترها فقط به حروف الفبا محدود نمیشوند و میتوانند هر کاراکتری در Character Set از ۰ تا ۲۵۵ باشند؛ یعنی حروف، اعداد و Control Characterها. بسته به Language Code Page ممکن است خود کاراکترها متفاوت باشند، اما تعداد کل همچنان ۲۵۶ است.
String برای نمایش پیام به کاربر یا ایجاد Caption مفید است. یک String میتواند "Richard" یا حتی "1234" باشد.
VBA چند Function برای اتصال رشتهها، حذف بخشهایی از رشته، جستوجو و تغییر بزرگی و کوچکی حروف فراهم میکند. برای نمونه دو رشتهٔ "Your answer" و " is wrong" را میتوان به "Your answer is wrong" تبدیل کرد. همچنین میتوان کل متن را Uppercase کرد تا "YOUR ANSWER IS WRONG" شود یا واژه و مجموعهکاراکتر خاصی را در آن جستوجو کرد.
Concatenation؛ اتصال رشتهها
Concatenation یعنی متصلکردن رشتهها که معمولاً با علامت & انجام میشود. این قابلیت هنگام نمایش پیامها بسیار مفید است. فرض کنید برنامهای تعداد Tableهای پایگاهداده را میشمارد و عدد را در متغیری ذخیره میکند. نمایش خود عدد ممکن است برای کاربر مفهوم روشنی نداشته باشد، بنابراین بهتر است پیام کاملی مثل «There are n tables within the database» ساخته شود.
MsgBox "There are " & n & " tables within the database "
حتی میتوان کد را طوری نوشت که اگر n برابر ۱ باشد عبارت There is استفاده شود تا متن از نظر دستوری درست بماند.
مثال سادهٔ حلقهٔ For..Next فصل ۴ را در نظر بگیرید:
For n = 1 to 5
MsgBox n
Next n
Message Box مقدار n را نمایش میدهد، اما عدد بهتنهایی معنای زیادی ندارد. با افزودن String پیام برای کاربر روشنتر میشود:
For n = 1 to 5
MsgBox "The value of n is " & n
Next n
اکنون پیام مثلاً The value of n is 1 را نشان میدهد و در مجموع پنج بار، با افزایش n، نمایش داده میشود. فراموش نکنید بعد از واژهٔ is یک Space قرار دهید تا عدد به متن نچسبد.
محدودیتی در تعداد Stringها و Valueهایی که به این شکل به هم متصل میکنید وجود ندارد. حتی اگر n عددی باشد، VBA هنگام Concatenation آن را خودکار به رشتهٔ کاراکتری تبدیل میکند.
تقسیم رشتهها
گاهی فقط بخشی از یک String لازم است. فرض کنید ابتدای رشته یک شمارهٔ مرجع دو رقمی قرار دارد و میخواهید آن را در بخش دیگری استفاده کنید، در حالی که فقط نام را نمایش دهید:
"12Richard"
برای استخراج نام میتوان از Mid استفاده کرد:
x=Mid("12Richard",3)
جستوجو از کاراکتر سوم آغاز میشود و تا انتهای String ادامه پیدا میکند؛ بنابراین x برابر "Richard" خواهد شد. Mid یک Parameter اختیاری برای Length نیز دارد. اگر Length را مشخص نکنید، تمام کاراکترها از نقطهٔ شروع تا انتهای String برگردانده میشوند.
بهجای Literal میتوانید متغیری حاوی String بدهید:
temp="12Richard"
x=Mid(temp,3)
برای استخراج بخش عددی ابتدای String نیز میتوان نوشت:
x=Mid("12Richard",1,2)
این کد از اولین کاراکتر شروع میکند و دو کاراکتر برمیدارد؛ x دارای String با مقدار 12 خواهد بود. این مقدار در اصل عدد نیست، اما VBA تا حد زیادی انعطافپذیر است و برای بسیاری از محاسبات بدون تبدیل صریح نیز با آن کار میکند.
اگر بخواهید مقدار را دوباره در Field عددی یک Table ذخیره کنید، ممکن است از نظر Formatting لازم باشد آن را به Number تبدیل کنید. برای این کار از Val استفاده میشود:
Dim iValue as Integer
iValue = Val("12")
در این حالت iValue واقعاً یک عدد است.
VBA توابع String با نامهای Left و Right نیز دارد. برای جداکردن 12 میتوان نوشت:
x=Left("12Richard",2)
x مقدار 12 را خواهد داشت. اگر از Right استفاده شود:
x=Right("12Richard",2)
x برابر rd میشود. همانطور که از نامشان پیداست، Left و Right از سمت چپ یا راست String کاراکترها را برمیدارند.
تغییر ظاهر String
UCase همهٔ حروف String را Uppercase میکند:
x=UCase("Richard")
x برابر RICHARD خواهد بود.
LCase همهٔ حروف را Lowercase میکند:
x=LCase("Richard")
x برابر richard خواهد بود. در هر دو حالت کاراکترهای غیرحرفی مانند اعداد بدون تغییر باقی میمانند.
جستوجوی Stringها
Function دیگری با نام InStr برای جستوجوی یک Substring داخل String وجود دارد. Syntax آن به دلیل وجود دو Argument اختیاری کمی پیچیده است:
InStr([start, ]string1, string2[, compare])
Start اختیاری است و محل آغاز جستوجو را تعیین میکند. اگر حذف شود، جستوجو از Position 1 شروع میشود. Start نباید Null باشد و اگر Start استفاده شود باید Compare نیز مشخص شود.
String1 رشتهای است که در آن جستوجو انجام میشود، مثلاً "Richard Shepherd". String2 رشتهٔ مورد جستوجو است، مثلاً "shepherd".
Compare روش مقایسه را تعیین میکند. دو مقدار اصلی vbBinaryCompare و vbTextCompare هستند. Binary Compare Case-sensitive است؛ A با A برابر است اما با a برابر نیست. Text Compare بزرگی و کوچکی حروف را نادیده میگیرد و A را برابر a میداند. Null در Compare خطا تولید میکند و مقدار پیشفرض Binary است.
جدول ۵-۱ — مقادیر برگشتی InStr| مقدار | معنا |
| 0 | طول String1 صفر است. |
| Null | String1 برابر Null است. |
| Start Value | طول String2 صفر است. |
| Null | String2 برابر Null است. |
| 0 | String2 پیدا نشده است. |
| Position | موقعیت String2 داخل String1. |
| 0 | Start از طول String1 بزرگتر است. |
x=Instr("Richard Shepherd","Shepherd")
نتیجه ۹ است. چون Compare پیشفرض Case-sensitive است، عبارت زیر صفر برمیگرداند:
x = Instr("Richard Shepherd","shepherd")
اما با Text Compare نتیجه ۹ میشود:
MsgBox InStr(1, "Richard Shepherd", "shepherd", vbTextCompare)
در مثال بعدی Start برابر ۱۰ است:
MsgBox InStr(10, "Richard Shepherd", "shepherd", vbTextCompare)
نتیجه صفر است، زیرا نقطهٔ شروع جستوجو بعد از محل قرارگرفتن عبارت موردنظر است.
Function با نام InStrRev جستوجوی معکوس انجام میدهد؛ یعنی از انتهای String به سمت ابتدای آن جستوجو میکند.
Functionهای پرکاربرد
در ادامه مروری بر Functionهای رایج VBA ارائه میشود. Functionهای دیگری نیز وجود دارند، اما موارد زیر از مهمترین و پرکاربردترینها هستند.
Len
Len تعداد کاراکترهای String را برمیگرداند:
MsgBox Len("abc")
Msgbox Len("shepherd")
نتیجهٔ اول ۳ و نتیجهٔ دوم ۸ است. Len همراه با سایر Functionهای String مفید است؛ مثلاً اگر چهار کاراکتر آخر Stringای با طول متغیر را بخواهید، ابتدا باید طول String را بدانید.
Abs
Abs مقدار Absolute یا قدر مطلق را برمیگرداند؛ هر دو مثال زیر مقدار ۱ میدهند:
MsgBox Abs(1)
MsgBox Abs(-1)
Int
Int عدد را به Integer Truncate میکند و به نزدیکترین عدد صحیح Round نمیکند:
MsgBox Int(1.2)
MsgBox Int(1.99)
هر دو مقدار ۱ را برمیگردانند، حتی دومی که بسیار به ۲ نزدیک است.
Sqr
Sqr جذر عدد را برمیگرداند:
MsgBox Sqr(4) '2
MsgBox Sqr(3) '1.732
MsgBox Sqr(100) '10
Asc
Asc کد ASCII یک کاراکتر را، در بازهٔ ۰ تا ۲۵۵، برمیگرداند:
MsgBox Asc("A")
MsgBox Asc("i")
Asc("richard")
نتیجهها بهترتیب ۶۵، ۱۰۵ و ۱۱۴ هستند. Asc فقط روی اولین کاراکتر String عمل میکند؛ بنابراین در richard کد حرف r را برمیگرداند.
Chr
Chr عکس Asc است؛ یک شمارهٔ ASCII را به کاراکتر تبدیل میکند:
MsgBox Chr(65)
MsgBox Chr(105)
خروجیها بهترتیب A و i هستند. چون Chr کل Character Set را پوشش میدهد، کاراکترهای غیرقابلچاپ را نیز شامل میشود. مثلاً کد ASCII شمارهٔ ۱۳ یک Carriage Return است:
MsgBox "This is " & Chr(13) & "a carriage return"
Functionهای تبدیل
Conversion Functionها مقدار را از یک قالب به قالب دیگر تبدیل میکنند؛ برای مثال Number را به String یا String را دوباره به Number تبدیل میکنند. این قابلیت برای جابهجایی داده میان قالبهای مختلف مفید است. فرض کنید عددی چهاررقمی دارید و فقط رقم دوم آن را میخواهید. یک روش ساده این است که عدد را به String تبدیل کنید، با Mid رقم موردنظر را جدا کنید و سپس برای محاسبات بیشتر دوباره آن را به Number برگردانید.
CStr
CStr مقدار را به String تبدیل میکند:
CStr(1234)
خروجی String با مقدار "1234" است.
CInt
CInt مقدار یا String را به Integer دو بایتی تبدیل میکند و بخش اعشاری در خروجی وجود ندارد:
CInt(123.45)
CInt("123.45")
هر دو مقدار ۱۲۳ میدهند. CInt برخلاف Int عدد را به نزدیکترین Integer Round میکند، نه اینکه صرفاً آن را Truncate کند. اگر Expression شامل کاراکتر غیرعددی باشد، خطای Type Mismatch رخ میدهد.
CLng
CLng مقدار یا String را به Long چهار بایتی تبدیل میکند و اعشار را نشان نمیدهد:
CLng(123456789.45)
CLng("123456789.45")
هر دو مقدار 123456789 را برمیگردانند. CLng نیز به نزدیکترین عدد صحیح Round میکند و وجود کاراکتر غیرعددی Type Mismatch ایجاد میکند.
CDbl
CDbl مقدار یا String را به Double هشت بایتی با امکان اعشار تبدیل میکند:
CDbl("123.56789")
نتیجه 123.56789 است. وجود کاراکتر غیرعددی خطای Type Mismatch ایجاد میکند.
Val
Val String را به مقدار عددی تبدیل میکند و نسبت به CInt یا CLng انعطافپذیرتر است، چون وجود کاراکترهای غیرعددی در ادامهٔ String را تحمل میکند:
Val("123")
Val("123.45")
Val("12richard")
Val("richard")
نتیجهها بهترتیب ۱۲۳، ۱۲۳٫۴۵، ۱۲ و ۰ هستند. در مثال آخر هیچ کاراکتر عددی برای ارزیابی وجود ندارد.
Function قالببندی Format
Format یکی از مفیدترین و پیچیدهترین Functionهای VBA است. با آن میتوانید عدد را در قالب خروجی دلخواه نمایش دهید، مشابه Formatting در Access یا Spreadsheet. این کار از داخل کد انجام میشود و هنگام نمایش عدد در Message Box یا User Form، بهویژه برای اعداد بزرگ، خوانایی را افزایش میدهد:
MsgBox Format(1234567.89, "#,###.#")
خروجی 1,234,567.9 است. هر # یک Digit Placeholder است؛ کاما جداکنندهٔ هزارگان را مشخص میکند و تنها یک Placeholder پس از Decimal Point باعث Round شدن به یک رقم اعشار میشود.
میتوان از نامهای قالب ازپیشتعریفشده نیز استفاده کرد:
MsgBox Format(1234567.89, "Currency")
با توجه به Symbol ارز در Windows، مثلاً $1,234,567.89 نمایش داده میشود. تنظیمات دیگر ممکن است Pound یا Euro نشان دهند.
جدول ۵-۲ — قالبهای ازپیشتعریفشده| نام قالب | توضیح |
| General Number | عدد را همانطور که هست نمایش میدهد. |
| Currency | نمایش با Symbol ارز و جداکنندهٔ هزارگان؛ مقدار منفی در پرانتز و دو رقم اعشار. |
| Fixed | حداقل یک رقم سمت چپ و دو رقم سمت راست Decimal Point. |
| Standard | نمایش با جداکنندهٔ هزارگان و دو رقم اعشار. |
| Percent | عدد را در ۱۰۰ ضرب کرده، % اضافه میکند و دو رقم اعشار نشان میدهد. |
| Scientific | Scientific Notation استاندارد. |
| Yes/No | اگر صفر باشد No و در غیر این صورت Yes. |
| True/False | اگر صفر باشد False و در غیر این صورت True. |
| On/Off | اگر صفر باشد Off و در غیر این صورت On. |
Format String میتواند حداکثر چهار Section داشته باشد که با Semicolon جدا میشوند؛ این امکان برای اعمال قالب متفاوت به مقدارهای مثبت، منفی، صفر و Null است. مثلاً برای قرار دادن مقدار منفی در پرانتز:
MsgBox Format(-12345.67,"$#,##0;($#,##0)")
| تعداد Section | کاربرد |
|---|
| یک | برای تمام مقادیر. |
| دو | اولی برای مثبت و دومی برای منفی. |
| سه | مثبت، منفی و صفر. |
| چهار | مثبت، منفی، صفر و Null. |
جدول ۵-۳ — کاراکترهای قالب سفارشی| کاراکتر | توضیح |
| رشتهٔ Null | بدون Formatting. |
| 0 | Digit Placeholder؛ اگر رقمی نباشد صفر نشان میدهد. صفرهای ابتدا یا انتها را در صورت نیاز اضافه میکند و تعداد Decimalها را بر اساس Placeholderها Round میکند. |
| # | Digit Placeholder؛ اگر رقمی نباشد چیزی نشان نمیدهد و صفرهای غیرضروری ابتدا و انتها را نمایش نمیدهد. |
| . | Decimal Point؛ فقط یکی در هر Format String مجاز و وابسته به تنظیمات Windows است. |
| % | عدد را در ۱۰۰ ضرب کرده و % را در محل مشخصشده قرار میدهد. |
| , | Thousand Separator؛ بسته به محل میتواند برای Round کردن به هزار یا میلیون نیز استفاده شود. |
| E- E+ | نمایش Scientific/Exponential. |
| : | Time Separator برای ساعت، دقیقه و ثانیه. |
| / | Date Separator. |
| - + £ $ ( ) | کاراکتر Literal؛ برای سایر Literalها از Backslash استفاده میشود. |
جدول ۵-۴ — قالبهای ازپیشتعریفشدهٔ تاریخ و زمان| نام | توضیح |
| General Date | تاریخ و/یا زمان؛ برای عدد Real تاریخ و زمان، برای Integer زمان و اگر بخش صحیح نداشته باشد فقط زمان. |
| Long Date | تاریخ بلند مطابق International Settings ویندوز. |
| Medium Date | مشابه Short Date ویندوز، با نام اختصاری ماه. |
| Short Date | تاریخ کوتاه مطابق International Settings. |
| Long Time | زمان بلند مطابق International Settings. |
| Medium Time | زمان ۱۲ ساعته با ساعت، دقیقه، ثانیه و AM/PM. |
| Short Time | زمان ۲۴ ساعته، مثلاً 18:10. |
جدول ۵-۵ — کاراکترهای Format تاریخ/زمان| کاراکتر | معنا |
| c | تاریخ به شکل ddddd و زمان به شکل ttttt. |
| d | روز بدون صفر ابتدایی. |
| dd | روز با صفر ابتدایی. |
| ddd | نام اختصاری روز. |
| dddd | نام کامل روز. |
| ddddd | تاریخ کامل مطابق Short Date ویندوز. |
| dddddd | تاریخ کامل مطابق Long Date ویندوز. |
| w | روز هفته بهصورت عدد؛ 1=Sunday. |
| ww | شمارهٔ هفتهٔ سال، ۱ تا ۵۲. |
| m | ماه بدون صفر ابتدایی. |
| mm | ماه با صفر ابتدایی. |
| mmm | نام اختصاری ماه. |
| mmmm | نام کامل ماه. |
| q | Quarter سال، ۱ تا ۴. |
| y | روز سال، ۱ تا ۳۶۶. |
| yy | سال دو رقمی. |
| yyyy | سال چهار رقمی. |
| h | ساعت بدون صفر ابتدایی. |
| hh | ساعت با صفر ابتدایی. |
| n | دقیقه بدون صفر ابتدایی. |
| nn | دقیقه با صفر ابتدایی. |
| s | ثانیه بدون صفر ابتدایی. |
| ss | ثانیه با صفر ابتدایی. |
| ttttt | Time Serial بهصورت زمان کامل. |
| AM/PM | ساعت ۱۲ ساعته با AM یا PM. |
| am/pm | همان با حروف کوچک. |
| A/P | ساعت ۱۲ ساعته با A یا P. |
| a/p | همان با حروف کوچک. |
MsgBox Format(Now(), "hh:mm:ss AM/PM")
Formatهای تاریخ نیز مانند Number میتوانند Section داشته باشند. یک Section برای همهٔ دادهها و دو Section یعنی اولی برای دادهٔ معمولی و دومی برای Zero-length String و Null. نمونهها:
| Format String | نمونهٔ نتیجه |
|---|
| mm/dd/yy | 01/03/03 |
| dd-mmm-yyyy | 01-Mar-2003 |
| hh:mm | a.m./p.m. |
جدول ۵-۶ — کاراکترهای اضافهٔ Format| کاراکتر | معنا |
|---|
| @ | Character Placeholder؛ کاراکتر یا Space. |
| & | Character Placeholder؛ کاراکتر یا هیچچیز. |
| < | اجبار Lowercase. |
| > | اجبار Uppercase. |
| ! | پرشدن Placeholderها از چپ به راست. |
MsgBox "This is " & Format("1000", "@@@,@@@")
MsgBox "This is " & Format("1000", "&&&,&&&")
MsgBox Format("richard", ">")
Functionهای تاریخ و زمان
Now
Now تاریخ و زمان جاری را برمیگرداند:
MsgBox Now
قالب Short Date و Time از Control Panel ویندوز گرفته میشود.
Date
تاریخ جاری را در قالب Short Date برمیگرداند:
MsgBox Date
Time
زمان فعلی سیستم را برمیگرداند:
MsgBox Time
DateAdd
DateAdd یک بازهٔ زمانی مشخص را به تاریخ اضافه یا از آن کم میکند و در فصل ۲۸ با جزئیات بیشتری بررسی میشود:
DateAdd (interval, number, date)
| دوره | Interval |
|---|
| سال | yyyy |
| Quarter | q |
| ماه | m |
| روز سال | y |
| روز | d |
| روز هفته | w |
| هفته | ww |
| ساعت | h |
| دقیقه | n |
| ثانیه | s |
Number تعداد Intervalهاست و میتواند منفی باشد که در آن صورت از تاریخ کم میشود. Date همان تاریخی است که تغییر روی آن انجام میشود یا Variant حاوی آن تاریخ.
MsgBox DateAdd ("m",1,"1-Jan-03")
MsgBox DateAdd ("ww",2,"1-Jan-03")
MsgBox DateAdd ("d", -2, "1-Jan-03")
نتیجهها بهترتیب 1-Feb-03، 15-Jan-03 و 30-Dec-02 هستند؛ البته نمایش دقیق به Date Format سیستم وابسته است.
DateDiff
DateDiff تعداد Intervalهای زمانی میان دو تاریخ را برمیگرداند:
DateDiff (interval, date1, date2)
MsgBox DateDiff("m", "1-jan-03", "15-mar-03")
در مثال بالا نتیجه ۲ است، زیرا دو ماه کامل میان تاریخها وجود دارد. Function مقدار را به Interval پایینتر Truncate میکند؛ حتی اگر date2 برابر 30-Mar باشد باز هم ۲ میدهد و تنها در 1-Apr نتیجه ۳ میشود. Intervalهای قابل استفاده همان Year, Quarter, Month, Day of Year, Day, Weekday, Week, Hour, Minute و Second با کدهای yyyy, q, m, y, d, w, ww, h, n و s هستند.
DatePart
DatePart بخش مشخصی از تاریخ را برمیگرداند:
DatePart (interval, date)
MsgBox DatePart("q", "1-mar-03")
MsgBox DatePart("m", "1-mar-03")
مثال اول ۱ برمیگرداند، چون 1-Mar در Quarter اول است و مثال دوم مقدار ۳ را بهعنوان ماه March میدهد.
DateSerial
DateSerial شمارهٔ Serial تاریخ را برای Year، Month و Day دادهشده بهصورت Integer برمیگرداند:
DateSerial (year, month, day)
MsgBox CDbl(DateSerial(2003, 3, 6))
Year میتواند ۱۰۰ تا ۹۹۹۹ یا یک Expression عددی، Month بین ۱ تا ۱۲ و Day بین ۱ تا ۳۱ باشد. مثال مقدار 37686 را برای تاریخ 6-Mar-2003 برمیگرداند. استفاده از CDbl لازم است تا خود Serial Number نمایش داده شود و نه تاریخ قالببندیشدهٔ Windows.
DateValue
Msgbox CDbl(DateValue("06-Mar-2003"))
این مثال نیز مقدار 37686 را برمیگرداند. بدون CDbl کادر پیام تاریخ را مطابق قالب Windows نمایش میدهد.
Day
Day عددی بین ۱ تا ۳۱ برای روز ماه برمیگرداند:
Day (dateexpression)
Msgbox Day(37686)
Msgbox Day("6-Mar-2003")
هر دو مقدار ۶ را میدهند.
Hour
Hour عددی بین ۰ تا ۲۳ برای ساعت روز برمیگرداند:
MsgBox Hour("17:50")
MsgBox Hour("6-Mar-2003 4:30pm")
MsgBox Hour(11 / 24)
نتیجهها بهترتیب ۱۷، ۱۶ و ۱۱ هستند.
Month
Msgbox Month(37686)
Msgbox Month("6-Mar-2003")
هر دو مقدار ۳ را برمیگردانند.
Second
Msgbox Second("4:35:48pm")
نتیجه ۴۸ است.
Minute
Msgbox Minute(11.27 / 24)
Msgbox Minute("4:35pm")
Msgbox Minute(11.25 / 24)
مثال اول مقدار ۱۶ را میدهد، چون 11.27 در قالب Decimal Hour تقریباً 11:16:12 a.m. است.
Year
Msgbox Year(37686)
Msgbox Year("6-Mar-2003")
هر دو سال ۲۰۰۳ را برمیگردانند.
Weekday
Weekday عددی بین ۱ برای Sunday و ۷ برای Saturday را برمیگرداند:
MsgBox WeekDay("6-Mar-2003")
نتیجه ۵ یعنی Thursday است. این Function برای ساخت تاریخهایی بر مبنای روز خاص هفته مفید است. برای مثال برای بهدستآوردن Friday پایان هفتهٔ جاری:
MsgBox Now - WeekDay(Now) + 6
Weekday از Sunday شروع میکند؛ بنابراین Now به Sunday قبلی برگردانده و سپس ۶ روز برای رسیدن به Friday اضافه میشود.
منبع همچنین نمونهای برای محاسبهٔ روزهای کاری میان دو تاریخ ارائه میکند:
For n = DateValue("1-Jan-03") To DateValue("18-Jan-03")
If Weekday(n) <> 1 Or Weekday(n) <> 7 Then
WorkDay = WorkDay + 1
End If
Next n
MsgBox WorkDay
طبق متن منبع، WorkDay مقدار ۱۳ را بهعنوان تعداد روزهای کاری میان دو تاریخ برمیگرداند.
فرمان SendKeys
SendKeys در واقع Function نیست، بلکه Command Statement است و میتواند در Function یا Subroutine استفاده شود. این دستور با ارسال Keypress به برنامهٔ دیگر، تقریباً مانند تایپکردن واقعی روی Keyboard، امکان کنترل آن را فراهم میکند. بنابراین برای Automation سطح پایین برنامههایی مفید است که OLE Automation را پشتیبانی نمیکنند.
همهٔ برنامههای Microsoft Office از OLE Automation پشتیبانی میکنند؛ میتوانید Reference مدل شیء آنها را بارگذاری کرده و از داخل کد آن برنامه را کنترل کنید. این موضوع در فصل ۱۷ توضیح داده میشود. بعضی برنامهها مانند Calculator ویندوز چنین Object Modelای ندارند، اما با SendKeys قابل کنترلاند.
SendKeys keytext [,wait]
keytext رشتهٔ کلیدهایی است که به Active Window فرستاده میشوند. wait مقدار Boolean است. اگر True باشد ابتدا کلیدها پردازش میشوند و بعد کنترل به Procedure برمیگردد؛ اگر False باشد بلافاصله بعد از ارسال Keypress کنترل بازگردانده میشود. مقدار پیشفرض False است.
Wait میتواند بسیار مهم باشد. اگر برنامهٔ مقصد سریع جلو برود، ممکن است تا رسیدن SendKeys از مرحلهٔ موردنظر عبور کرده باشد و Keystroke نادیده گرفته شود. True کردن Wait باعث میشود کلیدها پیش از ادامهٔ اجرای برنامه پردازش شوند.
SendKeys "A123"
این دستور A123 را به پنجرهٔ فعال میفرستد؛ بدیهی است برنامهٔ مناسب باید در حال اجرا و Active باشد.
برای بازکردن یک برنامه میتوان از Shell استفاده کرد:
Shell (commandstring [,windowstyle])
commandstring همان Command Line اجرای برنامه است؛ مشابه Target در Shortcutهای Desktop. windowstyle تعیین میکند برنامه بهصورت Normal Window، Icon یا Hidden باز شود.
x = Shell("calc.exe",1)
این مثال Windows Calculator را در پنجرهٔ استاندارد و با Focus باز میکند و سپس SendKeys میتواند به آن کلید بفرستد.
اگر برنامه از قبل باز است، بهجای اجرای دوبارهٔ Shell میتوان با AppActivate Focus را به آن منتقل کرد:
AppActivate "Microsoft Word"
نمونهٔ Automation ساده:
Sub test_sendkeys()
x = Shell("calc.exe")
For n = 1 To 10
SendKeys n & "{+}", True
Next n
MsgBox "Press OK to close calculator"
AppActivate "calculator"
SendKeys "%{F4}", True
End Sub
Calculator باز میشود و حلقهٔ For..Next اعداد ۱ تا ۱۰ را با هم جمع میکند. Message Box در Access ظاهر میشود، زیرا کد از Access اجرا شده است. آیکون Access در Taskbar چشمک میزند؛ Access را انتخاب کرده و OK بزنید تا Calculator بسته شود.
علامتهای +، ^، %، ~ و پرانتزها در SendKeys معنای ویژه دارند. برای ارسال خود این کاراکترها باید آنها را داخل Brace قرار دهید؛ مثلاً {+}. Bracketها معنای ویژه ندارند، اما در SendKeys باید آنها را نیز در Brace قرار دهید.
برای کلیدهایی که کاراکتر قابلنمایش ندارند، مانند ENTER و TAB، از کدهای جدول ۵-۷ استفاده میشود. برای ترکیب کلیدها با SHIFT، CTRL و ALT نیز بهترتیب از +، ^ و % پیش از کد کلید استفاده میشود.
جدول ۵-۷ — کد کلیدهای ویژه در SendKeys| کلید | کد |
| BACKSPACE | {BACKSPACE}, {BS}, {BKSP} |
| BREAK | {BREAK} |
| CAPS LOCK | {CAPSLOCK} |
| DEL / DELETE | {DELETE}, {DEL} |
| DOWN ARROW | {DOWN} |
| END | {END} |
| ENTER | {ENTER} یا ~ |
| ESC | {ESC} |
| HELP | {HELP} |
| HOME | {HOME} |
| INS / INSERT | {INSERT}, {INS} |
| LEFT ARROW | {LEFT} |
| NUM LOCK | {NUMLOCK} |
| PAGE DOWN | {PGDN} |
| PAGE UP | {PGUP} |
| PRINT SCREEN | {PRTSC} |
| RIGHT ARROW | {RIGHT} |
| SCROLL LOCK | {SCROLLLOCK} |
| TAB | {TAB} |
| UP ARROW | {UP} |
| F1 تا F12 | {F1} ... {F12} |
برای نگهداشتن SHIFT، CTRL یا ALT هنگام فشردن چند کلید، کد آن کلیدها را داخل پرانتز قرار دهید. مثلاً +(EC) یعنی SHIFT هنگام فشردن E و C نگه داشته شود، در حالی که +EC یعنی SHIFT فقط برای E استفاده شود و C بدون SHIFT ارسال شود.
نویسنده نمونهای واقعی از برنامهای برای یک بانک بزرگ در بریتانیا شرح میدهد. برنامه با SendKeys شبانه یک سیستم ثبت زمان را کنترل میکرد و Timesheetهای مورد نیاز صبح جمعه را میساخت. یک جمعه هیچ Timesheetی تولید نشد، زیرا شب قبل نظافتچی هنگام گردگیری تصادفاً کلید RIGHT ARROW را فشرده بود و ترتیب دقیق Keystrokeها جابهجا شده بود. برنامه بهجای یک ستون، وارد ستون بعدی شد و بقیهٔ کلیدها اثر مورد انتظار را نداشتند. پس از آن هنگام اجرای برنامه در پنجشنبهشبها Keyboard را پشت Monitor قرار میدادند تا کسی به آن دست نزند.
SendKeys شیکترین راه Automation نیست، اما در آن پروژه به دلیل محدودیت برنامه تنها گزینه بود. هزاران کاربر صبح جمعه همزمان وارد سیستم میشدند و Timesheet میساختند؛ این فشار سنگینی روی Server ایجاد میکرد و حتی باعث Down شدن Server و نارضایتی Project Managerها میشد. اجرای شبانه با SendKeys اجازه داد Timesheetها از قبل ساخته شوند، مدیران راضی بمانند و Serverها نیز پایدار بمانند.
Message Boxها
در بسیاری از مثالهای کتاب از MsgBox برای برگرداندن نتیجه به کاربر استفاده شده است. میتوان نتیجه را در یک Cell یا کنترل خاص قرار داد، اما Message Box سادهترین روش برای ارسال داده به کاربر است و تنها یک Command به همراه متن لازم دارد.
MsgBox "Hello World",vbInformation
شکل ۵-۱ نتیجه را نشان میدهد. Message Box پیشفرض Caption با عنوان Microsoft Access دارد و در سادهترین حالت فقط یک دکمه و تنظیمات محدود نشان میدهد. میتوانید Title Bar و Icon را برای نیاز خود سفارشی کنید:
MsgBox "Hello World", vbInformation
هنگام تایپ Parameter نوع، VBA List Boxای از گزینههای موجود نشان میدهد. چهار Icon اصلی عبارتاند از:
| Constant | کاربرد |
|---|
| vbCritical | علامت توقف؛ ضربدر سفید روی دایرهٔ قرمز، برای جلوگیری از اقدام نامناسب. |
| vbExclamation | علامت تعجب برای هشدار، مثلاً احتمال از دسترفتن داده. |
| vbInformation | آیکون اطلاعات برای ارائهٔ نکتهٔ مفید در آن مرحله از برنامه. |
| vbQuestion | علامت سؤال، معمولاً همراه چند Button، مثلاً Yes/No. |
شکل ۵-۱ — یک Message Box ساده
جدول ۵-۸ — Constantهای Message Box| Constant | Value | توضیح |
| vbAbortRetryIgnore | 2 | دکمههای Abort، Retry و Ignore. |
| vbCritical | 16 | آیکون Stop. |
| vbDefaultButton1 | 0 | Button اول پیشفرض. |
| vbDefaultButton2 | 256 | Button دوم پیشفرض. |
| vbDefaultButton3 | 512 | Button سوم پیشفرض. |
| vbDefaultButton4 | 768 | Button چهارم پیشفرض. |
| vbExclamation | 48 | آیکون Exclamation. |
| vbInformation | 64 | آیکون Information. |
| vbOKCancel | 1 | دکمههای OK و Cancel. |
| vbOKOnly | 0 | فقط دکمهٔ OK. |
| vbQuestion | 32 | آیکون Question. |
| vbRetryCancel | 5 | دکمههای Retry و Cancel. |
| vbYesNo | 4 | دکمههای Yes و No. |
| vbYesNoCancel | 3 | دکمههای Yes، No و Cancel. |
برای نمایش Yes و No همراه با Caption مشخص:
MsgBox "Test message", vbYesNo, "My message"
میتوانید Constantهای Icon و Button را با Or ترکیب کنید:
x = MsgBox("Test Message", vbAbortRetryIgnore Or vbCritical)
این کد دکمههای Abort، Retry و Ignore همراه با Critical Icon را نمایش میدهد.
برای فهمیدن اینکه کاربر کدام Button را کلیک کرده است، Response را در متغیر بگیرید:
x = MsgBox ("Test Yes No",vbYesNo,"Test")
Msgbox x
در این حالت به دلیل فراخوانی Function و دریافت Return Value باید از x = و پرانتز دور Parameterها استفاده شود. بدون پرانتز خطا رخ میدهد.
اگر Yes کلیک شود مقدار ۶ یعنی vbYes و اگر No کلیک شود مقدار ۷ یعنی vbNo برمیگردد. سپس میتوان منطق برنامه را بر اساس پاسخ نوشت:
If x = vbYes Then Action1 Else Action2
مقادیر برگشتی Message Box| Constant | Value | معنا |
|---|
| vbOK | 1 | OK کلیک شده است. |
| vbCancel | 2 | Cancel کلیک شده است. |
| vbAbort | 3 | Abort کلیک شده است. |
| vbRetry | 4 | Retry کلیک شده است. |
| vbIgnore | 5 | Ignore کلیک شده است. |
| vbYes | 6 | Yes کلیک شده است. |
| vbNo | 7 | No کلیک شده است. |