اذهب الي المحتوي
أوفيسنا
بحث مخصص من جوجل فى أوفيسنا
Custom Search

قراءة وتفكيك بيانات الحقل الى حقول


jjafferr

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

السلام عليكم 🙂 

 

هذه طريقتي لتفكيك الحقل الى حقول 🙂

 

نأخذ المرفق كالمثال من هذا الرابط :

 

.

هكذا تبدو السجلات ، بالعين المجردة :

image.png.4a1d4a356b03a9ffd91e1d4f8dc62fb9.png

.

والمطلوب ان نقسم بيانات السجل الواحد الى: الاسم ورقم التسلسل (وخلينا نستخدم السجل الاول كمثال) ، ونريد النتيجة تكون :

image.png.1ee4bc622fe25a9770cadd10b2de7ec7.png

.

هناك طريقتين لفرز هذه البيانات :

  1.  عن طريق كود ليقرأ الحروف/الارقام/العلامات واحدا واحدا ، ثم بوضع شروط اذا جصلنا على رقم ، فنتوقف ونحفظ الجزء الاول ، ثم نواصل ... ، وهذه العملية مرهقة وتحتاج الى تفاصيل كثيرة ،
  2.  عن طريق الكود ، ولكن بإستخدام الدالة Split ، ويشترط فيها ان نعرف اين (بعد اي حرف/رقم/علامات) نقسم السطر ، ولنسمية شرط القطع .

 

سنتعامل مع الطريقة الثانية وهي الاسهل 🙂 

لمعرفة شرط القطع ، يمكننا ان نتعامل مع الحروف/الارقام/العلامات مباشرة ChrW ، او نتعامل مع ارقام هذه (الحروف/الارقام/العلامات) AscW ،

وانا لا استغني عن هذه الصورة المرفقة لعملي ، الحرف Chr ، ومقابله رقمه Dec :

ascii-full.gif.eaf5c8344693af7936254bd75851caf6.gif

.

وبالنسبة للحروف العربية ، هذا رابطها https://sites.psu.edu/symbolcodes/languages/mideast/arabic/arabicchart/

او https://www.ssec.wisc.edu/~tomw/java/unicode.html#x0600

وقد قمت باخذ البيانات من الموقع ورتبتها في صفحة واحد :

ascii_Arabic.jpg.8fe192e4e4fc5ec2b3d3401ae8f55841.jpg

فمثلا اول حروف اسم ابراهيم : ا = 1575  ، ب = 1576  ، ر = 1585 ، بمعنى

AscW(ا) = 1575  , AscW(ب) = 1576  , AscW(ر) = 1585

والعكس يكون
ChrW(1575) = ا  , ChrW(1576) = ب  , ChrW(1585) = ر

 

image.png.f53454004d640386ff0d3e6995a30f31.png

.

للحصول على الاسم ، نريد ان يكون لدينا شرط القطع بعد الاسم وقبل بداية الرقم (اي في المنطقة 1) ،

للحصول على التسلسل ، نريد ان يكون لدينا شرط القطع بعد التسلسل وقبل بداية الاسم التالي (اي في المنطقة 2) ،  

image.png.0958879c6b7891feb5c7dc22a8caf73b.png

 

لمعرفة شرط القطع يجب علينا ان نحلل البيانات التي يراها الكمبيوتر ، وذلك بتحويل الحروف/الارقام/العلامات الى AscW ،

هذا الكود يقوم بهذه العملية:

Public Function Split_Names()

    Dim rst As DAO.Recordset
    Dim x() As String
    Dim i As Long
    Dim a As String
    

        Set rst = CurrentDb.OpenRecordset("Select * From MyTxt_from_pdf")
    
        Do Until rst.EOF
            
            For i = 1 To Len(rst!Field1)
                a = Mid(rst!Field1, i, 1)           'الحروف/الارقام/العلامات
                a = a & "(" & AscW(a) & ")  "       'رقمها AscW
                Debug.Print a
            Next i
     
        Loop
    
        rst.Close: Set rst = Nothing
    
End Function

ونناديه من نافذة الكود هكذا (يجب ان يكون الكيبور باللغة الانجليزة عند كتابة علامة الاستفهام) :

image.png.cc3238020a7568b01014b93d0ab03761.png

.

ونرى ان النتيجة للسجل الاول فقط :

