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

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

قام بنشر

السلام عليكم

 

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

30/11/2009  ،  2012-06-25  ،  21/6/2015م  ،  " 9/1/2014"  ،  30\11\2009  ، 5/1999/26  ،  25/1999/6  ،  5/1994/ 26  ،  وحتى بعضها بالارقام الهندية ،

فعملت الدالة التالية ، والتي ترسل لها التاريخ المطلوب تعديله ، والدالة تصلح التاريخ وترجعه.

 

وستلاحظون اني استخدمت الدالة DateSerial ، حتى اعطي اليوم والشهر والسنة بياناتهم يدويا ، بدلا عن استعمال CDate .

 

هذه هي الدالة:


Function Date_Rectified(D As String) As Date
On Error Resume Next

    Dim x() As String
    Dim P1 As String, P2 As String, P3 As String
    
    
    D = Trim(D)
    D = Replace(D, "(", "")
    D = Replace(D, ")", "")
    D = Replace(D, "    ", "")
    D = Replace(D, "   ", "")
    D = Replace(D, "  ", "")
    D = Replace(D, " ", "")
    D = Replace(D, "*", "")
    D = Replace(D, "م", "")
    
    D = Replace(D, ChrW(1632), "0") 'الرقم الهندي صفر
    D = Replace(D, ChrW(1633), "1")
    D = Replace(D, ChrW(1634), "2")
    D = Replace(D, ChrW(1635), "3")
    D = Replace(D, ChrW(1636), "4")
    D = Replace(D, ChrW(1637), "5")
    D = Replace(D, ChrW(1638), "6")
    D = Replace(D, ChrW(1639), "7")
    D = Replace(D, ChrW(1640), "8")
    D = Replace(D, ChrW(1641), "9")
    
    D = Replace(D, "!", "-")
    D = Replace(D, "/", "-")
    D = Replace(D, "//", "-")
    D = Replace(D, "\", "-")
    D = Replace(D, ".", "-")
    D = Replace(D, "_", "-")
    D = Replace(D, "|", "-")
    D = Replace(D, ",", "-")
    D = Replace(D, Chr(34), "")
 
    
    If Len(D) = 4 Then
        'starts with year, but its 4 digits only:1999
        'convert to 1-1-1999 OR EMPTY
        
        Date_Rectified = DateSerial(D, 1, 1)
        Exit Function
    End If
    
If D = "5/1994/ 26" Then
Debug.Print D
End If
    
    
    x = Split(D, "-")
    P1 = x(0): P2 = x(1): P3 = x(2)
    
    
    If Len(P1) = 4 And Len(P2) <> 0 Then
        'starts with year, and month exist: 1999-1-2
        
        Date_Rectified = DateSerial(P1, P2, P3)
        
    ElseIf Len(P3) = 4 And Len(P2) <> 0 Then
        'ends with year, and month exist: 2-1-1999
        
        Date_Rectified = DateSerial(P3, P2, P1)
                
                
    ElseIf Len(P2) = 4 And Len(P1) <= 12 Then
        'year in the middle, day and month exist: 5/1999/26
        
        Date_Rectified = DateSerial(P2, P1, P3)
        
    ElseIf Len(P2) = 4 And Len(P1) > 12 Then
        'year in the middle, day and month exist: 25/1999/6

        Date_Rectified = DateSerial(P2, P3, P1)
                
                
    Else
        'otherwise
        Date_Rectified = Null
        
    End If
    
End Function

 

  • Like 6
  • Thanks 2
قام بنشر (معدل)

بعد اذن استاذى الجليل و معلمى القدير و والدى الحبيب الاستاذ @jjafferr :fff:

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

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

 

Function RectifyDateFormat(inputString As String) As Variant
    ' Enable error handling
    ' This line sets up an error handling routine. If an error occurs in the code that follows,
    ' execution will jump to the ErrorHandler label, allowing for controlled error management.
    On Error GoTo ErrorHandler

    ' Remove leading and trailing spaces
    ' This line uses the Trim function to eliminate any spaces at the beginning and end of the input string.
    ' This is important for ensuring that the date format is clean and free of unnecessary spaces
    ' which could lead to incorrect parsing of date parts later in the function.
    inputString = Trim(inputString)

    ' Replace Indian numerals with standard numerals
    ' This block replaces Indian numerals (Unicode character codes from 1632 to 1641) with standard Arabic numerals (0-9).
    ' The loop iterates through the Unicode range for Indian numerals and replaces each occurrence
    ' in the input string with its equivalent standard numeral by calculating its index.
    Dim i As Integer
    For i = 1632 To 1641
        inputString = Replace(inputString, ChrW(i), CStr(i - 1632))
    Next i

    ' Replace non-standard symbols with hyphens
    ' This section defines an array of symbols that are considered non-standard for date formatting.
    ' The goal is to standardize the date input by replacing these symbols with hyphens,
    ' making it easier to parse the date parts later on.
    Dim SymbolsToRemove As Variant
    SymbolsToRemove = Array("(", ")", "?", "*", " ", "!", "\", "/", "//", ".", "_", "--", "|", ",", Chr(227), Chr(34))
    inputString = ReplaceSymbols(inputString, SymbolsToRemove)

    ' Remove leading and trailing hyphens
    ' This line first replaces any occurrence of double hyphens (--) with a single hyphen (-).
    ' After replacing, Trim is used to remove any spaces around the string.
    ' This ensures that any malformed input resulting in multiple hyphens is corrected before further processing.
    inputString = CleanHyphens(inputString)

    ' Split the input string into date parts
    ' This line splits the cleaned input string into an array of date parts using the hyphen (-) as a delimiter.
    ' The result is stored in strDateParts, which will contain the individual components of the date (day, month, year).
    Dim strDateParts() As String
    strDateParts = Split(inputString, "-")

    ' Ensure the input contains exactly three parts
    ' This condition checks if the upper bound of the strDateParts array is not equal to 2.
    ' In VBA, the array index starts from 0, so an array with exactly three elements will have
    ' an upper bound of 2 (i.e., elements at index 0, 1, and 2).
    ' If the input does not contain exactly three parts, the function returns Null
    ' to indicate an invalid date format, and exits the function to prevent further processing.
    If UBound(strDateParts) <> 2 Then
        RectifyDateFormat = Null
        Exit Function
    End If

    ' Assign the split parts to variables, ensuring they are trimmed
    ' This line assigns the individual parts of the date from the strDateParts array
    ' to three separate variables (strPartOne, strPartTwo, strPartThree).
    ' The Trim function is used to remove any leading or trailing whitespace from each part.
    ' This ensures that any extra spaces do not affect the subsequent processing of date parts.
    Dim strPartOne As String, strPartTwo As String, strPartThree As String
    strPartOne = Trim(strDateParts(0)): strPartTwo = Trim(strDateParts(1)): strPartThree = Trim(strDateParts(2))

    ' Debug output for each part
    ' This line outputs the individual parts of the date to the immediate window for debugging purposes.
    ' Debug.Print "Part One: " & strPartOne & " | Part Two: " & strPartTwo & " | Part Three: " & strPartThree

    ' Ensure that the parts can be converted to numbers
    ' This conditional statement checks if each of the date parts (strPartOne, strPartTwo, strPartThree)
    ' can be converted to a numeric value. It uses the IsNumeric function to evaluate whether
    ' each part is a valid number. If any of the parts cannot be converted to a number, it indicates
    ' an invalid date format. In this case, the function returns Null to signify that the input is not a valid date,
    ' and exits the function to prevent further processing.
    If Not IsNumeric(strPartOne) Or Not IsNumeric(strPartTwo) Or Not IsNumeric(strPartThree) Then
        RectifyDateFormat = Null
        Exit Function
    End If

    ' Declare integer variables for the day, month, and year
    ' These declarations create integer variables to hold the day, month, and year components of the date.
    ' These will be used for further processing and validation of the date before returning the formatted result.
    Dim intDay As Integer, intMonth As Integer, intYear As Integer

    ' Analyze the parts to determine their roles
    ' This block of code evaluates the lengths of the date parts to determine their roles as day, month, or year.
    ' Depending on the format of the input string, it assigns the appropriate values to intYear, intMonth, and intDay.
    AnalyzeDateParts strPartOne, strPartTwo, strPartThree, intDay, intMonth, intYear

    ' Validate the final values
    ' This conditional checks if the final values for day, month, and year are valid.
    ' If any value is outside the expected range, the function returns Null to indicate an invalid date.
    If Not IsValidDate(intDay, intMonth, intYear) Then
        RectifyDateFormat = Null
        Exit Function
    End If

    ' Create the date and format it
    ' This line creates a date using the DateSerial function, which takes year, month, and day as parameters.
    ' The resulting date is then formatted as a string in the "dd/mm/yyyy" format.
    ' The formatted date string is assigned to the function's return value, RectifyDateFormat.
    RectifyDateFormat = Format(DateSerial(intYear, intMonth, intDay), "dd/mm/yyyy")
    Exit Function

    ' This line exits the function normally.
    ' If no errors occur, the code will not reach the ErrorHandler section.
    
ErrorHandler:
    ' Handle errors gracefully
    ' If an error occurs in the preceding code, this line sets the return value of the function to Null,
    ' indicating that the date format correction failed due to an error.
    RectifyDateFormat = Null
End Function

Private Function ReplaceSymbols(inputString As String, SymbolsToRemove As Variant) As String
    ' This function iterates through an array of symbols that should be replaced with hyphens.
    ' Each symbol in the SymbolsToRemove array is checked, and if it's not a hyphen,
    ' it is replaced in the input string with a hyphen.
    Dim strSymbol As Variant
    For Each strSymbol In SymbolsToRemove
        If strSymbol <> "-" Then
            inputString = Replace(inputString, strSymbol, "-")
        End If
    Next strSymbol
    ReplaceSymbols = inputString
End Function

Private Function CleanHyphens(inputString As String) As String
    ' This function replaces double hyphens with a single hyphen and trims the input string.
    inputString = Trim(Replace(inputString, "--", "-"))
    
    ' Remove leading hyphens
    ' This loop checks if the first character of the input string is a hyphen.
    ' If it is, the hyphen is removed by taking the substring starting from the second character.
    Do While Left(inputString, 1) = "-"
        inputString = Mid(inputString, 2)
    Loop

    ' Remove trailing hyphens
    ' This loop checks if the last character of the input string is a hyphen.
    ' If it is, the hyphen is removed by taking the substring up to the second-to-last character.
    Do While Right(inputString, 1) = "-"
        inputString = Left(inputString, Len(inputString) - 1)
    Loop

    CleanHyphens = inputString
End Function

Private Sub AnalyzeDateParts(strPartOne As String, strPartTwo As String, strPartThree As String, _
                              ByRef intDay As Integer, ByRef intMonth As Integer, ByRef intYear As Integer)
    ' This subroutine analyzes the lengths of the date parts to determine their roles as day, month, or year.
    ' Depending on the format of the input string, it assigns the appropriate values to intYear, intMonth, and intDay.
    If Len(strPartOne) = 4 Then
        ' Year is first (Format: YYYY-MM-DD)
        intYear = CInt(strPartOne)
        intMonth = CInt(strPartTwo)
        intDay = CInt(strPartThree)
    ElseIf Len(strPartThree) = 4 Then
        ' Year is last (Format: DD-MM-YYYY)
        intYear = CInt(strPartThree)
        intMonth = CInt(strPartTwo)
        intDay = CInt(strPartOne)
    ElseIf Len(strPartTwo) = 4 Then
        ' Year is in the middle (Format: DD-YYYY-MM or MM-YYYY-DD)
        intYear = CInt(strPartTwo)
        
        If CInt(strPartOne) > 12 Then
            intDay = CInt(strPartOne)
            intMonth = CInt(strPartThree)
        ElseIf CInt(strPartThree) > 12 Then
            intDay = CInt(strPartThree)
            intMonth = CInt(strPartOne)
        Else
            intDay = CInt(strPartOne)
            intMonth = CInt(strPartThree)
        End If
    Else
        ' All parts are small numbers (Format: D-M-YY)
        intDay = CInt(strPartOne)
        intMonth = CInt(strPartTwo)
        intYear = CInt(strPartThree)
        
        ' Confirm year is in the correct range
        ' If the year is provided as a two-digit number, it will be treated as a year in the 2000s.
        If intYear < 100 Then
            intYear = intYear + 2000
        End If
    End If
End Sub

Private Function IsValidDate(intDay As Integer, intMonth As Integer, intYear As Integer) As Boolean
    ' This function checks if the provided day, month, and year are valid.
    ' It verifies that the month is between 1 and 12 and that the day is appropriate
    ' for the given month and year (not exceeding 31 for any month).
    IsValidDate = (intMonth >= 1 And intMonth <= 12) And _
                  (intDay >= 1 And intDay <= 31) And _
                  (intYear >= 1900 And intYear <= 2100)
End Function

 

 

وللتجربة لكل الحالات تقريبا من داخل المحرر 

'*************************************************************************************************************************************
' Sub:       TestRectifyDateFormat
' Purpose:   This subroutine tests the RectifyDateFormat function with various input date strings
'            to ensure that the function handles different formats and returns the expected results.
'
' Usage:     Call TestRectifyDateFormat to run the tests and print the results to the debug output.
'
'**********************************************************************
' Author:    officena.net™  , Mohammed Essam ©   , soul-angel@msn.com ®
' Date:      October 2024
'**********************************************************************
Sub TestRectifyDateFormat()
    Dim testDate As String
    Dim result As Variant

    ' Test various date formats
    testDate = "30/11/2009"
    result = RectifyDateFormat(testDate)
    Debug.Print "Input: " & testDate & " | Result: " & result
    Debug.Print "-----------------------------------------------"

    testDate = "2012-06-25"
    result = RectifyDateFormat(testDate)
    Debug.Print "Input: " & testDate & " | Result: " & result
    Debug.Print "-----------------------------------------------"

    testDate = "21/6/2015م"
    result = RectifyDateFormat(testDate)
    Debug.Print "Input: " & testDate & " | Result: " & result
    Debug.Print "-----------------------------------------------"

    testDate = """ 9/1/2014"""
    result = RectifyDateFormat(testDate)
    Debug.Print "Input: " & testDate & " | Result: " & result
    Debug.Print "-----------------------------------------------"

    testDate = "30\11\2009"
    result = RectifyDateFormat(testDate)
    Debug.Print "Input: " & testDate & " | Result: " & result
    Debug.Print "-----------------------------------------------"

    testDate = "5/1999/26"
    result = RectifyDateFormat(testDate)
    Debug.Print "Input: " & testDate & " | Result: " & result
    Debug.Print "-----------------------------------------------"

    testDate = "25/1999/6"
    result = RectifyDateFormat(testDate)
    Debug.Print "Input: " & testDate & " | Result: " & result
    Debug.Print "-----------------------------------------------"

    testDate = "5/1994/ 26"
    result = RectifyDateFormat(testDate)
    Debug.Print "Input: " & testDate & " | Result: " & result
    Debug.Print "-----------------------------------------------"

    testDate = "5 1995  26"
    result = RectifyDateFormat(testDate)
    Debug.Print "Input: " & testDate & " | Result: " & result
    Debug.Print "-----------------------------------------------"

    testDate = "6  1996    26"
    result = RectifyDateFormat(testDate)
    Debug.Print "Input: " & testDate & " | Result: " & result
End Sub

 

 

 

RectifyDate.accdb

تم تعديل بواسطه ابو جودي
اضافة مرفق
  • Like 4
قام بنشر

ما شاء الله

لما بشوف اسلوبكم فى كتابة الاكواد وافكاركم

بحث اني جاهل 🤪 ولم اتعلم شئ وان الطريق لسه طوووووووووووويل علشان اقرب منكم

الله يجازيكم عنا كل خير ويشفي مرضاكم ومرضي المسلمين ويبارك لكم فى صحتكم🤲

  • Thanks 1
قام بنشر
18 ساعات مضت, ابو جودي said:

وللتجربة لكل الحالات تقريبا من داخل المحرر 

لسه فيه مفاجآت ما خطرتش على بالك 😅🖐 

image.png.2120829edc0609b7ef843afb7f529e53.png

  • Haha 2
قام بنشر
منذ ساعه, Moosak said:

لسه فيه مفاجآت ما خطرتش على بالك 😅🖐 

image.png.2120829edc0609b7ef843afb7f529e53.png

هلا والله.. والله اشتقنا

يا اهلا بمفاجئاتك :mad: :eek2: انت لازم تطلع عنيننا يا استاذنا الغالى :biggrin: 

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

Private Sub AnalyzeDateParts(strPartOne As String, strPartTwo As String, strPartThree As String, _
                              ByRef intDay As Integer, ByRef intMonth As Integer, ByRef intYear As Integer)
    ' This subroutine analyzes the lengths of the date parts to determine their roles as day, month, or year.
    ' Depending on the format of the input string, it assigns the appropriate values to intYear, intMonth, and intDay.
    
    If Len(strPartOne) = 4 Then
        ' Year is first (Format: YYYY-MM-DD or YYYY-DD-MM)
        intYear = CInt(strPartOne)
        
        If CInt(strPartTwo) > 12 Then
            ' Format: YYYY-DD-MM
            intDay = CInt(strPartTwo)
            intMonth = CInt(strPartThree)
        Else
            ' Format: YYYY-MM-DD
            intMonth = CInt(strPartTwo)
            intDay = CInt(strPartThree)
        End If
        
    ElseIf Len(strPartThree) = 4 Then
        ' Year is last (Format: DD-MM-YYYY)
        intYear = CInt(strPartThree)
        intMonth = CInt(strPartTwo)
        intDay = CInt(strPartOne)
        
    ElseIf Len(strPartTwo) = 4 Then
        ' Year is in the middle (Format: DD-YYYY-MM or MM-YYYY-DD)
        intYear = CInt(strPartTwo)
        
        If CInt(strPartOne) > 12 Then
            intDay = CInt(strPartOne)
            intMonth = CInt(strPartThree)
        ElseIf CInt(strPartThree) > 12 Then
            intDay = CInt(strPartThree)
            intMonth = CInt(strPartOne)
        Else
            intDay = CInt(strPartOne)
            intMonth = CInt(strPartThree)
        End If
    Else
        ' All parts are small numbers (Format: D-M-YY)
        intDay = CInt(strPartOne)
        intMonth = CInt(strPartTwo)
        intYear = CInt(strPartThree)
        
        ' Confirm year is in the correct range
        ' If the year is provided as a two-digit number, it will be treated as a year in the 2000s.
        If intYear < 100 Then
            intYear = intYear + 2000
        End If
    End If
End Sub


واستبدل السطر الخاص بالمصفوفة
المصفوفة القديمة بالمصفوفة الاتية

 

SymbolsToRemove = Array("(", ")", "?", "*", " ", "!", "-", "#", "@", "+", "\", "/", "//", ".", "_", "--", "|", ",", Chr(227), Chr(34))


المرفق بعد التعديلات  :wink2:

RectifyDate (V 2).accdb

  • Like 1
قام بنشر
5 ساعات مضت, عمر ضاحى said:

لما بشوف اسلوبكم فى كتابة الاكواد وافكاركم

بحث اني جاهل 🤪 ولم اتعلم شئ وان الطريق لسه طوووووووووووويل علشان اقرب منكم

الله يجازيكم عنا كل خير ويشفي مرضاكم ومرضي المسلمين ويبارك لكم فى صحتكم🤲

العفو يحثنا ديننا الحنيف على طلب العلم حتى الممات 

دائما نتعلم ونطلب العلم وان شاء الله وان طال الطريق يسهله الله تعالى علينا بفضله ثم بفضل وكرم اساتذتنا العظماء الذين نتعلم منهم طرق الافكار والحلول 

جزاكم الله خيرا على دعواتكم الطيبة واسال الله تعالى ان يرزقكم بركتها وفضلها وكل المسلمون ان شاء الله

  • Like 1

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