اذهب الي المحتوي
أوفيسنا

الردود الموصى بها

قام بنشر

السلام عليكم ...

أعتذر أولاً عن هذا العنوان الغريب ، ولكن كان لا بد منه (لزوم التشويق :d ).

عندما يخوض المرء في غمار الـ VBA فإنه يكتشف الكثير و الكثير من الثنائيات المميزة التي لا يجدها في كتب البرمجة التقليدية . هذه الثنائيات ترقى بالمبرمج إلى مستوى الاحتراف و تسهل عليه الكثير من الأمور.

سوف أقوم إنشاء الله بعرض متتابع لهذه الثنائيات و ذلك على شكل مشاركات مرتبة و مرقمة في هذا الموضوع وذلك كلما خطرت على بالي واحدة منها ، وهذا الموضوع مفتوح للنقاش من كل الأعضاء ، ولكن رجائي لكل من يريد عرض تجاربه التقيد بالترقيم الموضح للمشاركات .

وشكراً سلفاً على التفاعل:fff:

  • Like 1
قام بنشر

1. الفرق بين Select و Activate :

قد يتساءل المرء : ما الفرق بين تحديد الهدف Select وتنشيطه Activate :

قد يكون من الصعوبة بمكان الإجابة عن هذا السؤال ببضع كلمات ، و لكن وكما تعودنا ، فإن الأمثلة هي خير طريقة لإيصال المعلومات ، لاحظ الكود التالي :

Sub SelectAndActivate1()
  With Sheets("Sheet1")
    .Range("A1:E10").Select
    .Range("C5").Activate
  End With
End Sub
نلاحظ أننا قمنا بتحديد المجال A1:E10 و لكن الخلية النشطة في هذا المجال (الخلية الجاهزة لإستقبال البيانات) هي الخلية C5 . يمكننا تطبيق نفس الأسلوب السابق على أوراق العمل ، لاحظ الكود التالي :
Sub SelectAndActivate2()
  Sheets(Array("Sheet1", "Sheet2", "Sheet3")).Select
  Sheets("Sheet2").Activate
End Sub
ولكن يجب عليك الانتباه إلى أن هذه الميزة متوفرة فقط في حال كون الهدف المنشط ينتمي إلى مجال الأهداف المحددة ، لفهم الموضوع بصورة أوضح راقب ما ينج عن هذه الأكواد :
Sub SelectAndActivate3()
  With Sheets("Sheet1")
    .Range("A1:E10").Select
    .Range("H6").Activate
  End With
End Sub
Sub SelectAndActivate4()
  Sheets(Array("Sheet1", "Sheet2", "Sheet3")).Select
  Sheets("Sheet4").Activate
End Sub
لاحظ أن الهدف المحدد هو نفسه الهدف المنشط :p خذ هذا الأمر في الحسبان :pp: نفس الشيء يحصل عندما يكون الهدف المحدد هو هدف واحد ، في هذه الحالة فإن الهدف المحدد يكون منشطاً بصورة تلقائية ، وهنا لا فرق نستطيع استناجه بين هذين الكودين :
Sub SelectAndActivate5()
  Sheets("Sheet1").Activate
End Sub  
Sub SelectAndActivate6()
  Sheets("Sheet1").Select
End Sub

مرفق ملف يتضمن الحالات السابقة مع أكوادها :

بالتوفيق :fff:

Select_Activate.zip

  • Like 1
قام بنشر

2. الفرق بين Sheets و Worksheets :

الكلمة المحجوزة Worksheets تستخدم للإشارة إلى أوراق العمل فقط في المصنف ، أما الكلمة المحجوزة Sheets فتستخدم للإشارة إلى الأوراق بكافة أنواعها (أوراق العمل ، أوراق التخطيط ، ... ، الخ) في المصنف ، لاحظ الأكواد التالية :

Sub WorksheetsAndSheets1()
  Sheets("Sheet1").Activate
End Sub
Sub WorksheetsAndSheets2()
  Sheets("Chart1").Activate
End Sub
Sub WorksheetsAndSheets3()
  Worksheets("Sheet1").Activate
End Sub
Sub WorksheetsAndSheets4()
  Worksheets("Chart1").Activate
End Sub
نلاحظ أن الكود الرابع يعطي الخطأ رقم 9 عند تشغيله :
Subscript out of range
و هذا ينطبق مع ما قلناه سابقاً ولكن ألم يخطر في بالك السؤال التالي: لماذا لا نستخدم الكلمة المحجوزة Sheets في جميع أكوادنا ؟!!!! هذا بالفعل ما أقوم به :rol: وذلك لأن الكلمة المحجوزة Sheets أسهل بالكتابة و أريح على الذهن :d ، ولكن مهلاً يمكننا الاستفادة من التفريق السابق في أكوادنا : بفرض أنه لدينا مصنف يحتوي على ثلاثة أوراق عمل Sheet1 ، Sheet2 ، Sheet3 و ورقة تخطيط واحدة Chart1 ، وبفرض أن ترتيب الأوراق كان كما يلي : Sheet1 ، Sheet2 ، Chart1 ، Sheet3 الآن لنقم بتطبيق الكود التالي :
Sub WorksheetsAndSheets5()
  Worksheets(3).Activate