اقتباس
?(8235)   ?(8235)   ?(8235)  
ا(1575)   ا(1575)   ا(1575)  
ب(1576)   ب(1576)   ب(1576)  
ر(1585)   ت(1578)   ت(1578)  
ا(1575)   ه(1607)   س(1587)  
ه(1607)   ا(1575)   ا(1575)  
ي(1610)   ج(1580)   م(1605)  
م(1605)    (32)    (32)  
 (32)   س(1587)   م(1605)  
ا(1575)   ا(1575)   ح(1581)  
ح(1581)   م(1605)   م(1605)  
م(1605)   ح(1581)   د(1583)  
د(1583)    (32)    (32)  
 (32)   ن(1606)   ع(1593)  
ي(1610)   س(1587)   ب(1576)  
ح(1581)   ي(1610)   د(1583)  
ي(1610)   م(1605)   ا(1575)  
ى(1609)    (32)    (32)  
 (32)   ا(1575)   ح(1581)  
ا(1575)   ق(1602)   م(1605)  
ح(1581)   ل(1604)   ا(1575)  
م(1605)   د(1583)   د(1583)  
د(1583)   ي(1610)   ه(1607)  
?(8236)   و(1608)   ?(8236)  
 (32)   س(1587)    (32)  
 (32)   ?(8236)    (32)  
 (32)    (32)    (32)  
 (32)    (32)   ?(8235)  
 (32)    (32)   ?(8234)  
 (32)    (32)   1(1633)  
 (32)    (32)   ?(8236)  
 (32)    (32)   ?(8236)
 (32)    (32)    
?(8235)    (32)    
?(8234)    (32)    
3(1635)    (32)    
?(8236)   ?(8235)    
?(8236)   ?(8234)    
 (32)   2(1634)    
 (32)   ?(8236)    
 (32)   ?(8236)    
 (32)    (32)    
 (32)    (32)    
 (32)    (32)    
 (32)    (32)    
 (32)    (32)    
   (32)    
   (32)    
   (32)    
   (32)    
   (32)    
   (32)    
   (32)    
   (32)    
   (32)    
   (32)    
   (32)    
   (32)    
   (32)    
   (32)    
   (32)    
   

.

وبعد التدقيق ، نلاحظ ان في نهاية الارقام نرى ان AscW التالية متكررة 8236 ثم 8236 ثم 32 ثم 32 ، وبذلك يمكننا استعمال هذه كشرط القطع

بعد الاسم
    ا(1575)      
    ق(1602)      
    ل(1604)     ح(1581)  
ا(1575)     د(1583)     م(1605)  
ح(1581)     ي(1610)     ا(1575)  
م(1605)     و(1608)     د(1583)  
د(1583)     س(1587)     ه(1607)  
?(8236)     ?(8236)     ?(8236)  
-32   -32   -32
-32   -32   -32

.

بعد الرقم
3(1635)     2(1634)      
?(8236)     ?(8236)      
?(8236)     ?(8236)      
-32   -32    
-32   -32    

.

وعليه نستعمل هذا الكود ، ونرى نتيجته (للسجل الاول) :

    Do Until rst.EOF

        x = Split(rst!Field1, ChrW(8236) & ChrW(8236) & ChrW(32) & ChrW(32))    'Name + ID
        
        For i = LBound(x) To UBound(x)
            Debug.Print x(i)
            
        Next i
            
        rst.MoveNext
    Loop
      
      
      ونتيجته
?ابراهيم احمد يحيى احمد?         ??3
?ابتهاج سامح نسيم اقلديوس?          ??2
?ابتسام محمد عبدا حماده?   ??1??
      

.

والآن خلينا نفكك الاسم من الرقم :

    Do Until rst.EOF

        x = Split(rst!Field1, ChrW(8236) & ChrW(8236) & ChrW(32) & ChrW(32))    'Name + ID
        For i = LBound(x) To UBound(x)
            'Debug.Print x(i)
            
            x2 = Split(x(i), ChrW(8236) & ChrW(32) & ChrW(32))
            For j = LBound(x2) To UBound(x2)
                
                Debug.Print x2(j)
            Next j
            
        Next i
            
        rst.MoveNext
    Loop

      والنتيجة
      
?ابراهيم احمد يحيى احمد
  ??3
?ابتهاج سامح نسيم اقلديوس
 ??2
?ابتسام محمد عبدا حماده
    ??1??
      

.

ونلاحظ من القائمة اعلاه ، ان علامات الاستفهام ارقامها

