السلام عليكم
قبل أن نبدأ في حلقة اليوم سنلقي نظرة شاملة علي الواجهة الرئيسية للبرنامج ، قم بتشغيل المشروع الوجود في المرفقات ، ستلاحظ أنه تم تقسيم قوائم المشروع إلي مجموعات كل مجموعة تختص بقسم من أقسام النظام ، فيوجد قائمة للمشتريات وأخري للمخازن وثالثة للمبيعات ورابعة قسم عام للتقارير ، وباستعراض قوائم البرنامج ستلاحظ أن كل قائمة تحتوي علي خيار لتسجيل نوع من البيانات الثابتة ، ففي قائمة المشتريات ستجد خيار لتسجيل بيانات الموردين ، وفي قائمة المخازن ستجد خيار لحفظ بيانات المخزون ، وفي قائمة المبيعات ستجد خيار لحفظ بيانات العملاء وآخر لتسجيل بيانات مندوبي البيع ، ونقول عن هذه البيانات ثابتة لأن البيانات التي يتم تسجيلها بهذه الخيارات تكون ثابتة نسبيا وتتعامل مع جدول واحد في الغالب
واعتبارا من هذه الحلقة وبعض حلقات قادمة سنبدأ في تصميم وتغذية النظام بالبيانات الثابتة التي لابد منها لكي نبدأ في تصميم حركة المبيعات والمخازن ، وسنبدأ بالترتيب المنطقي للحركة ، لكي تقوم بأي عملية مشتريات نحن نحتاج إلي بيانات الموردين ، لذلك سنقوم بتصميم نموذج الموردين ، كما نحتاج لبيانات المخزون لذلك سنقوم بعد ذلك بتصميم عمليات تسجيل المخزون ، ولكي نقوم بأي عملية بيع نحن نحتاج إلي بيانات العملاء كما نحتاج إلي بيانات مندوبي البيع ، وستكون خطتنا في العمل هو تصميم جميع نماذج البيانات الثابتة وتغذيتها بالبيانات التجريبية ، ثم سنبدأ بعد ذلك في تصميم الحركة وهي ثلاث عمليات رئيسية إضافة المشتريات ، وإضافة مخزون أول المدة وفاتورة المبيعات .
وستكون حلقة اليوم عن نموذج التعامل مع بيانات الموردين
بخصوص قاعدة البيانات سنقوم بتصميم جداول قاعدة البيانات خلال تقديم الحلقات وكلما أقتضي الأمر إضافة جدول جديد ، في المرفقات وفي داخل مجلد المشروع يوجد تصميم جدول الموردين وبعض البيانات التجريبية للموردين
في هذه الحلقة سنقوم بإنشاء نموذج يسمح لنا بتحديث بيانات الموردين ولكن قبل أن نبدأ في تصميم النموذج يجب علينا إنشاء جدول Supplier والذي سنستخدمه في تسجيل بيانات الموردين ، ويتكون هذا الجدول من 6 حقول بيانها كما هو موضح في المستند الموجود في المرفقات
وقد تم إنشاء هذا الجدول في قاعدة البيانات المرفقة
من القائمة Project أختر Major Properties ثم من Startup Object اختر frmSupplier ثم أضغط زر OK لتعود إلي المشروع ، ثم أضغط F5 لتشغيل المشروع لنلقي نظرة علي النموذج.
ستلاحظ أن النموذج يتكون من جزيئين ، الجزء السفلي ويحتوي علي الأداة MajorIndex تعرض بعض أسماء الموردين وصندوق نصوص للبحث في جدول الموردين ، أما الجزء العلوي به مجموعة من أدوات النصوص لتسجيل وتعديل بيانات الموردين مع زرين زر جديد وزر حفظ ، نموذج بسيط في شكله ولكنه قوي في أدائه ، كما ستلاحظ من السطور التالية .
استخدم مستند Word الموجود في المرفقات لدراسة الجدول وإضافة البيانات التجريبية إلي الجدول
إضافة سجل جديد إلي جدول الموردين
1- أنقر علي زر جديد سيظهر رقم المورد في أعلا النموذج كما سينتقل المؤشر إلي صندوق أسم المورد ، أكتب أسم المورد ثم أضغط مفتاح Enter سينتقل المؤشر إلي صندوق العنوان أكتب العنوان ثم أضغط Enter
2- كرر هذه الخطوات مع باقي الصناديق وأدخل باقي بيانات النموذج وعند الضغط علي مفتاح Enter في صندوق رقم التليفون سينتقل المؤشر إلي زر حفظ ، أضغط مفتاح Enter أو أنقر عليه بواسطة الماوس ، سيتم حفظ سجل المورد وستلاحظ ظهوره في الأداة Majorindex في أسفل النموذج ، كما سينتقل التركيز إلي الزر جديد ، لتلقي بيانات سجل جديد
3- كرر الخطوات السابقة باستخدام مورد آخر من الجدول السابق ، لتلاحظ هذه العملية
تعديل بيانات مورد
1- انقر علي اسم المورد المطلوب تعديل بياناته في أداة الفهرس ، ستلاحظ ظهور البيانات في صناديق النصوص
2- قم بإجراء التعديلات المطلوبة ثم أنقر علي زر حفظ ، سيتم حفظ التعديلات .
أعتقد أنها عمليات بسيطة لا يوجد بها أي تعقيد
إما عملية الحذف فسيتم إضافتها بعد إضافة حركة المشتريات ، حيث لا يمكن حذف مورد وله قيود مشتريات في النظام
لنلقي الآن نظرة فاحصة علي الكود المستخدم في تصميم النموذج ، وهو كود بسيط جدا يسهل فهمه
في قسم الإجراءات العام للنموذج ستجد السطور التالية
Dim dbcon As adodb.Connection Dim RecordArry(0 To 5) As Variant
في السطر الأول الإعلان التقليدي عن كائن الاتصال
في السطر الثاني الإعلان عن المصفوفة RecordArry بحيث يكون عدد عناصرها مساويا لعدد حقول جدول الموردين Supplier و كما هو واضح من قاعدة البيانات يتكون الجدول من 6 حقول يبدأ ترقيمها من الرقم 0 وسنقوم بربط عناصر هذه المصفوفة بصناديق النصوص بحيث أن أي تغيير في هذه الصناديق يتم تسجيله في هذه المصفوفة وذلك في الحدث Change لكل صندوق من صناديق الأدوات كما هو واضح من السطور التالية
Private Sub lblId_Change() RecordArry(0) = lblId End Sub Private Sub TxtAdress_Change() RecordArry(2) = TxtAdress End Sub Private Sub txtCuntry_Change() RecordArry(3) = txtCuntry End Sub Private Sub TxtName_Change() RecordArry(1) = TxtName End Sub Private Sub txtPhone_Change() RecordArry(5) = txtPhone End Sub Private Sub Txtpostal_Change() RecordArry(4) = Txtpostal End Sub
وبالتالي أصبح أي تغير يقوم بها المستخدم علي صناديق النصوص الموجودة علي النموذج سينعكس أثره علي عناصر هذه المصفوفة فيصبح عندنا مصفوفة تعكس عناصرها بيانات سجل من سجلات الموردين وسنستخدم هذه المصفوفة في تسجيل بيانات السجل في الجدول
إجراء تحميل النموذج يكون بالشكل التالي
Private Sub Form_Load() Dim Dbname As String Dbname = App.Path & "\major.mdb" AdoOpenConnection Dbname, dbcon clearbound setColCaption View_index End Sub
في السطور الثلاث الأولي تم تحديد وإنشاء الاتصال بقاعدة البيانات
في السطر الرابع تم استدعاء الإجراء clearbound لتنظيف الأدوات من البيانات
في السطر الخامس تم استخدام الإجراء setColCaption لتحديد أتساع أعمدة الأداة MajorIndex ووضع العناوين لهذه الأعمدة
في السطر السادس يتم استدعاء الإجراء View_index لعرض بيانات الموردين في الأداة MajorIndex
ويمكنك مراجعة الحلقة السابقة للتعرف علي هذه الإجراءات ، وسنقابل هذه المجموع من الإجراءات في جميع النماذج تقريبا ، إنشاء الاتصال بقاعدة البيانات ، ثم تنظيف الأدوات من البيانات ثم وضع عناوين الفهرس ثم عرض فهرس النموذج ، قبل أن يبدأ أي نموذج في الظهور
وعندما ينقر المستخدم علي زر جديد يقع الحدث CmdAddnew_Click وهو كما يلي
Private Sub CmdAddnew_Click()
clearbound
RecordArry(0) = GEtNewNumber("SupplierID", "Supplier", dbcon)
lblId = RecordArry(0)
TxtName.SetFocus
End Sub
في السطر الأول يتم تنظيف صناديق النصوص من البيانات القديمة إن وجدت استعدادا لاستقبال البيانات الجديدة
في السطر الثاني يتم استدعاء GEtNewNumber لإعداد رقم جديد للمورد الجديد الذي سيتم إضافته وكما هو واضح تحتاج هذه الوظيفة إلي ثلاث معاملات الحقل الذي سيتم إنشاء الرقم فيه واسم الجدول وكائن الاتصال ويتم تخزين القيمة التي تعود من هذه الوظيفة في العنصر رقم 0 في المصفوفة RecordArry
في السطر الربع يتم وضع هذه القيمة في الأداة lblId ،
في السطر الخامس يتم نقل التركيز إلي صندوق نصوص اسم المورد لاستقبال اسم المورد من المستخدم
وعندما ينتهي المستخدم من كتابة الاسم ويقوم بالضغط علي مفتاح Enter يقع الحدث TxtName_KeyPress وهو كالتالي
Private Sub TxtName_KeyPress(KeyAscii As Integer) If KeyAscii = 13 Then TxtAdress.SetFocus End If End Sub
فينتقل التركيز إلي صندوق عنوان المورد كما هو واضح من السطر الثاني من الحدث ، طباعا سيتم تسجيل اسم العميل في العنصر رقم 1 من المصفوفة RecordArry كما هو واضح في الإجراء TxtName_Change الموضح فيما يلي
Private Sub TxtName_Change() RecordArry(1) = TxtName End Sub
وتتكرر هذه العملية مع باقي صناديق النصوص فيتم استخدام الحدث Change للأداة في تسجيل البيانات في عنصر المصفوفة المربوط بصندوق الأدوات والحدث KeyPress للانتقال إلي صندوق النصوص التالي .
وعندما ينتهي المستخدم من إدخال رقم التليفون والضغط علي مفتاح Enter ينتقل التركيز إلي الزر حفظ ، وعندما يضغط المستخدم علي هذا الزر يقع الحدث cmdSave_Click والموضح فيما يلي
Private Sub cmdSave_Click() If Val(lblId) < 1 Then Exit Sub Dim RecSet As adodb.Recordset Set RecSet = New adodb.Recordset RecSet.Open "Supplier", dbcon, adOpenDynamic, adLockOptimistic UpDateTable RecSet, RecordArry() View_index CmdAddnew.SetFocus End Sub
في السطر الأول يتم اختبار القيمة الموجودة في الأداة LblId فإذا كانت أقل من الواحد ، معني هذا أنه لا يوجد سجل جديد أو سجل قديم في النموذج وقام المستخدم بالضغط علي الزر عشوائيا ، لذلك ننهي الإجراء بدون حفظ .
في السطور الثلاث التالية تم الإعلان وإعداد مجموعة سجلات جدول الموردين Supplier للتعامل معها
في السطر الخامس تم استدعاء الإجراء UpDateTable لتسجيل بيانات المورد في جدول الموردين ومن الواضح أن هذا الإجراء يحتاج إلي معاملين ، الأول مجموعه سجلات جدول الموردين في المتغير RecSet وبيانات المورد الجديد والمخزنة في المصفوفة RecordArry
في السطر السادس يتم إعادة عرض مجموعة الموردين باستدعاء الإجراء View_index لعكس التغيرات التي حدثت
في السطر السابع يتم نقل التركيز إلي الزر جديد CmdAddnew
في الدورة السابقة لإضافة مورد جديد استخدمنا وظيفة وإجراء جديدين وسنتعرض لهم في السطور التالية
الوظيفة GEtNewNumber
كما ذكرت سابقا تقوم هذه الوظيفة بتوليد رقم جديد للمورد وتحتاج هذه الوظيفة كما ذكرت سابقا إلي ثلاث معاملات يجب تمريرهم إليها حقل رقم المورد SupplierID وجدول الموردين Supplier وكائن الاتصال وهو هنا dbcon وهي كما يلي
Function GEtNewNumber(FieldName As String, TableName As String, DB As Connection)
On Error GoTo NewEntry
Dim MySql As String
Dim RecSet As adodb.Recordset
Set RecSet = New adodb.Recordset
MySql = " SELECT MAX(" & FieldName & ") FROM " & TableName
RecSet.Open MySql, DB, adOpenForwardOnly, adLockOptimistic
GEtNewNumber = Val(RecSet.Fields(0)) + 1
GoTo EndGetEntry
NewEntry:
GEtNewNumber = 1
Resume EndGetEntry
EndGetEntry:
End Function
في السطر الأول إذا وقع خطأ في الوظيفة وناتج عند عدم وجود سجلات في الجدول يتم التوجهة إلي البرنامج الفرعي NewEntry حيث يتم شحن الوظيفة بالقيمة 1
في السطور الخمسة التالية تم إعداد وتحديد أعلي رقم في الجدول باستخدام الدالة Max
في السطر السابع تم شحن الدالة GEtNewNumber بهذه القيمة مضافا إليها 1 لتصبح القيمة الجديدة للمورد الجديد
في السطر الثامن تم العودة من الوظيفة
الإجراء UpDateTable
كما ذكرت يستخدم هذا الإجراء في تحديث بيانات جدول ، وفي هذا النموذج هو جدول الموردين ويحتاج هذا الإجراء إلي معاملين مجموعة السجلات التي سيتم تحديثها وهي في هذا النموذج جدول Supplier و مصفوفة بالبيانات التي سيتم إضافتها إلي مجموعة السجلات وهي المصفوفة RecordArry وهي كما يلي
Public Function UpDateTable Fds As adodb.Recordset, FieldsValue()) As Boolean Dim i As Integer Dim ItemNum ItemNum = Val(FieldsValue(0)) If LookForItem(Fds, 0, ItemNum) Then GoSub UpDateField Else Fds.AddNew GoSub UpDateField End If UpDateTable = True Exit Function UpDateField: With Fds For i = 0 To .Fields.Count - 1 .Fields(i).Value = FieldsValue(i) Next .Update End With Return End Function
في السطر الأول والثاني الإعلان عن مجموعة المتغيرات التي سيستخدمها البرنامج
في السطر الثالث تم شحن المتغير ItemNum برقم المورد الموجود في العنصر 0
في السطر الرابع تم استدعاء الوظيفة LookForItem للبحث عن المورد في الجدول ويتم اختبار الحالة
كما هو واضح في هذا السطر
إذا كان رقم المورد موجودا في قاعدة البيانات معني هذا أن المستخدم يريد تحديث بيانات هذا المورد فيتم الانتقال إلي الإجراء الفرعيUpDateField لتحديث البيانات كما هو واضح من السطر الخامس ، أما إذا كان رقم المورد غير موجود فمعني هذا أن المستخدم يرغب في إضافة مورد جديد فيتم استخدام Addnew كما في السطر السابع ثم التفرع إلي الإجراء الفرعي UpDateField لإضافة هذا المورد إلي قاعدة البيانات
في الإجراء UpDateField يتم استخدام دوارة For Next لنقل عنصر المصفوفة إلي الحقل المناظر ثم التحديث ثم العودة
في السطور التالية التعرض للوظيفة LookForItem المستخدمة في البحث عن سجل في جدول بيانات والتي والمستخدمة داخل الإجراء . UpDateTable ، وتحتاج هذه الوظيفة إلي ثلاث معاملات حتى تؤدي عملها مجموعة السجلات التي سيتم البحث فيها ورقم الحقل الذي سيتم البحث فيه والقيمة التي سيتم البحث عنها .وبينها كما يلي
Function LookForItem(Ds As adodb.Recordset, FieldNum As Long, LookValue As Variant) As Boolean Dim MyKey As String Dim FieldName As String FieldName = Ds.Fields(FieldNum).Name MyKey = FieldName & "=" & " " & LookValue & " " Ds.Filter = MyKey If Ds.RecordCount = 1 Then LookForItem = True Else LookForItem = False End If Exit Function FuncErr: LookForItem = False Exit Function End Function
في السطر الثالث يتم استخلاص وشحن المتغير FieldName باسم الحقل الوارد في معاملات الوظيفة
في السطر الرابع جملة Sql للبحث عن القيمة الواردة في معاملات الوظيفة
في السطر الخامس يتم استخدام الأسلوب Filter مع مجموع السجلات لتصفية السجلات علي السجل المطلوب فقط
في السطر السادس يتم اختبار عدد السجلات العائدة من عملية التصفية فإذا كانت القيمة 1 معني ذلك السجل موجود فيتم شجن الوظيفة بالقيمة True ، أما خلاف ذلك معني هذا أن المورد غير موجود فيتم شحن الوظيفة بالقيمة False والعودة بهذه النتائج إلي الإجراء UpDateTable لتحديد كيفية التعامل مع هذا السجل
ونبدأ الأن دورة تحديث بيانات مورد ، عندما ينقر المستخدم علي احد الموردين في الفهرس يقع الحدث index1_Click الموضح فيما يلي
Private Sub index1_Click() Dim ItemNum ItemNum = index1.TextMatrix(index1.Row, 0) Dim RecSet As adodb.Recordset Set RecSet = New adodb.Recordset RecSet.Open "Supplier", dbcon, adOpenForwardOnly, adLockOptimistic If LookForItem(RecSet, 0, ItemNum) Then lblId = RecSet.Fields(0) TxtName = RecSet.Fields(1) TxtAdress = RecSet.Fields(2) txtCuntry = RecSet.Fields(3) txtPhone = RecSet.Fields(4) Txtpostal = RecSet.Fields(5) TxtName.SetFocus End If End Sub
في هذا الإجراء تم استخدام الخاصية TextMatrix في شحن المتغير ItemNum برقم المورد من العامود 0 للفهرس كما هو وضح من السطر الثاني.
في السطر الثالث والرابع والخامس تم إنشاء مجموعة سجلات للجدول Supplier
في السطر السادس تم استخدام الوظيفة LookForItem التي سبق أن تعرضنا لها في البحث عن السجل ووضع مؤشر الملف علي هذا السجل
في السطور من السابع إلي الثاني عشر تم شحن صناديق النصوص بقيم حقول هذا السجل
في السطر الثالث عشر تم نقل التركيز إلي صندوق النصوص TxtName استعدادا لإجراء التعديلات علي سجل المورد ، وعندما ينتهي المستخدم من إجراء التعديلات والضغط علي زر حفظ تبدأ دورة الحفظ السابق شرحها
وهذا كل شئ
أرجو أن يكون الشرح واضح ، وقد حاولت بقدر الأمكان تبسيط وظائف وإجراءات البرنامج كما حاولت تبسيط الشرح بقدر الأمكان .
وإلي القاء مع نموذج أقسام المخزون من قائمة المخازن في الحلقة الرابعه بإذن الله
والسلام عليكم
Major

