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

شرح : تتبع التغييرات التى تمت على جميع السجلات فى برنامجك Dynamic Audit Trail


Amr Ashraf

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

السلام عليكم .. الاساتذة الكرام

الموضوع اليوم عن تتبع التغييرات التى تقوم بها على اى سجل موجود فى قاعدة البيانات .. لنبدأ

لنفترض ان لدى مجموعة من النماذج التى تقوم بتعديل بيانات معينة فى الجداول واريد ان اتتبع التغييرات التى تمت بحيث يتم تسجيل البيانات قبل التعديل وبعد التعديل

مثال : لدى هذا النموذج ومهمته التعديل على رصيد المخزن .. انظر للقيمة قبل التعديل :

1.png.d5cc21d8b302544811856d84695c92db.png

قمت بالتعديل وضغطت على زر الأمر ..

2.png.811ed84cf6f8084dc2fe01c9ee3f74ee.png

النتيجة .. فى جدول التعديلات TblAudit تم تسجيل التالى :

3.png.815b63f0880f49193561b6ae685e8aa7.png

القيمة قبل التعديل وبعد التعديل .. والشخص القائم بالتعديل .. وتاريخ ووقت التعديل  .. و النموذج المستخدم فى التعديل .. ومصدر بيانات هذا النموذج .

فلنجرب تعديل اكثير من حقل فى النموذج دفعة واحدة :

4.png.8f26c678c4b1e4dfa5a9000150fd4eb3.png

النتيجة :

5.png.5695b08a2ae679ed54f38652b3bab0de.png

تابع معى لتعرف الطريقة :

مبدأياً لم اكتب الكود ولكن قمت بالتعديل عليه وعملت امثلة مصمم الكود كتبت اسمها فى الكود نفسه ..

افتح موديول جديد والصق هذا الكود :

Public Function WriteAudit(frm As Form, lngID As Long) As Boolean
On Error GoTo err_WriteAudit

    Dim ctlC As Control
    Dim strSQL As String
    Dim bOK As Boolean
   
   
   
    bOK = False
    
   DoCmd.SetWarnings False
    
    ' For each control.
    For Each ctlC In frm.Controls
        If TypeOf ctlC Is TextBox Or TypeOf ctlC Is ComboBox Then
            If ctlC.Value <> ctlC.OldValue Or IsNull(ctlC.OldValue) Then
                If Not IsNull(ctlC.Value) Then
                    strSQL = "INSERT INTO tblAudit ( ID, FieldChanged, FieldChangedFrom, FieldChangedTo, User, DateofHit, FrmName , FrmRcrdSrc  ) " & _
                           " SELECT " & lngID & " , " & _
                           "'" & ctlC.Name & "', " & _
                           "'" & ctlC.OldValue & "', " & _
                           "'" & ctlC.Value & "', " & _
                           "'" & GetUserName_TSB & "', " & _
                           "'" & Now & "' , " & _
                           "'" & M & "', " & _
                           "'" & R & "'"

                    'Debug.Print strSQL
                    DoCmd.RunSQL strSQL
                End If
            End If
        End If
    Next ctlC
    
    WriteAudit = bOK
    
exit_WriteAudit:
    DoCmd.SetWarnings True
    Exit Function
    
err_WriteAudit:
    MsgBox Err.Description
    Resume exit_WriteAudit
    
End Function

اذا اردت ان تنادى هذا الكود يتم بهذه الطريقة

WriteAudit(Form Name, Record ID)

مثلا كالتالى فى زر امر  :

On Error GoTo Err_cmdClose_Click
    
    If Not IsNull(Me!ID) Then
        M = Me.Name
      '  Debug.Print M
        R = Me.RecordSource
      '  Debug.Print R
        X = WriteAudit(Me, Me!ID)
    End If
    
    DoCmd.Close

Exit_cmdClose_Click:
    Exit Sub
    
Err_cmdClose_Click:
    MsgBox Err.Description
    Resume Exit_cmdClose_Click

ملاحظة :

- يمكن استخدام الكود فى اى نموذج يقوم بتعديل البيانات وسيقوم الكود بتسجيل التعديلات وبياناتها كما اشرت سابقاً.

قام استاذنا جعفر @jjafferr بعمل موضوع رائع مشابه فى الفكرة ولكن يقوم بتسجيل التعديلات التى تتم على الجداول عن طريق الماكرو يمكنك مشاهدته من هنا :

مرفق مثال به نموذجين وتم استخدام نفس الاكواد فيهما .. دمتم بود :fff:

 