?(8235)  
?(8234)  
?(8236)  

.

الخطوة الاخيرة هي تنظيف النتيجة من علامات الاستفهام هذه عن طريق الامر Replace ، والتخلص من المسافة الزائدة قبل وبعد النتيجة عن طريق الامر Trim ،

وبعدها نريد ان نحفظ الاسم في اول حقل ، والرقم في الحقل الثاني:

LBound دائما تساوي صفر

 

    Do Until rst.EOF

        x = Split(rst!Field1, ChrW(8236) & ChrW(8236) & ChrW(32) & ChrW(32))    'Name + ID
        For i = LBound(x) To UBound(x)
            'Debug.Print x(i)
            
            x2 = Split(x(i), ChrW(8236) & ChrW(32) & ChrW(32))
            For j = LBound(x2) To UBound(x2)
                'Debug.Print x2(j)
                a = Replace(x2(j), ChrW(8234), "")
                a = Replace(a, ChrW(8235), "")
                a = Replace(a, ChrW(8236), "")
                a = Trim(a)
                
                'If j / 2 = Int(j / 2) Then
                If j = 0 Then
                    'even
                    Debug.Print "Name: ", a
                Else
                    'odd
                    Debug.Print "ID: " & a
                End If
                
                'Debug.Print a
            Next j
            
        Next i
            
        rst.MoveNext
    Loop
      
      
      والنتيجة
Name:         ابراهيم احمد يحيى احمد
ID: 3
Name:         ابتهاج سامح نسيم اقلديوس
ID: 2
Name:         ابتسام محمد عبدا حماده
ID: 1
Name:         احمد السيد على محمد
ID: 6
Name:         ابراهيم كمال ابراهيم محمد
ID: 5
Name:         ابراهيم سمير عياد عطاا
ID: 4
Name:         احمد حسن احمد رسلن
ID: 9
Name:         احمد حجازى على محمد
ID: 8
Name:         احمد السيد محمد عبدالرحمن
ID: 7      

.

 

--------------------------------------------------------

وفي سياق هذا الموضوع ، كان عندي مشروع القرآن الكريم ، وحفظه في قاعدة البيانات بعدة طرق:

  • كل صفحة عبارة عن سجل ، 
  • وفي جدول آخر ، كل سطر في سجل ،
  • وفي جدول آخر ، كل آية في سجل 

 

وقمت بتنزيل القرآن الكريم من مجمع الملك فهد لطباعة المصحف الشريف : https://fonts.qurancomplex.gov.sa/wp02/حفص 

والمرفق يحتوي على الخط العثماني ، والذي تم عمله في المجمع ، ولذا فهو يحتوي على حروف/ارقام/علامات AscW تختلف عن غيرها من الخطوط ، والطريقة الوحيدة لتفكيك الاسطر كانت بإتباع خطوات شبيهه بالخطوات اعلاه 🙂 

 

جعفر

 

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

1 دقيقه مضت, ابوخليل said:

كل كلمات الشكر لا تفي بحقك استاذنا :fff:

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

الشكر لله على ما انعم ،

ولك ولمن احببت مثل ما دعوت لي ، والشكر لك اخوي العود ابوخليل على جميل كلماتك 🙂 

 

جعفر

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

ماشاء الله شرح اكثر من رائع ووافى جلعله الله فى ميزان حسناتك ان شاء الله

جزاك الله خيرا معلمنا العزيز جعفر وبارك الله لنا فيك وبارك لك فى كل ما تحب  💐

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

أهلا بالجميع..

لا أدري إن كنت فتحت هذه المشاركة أكثر سبعين مرة! المهم ليست مرة ولا مرتين ولا حتى عشرة..

تعاطي الأستاذ @jjafferr مع البيانات أبهرني وأذهلني حقيقيةً..

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

ولذا أرجو من أ. جعفر أن يشير إلى ما يمكن فعله بهذا الخصوص..     

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

السلام عليكم 🙂

شكرا جزيلا اخوي أبو إبراهيم على كلماتك العطرة 🙂 

 

21 ساعات مضت, أبو إبراهيم الغامدي said:

ولذا أرجو من أ. جعفر أن يشير إلى ما يمكن فعله بهذا الخصوص.. 

 

انا احاول قد الامكان ان استعمل الاستعلام لتنفيذ اي موضوع في الاكسس ، لأنه سيكون الاسرع ،