End Sub

نلاحظ أنه تم تنشيط الورقة Sheet3 ، هل تعرف لماذا؟

الكود السابق يقوم بتنشيط ورقة العمل الواقعة في الترتيب الثالث ، وبما أننا هنا نتعامل مع الكلمة المحجوزة Worksheets فإنه لم يتم أخذ الورقة Chart1 في الحسبان أثناء حساب ترتيب الأوراق.

مرفق ملف يتضمن الحالات السابقة مع أكوادها :

بالتوفيق :fff:

Worksheets_Sheets.zip

  • Like 1
  • 2 weeks later...
قام بنشر

3. الفرق بين Range و Cells :

- يستخدم الأسلوب Range للإشارة إلى مجال الخلايا و ذلك عن طريق كتابة المجال باستخدام نظام الترميز A1 (تتم الإشارة إلى خلية ما بإدخال حرف العمود متبوعاً برقم الصف) ، لاحظ الأكواد التالية :

Sub Test1()
  Sheets("Sheet1").Range("A1").ClearContents
End Sub
الكود السابق يقوم بمسح القيم الموجودة في الخلية A1 .
Sub Test2()
  Sheets("Sheet1").Range("B2:C5").ClearContents
End Sub
الكود السابق يقوم بمسح القيم الموجودة في المجال B2:C5 .
Sub Test3()
  Sheets("Sheet1").Range("A2:B3,D3,E5:G7,H11").ClearContents
End Sub
الكود السابق يقوم بمسح القيم الموجودة في المجالات A2:B3 ، D3 ، E5:G7 ، H11 . - أما الأسلوب Cells فيستخدم للإشارة إلى الخلايا المختلفة عن طريق كتابة رقم صف الخلية يليه رقم العامود ، لاحظ الكود التالي :
Sub Test4()
  Sheets("Sheet1").Cells(2, 5).ClearContents
End Sub
الكود السابق يقوم بمسح القيم الموجودة في الخلية الواقعة في الصف الثاني و العامود الخامس من الورقة Sheet1 (أي الخلية E2). بالنسبة لقدرة الأسلوب Cells على الإشارة للمجالات المختلفة فهي محدودة ، ولا يستطيع ذلك إلى عن طريق الاستعانة بالأسلوب Range ، لاحظ الكود التالي :
Sub Test5()
  Sheets("Sheet1").Range(Cells(2, 3), Cells(5, 7)).ClearContents
End Sub
الكود السابق يقوم بمسح القيم الموجودة في المجال C2:G5 الموجود في الورقة Sheet1 . مما سبق فإنه يبدو لنا أن التعامل مع الأسلوب Range هو أسهل بكثير من التعامل مع مثيلها Cells ، ولكن مهلاً ....... فالأسلوب Cells يمتلك مرونة عالية في التعامل مع الأهداف المتغيرة ، لاحظ الكود التالي :
Sub MultiplicationTable1()
  Dim i As Byte, ii As Byte
  With Sheets("Sheet1")
    For i = 1 To 10
      For ii = 1 To 10
        .Cells(i, ii) = i * ii
      Next ii
    Next i
  End With
End Sub
الكود السابق هو كود مدرج في أحد مشاركاتنا السابقة ، ويقوم بإنشاء جدول الضرب في الورقة Sheet1 . لاحظ مقدار المرونة الذي يوفره لنا الأسلوب Cells ، و فكر بالصعوبات التي من المحتمل أن تواجهنا عند استخدام الأسلوب Range (و خصوصاً عند التعامل مع ترتيب الأعمدة) . مثال آخر يظهر مرونة الأسلوب Cells : بفرض أن لدينا جدول متوضع بين العامودين B و E ، ونريد إنشاء زر أمر لمسح قيم أي سجل بالاعتماد على رقمه . بالاعتماد على الأسلوب Cells فإننا نستطيع كتابة الكود التالي :
Sub DeleteRecord1()
  Dim NumberRow As Long
  NumberRow = Application.InputBox(prompt:="ادخل رقم الصف", Title:="رقم الصف", Type:=1)
  If NumberRow = False Or NumberRow > 65536 Then Exit Sub
  Sheets("Sheet1").Range(Cells(NumberRow, 2), Cells(NumberRow, 5)).ClearContents
End Sub
الآن إذا أردنا الاعتماد على الأسلوب Range في الكود السابق عوضاً عن الأسلوب Cells ، فإننا سنحتاج لتعريف متغير إضافي MyRange من نوع نص و كتابة سطر إضافي لإنشاء المرجع المطلوب قبل استخدامه في الأسلوب Range ، لاحظ الكود التالي :
Sub DeleteRecord2()
  Dim NumberRow As Long
  Dim MyRange As String
  NumberRow = Application.InputBox(prompt:="ادخل رقم الصف", Title:="رقم الصف", Type:=1)
  If NumberRow = False Or NumberRow > 65536 Then Exit Sub
  MyRange = "B" & NumberRow & ":E" & NumberRow
  Sheets("Sheet1").Range(MyRange).ClearContents