Dynamic Audit Trail - Amr Ashraf.accdb

  • Like 5
  • Thanks 2
رابط هذا التعليق
شارك

2 دقائق مضت, Eng.Qassim said:

اقتراحي ان يتم التعديل عليه بان ياخذ GetUserName من جدول ال Users

هوا بيسجل اسم المستخدم الخاص بالويندوز مش البرنامج.. وعامة زيادتها سهلة يبقوا الاتنين موجودين .. شرفنى مرورك :fff:

رابط هذا التعليق
شارك

ما شاء الله عاشت ايدك فوق الممتاز 

ولكن عندي سؤال لما استورد الوحدات النمطية للبرنامج بتاعي مش شغال الا علي الجداول االي حضرتك عملتها اما اي جدول خاص بيا مش شغال مع العمل ان جدول تسجيل التغيرات استورته لبرنامجي كما هو 

رابط هذا التعليق
شارك

29 دقائق مضت, moamen salem said:

ولكن عندي سؤال لما استورد الوحدات النمطية للبرنامج بتاعي مش شغال الا علي الجداول االي حضرتك عملتها اما اي جدول خاص بيا مش شغال مع العمل ان جدول تسجيل التغيرات استورته لبرنامجي كما هو 

ارفق ما قمت به .. لا علاقة للجداول بالموضوع الفكرة كلها فى الاكواد .. الجدول الوحيد المطلوب هو TblAudit لتسجيل التغيرات به

رابط هذا التعليق
شارك

39 دقائق مضت, moamen salem said:

لما استورد الوحدات النمطية للبرنامج بتاعي مش شغال الا علي الجداول االي حضرتك عملتها

طبعا استاذ مؤمن ..لو تلاحظ حضرتك لجملة السكوال في الموديول لازم تغيرها حسب جدولك بما يتطابق واسماء الكنترول الي في النموذج

رابط هذا التعليق
شارك

4 دقائق مضت, Eng.Qassim said:

لجملة السكوال في الموديول لازم تغيرها حسب جدولك بما يتطابق واسماء الكنترول الي في النموذج

يا هندسة هل تقصد جدول TblAudit ؟ .. هذا هو الجدول الوحيد المطلوب استيراده مع الموديولات اما باقى الجداول لا علاقة لها بالموضوع .. أيا كانت الجداول الموجودة فى القاعدة لن يتغير فى الكود أى شئ .. تشرفت بمرورك :fff:

رابط هذا التعليق
شارك

لما سحبت النموذج اللي فيه المشكلة في قاعدة بيانات تاني فارغة وحذفت كل الاكواد اللي فيه اشتغل بدون مشكلة كدة تقريبا في بعض الاكواد متعارضة معاه هشوف كدة ان شاء الله وشكرا جدا علي المعلومة دي 

  • Like 1
رابط هذا التعليق
شارك

5 دقائق مضت, moamen salem said:

شاء الله وشكرا جدا علي المعلومة دي 

لا شكر على واجب , لا تنسى موافاتنا بتحليلك للمشكلة .

الان, moamen salem said:

ولكن هتفضل عندنا مشكلة جوهرية ومحدش اتكلم فيها اللي هي النماذج الفرعية اللي بداخل النماذج الرئيسية

أحسنت كنت مستنى حد يذكرها .. ممكن تعديل الكود ليعمل فى الحالتين سأحاول عملها فى اقرب وقت ودمجها فى الموضوع .

الموضوع فى بالى من الاول بس مستنى المناقشات .

رابط هذا التعليق
شارك

7 دقائق مضت, Amr Ashraf said:

لا شكر على واجب , لا تنسى موافاتنا بتحليلك للمشكلة .

المشكلة طلعت في الكود دا 

DoCmd.GoToRecord , , acNewRec
حاطه في حدث عند التحميل اول ما احذفه الامور تكون تمام ولما اخليه ترجع المشكلة تاني

9 دقائق مضت, Amr Ashraf said:

لا شكر على واجب , لا تنسى موافاتنا بتحليلك للمشكلة .

أحسنت كنت مستنى حد يذكرها .. ممكن تعديل الكود ليعمل فى الحالتين سأحاول عملها فى اقرب وقت ودمجها فى الموضوع .

الموضوع فى بالى من الاول بس مستنى المناقشات .

ان شاء الله تتوصل ليها ممكن نحط نفس الكود في حدث بعد تحديث للسجل في النموذج الفرعي وحضرتك اكيد عندك فكر احسن مني

  • Like 1