ونفس الشيء حاولته لهذا التفكيك قبل ان اعمل الموضوع ، ولكني لم اصل لنتيجة !!

ومن الوقت الذي وضعت فيه ملاحظتك ، وانا افكر ، وما توصلت لنتيجة :

  1. ما ممكن نستعمل Split ، إلا اذا عرفنا "شرط القطع" (علامة تجارية مسجلة 🙂 ) ،
  2. حاولت مع Split ان اخليه يتعرف على الارقام بواسطة "شرط القطع" isNumeric و IN ، ولكن اكسس لا يقبل هذا ،
  3. ما ممكن نستعمل inStr و inStrRev ثم isNumeric ، لأن الارقام اللي في السجلات ، ليست بأرقام في نظر الاكسس (استعملت inStrRev في الصورة المرفقة) :

image.png.fa4c0058f1029e0b7ecacb2e430ca9bd.png

.

وفي كل خطوة من الخطوات اعلاه في الاستعلام ، اشوف نفسي انجذب لعمل وحدة نمطية لجزئية معينه من كود الاستعلام :biggrin:

 

جعفر

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

أهلا بك أ @jjafferr

18 ساعات مضت, jjafferr said:

انا احاول قد الامكان ان استعمل الاستعلام لتنفيذ اي موضوع في الاكسس ، لأنه سيكون الاسرع ،

ونفس الشيء حاولته لهذا التفكيك قبل ان اعمل الموضوع ، ولكني لم اصل لنتيجة !!

ومن الوقت الذي وضعت فيه ملاحظتك ، وانا افكر ، وما توصلت لنتيجة :

أجل لنفكر في شئ آخر خارج الصندوق..

من ضمن المكتبات المرجعية التي توفرها ويندوز: مكتبة التعابير القياسية (النمطية)، وهي مكتبة تقوم بمعالجة النصوص وفق معايير متعددة، يمكن التعرف هذه المعايير عن طرق الرجوع إلى الموقع الرسمية لهذه المكتبة هنا 

كما يمكن الوصول إلى معايير استخدام ترميز UNICODE  من هنا

فيما تعلق بترميز محارف النص العربي في مقاييس UNICODE: فإنها تبدأ من الرمز: U+0060 وتنتهي بالرمز: U+06FF ، يشمل هذا الترميز جميع ما يتعلق بمحارف النص العربي (حروف، أرقام، زخارف، روابط، إلخ ). راجع الرابط هنا

يمكن الوصول إلى المكتبة في أكسس بالنظر إلى الصورة التالية:REG_EXP_LIB.png.91032540153898fd058cd82161637f01.png

نأتي الآن إلى مثال لتكون الشفرة المتعلقة بالبحث في النص المرفق مع المشاركة لكون النص في غير مطابق لترميز أكسس، ولهذا سوف نلجأ إلى استخدام ترميز UNICODE الموسع للغة العربية كما فعل أ. جعفر، والفرق هنا: أنه بعد كتابة الشفرة يمكن أن نستخدمها عن طريق الاستعلام. هذا مثال مصغر للشفرة استخدام المكتبة..

Public Function TEST_STRING(V As Variant, Optional P As String)
On Error GoTo EXIT_FUNCTION
   
   Dim RE As New RegExp
   Dim MATCH As MATCH
   Dim MATCHX As MatchCollection
   Dim R As Variant
   
   '-- INITIAL RE
   RE.IgnoreCase = True
   RE.Global = True
   
   '-- GET RE PATTREN
   RE.Pattern = P
   '-- SET MATCHX AS OBJECT
   Set MATCHX = RE.Execute(V)
   
   '-- CHECK IF ANY MATCHED
   If MATCHX.Count = 0 Then
      GoTo EXIT_FUNCTION
   End If
   
   '-- INITIAL RESULT VARIABLE
   R = vbNullString
   
   '-- LOOP THROU MATCHX
   For Each MATCH In MATCHX
      Debug.Print MATCH.Value
      R = R & MATCH.Value
   Next
   TEST_STRING = R

EXIT_FUNCTION:
   '-- TERMINATE OBJECTS
   Set MATCHX = Nothing
End Function

قمت بإدراج الوظيفة في الاستعلام بالطريقة التالية:

RESULT: TEST_STRING([FIELD1],[PATTREN])

في مربع الحوار وضعت معايير تعيد جميع الترميز العربي إذا كان بعدها فراغ أو كانت في آخر السطر: 

