تطبيقات برمجة أوتوكاد - التطبيق الثاني - حساب مجموع مساحات
تم نشر هذا التطبيق في موقع ملتقى المهندسين العرب بعنوان (تمرين 1: استخدام vba وأوتوكاد)، وللتفاعل معه يمكنكم المشاركة على الرابط التالي:
http://www.arab-eng.org/vb/t135680.html
المستوى
- مبتدئ
مقدمة
سأقوم في هذا الموضوع بتقديم تمرين حول استخدام لغة Visual Basic for Application (اختصاراً VBA) المدمجة مع أوتوكاد عن طريق شرح برنامج بسيط يقوم بعملية حساب مجموع مساحات أشكال مختارة.
المهارات المطلوبة لفهم الموضوع
- معرفة بسيطة باستخدام برنامج أوتوكاد.
- معرفة بالأوامر الأساسية للغة البرمجة Visual Basic.
- يفضل قراءة الدرس الثاني المشروح في هذا الموقع.
النقاط الرئيسية
سنتعلم في هذا التمرين ما يلي:
- اختيار الكائنات.
- التنقل بين الكائنات المختارة ومعرفة نوع كل منها.
- قراءة خصائص كائن ما.
نص المسألة
المطلوب كتابة برنامج يقوم بحساب مجموع مساحات الأشكال المغلقة التي يقوم المستخدم باختيارها، هذه الأشكال من النوع Polyline مغلق أو Region.
خطوات الحل
يفضل قراءة البرنامج أولاً وهو في آخر الصفحة للاطلاع عليه فقط حتى لو لم يكن مفهوماً الآن.
1- افتح بيئة البرمجة بالضغط على Alt+F11 من ضمن أوتوكاد فتظهر بيئة البرمجة Microsoft Visual Basic.
2- أضف وحدة برمجية Module من قائمة Insert، يختلف Module عن User Form بأن الأخير هو عبارة عن نافذة يمكن أن تحوي عدة كائنات برمجية، أما ال Module فهو يحوي برامج جزئية فقط، وفي هذا المثال لا نحتاج أكثر من هذا.
3- تم الآن إضافة وحدة برمجية اسمها Module1 وتظهر لنا صفحة بيضاء فارغة.
4- ضمن الصفحة الفارغة اكتب العبارة التالية : Public Sub CalcTotalArea ثم اضغط Enter فيتم إضافة السطر End Sub تلقائياً، كما في الشكل (1).
حتى هذه المرحلة قمنا بإضافة برنامج جزئي Sub اسمه CalcTotalArea، أما كلمة Public فهي تشير إلى أن هذا البرنامج يمكن الوصول إليه من خارج هذه الوحدة البرمجية وبالتالي يمكن استدعاؤه من أوتوكاد على أنه ماكرو.
أما عبارة End Sub فهي تشير إلى انتهاء البرنامج، وسنقوم بكتابة برنامجنا بين السطرين السابقين.
5- قبل البدء بكتابة البرنامج اذهب إلى أوتوكاد ثم اختر الأمر Macros من قائمة Tools->Macro فتظهر نافذة Macros التي تحوي ضمنها اسم البرنامج السابق، لتشغيله اختر الاسم ثم انقر على زر Run، حتى هذه النقطة لم نقم بكتابة أي شيء ضمن البرنامج لذلك فإن تنفيذه لن يؤدي إلى شيء.
6- نقوم بتعريف متحول اسمه TotalArea ليحمل ضمنه مجموع المساحات (أسماء المتحولات اختيارية ويفضل أن تكون معبرة عن قيمة المتحول).
كما هو معروف في VB فإن هناك عدة عبارات لتعريف (حجز) المتحولات لا مجال لذكرها، منها عبارة Dim ثم نكتب اسم المتحول ثم As ثم نوع المتحول وهو في حالتنا رقم حقيقي من النوع Single أو Double، سنستخدم Double، فتصبح العبارة:
Dim TotalArea As Double
7- حتى يقوم البرنامج بسؤال المستخدم أن يقوم باختيار مجموعة كائنات سنستخدم كائن من النوع AcadSelectionSet، وسنسميه ss (اختصار SelectionSet، كما قلنا الاسم اختياري)
نحجز المتحول ss كما سبق:
Dim ss As AcadSelectionSet
حتى الآن الكائن المحجوز ss لا يشير إلى أي شيء أي هو كائن فارغ، لذلك يجب أن نسند له قيمة عن طريق العبارة التالية:
Set ss = ThisDrawing.SelectionSets.Add("TEMP")
في السطر السابق قمنا بإضافة SelectionSet جديدة اسمها (Temp) إلى لوحة أوتوكاد الحالية ThisDrawing، ثم جعلنا المتحول ss يشير إليها عن طريق العبارة Set.
أي يمكننا الآن الوصول إلى ال SelectionSet الجديدة عن طريق التعامل مع المتحول ss.
أما الاسم Temp فهو يشير إلى الاسم الداخلي لل SelectionSet هذه في أوتوكاد، وقد اخترت لها الاسم Temp للإشارة إلى أنها مؤقتة Temporary لأننا سنقوم بحذفها لاحقاً.
8- نقوم بتنفيذ الأمر SelectOnScreen التابع لل SelectionSet السابقة عن طريق المتحول ss كما يلي:
ss.SelectOnScreen
عند وصول البرنامج إلى هذه النقطة سيقوم أوتوكاد بسؤال المستخدم أن يقوم باختيار الكائنات في لوحة الرسم الحالية، ويقوم بتخزين هذه الكائنات في ss.
9- للتنقل بين الكائنات المختارة والتي وضعها أوتوكاد في ss سنستخدم الأمر المعروف في Visual Basic وهو حلقة For Each...Next، ونحتاج لتعريف متحول لنستخدمه ضمن هذه الحلقة وسنسميه ent وهو من النوع AcadEntity على اعتبار أن ss تحوي فقط كائنات أوتوكاد وجميعها لها النوع AcadEntity.
نكتب السطرين التاليين:
For Each ent In ss
Next
يمكننا ترجمة الحلقة السابقة كما يلي: من أجل كل كائن موجود في ss إجعل المتحول ent يشير إليه ثم نفذ الأوامر الموجودة ضمن الحلقة ثم انتقل إلى الكائن التالي وهكذا حتى الانتهاء.
فإذا كنا قد اخترنا كائنين في الخطوة 8 سيقوم البرنامج عند الأمر For بإسناد الكائن المختار الأول إلى المتحول ent ثم ينفذ الأوامر بعد For وقبل Next وعند الوصول إلى Next يسند الكائن المختار الثاني إلى المتحول ent ويعيد تنفيذ الأوامر حتى يصل إلى Next، وبعد الانتهاء من جميع الكائنات في ss ينتقل إلى خارج الحلقة أي إلى بعد سطر Next.
مابين السطرين السابقين سنقوم بإضافة الأوامر التي تقوم بجمع المساحة كما يلي.
10- من نص المسألة نريد جمع مساحات الكائنات من النوع Polyline و Region، والتي أسماؤها في VBA هي AcadLWPolyline و AcadRegion على الترتيب، لذلك يجب أن نختبر نوع كل كائن عن طريق أمر Visual Basic وهو If مع TypeOf كما يلي:
If TypeOf ent Is AcadLWPolyline Then
ترجمتها: إذا كان نوع الكائن الذي يشير إليه المتحول ent هو AcadLWPolyline نفذ الأوامر التالية، حيث نضيف الأوامر في السطر الذي يليه، ويجب أن نتذكر أن نضيف عبارة End If التي تشير إلى انتهاء العبارات البرمجية التي سينفذها البرنامج في حال تحقق الشرط.
سنقوم بقراءة مساحة الكائن عن طريق الخاصية Area التابعة له، ولكن هذه الخاصية ليست من خصائص ent لأنه من النوع AcadEntity، وإنما هي من خصائص كائن من النوع AcadLWPolyline لذلك سنقوم بتعريف متحول آخر من النوع AcadLWPolyline اسمه pl سيشير إلى نفس الكائن الذي يشير إليه المتحول ent ولكنه يمكّننا من الوصول إلى خصائص أكثر خاصة بالكائن Polyline، لذلك سنقوم بإضافة العبارات التالية:
Dim pl As AcadLWPolyline
Set pl = ent
الآن يمكننا معرفة مساحة هذا الكائن عن طريق الخاصية Area للمتحول pl وسنقوم بجمع هذه المساحة إلى المتحول الذي قمنا بتعريفه في بداية البرنامج TotalArea كما يلي:
TotalArea = TotalArea + pl.Area
ولكننا نريد جمع المساحة فقط في حالة كان هذا ال Polyline مغلقاً لذلك نضع الشرط If pl.Closed قبل العبارة السابقة لتصبح:
If pl.Closed Then TotalArea = TotalArea + pl.Area
تصبح العبارات كما يلي:
If TypeOf ent Is AcadLWPolyline Then
Dim pl As AcadLWPolyline
Set pl = ent
If pl.Closed Then TotalArea = TotalArea + pl.Area
End If
11- نكرر نفس الخطوات السابقة من أجل الكائن من النوع AcadRegion، كما يلي:
If TypeOf ent Is AcadRegion Then
Dim rg As AcadRegion
Set rg = ent
TotalArea = TotalArea + rg.Area
End If
12- نلاحظ أننا وضعنا شرطين متتاليين لا يمكن تحققهما معاً لذلك يمكننا تقليص العبارات السابقة بأن نضع الشرط الأول بدون End If ثم العبارات التابعة لهذا الشرط ثم ElseIf بدلاً من If الثانية ثم العبارات البرمجية التابعة للشرط الثاني ثم End If، كما هو موضح في البرنامج النهائي المبين أدناه.
13- نضيف سطر ss.Delete لحذف ال SelectionSet التي قمنا بإنشائها لأننا لن نحتاجها.
14- نظهر قيمة المساحة عن طريق أمر VisualBasic وهو MsgBox والذي يظهر صندوق رسائل كما يلي:
MsgBox TotalArea
أو يمكننا جعله أكثر وضوحاً للمستخدم كما يلي:
MsgBox "Total Area is: " & TotalArea
15- لتجربة البرنامج أضف كائنات Polyline مغلقة وكائنات Region في لوحة الأوتوكاد ثم نفذ البرنامج كما في الخطوة 5، سيسألك البرنامج أن تختار كائنات، اختر الكائنات السابقة ثم اضغط Enter وسيعطيك البرنامج قيمة مجموع المساحات.
ملاحظة: لإضافة برنامج جزئي آخر (ماكرو) ليس من الضروري إضافة وحدة برمجية جديدة، إنما يمكن أن نكتب البرنامج الجديد تحت عبارة End Sub السابقة، أي أن الوحدة البرمجية يمكن أن تحوي أكثر من برنامج جزئي (ماكرو)
ملاحظة2: قمت في هذا المثال بإطالة الشرح أحياناً (كما في 4،6،7،9،10،12) وذلك من أجل المبتدئين جداً في لغة Visual Basic، وفي المرات القادمة -إن شاء الله- سأفترض أن هذا أصبح مفهوماً ولن أطيل فيه.
نص البرنامج النهائي
Public Sub CalcTotalArea()
Dim TotalArea As Double
Dim ss As AcadSelectionSet
Set ss = ThisDrawing.SelectionSets.Add("TEMP")
ss.SelectOnScreen
Dim ent As AcadEntity
For Each ent In ss
If TypeOf ent Is AcadLWPolyline Then
Dim pl As
AcadLWPolyline
Set pl = ent
If pl.Closed
Then TotalArea = TotalArea + pl.Area
ElseIf TypeOf ent Is AcadRegion Then
Dim rg As
AcadRegion
Set rg = ent
TotalArea =
TotalArea + rg.Area
End If
Next
ss.Delete
MsgBox "Total Area is: " & TotalArea
End Sub
تحميل
ملحق
سأل أحد الإخوة: كلما أقوم بتشغيل البرنامج تظهر رسالة خطأ تقول بأن اسم ال SelectionSet موجود، هل هناك طريقة للتخلص من هذا الخطأ بدلاً من تغيير اسم المجموعة في كل مرة؟
الجواب: الخطأ هو بسبب وجود SelectionSet اسمها Temp في قاعدة بيانات ملف الأوتوكاد الحالي، وهذا لأن البرنامج قد توقف في إحدى مرات تشغيله قبل أن يصل إلى سطر حذف هذه ال SelectionSet والتي اسمها Temp.
وعند التشغيل التالي للبرنامج حاول إضافة واحدة جديدة بنفس الاسم وعندما وجدها لم يستطع إضافتها وحصل الخطأ.
حقيقة كنت متوقعاً حصول هذا الخطأ ولكن تركته حتى لا أعقد البرنامج، والآن يمكنني كتابة أسطر معالجة هذا الخطأ كما سيلي وأعتقد أن فهمها الآن سيكون أسهل من لو أنني عالجته في بداية التمرين.
سنقوم بإضافة السطر التالي قبل إنشاء ال SelectionSet
On Error Resume Next
هذا السطر يخبر Visual Basic أنه في حال حدوث خطأ بعد هذا السطر تجاهله وانتقل إلى السطر الذي يليه:
الآن سنضيف سطراً بعد إنشاء ال SelectionSet وهو:
If Err.Number <> 0 Then Set ss = ThisDrawing.SelectionSets("Temp")
عند حدوث خطأ يتم تخزين رقم الخطأ في الكائن Err، لذلك نختبر الرقم بعد السطر الذي نتوقع حصول خطأ فيه، فإن كان مساوياً للصفر فهذا يعني عدم وجود خطأ وإلا فالخطأ موجود.
في حالتنا فإن الخطأ هو وجود هذه ال SelectionSet والتي اسمها Temp لذلك سنسندها إلى المتحول ss بدلاً من إنشاء واحدة جديدة كما هو مبين أعلاه.
بعد السطر السابق نكتب On Error Goto 0 لإلغاء وضع تجاهل الأخطاء، فهو عادة غير محبذ.
تصبح بداية البرنامج كما يلي:
Dim ss As AcadSelectionSet
On Error Resume Next
Set ss = ThisDrawing.SelectionSets.Add("Temp")
If Err.Number <> 0 Then Set ss = ThisDrawing.SelectionSets("Temp")
On Error GoTo 0
ss.SelectOnScreen
يمكن معالجة الخطأ السابق بعدة طرق والطريقة التي شرحتها أعلاه هي إحداها.
هاتف: +963-31-2220008
جوال: +963-999-824193
سوريا - حمص