End Sub
بنظرة بسيطة نلاحظ أ الكود الأول هو أكثر كفاءة من الكود الثاني . لأخذ العلم ، فإن الطريقة السابقة أدرجت لتبيان الفرق بين الأسلوبين ، وذلك مع العلم بأنه يمكن حل المشكلة السابقة بطريقة أكثر بساطة و ذلك إذا ما اعتمدنا على الأسلوب Offset . ملاحظات هامة جداً عن الأسلوبين Cells و Range : 1. عندما تجري عملية مناقلة بين خلايا معينة ، فإنه لا يشترط استخدام نفس الأسلوب للإشارة إلى الخلايا أو النطاقات في كلتا المجموعتين : فمثلاً إذا أردنا لصق قيم المجال A1:A5 في المجال B1:B5 فإننا نستطيع عمل ذلك باستخدام أي طريقة من الطرق التالية :
Sub Test6()
  With Sheets("Sheet1")
    Range("B1:B5").Value = Range("A1:A5").Value
  End With
End Sub
Sub Test7()
  With Sheets("Sheet1")
    Range(Cells(1, 2), Cells(5, 2)).Value = Range(Cells(1, 1), Cells(5, 1)).Value
  End With
End Sub
Sub Test8()
  With Sheets("Sheet1")
    Range(Cells(1, 2), Cells(5, 2)).Value = Range("A1:A5").Value
  End With
End Sub
Sub Test9()
  With Sheets("Sheet1")
    Range("B1:B5").Value = Range(Cells(1, 1), Cells(5, 1)).Value
  End With
End Sub
2. قدرة كلا الأسلوبين Cells و Range على التكيف مع مجموعات الأهداف المختلفة : وهذه برأيي أهم ميزة يمتلكها هذين الأسلوبين ، وتقوم هذه الميزة على أن الأسلوب يشير للموضع النسبي للهدف المحتضن بالاعتماد على الهدف الحاضن له . لفهم هذه الميزة بشكل أوضح لاحظ الكودين التاليين :
Sub Cells_Place1()
  Dim MyRange As Range
  Set MyRange = Sheets("Sheet1").Range("C5:H10")
  Sheets("Sheet1").Cells(1, 1).Value = "هذه الخلية الأولى من الورقة Sheet1"
  MyRange.Cells(1, 1).Value = "هذه الخلية الأولى من المجال  MyRange"
End Sub
Sub Cells_Place2()
  Dim MyRange As Range
  Set MyRange = Sheets("Sheet1").Range("C5:H10")
  Sheets("Sheet1").Range("A1").Value = "هذه الخلية الأولى من الورقة Sheet1"
  MyRange.Range("A1").Value = "هذه الخلية الأولى من المجال  MyRange"
End Sub
نلاحظ أن الأسلوبين Cells و Range قد اعتمدا على كل من الهدفين Sheet1 و MyRange ـ (C5:H10) من أجل تحديد الهدف الناتج (المحتضن) . بالنسبة لي ، فإنني أعتقد أن الأسلوب Cells أقدر على التعامل مع هذه الميزة بصورة أكثر كفاءة ، لاحظ الكود التالي :
Sub Cell_Index()
  On Error GoTo NoRange
  Dim MyRange As Range
  Dim NumberRow As Long
  Dim NumberColumn As Long
  Set MyRange = Application.InputBox(prompt:="أدخل مجال الخلايا الذي تريده", Title:="مجال الخلايا", Type:=8)
  On Error GoTo 0
  For NumberRow = 1 To MyRange.Rows.Count
    For NumberColumn = 1 To MyRange.Columns.Count
      MyRange.Cells(NumberRow, NumberColumn).Value = NumberRow & "×" & NumberColumn
    Next NumberColumn
  Next NumberRow
  Exit Sub
  
NoRange:
  If Err = 424 Then
    Exit Sub
  Else
    MsgBox Err.Description
  End If
End Sub

الكود السابق يقوم بإدراج ترتيب كل خلية (رقم صفها و عامودها) وذلك بالنسبة للهدف الحاضن MyRange .

لا تقلق أخي إذا لم تفهم هذه الميزة بصورة كاملة ، وذلك لأن لنا عودة معها عندما نقوم بشرح الأسلوبين CurrentRegion و UsedRange .

تحياتي :fff:

  • Like 1
زائر
هذا الموضوع مغلق.
  • تصفح هذا الموضوع مؤخراً   0 اعضاء متواجدين الان

    • لايوجد اعضاء مسجلون يتصفحون هذه الصفحه
×
×
  • اضف...

Important Information