رابط هذا التعليق
شارك

7 ساعات مضت, moamen salem said:

ولكن هتفضل عندنا مشكلة جوهرية ومحدش اتكلم فيها اللي هي النماذج الفرعية اللي بداخل النماذج الرئيسية

لسه شايف الموضوع الان

ولما جربته ظهرت معايا نقطة النماذج الفرعيه وخصوصا ان اغلب الاشياء المهمه المطلوب مراقبتها فى التعديلات بتكون فى نماذج فرعيه 

 

7 ساعات مضت, Amr Ashraf said:

لا شكر على واجب , لا تنسى موافاتنا بتحليلك للمشكلة .

أحسنت كنت مستنى حد يذكرها .. ممكن تعديل الكود ليعمل فى الحالتين سأحاول عملها فى اقرب وقت ودمجها فى الموضوع .

الموضوع فى بالى من الاول بس مستنى المناقشات .

اشكر شكرا جزيلا على المجهود :fff:

بارك الله فيك 

وفى انتظار تعديل حضرتك

رابط هذا التعليق
شارك

1 ساعه مضت, moamen salem said:

لمشكلة هنا في سند القبض للاسف الكود بيعطي رسالة خطأ

اعتقد المشكلة في رقم المستند المرتبط بالنموذج الفرعي ..فالموديول هنا هل يقرا من الرئيسي ام الفرعي ؟

ويجب ان يكون المعرف باللغة الانكليزية =ID

رابط هذا التعليق
شارك

2 ساعات مضت, moamen salem said:

المشكلة هنا في سند القبض للاسف الكود بيعطي رسالة خطأ

لأن الحقل ID عندك String او حقل نصى ولكن فى الموديول ID متعرف As Long وبالتالى الموديول بيتوقع لما يتم تمرير ID من النموذج انه هيكون رقم وليس حروف وارقام وبالتالى بيطلعلك الخطأ Type Mismatch ان الID متعرف كمتغير رقمى ولكن اللى بيطلع من النموذج متغير نصى . فهمت ؟ حل الموضوع كالتالى .. يتم تعديل الموديول ليقبل النص والرقم

Public Function WriteAudit(frm As Form, StrID As String) As Boolean
On Error GoTo err_WriteAudit

    Dim ctlC As Control
    Dim strSQL As String
    Dim bOK As Boolean
   
   
   
    bOK = False
    
   DoCmd.SetWarnings False
    
    ' For each control.
    For Each ctlC In frm.Controls
        If TypeOf ctlC Is TextBox Or TypeOf ctlC Is ComboBox Then
            If ctlC.Value <> ctlC.OldValue Or IsNull(ctlC.OldValue) Then
                If Not IsNull(ctlC.Value) Then
                    strSQL = "INSERT INTO tblAudit ( ID, FieldChanged, FieldChangedFrom, FieldChangedTo, User, DateofHit, FrmName , FrmRcrdSrc  ) " & _
                           " SELECT '" & StrID & "', " & _
                           "'" & ctlC.Name & "', " & _
                           "'" & ctlC.OldValue & "', " & _
                           "'" & ctlC.Value & "', " & _
                           "'" & GetUserName_TSB & "', " & _
                           "'" & Now & "' , " & _
                           "'" & M & "', " & _
                           "'" & r & "'"

                    'Debug.Print strSQL
                    DoCmd.RunSQL strSQL
                End If
            End If
        End If
    Next ctlC
    
    WriteAudit = bOK
    
exit_WriteAudit:
    DoCmd.SetWarnings True
    Exit Function
    
err_WriteAudit:
    MsgBox Err.Description
    Resume exit_WriteAudit
    
End Function

لاحظ هذا السطر

قديم
Public Function WriteAudit(frm As Form, lngID As Long) As Boolean

بعد التعديل
  
Public Function WriteAudit(frm As Form, StrID As String) As Boolean

جرب ووافنى بالنتيجة

@Eng.Qassim لاحظ سبب المشكلة .

 

Dynamic Audit Trail - Amr Ashraf v2.0.accdb

رابط هذا التعليق
شارك

السادة الافاضل .. بالنسبة لمشكلة عدم عمل الكود على النموذج الفرعى Subform تم حلها بدون تعديل فى الموديول .. شرح الحل