[\u0060-\u06FF]+\s*|$

كانت النتيجة كما في الصورة التالية..

QUERY_RESULT.png.4b15d30a21abecea46e7678ea723aa04.png

يمكن وضع تعابيير أكثر دقة بمراجعة ماسبق الإشارة إليه، وتجربيه على المثال التالي:

ACCESS WITH REGEXP.accdb

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

 

عمل جميل استاذ ابو ابراهيم ، ولكننا اضطررنا الى العودة الى الوحدة النمطية 🙂 

والشيء الجميل في طريقتك ، انها تخلصت من علامات الاستفهام كذلك مرة واحدة 🙂

يبقى تفكيك نتيجة السجل النظيف الى 3 سجلات 🙂

 

جعفر

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

في ٥‏/٩‏/٢٠٢٠ at 00:37, jjafferr said:

ولكننا اضطررنا الى العودة الى الوحدة النمطية 🙂 

لم يكن قصدي الاستغناء عن الوحدة النمطية؛ بل طلب البيانات دون الاضطرار إلى فحصها من الداخل..

في ٥‏/٩‏/٢٠٢٠ at 00:37, jjafferr said:

يبقى تفكيك نتيجة السجل النظيف الى 3 سجلات 🙂

لكي نتمكن من معرفة النمط الذي يمكن تفكيك النص بواسطته، لابد من النظر إلى الحدود الممكن استخدامها لذلك..

1620224302_CORRUPTEDTEXT.png.f0eb52c5ebaed7abad1fca56126f9e57.png

بالنظر إلى النص أعلاه: لدينا مجموعة من الأحرف الأبجدية العربية محاطة بعلامات استفهام، بعدها فراغ، بعدها أرقام محاطة بعلامات استفهام، بعدها فراغ.. هذا هو النمط التمتكرر في النص.

سيكون رسم النمط وفق النسق التالي..

([\u0621-\u064A\u0661-\u0669]+\s*){1,4}

 

يتجاهل النمط علامات الاستفهام، ويبحث في مجموعة الحروف والأرقام.

u0621-\u064A\ الحروف (ء-ي) 

u0661-\u0669\ الأرقام (1-9)

علامة الزائد تعني واحدً فأكثر..

*s\  تعني صفر فأكثر من الفراغات (الصفر من أجل إدخال الكلمات التي ليس بعدها فراغ)

{1,4}  تقوم بتجميع الكلمات أربع كلمات فما دون إلى الواحد (لكون اسم الموظف في النص من أربع كلمات -أسماء-). يمكن تغيير هذا الحد إذا كانت الأسماء مركبة أو أكثر من أربعة..

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

لتسجيل البيانات في جدول الاسماء نحتاج لعمل دورة متسلسة للمصفوفة  مع مراعات القفز خطوتين في كل دورة لكون رقم الموظف يقع في الخلية التي تلي اسمه، كمايلي

      '-- LOOP THROU RECORD VALUE
      For I = 0 To MZ.Count - 1 Step 2
         RSD.AddNew
         RSD("IID") = MZ(I + 1).Value
         RSD("INAME") = MZ(I).Value
         RSD.Update
      Next

أرجو أن أكون قد وفقت في الشرح..

  ACCESS WITH REGEXP.accdb

Microsoft-Beefs-Up-VBScript-With-Regular-Expressions.pdf

 

 

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

15 ساعات مضت, أبو إبراهيم الغامدي said:

لم يكن قصدي الاستغناء عن الوحدة النمطية؛ بل طلب البيانات دون الاضطرار إلى فحصها من الداخل

في الواقع هذه الخطوة عبارة عن تسهيل جدا كبير للمبرمج 🙂 

 

15 ساعات مضت, أبو إبراهيم الغامدي said:

لكي نتمكن من معرفة النمط الذي يمكن تفكيك النص بواسطة لابد من النظر إلى الحدود الممكن استخدامها لذلك

وقد يكون في الامكان الاستغناء عن الخطوة السابقة ، وعمل كل شيء في هذه الخطوة ، طبعا هذا سيعقد الكود و "رسم النمط وفق النسق" 🙂 

 

شكرا جزيلا اخوي ابو ابراهيم لهذه المشاركة الدسمة 🙂 

 

جعفر

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

  • 1 year later...

من فضلك سجل دخول لتتمكن من التعليق

ستتمكن من اضافه تعليقات بعد التسجيل



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

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

Important Information