اذا قمت بمناداة الموديول عند حدث بعد التحديث لحقول النموذج الفرعى فما سيتم انه سيقوم بالحاق نفس السجل متكرر بنفس عدد التعديلات وبالتالى اذا قمنا ب4 تعديلات فإن اول 3 تعديلات سيتم تكرارهم 4 مرات والتعديل الاخير لن يتم تكراره وذلك لأن القيم المخزنة هى قيم السجل بالكامل وليس حقل واحد وبالتالى عند الحاقها بالجدول سيقوم بتقسيم السجل الى سطور وبهذا يتم التكرار .. انظر للمثال

529957604_Recording2022-02-14at10_33_03.thumb.gif.c6377f63bfb1eb0c6c100ce498c62e29.gif

كما تلاحظ تم تكرار التعديل الاول مرتين والثانى لم يتم تكراره لأن ليس هناك تعديلات بعده

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

مرفق التعديل على مرفق الاستاذ @moamen salem , انظر التعديل @عمر ضاحى

 

Dynamic Audit Trail + Subforms - Amr Ashraf v3.0.accdb

  • Like 1
رابط هذا التعليق
شارك

3 ساعات مضت, Amr Ashraf said:

لأن الحقل ID عندك String او حقل نصى ولكن فى الموديول ID متعرف As Long وبالتالى الموديول بيتوقع لما يتم تمرير ID من النموذج انه هيكون رقم وليس حروف وارقام وبالتالى بيطلعلك الخطأ Type Mismatch ان الID متعرف كمتغير رقمى ولكن اللى بيطلع من النموذج متغير نصى . فهمت ؟ حل الموضوع كالتالى .. يتم تعديل الموديول ليقبل النص والرقم

Public Function WriteAudit(frm As Form, StrID As String) As Boolean
On Error GoTo err_WriteAudit

    Dim ctlC As Control
    Dim strSQL As String
    Dim bOK As Boolean
   
   
   
    bOK = False
    
   DoCmd.SetWarnings False
    
    ' For each control.
    For Each ctlC In frm.Controls
        If TypeOf ctlC Is TextBox Or TypeOf ctlC Is ComboBox Then
            If ctlC.Value <> ctlC.OldValue Or IsNull(ctlC.OldValue) Then
                If Not IsNull(ctlC.Value) Then
                    strSQL = "INSERT INTO tblAudit ( ID, FieldChanged, FieldChangedFrom, FieldChangedTo, User, DateofHit, FrmName , FrmRcrdSrc  ) " & _
                           " SELECT '" & StrID & "', " & _
                           "'" & ctlC.Name & "', " & _
                           "'" & ctlC.OldValue & "', " & _
                           "'" & ctlC.Value & "', " & _
                           "'" & GetUserName_TSB & "', " & _
                           "'" & Now & "' , " & _
                           "'" & M & "', " & _
                           "'" & r & "'"

                    'Debug.Print strSQL
                    DoCmd.RunSQL strSQL
                End If
            End If
        End If
    Next ctlC
    
    WriteAudit = bOK
    
exit_WriteAudit:
    DoCmd.SetWarnings True
    Exit Function
    
err_WriteAudit:
    MsgBox Err.Description
    Resume exit_WriteAudit
    
End Function

لاحظ هذا السطر

قديم
Public Function WriteAudit(frm As Form, lngID As Long) As Boolean

بعد التعديل
  
Public Function WriteAudit(frm As Form, StrID As String) As Boolean

جرب ووافنى بالنتيجة

@Eng.Qassim لاحظ سبب المشكلة .

 

Dynamic Audit Trail - Amr Ashraf v2.0.accdb 760 kB · 3 downloads

اشتغلت ممتازة ولكن بقي مشكلة ان لو النموذج مصدره استعلام مدمج وليس اسم جدول بيحط الاستعلام كله في جدول التغيرات وليس اسم الشاشة

WhatsApp Image 2022-02-14 at 4.34.41 PM.jpeg

WhatsApp Image 2022-02-14 at 4.34.58 PM.jpeg

رابط هذا التعليق
شارك

1 دقيقه مضت, moamen salem said:

اشتغلت ممتازة ولكن بقي مشكلة ان لو النموذج مصدره استعلام مدمج وليس اسم جدول بيحط الاستعلام كله في جدول التغيرات وليس اسم الشاشة

عارف الموضوع ده بس مفيش ليه فكرة عندى لأنه بيجيب المصدر أياً كان هوا ايه جدول او استعلام عادى او جملة Sql , ممكن نفكر ليها فى طريقة اخرى بس حاليا معنديش

رابط هذا التعليق
شارك

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

زائر
اضف رد علي هذا الموضوع....

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • تصفح هذا الموضوع مؤخراً   0 اعضاء متواجدين الان

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

Important Information