├── Xlib.min.bas ├── XlibTests.min.bas ├── Modules ├── xlibColor.bas ├── xlibColorTests.bas ├── xlibStringManipulation.bas ├── xlibMeta.bas ├── Tests.bas ├── xlibDateTimeTests.bas ├── xlibRegexTests.bas ├── xlibMetaTests.bas ├── xlibEnvironment.bas ├── xlibEnvironmentTests.bas ├── xlibStringMetricsTests.bas ├── xlibNetworkTests.bas ├── xlibRandomTests.bas ├── xlibRegex.bas ├── xlibMathTests.bas ├── xlibRandom.bas ├── xlibArrayTests.bas ├── xlibValidatorsTests.bas ├── xlibMath.bas ├── xlibUtilitiesTests.bas ├── xlibStringMetrics.bas ├── xlibDateTime.bas ├── xlibArray.bas ├── xlibValidators.bas ├── xlibFileTests.bas ├── xlibNetwork.bas ├── xlibUtilities.bas └── xlibStringManipulationTests.bas └── Unminified ├── Xlib.bas └── XlibTests.bas /Xlib.min.bas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-vba/xlib/HEAD/Xlib.min.bas -------------------------------------------------------------------------------- /XlibTests.min.bas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-vba/xlib/HEAD/XlibTests.min.bas -------------------------------------------------------------------------------- /Modules/xlibColor.bas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-vba/xlib/HEAD/Modules/xlibColor.bas -------------------------------------------------------------------------------- /Unminified/Xlib.bas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-vba/xlib/HEAD/Unminified/Xlib.bas -------------------------------------------------------------------------------- /Modules/xlibColorTests.bas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-vba/xlib/HEAD/Modules/xlibColorTests.bas -------------------------------------------------------------------------------- /Unminified/XlibTests.bas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-vba/xlib/HEAD/Unminified/XlibTests.bas -------------------------------------------------------------------------------- /Modules/xlibStringManipulation.bas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x-vba/xlib/HEAD/Modules/xlibStringManipulation.bas -------------------------------------------------------------------------------- /Modules/xlibMeta.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibMeta" 2 | '@Module: This module contains a set of functions that return information on the Xlib library, such as the version number, credits, and a link to the documentation. 3 | 4 | Option Explicit 5 | 6 | 7 | Public Function XlibVersion() As String 8 | 9 | '@Description: This function returns the version number of XPlus 10 | '@Author: Anthony Mancini 11 | '@Version: 1.0.0 12 | '@License: MIT 13 | '@Returns: Returns the XPlus version number 14 | '@Example: =XlibVersion() -> "1.0.0"; Where the version of XPlus you are using is 1.0.0 15 | 16 | XlibVersion = "1.0.0" 17 | 18 | End Function 19 | 20 | 21 | Public Function XlibCredits() As String 22 | 23 | '@Description: This function returns credits for the XPlus library 24 | '@Author: Anthony Mancini 25 | '@Version: 1.0.0 26 | '@License: MIT 27 | '@Returns: Returns the XPlus credits 28 | '@Example: =XlibCredits() -> "Copyright (c) 2020 Anthony Mancini. XLib is Licensed under an MIT License." 29 | 30 | XlibCredits = "Copyright (c) 2020 Anthony Mancini. XLib is Licensed under an MIT License." 31 | 32 | End Function 33 | 34 | 35 | Public Function XlibDocumentation() As String 36 | 37 | '@Description: This function returns a link to the Documentation for XPlus 38 | '@Author: Anthony Mancini 39 | '@Version: 1.0.0 40 | '@License: MIT 41 | '@Returns: Returns the XPlus Documentation link 42 | '@Example: =XlibDocumentation() -> "https://x-vba.com/xlib" 43 | 44 | XlibDocumentation = "https://x-vba.com/xlib" 45 | 46 | End Function 47 | 48 | -------------------------------------------------------------------------------- /Modules/Tests.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "Tests" 2 | Public Sub XlibTests() 3 | 4 | Dim TestStatus As Boolean 5 | TestStatus = True 6 | 7 | TestStatus = TestStatus And AllXlibArrayTests 8 | Debug.Print "" 9 | 10 | TestStatus = TestStatus And AllXlibColorTests 11 | Debug.Print "" 12 | 13 | TestStatus = TestStatus And AllXlibDateTimeTests 14 | Debug.Print "" 15 | 16 | TestStatus = TestStatus And AllXlibEnvironmentTests 17 | Debug.Print "" 18 | 19 | TestStatus = TestStatus And AllXlibFileTests 20 | Debug.Print "" 21 | 22 | TestStatus = TestStatus And AllXlibMathTests 23 | Debug.Print "" 24 | 25 | TestStatus = TestStatus And AllXlibMetaTests 26 | Debug.Print "" 27 | 28 | TestStatus = TestStatus And AllXlibNetworkTests 29 | Debug.Print "" 30 | 31 | TestStatus = TestStatus And AllXlibRandomTests 32 | Debug.Print "" 33 | 34 | TestStatus = TestStatus And AllXlibRegexTests 35 | Debug.Print "" 36 | 37 | TestStatus = TestStatus And AllXlibStringManipulationTests 38 | Debug.Print "" 39 | 40 | TestStatus = TestStatus And AllXlibStringMetricsTests 41 | Debug.Print "" 42 | 43 | TestStatus = TestStatus And AllXlibUtilitiesTests 44 | Debug.Print "" 45 | 46 | TestStatus = TestStatus And AllXlibValidatorsTests 47 | Debug.Print "" 48 | 49 | Debug.Print "========================================" 50 | If TestStatus Then 51 | Debug.Print "Status of All Tests: Passed" 52 | Else 53 | Debug.Print "Status of All Tests: !!! FAILED !!!" 54 | End If 55 | Debug.Print "========================================" 56 | 57 | End Sub 58 | -------------------------------------------------------------------------------- /Modules/xlibDateTimeTests.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibDateTimeTests" 2 | Option Explicit 3 | 4 | Public Function AllXlibDateTimeTests() 5 | 6 | Dim TestStatus As Boolean 7 | TestStatus = True 8 | 9 | Debug.Print "========================================" 10 | 11 | ' Begin Tests 12 | If Not QuarterTest() Then 13 | Debug.Print "Failed: QuarterTest" 14 | TestStatus = False 15 | Else 16 | Debug.Print "Passed: QuarterTest" 17 | End If 18 | 19 | If Not DaysOfMonthTest() Then 20 | Debug.Print "Failed: DaysOfMonthTest" 21 | TestStatus = False 22 | Else 23 | Debug.Print "Passed: DaysOfMonthTest" 24 | End If 25 | ' End Tests 26 | 27 | Debug.Print "----------------------------------------" 28 | 29 | If TestStatus Then 30 | Debug.Print "Passed All Tests" 31 | Else 32 | Debug.Print "!!! FAILED TESTS !!!" 33 | End If 34 | 35 | Debug.Print "========================================" 36 | 37 | AllXlibDateTimeTests = TestStatus 38 | 39 | End Function 40 | 41 | 42 | 43 | Private Function QuarterTest() As Boolean 44 | 45 | '@Example: =Quarter(4) -> 2 46 | '@Example: =Quarter("April") -> 2 47 | '@Example: =Quarter(12) -> 4 48 | '@Example: =Quarter("December") -> 4 49 | '@Example: To get today's Quarter: =Quarter() 50 | 51 | QuarterTest = True 52 | 53 | QuarterTest = QuarterTest And Quarter(4) = 2 54 | QuarterTest = QuarterTest And Quarter(12) = 4 55 | 56 | End Function 57 | 58 | 59 | Private Function DaysOfMonthTest() As Boolean 60 | 61 | '@Example: =DaysOfMonth() -> 31; Where the current month is January 62 | '@Example: =DaysOfMonth(1) -> 31 63 | '@Example: =DaysOfMonth("January") -> 31 64 | '@Example: =DaysOfMonth(2, 2019) -> 28 65 | '@Example: =DaysOfMonth(2, 2020) -> 29 66 | 67 | DaysOfMonthTest = True 68 | 69 | DaysOfMonthTest = DaysOfMonthTest And DaysOfMonth(1) = 31 70 | DaysOfMonthTest = DaysOfMonthTest And DaysOfMonth(2, 2019) = 28 71 | DaysOfMonthTest = DaysOfMonthTest And DaysOfMonth(2, 2020) = 29 72 | 73 | End Function 74 | 75 | 76 | -------------------------------------------------------------------------------- /Modules/xlibRegexTests.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibRegexTests" 2 | Option Explicit 3 | 4 | Public Function AllXlibRegexTests() 5 | 6 | Dim TestStatus As Boolean 7 | TestStatus = True 8 | 9 | Debug.Print "========================================" 10 | 11 | ' Begin Tests 12 | If Not RegexSearchTest() Then 13 | Debug.Print "Failed: RegexSearchTest" 14 | TestStatus = False 15 | Else 16 | Debug.Print "Passed: RegexSearchTest" 17 | End If 18 | 19 | If Not RegexTestTest() Then 20 | Debug.Print "Failed: RegexTestTest" 21 | TestStatus = False 22 | Else 23 | Debug.Print "Passed: RegexTestTest" 24 | End If 25 | 26 | If Not RegexReplaceTest() Then 27 | Debug.Print "Failed: RegexReplaceTest" 28 | TestStatus = False 29 | Else 30 | Debug.Print "Passed: RegexReplaceTest" 31 | End If 32 | ' End Tests 33 | 34 | Debug.Print "----------------------------------------" 35 | 36 | If TestStatus Then 37 | Debug.Print "Passed All Tests" 38 | Else 39 | Debug.Print "!!! FAILED TESTS !!!" 40 | End If 41 | 42 | Debug.Print "========================================" 43 | 44 | AllXlibRegexTests = TestStatus 45 | 46 | End Function 47 | 48 | 49 | 50 | Private Function RegexSearchTest() As Boolean 51 | 52 | '@Example: =RegexSearch("Hello World","[a-z]{2}\s[W]") -> "lo W"; 53 | 54 | RegexSearchTest = True 55 | 56 | RegexSearchTest = RegexSearchTest And RegexSearch("Hello World", "[a-z]{2}\s[W]") = "lo W" 57 | 58 | End Function 59 | 60 | 61 | Private Function RegexTestTest() As Boolean 62 | 63 | '@Example: =RegexTest("Hello World","[a-z]{2}\s[W]") -> TRUE; 64 | 65 | RegexTestTest = True 66 | 67 | RegexTestTest = RegexTestTest And RegexTest("Hello World", "[a-z]{2}\s[W]") = True 68 | 69 | End Function 70 | 71 | 72 | Private Function RegexReplaceTest() As Boolean 73 | 74 | '@Example: =RegexReplace("Hello World","[W][a-z]{4}", "VBA") -> "Hello VBA" 75 | 76 | RegexReplaceTest = True 77 | 78 | RegexReplaceTest = RegexReplaceTest And RegexReplace("Hello World", "[W][a-z]{4}", "VBA") = "Hello VBA" 79 | 80 | End Function 81 | 82 | 83 | -------------------------------------------------------------------------------- /Modules/xlibMetaTests.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibMetaTests" 2 | Option Explicit 3 | 4 | Public Function AllXlibMetaTests() 5 | 6 | Dim TestStatus As Boolean 7 | TestStatus = True 8 | 9 | Debug.Print "========================================" 10 | 11 | ' Begin Tests 12 | If Not XlibVersionTest() Then 13 | Debug.Print "Failed: XlibVersionTest" 14 | TestStatus = False 15 | Else 16 | Debug.Print "Passed: XlibVersionTest" 17 | End If 18 | 19 | If Not XlibCreditsTest() Then 20 | Debug.Print "Failed: XlibCreditsTest" 21 | TestStatus = False 22 | Else 23 | Debug.Print "Passed: XlibCreditsTest" 24 | End If 25 | 26 | If Not XlibDocumentationTest() Then 27 | Debug.Print "Failed: XlibDocumentationTest" 28 | TestStatus = False 29 | Else 30 | Debug.Print "Passed: XlibDocumentationTest" 31 | End If 32 | ' End Tests 33 | 34 | Debug.Print "----------------------------------------" 35 | 36 | If TestStatus Then 37 | Debug.Print "Passed All Tests" 38 | Else 39 | Debug.Print "!!! FAILED TESTS !!!" 40 | End If 41 | 42 | Debug.Print "========================================" 43 | 44 | AllXlibMetaTests = TestStatus 45 | 46 | End Function 47 | 48 | 49 | 50 | Private Function XlibVersionTest() As Boolean 51 | 52 | '@Example: =XlibVersion() -> "1.0.0"; Where the version of XPlus you are using is 1.0.0 53 | 54 | If IsNumeric(Split(XlibVersion(), ".")(0)) Then 55 | If IsNumeric(Split(XlibVersion(), ".")(1)) Then 56 | If IsNumeric(Split(XlibVersion(), ".")(2)) Then 57 | XlibVersionTest = True 58 | End If 59 | End If 60 | End If 61 | 62 | End Function 63 | 64 | 65 | Private Function XlibCreditsTest() As Boolean 66 | 67 | '@Example: =XlibCredits() -> "Copyright (c) 2020 Anthony Mancini. XPlus is Licensed under an MIT License." 68 | 69 | If InStr(1, XlibCredits(), "XLib") > 0 Then 70 | XlibCreditsTest = True 71 | End If 72 | 73 | End Function 74 | 75 | 76 | Private Function XlibDocumentationTest() As Boolean 77 | 78 | '@Example: =XlibDocumentation() -> "https://x-vba.com/xlib" 79 | 80 | If Left(XlibDocumentation(), 4) = "http" Then 81 | XlibDocumentationTest = True 82 | End If 83 | 84 | End Function 85 | 86 | -------------------------------------------------------------------------------- /Modules/xlibEnvironment.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibEnvironment" 2 | '@Module: This module contains a set of functions for gathering information on the environment that Excel is being run on, such as the UserName of the computer, the OS Excel is being run on, and other Environment Variable values. 3 | 4 | Option Private Module 5 | Option Explicit 6 | 7 | 8 | Public Function OS() As String 9 | 10 | '@Description: This function returns the Operating System name. Currently it will return either "Windows" or "Mac" depending on the OS used. 11 | '@Author: Anthony Mancini 12 | '@Version: 1.0.0 13 | '@License: MIT 14 | '@Returns: Returns the name of the Operating System 15 | '@Example: =OS() -> "Windows"; When running this function on Windows 16 | '@Example: =OS() -> "Mac"; When running this function on MacOS 17 | 18 | #If Mac Then 19 | OS = "Mac" 20 | #Else 21 | OS = "Windows" 22 | #End If 23 | 24 | End Function 25 | 26 | 27 | Public Function UserName() As String 28 | 29 | '@Description: This function takes no arguments and returns a string of the USERNAME of the computer 30 | '@Author: Anthony Mancini 31 | '@Version: 1.1.0 32 | '@License: MIT 33 | '@Returns: Returns a string of the username 34 | '@Example: =UserName() -> "Anthony" 35 | 36 | #If Mac Then 37 | UserName = Environ("USER") 38 | #Else 39 | UserName = Environ("USERNAME") 40 | #End If 41 | 42 | End Function 43 | 44 | 45 | Public Function UserDomain() As String 46 | 47 | '@Description: This function takes no arguments and returns a string of the USERDOMAIN of the computer 48 | '@Author: Anthony Mancini 49 | '@Version: 1.1.0 50 | '@License: MIT 51 | '@Returns: Returns a string of the user domain of the computer 52 | '@Example: =UserDomain() -> "DESKTOP-XYZ1234" 53 | 54 | #If Mac Then 55 | UserDomain = Environ("HOST") 56 | #Else 57 | UserDomain = Environ("USERDOMAIN") 58 | #End If 59 | 60 | End Function 61 | 62 | 63 | Public Function ComputerName() As String 64 | 65 | '@Description: This function takes no arguments and returns a string of the COMPUTERNAME of the computer 66 | '@Author: Anthony Mancini 67 | '@Version: 1.1.0 68 | '@License: MIT 69 | '@Returns: Returns a string of the computer name of the computer 70 | '@Example: =ComputerName() -> "DESKTOP-XYZ1234" 71 | 72 | ComputerName = Environ("COMPUTERNAME") 73 | 74 | End Function 75 | -------------------------------------------------------------------------------- /Modules/xlibEnvironmentTests.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibEnvironmentTests" 2 | Option Explicit 3 | 4 | Public Function AllXlibEnvironmentTests() 5 | 6 | Dim TestStatus As Boolean 7 | TestStatus = True 8 | 9 | Debug.Print "========================================" 10 | 11 | ' Begin Tests 12 | If Not OSTest() Then 13 | Debug.Print "Failed: OSTest" 14 | TestStatus = False 15 | Else 16 | Debug.Print "Passed: OSTest" 17 | End If 18 | 19 | If Not UserNameTest() Then 20 | Debug.Print "Failed: UserNameTest" 21 | TestStatus = False 22 | Else 23 | Debug.Print "Passed: UserNameTest" 24 | End If 25 | 26 | If Not UserDomainTest() Then 27 | Debug.Print "Failed: UserDomainTest" 28 | TestStatus = False 29 | Else 30 | Debug.Print "Passed: UserDomainTest" 31 | End If 32 | 33 | If Not ComputerNameTest() Then 34 | Debug.Print "Failed: ComputerNameTest" 35 | TestStatus = False 36 | Else 37 | Debug.Print "Passed: ComputerNameTest" 38 | End If 39 | ' End Tests 40 | 41 | Debug.Print "----------------------------------------" 42 | 43 | If TestStatus Then 44 | Debug.Print "Passed All Tests" 45 | Else 46 | Debug.Print "!!! FAILED TESTS !!!" 47 | End If 48 | 49 | Debug.Print "========================================" 50 | 51 | AllXlibEnvironmentTests = TestStatus 52 | 53 | End Function 54 | 55 | 56 | 57 | Private Function OSTest() As Boolean 58 | 59 | '@Example: =OS() -> "Windows"; When running this function on Windows 60 | '@Example: =OS() -> "Mac"; When running this function on MacOS 61 | 62 | OSTest = True 63 | 64 | #If Mac Then 65 | OSTest = OSTest And OS() = "Mac" 66 | #Else 67 | OSTest = OSTest And OS() = "Windows" 68 | #End If 69 | 70 | End Function 71 | 72 | 73 | Private Function UserNameTest() As Boolean 74 | 75 | '@Example: =UserName() -> "Anthony" 76 | 77 | UserNameTest = True 78 | 79 | #If Mac Then 80 | UserNameTest = UserNameTest And UserName() = Environ("USER") 81 | #Else 82 | UserNameTest = UserNameTest And UserName() = Environ("USERNAME") 83 | #End If 84 | 85 | End Function 86 | 87 | 88 | Private Function UserDomainTest() As Boolean 89 | 90 | '@Example: =UserDomain() -> "DESKTOP-XYZ1234" 91 | 92 | UserDomainTest = True 93 | 94 | #If Mac Then 95 | UserDomainTest = UserDomainTest And UserDomain() = Environ("HOST") 96 | #Else 97 | UserDomainTest = UserDomainTest And UserDomain() = Environ("USERDOMAIN") 98 | #End If 99 | 100 | End Function 101 | 102 | 103 | Private Function ComputerNameTest() As Boolean 104 | 105 | '@Example: =ComputerName() -> "DESKTOP-XYZ1234" 106 | 107 | ComputerNameTest = True 108 | 109 | ComputerNameTest = ComputerNameTest And ComputerName() = Environ("COMPUTERNAME") 110 | 111 | End Function 112 | 113 | -------------------------------------------------------------------------------- /Modules/xlibStringMetricsTests.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibStringMetricsTests" 2 | Option Explicit 3 | 4 | Public Function AllXlibStringMetricsTests() 5 | 6 | Dim TestStatus As Boolean 7 | TestStatus = True 8 | 9 | Debug.Print "========================================" 10 | 11 | ' Begin Tests 12 | If Not HammingTest() Then 13 | Debug.Print "Failed: HammingTest" 14 | TestStatus = False 15 | Else 16 | Debug.Print "Passed: HammingTest" 17 | End If 18 | 19 | If Not LevenshteinTest() Then 20 | Debug.Print "Failed: LevenshteinTest" 21 | TestStatus = False 22 | Else 23 | Debug.Print "Passed: LevenshteinTest" 24 | End If 25 | 26 | If Not DamerauTest() Then 27 | Debug.Print "Failed: DamerauTest" 28 | TestStatus = False 29 | Else 30 | Debug.Print "Passed: DamerauTest" 31 | End If 32 | ' End Tests 33 | 34 | Debug.Print "----------------------------------------" 35 | 36 | If TestStatus Then 37 | Debug.Print "Passed All Tests" 38 | Else 39 | Debug.Print "!!! FAILED TESTS !!!" 40 | End If 41 | 42 | Debug.Print "========================================" 43 | 44 | AllXlibStringMetricsTests = TestStatus 45 | 46 | End Function 47 | 48 | 49 | 50 | Private Function HammingTest() As Boolean 51 | 52 | '@Example: =Hamming("Cat", "Bat") -> 1; Since all that is needed is 1 change (changing the "B" in Bat to "C") 53 | '@Example: =Hamming("Cat", "Bag") -> 2; 2 changes are needed, changing the "B" to "C" and the "g" to "t" 54 | '@Example: =Hamming("Cat", "Dog") -> 3; Every single character needs to be substituted in this case 55 | 56 | HammingTest = True 57 | 58 | HammingTest = HammingTest And Hamming("Cat", "Bat") = 1 59 | HammingTest = HammingTest And Hamming("Cat", "Bag") = 2 60 | HammingTest = HammingTest And Hamming("Cat", "Dog") = 3 61 | 62 | End Function 63 | 64 | 65 | Private Function LevenshteinTest() As Boolean 66 | 67 | '@Example: =Levenshtein("Cat", "Bat") -> 1; Since all that is needed is 1 change (changing the "B" in Bat to "C") 68 | '@Example: =Levenshtein("Cat", "Ca") -> 1; Since only one Insertion needs to occur (adding a "t" at the end) 69 | '@Example: =Levenshtein("Cat", "Cta") -> 2; Since the "t" in "Cta" needs to be substituted into an "a", and the final character "a" needs to be substituted into a "t" 70 | 71 | LevenshteinTest = True 72 | 73 | LevenshteinTest = LevenshteinTest And Levenshtein("Cat", "Bat") = 1 74 | LevenshteinTest = LevenshteinTest And Levenshtein("Cat", "Ca") = 1 75 | LevenshteinTest = LevenshteinTest And Levenshtein("Cat", "Cta") = 2 76 | 77 | End Function 78 | 79 | 80 | Private Function DamerauTest() As Boolean 81 | 82 | '@Example: =Damerau("Cat", "Bat") -> 1; Since all that is needed is 1 change (changing the "B" in Bat to "C") 83 | '@Example: =Damerau("Cat", "Ca") -> 1; Since only one Insertion needs to occur (adding a "t" at the end) 84 | '@Example: =Damerau("Cat", "Cta") -> 1; Since the "t" and "a" can be transposed as they are adjacent to each other. Notice how LEVENSHTEIN("Cat","Cta")=2 but DAMERAU("Cat","Cta")=1 85 | 86 | DamerauTest = True 87 | 88 | DamerauTest = DamerauTest And Damerau("Cat", "Bat") = 1 89 | DamerauTest = DamerauTest And Damerau("Cat", "Ca") = 1 90 | DamerauTest = DamerauTest And Damerau("Cat", "Cta") = 1 91 | 92 | End Function 93 | 94 | 95 | -------------------------------------------------------------------------------- /Modules/xlibNetworkTests.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibNetworkTests" 2 | Option Explicit 3 | 4 | Public Function AllXlibNetworkTests() 5 | 6 | Dim TestStatus As Boolean 7 | TestStatus = True 8 | 9 | Debug.Print "========================================" 10 | 11 | ' Begin Tests 12 | If Not HttpTest() Then 13 | Debug.Print "Failed: HttpTest" 14 | TestStatus = False 15 | Else 16 | Debug.Print "Passed: HttpTest" 17 | End If 18 | 19 | If Not SimpleHttpTest() Then 20 | Debug.Print "Failed: SimpleHttpTest" 21 | TestStatus = False 22 | Else 23 | Debug.Print "Passed: SimpleHttpTest" 24 | End If 25 | 26 | If Not ParseHtmlStringTest() Then 27 | Debug.Print "Failed: ParseHtmlStringTest" 28 | TestStatus = False 29 | Else 30 | Debug.Print "Passed: ParseHtmlStringTest" 31 | End If 32 | ' End Tests 33 | 34 | Debug.Print "----------------------------------------" 35 | 36 | If TestStatus Then 37 | Debug.Print "Passed All Tests" 38 | Else 39 | Debug.Print "!!! FAILED TESTS !!!" 40 | End If 41 | 42 | Debug.Print "========================================" 43 | 44 | AllXlibNetworkTests = TestStatus 45 | 46 | End Function 47 | 48 | 49 | 50 | Private Function HttpTest() As Boolean 51 | 52 | '@Example: =HTTP("https://httpbin.org/uuid") -> "{"uuid: "41416bcf-ef11-4256-9490-63853d14e4e8"}" 53 | '@Example: =HTTP("https://httpbin.org/user-agent", "GET", {"User-Agent","MicrosoftExcel"}) -> "{"user-agent": "MicrosoftExcel"}" 54 | '@Example: =HTTP("https://httpbin.org/status/404",,,,,TRUE) -> "#RequestFailedStatusCode404!"; Since the status error handler flag is set and since this URL returns a 404 status code. Also note that this formula is easier to construct using the Excel Formula Builder 55 | '@Example: =HTTP("https://en.wikipedia.org/wiki/Visual_Basic_for_Applications",,{"User-Agent","MicrosoftExcel"},,,,{"ID","mw-content-text","LEFT",3000}) -> Returning a string with the leftmost 3000 characters found within the element with the ID "mw-content-text" (we are trying to get the release date of VBA from the VBA wikipedia page, but we need to do more parsing first) 56 | '@Example: =HTTP("https://en.wikipedia.org/wiki/Visual_Basic_for_Applications",,{"User-Agent","MicrosoftExcel"},,,,{"ID","mw-content-text","LEFT",3000,"MID","appeared"}) -> Returns the prior string, but now with all characters right of the first occurance of the word "appeared" in the HTML (getting closer to parsing the VBA creation date) 57 | '@Example: =HTTP("https://en.wikipedia.org/wiki/Visual_Basic_for_Applications",,{"User-Agent","MicrosoftExcel"},,,,{"ID","mw-content-text","LEFT",3000,"MID","appeared","MID",""}) -> From the prior result, now returning everything after the first occurance of the "" in the prior string 58 | '@Example: =HTTP("https://en.wikipedia.org/wiki/Visual_Basic_for_Applications",,{"User-Agent","MicrosoftExcel"},,,,{"ID","mw-content-text","LEFT",3000,"MID","appeared","MID","","LEFT"," "1993"; Finally this is all the parsing needed to be able to return the date 1993 that we were looking for 59 | 60 | If InStr(1, Http("https://httpbin.org/user-agent", "GET", Array("User-Agent", "MicrosoftExcel")), Chr(34) & "user-agent" & Chr(34) & ": " & Chr(34) & "MicrosoftExcel" & Chr(34)) > 0 Then 61 | HttpTest = True 62 | End If 63 | 64 | End Function 65 | 66 | 67 | Private Function SimpleHttpTest() As Boolean 68 | 69 | '@Example: =SimpleHttp("https://en.wikipedia.org/wiki/Visual_Basic_for_Applications","ID","mw-content-text","LEFT",3000,"MID","appeared","MID","","LEFT"," "1993"; See the examples in the HTTP() function, as this example has the same result as the example in the HTTP() function. You can see that this function is cleaner and easier to set up than the corresponding HTTP() function. 70 | 71 | If InStr(1, SimpleHttp("https://httpbin.org/get?hello=world"), "world") > 0 Then 72 | SimpleHttpTest = True 73 | End If 74 | 75 | End Function 76 | 77 | 78 | Private Function ParseHtmlStringTest() As Boolean 79 | 80 | '@Example: =ParseHtmlString("HTML String from the webpage: https://en.wikipedia.org/wiki/Visual_Basic_for_Applications","ID","mw-content-text","LEFT",3000,"MID","appeared","MID","","LEFT"," "1993" 81 | 82 | If ParseHtmlString("

Hello World

", Array("id", "main")) = "Hello World" Then 83 | ParseHtmlStringTest = True 84 | End If 85 | 86 | End Function 87 | 88 | 89 | -------------------------------------------------------------------------------- /Modules/xlibRandomTests.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibRandomTests" 2 | Option Explicit 3 | 4 | Public Function AllXlibRandomTests() 5 | 6 | Dim TestStatus As Boolean 7 | TestStatus = True 8 | 9 | Debug.Print "========================================" 10 | 11 | ' Begin Tests 12 | If Not RandBetweenTest() Then 13 | Debug.Print "Failed: RandBetweenTest" 14 | TestStatus = False 15 | Else 16 | Debug.Print "Passed: RandBetweenTest" 17 | End If 18 | 19 | If Not BigRandBetweenTest() Then 20 | Debug.Print "Failed: BigRandBetweenTest" 21 | TestStatus = False 22 | Else 23 | Debug.Print "Passed: BigRandBetweenTest" 24 | End If 25 | 26 | If Not RandomSampleTest() Then 27 | Debug.Print "Failed: RandomSampleTest" 28 | TestStatus = False 29 | Else 30 | Debug.Print "Passed: RandomSampleTest" 31 | End If 32 | 33 | If Not RandomRangeTest() Then 34 | Debug.Print "Failed: RandomRangeTest" 35 | TestStatus = False 36 | Else 37 | Debug.Print "Passed: RandomRangeTest" 38 | End If 39 | 40 | If Not RandBoolTest() Then 41 | Debug.Print "Failed: RandBoolTest" 42 | TestStatus = False 43 | Else 44 | Debug.Print "Passed: RandBoolTest" 45 | End If 46 | 47 | If Not RandBetweensTest() Then 48 | Debug.Print "Failed: RandBetweensTest" 49 | TestStatus = False 50 | Else 51 | Debug.Print "Passed: RandBetweensTest" 52 | End If 53 | ' End Tests 54 | 55 | Debug.Print "----------------------------------------" 56 | 57 | If TestStatus Then 58 | Debug.Print "Passed All Tests" 59 | Else 60 | Debug.Print "!!! FAILED TESTS !!!" 61 | End If 62 | 63 | Debug.Print "========================================" 64 | 65 | AllXlibRandomTests = TestStatus 66 | 67 | End Function 68 | 69 | 70 | 71 | Private Function RandBetweenTest() As Boolean 72 | 73 | '@Example: =RandBetween(1, 20) -> 5 74 | '@Example: =RandBetween(1, 20) -> 9 75 | '@Example: =RandBetween(1, 20) -> 13 76 | '@Example: =RandBetween(1, 20) -> 2 77 | '@Example: =RandBetween(1, 20) -> 20 78 | '@Example: =RandBetween(1, 20) -> 6 79 | 80 | Dim randomNumber As Integer 81 | randomNumber = RandBetween(1, 20) 82 | 83 | RandBetweenTest = (randomNumber >= 1 And randomNumber <= 20) 84 | 85 | End Function 86 | 87 | 88 | Private Function BigRandBetweenTest() As Boolean 89 | 90 | '@Example: =RandBetween(0, 3000000000) -> Error; as RandBetween only works with 4-byte and less integers 91 | '@Example: =BigRandBetween(0, 3000000000) -> 2116642535; as BigRandBetween supports up to 14-byte integers 92 | 93 | Dim randomNumber As Integer 94 | randomNumber = BigRandBetween(1, 20) 95 | 96 | BigRandBetweenTest = (randomNumber >= 1 And randomNumber <= 20) 97 | 98 | End Function 99 | 100 | 101 | Private Function RandomSampleTest() As Boolean 102 | 103 | '@Example: =RandomSample(A1:A5) -> "Hello"; where "Hello" is the value in cell A3, and where A3 was the chosen random cell 104 | '@Example: =RandomSample(A1:A5) -> "World"; where "World" is the value in cell A2, and where A2 was the chosen random cell 105 | 106 | Dim randomNumber As Integer 107 | randomNumber = RandomSample(Array(1, 2, 3)) 108 | 109 | RandomSampleTest = (randomNumber = 1 Or randomNumber = 2 Or randomNumber = 3) 110 | 111 | End Function 112 | 113 | 114 | Private Function RandomRangeTest() As Boolean 115 | 116 | '@Example: =RandomRange(50, 100, 10) -> 60 117 | '@Example: =RandomRange(50, 100, 10) -> 50 118 | '@Example: =RandomRange(50, 100, 10) -> 90 119 | '@Example: =RandomRange(0, 10, 2) -> 8 120 | '@Example: =RandomRange(0, 10, 2) -> 0 121 | '@Example: =RandomRange(0, 10, 2) -> 4 122 | '@Example: =RandomRange(0, 10, 2) -> 10 123 | 124 | Dim randomNumber As Integer 125 | randomNumber = RandomRange(50, 60, 10) 126 | 127 | RandomRangeTest = (randomNumber = 50 Or randomNumber = 60) 128 | 129 | End Function 130 | 131 | 132 | Private Function RandBoolTest() As Boolean 133 | 134 | '@Example: =RANDBOOL() -> TRUE 135 | '@Example: =RANDBOOL() -> FALSE 136 | '@Example: =RANDBOOL() -> TRUE 137 | '@Example: =RANDBOOL() -> TRUE 138 | '@Example: =RANDBOOL() -> FALSE 139 | '@Example: =RANDBOOL() -> FALSE 140 | 141 | Dim randomBoolean As Boolean 142 | randomBoolean = RandBool() 143 | 144 | RandBoolTest = (randomBoolean = True Or randomBoolean = False) 145 | 146 | End Function 147 | 148 | 149 | Private Function RandBetweensTest() As Boolean 150 | 151 | '@Example: =RANDBETWEENS(1, 10, 5000, 5010) -> 6 152 | '@Example: =RANDBETWEENS(1, 10, 5000, 5010) -> 5002 153 | '@Example: =RANDBETWEENS(1, 10, 5000, 5010) -> 8 154 | '@Example: =RANDBETWEENS(1, 10, 5000, 5010) -> 3 155 | '@Example: =RANDBETWEENS(1, 10, 5000, 5010) -> 5010 156 | '@Example: =RANDBETWEENS(1, 10, 5000, 5010) -> 2 157 | '@Example: =RANDBETWEENS(5, 10, 15, 20, 25, 30, 35, 40) -> 32 158 | 159 | Dim randomNumber As Integer 160 | randomNumber = RandBetweens(1, 2, 51, 52) 161 | 162 | RandBetweensTest = (randomNumber = 1 Or randomNumber = 2 Or randomNumber = 51 Or randomNumber = 52) 163 | 164 | End Function 165 | 166 | -------------------------------------------------------------------------------- /Modules/xlibRegex.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibRegex" 2 | '@Module: This module contains a set of functions for performing Regular Expressions, which are a type of string pattern matching. For more info on Regular Expression Pattern matching, please check "https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference" 3 | 4 | Option Explicit 5 | 6 | 7 | Public Function RegexSearch( _ 8 | ByVal string1 As String, _ 9 | ByVal stringPattern As String, _ 10 | Optional ByVal globalFlag As Boolean, _ 11 | Optional ByVal ignoreCaseFlag As Boolean, _ 12 | Optional ByVal multilineFlag As Boolean) _ 13 | As String 14 | 15 | '@Description: This function takes a string that we will perform the Regular Expression on and a Regular Expression string pattern, and returns the first value of the matched string. This function also contains optional arguments for various Regular Expression flags. 16 | '@Author: Anthony Mancini 17 | '@Version: 1.0.0 18 | '@License: MIT 19 | '@Param: string1 is the string that the regex will be performed on 20 | '@Param: stringPattern is the regex pattern 21 | '@Param: globalFlag is a boolean value that if set TRUE will perform a global search 22 | '@Param: ignoreCaseFlag is a boolean value that if set TRUE will perform a case insensitive search 23 | '@Param: multilineFlag is a boolean value that if set TRUE will perform a mulitline search 24 | '@Returns: Returns a string of the regex value that is found 25 | '@Example: =RegexSearch("Hello World","[a-z]{2}\s[W]") -> "lo W"; 26 | 27 | Dim Regex As Object 28 | Set Regex = CreateObject("VBScript.RegExp") 29 | Dim searchResults As Object 30 | 31 | With Regex 32 | .Global = globalFlag 33 | .IgnoreCase = ignoreCaseFlag 34 | .MultiLine = multilineFlag 35 | .Pattern = stringPattern 36 | End With 37 | 38 | Set searchResults = Regex.Execute(string1) 39 | 40 | RegexSearch = searchResults(0).Value 41 | 42 | End Function 43 | 44 | 45 | Public Function RegexTest( _ 46 | ByVal string1 As String, _ 47 | ByVal stringPattern As String, _ 48 | Optional ByVal globalFlag As Boolean, _ 49 | Optional ByVal ignoreCaseFlag As Boolean, _ 50 | Optional ByVal multilineFlag As Boolean) _ 51 | As Boolean 52 | 53 | '@Description: This function takes a string that we will perform the Regular Expression on and a Regular Expression string pattern, and returns TRUE if the pattern is found in the string. This function also contains optional arguments for various Regular Expression flags. 54 | '@Author: Anthony Mancini 55 | '@Version: 1.0.0 56 | '@License: MIT 57 | '@Param: string1 is the string that the regex will be performed on 58 | '@Param: stringPattern is the regex pattern 59 | '@Param: globalFlag is a boolean value that if set TRUE will perform a global search 60 | '@Param: ignoreCaseFlag is a boolean value that if set TRUE will perform a case insensitive search 61 | '@Param: multilineFlag is a boolean value that if set TRUE will perform a mulitline search 62 | '@Returns: Returns TRUE if the regex value that is found, or FALSE if it isn't 63 | '@Example: =RegexTest("Hello World","[a-z]{2}\s[W]") -> TRUE; 64 | 65 | Dim Regex As Object 66 | Set Regex = CreateObject("VBScript.RegExp") 67 | 68 | With Regex 69 | .Global = globalFlag 70 | .IgnoreCase = ignoreCaseFlag 71 | .MultiLine = multilineFlag 72 | .Pattern = stringPattern 73 | End With 74 | 75 | RegexTest = Regex.Test(string1) 76 | 77 | End Function 78 | 79 | 80 | Public Function RegexReplace( _ 81 | ByVal string1 As String, _ 82 | ByVal stringPattern As String, _ 83 | ByVal replacementString As String, _ 84 | Optional ByVal globalFlag As Boolean, _ 85 | Optional ByVal ignoreCaseFlag As Boolean, _ 86 | Optional ByVal multilineFlag As Boolean) _ 87 | As String 88 | 89 | '@Description: This function takes a string that we will perform the Regular Expression on, a Regular Expression string pattern, and a string that we will replace if the pattern is found, and returns a new string with the replacement string in place of the pattern. This function also contains optional arguments for various Regular Expression flags. 90 | '@Author: Anthony Mancini 91 | '@Version: 1.0.0 92 | '@License: MIT 93 | '@Param: string1 is the string that the regex will be performed on 94 | '@Param: stringPattern is the regex pattern 95 | '@Param: replacementString is a string that will be replaced if the pattern is found 96 | '@Param: globalFlag is a boolean value that if set TRUE will perform a global search 97 | '@Param: ignoreCaseFlag is a boolean value that if set TRUE will perform a case insensitive search 98 | '@Param: multilineFlag is a boolean value that if set TRUE will perform a mulitline search 99 | '@Returns: Returns a new string with the replaced string values 100 | '@Example: =RegexReplace("Hello World","[W][a-z]{4}", "VBA") -> "Hello VBA" 101 | 102 | Dim Regex As Object 103 | Set Regex = CreateObject("VBScript.RegExp") 104 | 105 | With Regex 106 | .Global = globalFlag 107 | .IgnoreCase = ignoreCaseFlag 108 | .MultiLine = multilineFlag 109 | .Pattern = stringPattern 110 | End With 111 | 112 | RegexReplace = Regex.Replace(string1, replacementString) 113 | 114 | End Function 115 | 116 | -------------------------------------------------------------------------------- /Modules/xlibMathTests.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibMathTests" 2 | Option Explicit 3 | 4 | Public Function AllXlibMathTests() 5 | 6 | Dim TestStatus As Boolean 7 | TestStatus = True 8 | 9 | Debug.Print "========================================" 10 | 11 | ' Begin Tests 12 | If Not CeilTest() Then 13 | Debug.Print "Failed: CeilTest" 14 | TestStatus = False 15 | Else 16 | Debug.Print "Passed: CeilTest" 17 | End If 18 | 19 | If Not FloorTest() Then 20 | Debug.Print "Failed: FloorTest" 21 | TestStatus = False 22 | Else 23 | Debug.Print "Passed: FloorTest" 24 | End If 25 | 26 | If Not InterpolateNumberTest() Then 27 | Debug.Print "Failed: InterpolateNumberTest" 28 | TestStatus = False 29 | Else 30 | Debug.Print "Passed: InterpolateNumberTest" 31 | End If 32 | 33 | If Not InterpolatePercentTest() Then 34 | Debug.Print "Failed: InterpolatePercentTest" 35 | TestStatus = False 36 | Else 37 | Debug.Print "Passed: InterpolatePercentTest" 38 | End If 39 | 40 | If Not MaxTest() Then 41 | Debug.Print "Failed: MaxTest" 42 | TestStatus = False 43 | Else 44 | Debug.Print "Passed: MaxTest" 45 | End If 46 | 47 | If Not MinTest() Then 48 | Debug.Print "Failed: MinTest" 49 | TestStatus = False 50 | Else 51 | Debug.Print "Passed: MinTest" 52 | End If 53 | 54 | If Not ModFloatTest() Then 55 | Debug.Print "Failed: ModFloatTest" 56 | TestStatus = False 57 | Else 58 | Debug.Print "Passed: ModFloatTest" 59 | End If 60 | ' End Tests 61 | 62 | Debug.Print "----------------------------------------" 63 | 64 | If TestStatus Then 65 | Debug.Print "Passed All Tests" 66 | Else 67 | Debug.Print "!!! FAILED TESTS !!!" 68 | End If 69 | 70 | Debug.Print "========================================" 71 | 72 | AllXlibMathTests = TestStatus 73 | 74 | End Function 75 | 76 | 77 | 78 | Private Function CeilTest() As Boolean 79 | 80 | '@Example: =Ceil(1.5) -> 2 81 | '@Example: =Ceil(1.0001) -> 2 82 | '@Example: =Ceil(1.0) -> 1 83 | '@Example: =Ceil(1) -> 1 84 | 85 | CeilTest = True 86 | 87 | CeilTest = CeilTest And Ceil(1.5) = 2 88 | CeilTest = CeilTest And Ceil(1.0001) = 2 89 | CeilTest = CeilTest And Ceil(1) = 1 90 | 91 | End Function 92 | 93 | 94 | Private Function FloorTest() As Boolean 95 | 96 | '@Example: =Floor(1.9) -> 1 97 | '@Example: =Floor(1.1) -> 1 98 | '@Example: =Floor(1.0) -> 1 99 | '@Example: =Floor(1) -> 1 100 | 101 | FloorTest = True 102 | 103 | FloorTest = FloorTest And Floor(1.9) = 1 104 | FloorTest = FloorTest And Floor(1.1) = 1 105 | FloorTest = FloorTest And Floor(1) = 1 106 | 107 | End Function 108 | 109 | 110 | Private Function InterpolateNumberTest() As Boolean 111 | 112 | '@Example: =InterpolateNumber(10, 20, 0.5) -> 15; Where 0.5 would be 50% between 10 and 20 113 | '@Example: =InterpolateNumber(16, 124, 0.64) -> 85.12; Where 0.64 would be 64% between 16 and 124 114 | 115 | InterpolateNumberTest = True 116 | 117 | InterpolateNumberTest = InterpolateNumberTest And InterpolateNumber(10, 20, 0.5) = 15 118 | InterpolateNumberTest = InterpolateNumberTest And Round(InterpolateNumber(16, 124, 0.64), 2) = 85.12 119 | 120 | End Function 121 | 122 | 123 | Private Function InterpolatePercentTest() As Boolean 124 | 125 | '@Example: =InterpolatePercent(10, 18, 12) -> 0.25; As 12 is 25% of the way from 10 to 18 126 | '@Example: =InterpolatePercent(10, 20, 15) -> 0.5; As 15 is 50% of the way from 10 to 20 127 | 128 | InterpolatePercentTest = True 129 | 130 | InterpolatePercentTest = InterpolatePercentTest And InterpolatePercent(10, 18, 12) = 0.25 131 | InterpolatePercentTest = InterpolatePercentTest And InterpolatePercent(10, 20, 15) = 0.5 132 | 133 | End Function 134 | 135 | 136 | Private Function MaxTest() As Boolean 137 | 138 | '@Example: =Max(1, 2, 3) -> 3 139 | '@Example: =Max(4.4, 5, "6") -> 6 140 | '@Example: =Max(x) -> 3; Where x is an array with these values [1, 2.2, "3"] 141 | '@Example: =Max(x, y, 10) -> 15; Where x = [1, 2.2, "3"] and y = [5, 15, -100] 142 | 143 | MaxTest = True 144 | 145 | MaxTest = MaxTest And Max(1, 2, 3) = 3 146 | MaxTest = MaxTest And Max(4.4, 5, "6") = 6 147 | MaxTest = MaxTest And Max(Array(1, 2.2, "3")) = 3 148 | MaxTest = MaxTest And Max(Array(1, 2.2, "3"), Array(5, 15, -100), 10) = 15 149 | 150 | End Function 151 | 152 | 153 | Private Function MinTest() As Boolean 154 | 155 | '@Example: =Min(1, 2, 3) -> 1 156 | '@Example: =Min(4.4, 5, "6") -> 4.4 157 | '@Example: =Min(-1, -2, -3) -> -3 158 | '@Example: =Min(x) -> 1; Where x is an array with these values [1, 2.2, "3"] 159 | '@Example: =Min(x, y, 10) -> -100; Where x = [1, 2.2, "3"] and y = [5, 15, -100] 160 | 161 | MinTest = True 162 | 163 | MinTest = MinTest And Min(1, 2, 3) = 1 164 | MinTest = MinTest And Min(4.4, 5, "6") = 4.4 165 | MinTest = MinTest And Min(-1, -2, -3) = -3 166 | MinTest = MinTest And Min(Array(1, 2.2, "3")) = 1 167 | MinTest = MinTest And Min(Array(1, 2.2, "3"), Array(5, 15, -100), 10) = -100 168 | 169 | End Function 170 | 171 | 172 | Private Function ModFloatTest() As Boolean 173 | 174 | '@Example: =ModFloat(3.55, 2) -> 1.55 175 | 176 | ModFloatTest = True 177 | 178 | ModFloatTest = ModFloatTest And Round(ModFloat(3.55, 2), 2) = 1.55 179 | 180 | End Function 181 | 182 | -------------------------------------------------------------------------------- /Modules/xlibRandom.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibRandom" 2 | '@Module: This module contains a set of functions for generating and sampling random data. 3 | 4 | Option Explicit 5 | 6 | 7 | Public Function RandBetween( _ 8 | ByVal minNumber As Long, _ 9 | ByVal maxNumber As Long) _ 10 | As Variant 11 | 12 | '@Description: This function returns a random number between the min and max numbers 13 | '@Author: Anthony Mancini 14 | '@Version: 1.0.0 15 | '@License: MIT 16 | '@Param: minNumber is the minimum number in the range 17 | '@Param: maxNumber is the maximum number in the range 18 | '@Returns: Returns a random number between the range 19 | '@Example: =RandBetween(1, 20) -> 5 20 | '@Example: =RandBetween(1, 20) -> 9 21 | '@Example: =RandBetween(1, 20) -> 13 22 | '@Example: =RandBetween(1, 20) -> 2 23 | '@Example: =RandBetween(1, 20) -> 20 24 | '@Example: =RandBetween(1, 20) -> 6 25 | 26 | RandBetween = Fix(Rnd * (maxNumber - minNumber + 1) + minNumber) 27 | 28 | End Function 29 | 30 | 31 | Public Function BigRandBetween( _ 32 | ByVal minNumber As Variant, _ 33 | ByVal maxNumber As Variant) _ 34 | As Variant 35 | 36 | '@Description: This function is an implementation of RandBetween that allows for 14-byte integers to be used 37 | '@Author: Anthony Mancini 38 | '@Version: 1.0.0 39 | '@License: MIT 40 | '@Param: minNumber is the minimum number in the range 41 | '@Param: maxNumber is the maximum number in the range 42 | '@Returns: Returns a random number between the range 43 | '@Example: =RandBetween(0, 3000000000) -> Error; as RandBetween only works with 4-byte and less integers 44 | '@Example: =BigRandBetween(0, 3000000000) -> 2116642535; as BigRandBetween supports up to 14-byte integers 45 | 46 | BigRandBetween = Fix(Rnd * (maxNumber - minNumber + 1) + minNumber) 47 | 48 | End Function 49 | 50 | 51 | Public Function RandomSample( _ 52 | ByRef variantArray As Variant) _ 53 | As Variant 54 | 55 | '@Description: This function takes an array of cells and returns a random value from the cells chosen 56 | '@Author: Anthony Mancini 57 | '@Version: 1.0.0 58 | '@License: MIT 59 | '@Param: variantArray a single cell or multiple cells where the sample will be pulled from 60 | '@Returns: Returns a random cell value from the array of cells chosen 61 | '@Example: =RandomSample(A1:A5) -> "Hello"; where "Hello" is the value in cell A3, and where A3 was the chosen random cell 62 | '@Example: =RandomSample(A1:A5) -> "World"; where "World" is the value in cell A2, and where A2 was the chosen random cell 63 | 64 | Dim randomNumber As Long 65 | 66 | randomNumber = RandBetween(1, UBound(variantArray) - LBound(variantArray) + 1) 67 | 68 | RandomSample = variantArray(randomNumber - 1) 69 | 70 | End Function 71 | 72 | 73 | Public Function RandomRange( _ 74 | ByVal startNumber As Long, _ 75 | ByVal stopNumber As Long, _ 76 | ByVal stepNumber As Long) _ 77 | As Long 78 | 79 | '@Description: This function takes 3 numbers, a start number, a stop number, and a step number, and returns a random number between the start number and stop number that is an interval of the step number. 80 | '@Author: Anthony Mancini 81 | '@Version: 1.0.0 82 | '@License: MIT 83 | '@Param: startNumber is the beginning value of the range 84 | '@Param: stopNumber is the end value of the range 85 | '@Param: stepNumber is the step of the range 86 | '@Returns: Returns a random number between the start and stop that is a multiple of the step 87 | '@Example: =RandomRange(50, 100, 10) -> 60 88 | '@Example: =RandomRange(50, 100, 10) -> 50 89 | '@Example: =RandomRange(50, 100, 10) -> 90 90 | '@Example: =RandomRange(0, 10, 2) -> 8 91 | '@Example: =RandomRange(0, 10, 2) -> 0 92 | '@Example: =RandomRange(0, 10, 2) -> 4 93 | '@Example: =RandomRange(0, 10, 2) -> 10 94 | 95 | Dim randomNumber As Long 96 | 97 | randomNumber = RandBetween(startNumber / stepNumber, stopNumber / stepNumber) * stepNumber 98 | 99 | RandomRange = randomNumber 100 | 101 | End Function 102 | 103 | 104 | Public Function RandBool() As Boolean 105 | 106 | '@Description: This function generates a random Boolean (TRUE or FALSE) value 107 | '@Author: Anthony Mancini 108 | '@Version: 1.0.0 109 | '@License: MIT 110 | '@Returns: Returns either TRUE or FALSE based on the random value choosen 111 | '@Example: =RandBool() -> TRUE 112 | '@Example: =RandBool() -> FALSE 113 | '@Example: =RandBool() -> TRUE 114 | '@Example: =RandBool() -> TRUE 115 | '@Example: =RandBool() -> FALSE 116 | '@Example: =RandBool() -> FALSE 117 | 118 | RandBool = CBool(RandBetween(0, 1)) 119 | 120 | End Function 121 | 122 | 123 | Public Function RandBetweens( _ 124 | ParamArray startOrEndNumberArray() As Variant) _ 125 | As Variant 126 | 127 | '@Description: This function is similar to RANDBETWEEN, except that it allows multiple ranges from which to pick a random number. One of the ranges from which to generate a random number between is chosen at an equal probably. 128 | '@Author: Anthony Mancini 129 | '@Version: 1.0.0 130 | '@License: MIT 131 | '@Returns: Returns either TRUE or FALSE based on the random value choosen 132 | '@Note: This function always requires an even number of inputs. Essentially, when using multiple numbers, the 1st and 2nd will make up a range from which to pull a random number between, the 3rd and 4th will make a different range, and so on. If an even number is used, this function will return a User-Defined Error. See the ISERRORALL() function for how to handle these numbers. 133 | '@Example: =RandBetweens(1, 10, 5000, 5010) -> 6 134 | '@Example: =RandBetweens(1, 10, 5000, 5010) -> 5002 135 | '@Example: =RandBetweens(1, 10, 5000, 5010) -> 8 136 | '@Example: =RandBetweens(1, 10, 5000, 5010) -> 3 137 | '@Example: =RandBetweens(1, 10, 5000, 5010) -> 5010 138 | '@Example: =RandBetweens(1, 10, 5000, 5010) -> 2 139 | '@Example: =RandBetweens(5, 10, 15, 20, 25, 30, 35, 40) -> 32 140 | 141 | Dim pickNumber As Byte 142 | 143 | ' Checking for ParamArray length, as it needs to be even or it won't be 144 | ' possible to generate and min and max number. 145 | If (UBound(startOrEndNumberArray) - LBound(startOrEndNumberArray) + 1) Mod 2 = 1 Then 146 | RandBetweens = "#NotAnEvenNumberOfParameters!" 147 | End If 148 | 149 | pickNumber = Ceil(RandBetween(1, (UBound(startOrEndNumberArray) - LBound(startOrEndNumberArray) + 1)) / 2) * 2 150 | 151 | RandBetweens = RandBetween(startOrEndNumberArray(pickNumber - 2), startOrEndNumberArray(pickNumber - 1)) 152 | 153 | End Function 154 | 155 | -------------------------------------------------------------------------------- /Modules/xlibArrayTests.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibArrayTests" 2 | Option Explicit 3 | 4 | Public Function AllXlibArrayTests() 5 | 6 | Dim TestStatus As Boolean 7 | TestStatus = True 8 | 9 | Debug.Print "========================================" 10 | 11 | ' Begin Tests 12 | If Not CountUniqueTest() Then 13 | Debug.Print "Failed: CountUniqueTest" 14 | TestStatus = False 15 | Else 16 | Debug.Print "Passed: CountUniqueTest" 17 | End If 18 | 19 | If Not SortTest() Then 20 | Debug.Print "Failed: SortTest" 21 | TestStatus = False 22 | Else 23 | Debug.Print "Passed: SortTest" 24 | End If 25 | 26 | If Not ReverseTest() Then 27 | Debug.Print "Failed: ReverseTest" 28 | TestStatus = False 29 | Else 30 | Debug.Print "Passed: ReverseTest" 31 | End If 32 | 33 | If Not SumHighTest() Then 34 | Debug.Print "Failed: SumHighTest" 35 | TestStatus = False 36 | Else 37 | Debug.Print "Passed: SumHighTest" 38 | End If 39 | 40 | If Not SumLowTest() Then 41 | Debug.Print "Failed: SumLowTest" 42 | TestStatus = False 43 | Else 44 | Debug.Print "Passed: SumLowTest" 45 | End If 46 | 47 | If Not AverageHighTest() Then 48 | Debug.Print "Failed: AverageHighTest" 49 | TestStatus = False 50 | Else 51 | Debug.Print "Passed: AverageHighTest" 52 | End If 53 | 54 | If Not AverageLowTest() Then 55 | Debug.Print "Failed: AverageLowTest" 56 | TestStatus = False 57 | Else 58 | Debug.Print "Passed: AverageLowTest" 59 | End If 60 | 61 | If Not LargeTest() Then 62 | Debug.Print "Failed: LargeTest" 63 | TestStatus = False 64 | Else 65 | Debug.Print "Passed: LargeTest" 66 | End If 67 | 68 | If Not SmallTest() Then 69 | Debug.Print "Failed: SmallTest" 70 | TestStatus = False 71 | Else 72 | Debug.Print "Passed: SmallTest" 73 | End If 74 | 75 | If Not IsInArrayTest() Then 76 | Debug.Print "Failed: IsInArrayTest" 77 | TestStatus = False 78 | Else 79 | Debug.Print "Passed: IsInArrayTest" 80 | End If 81 | ' End Tests 82 | 83 | Debug.Print "----------------------------------------" 84 | 85 | If TestStatus Then 86 | Debug.Print "Passed All Tests" 87 | Else 88 | Debug.Print "!!! FAILED TESTS !!!" 89 | End If 90 | 91 | Debug.Print "========================================" 92 | 93 | AllXlibArrayTests = TestStatus 94 | 95 | End Function 96 | 97 | 98 | 99 | Private Function CountUniqueTest() As Boolean 100 | 101 | '@Example: =CountUnique(1, 2, 2, 3) -> 3; 102 | '@Example: =CountUnique("a", "a", "a") -> 1; 103 | '@Example: =CountUnique(arr) -> 3; Where arr = [1, 2, 4, 4, 1] 104 | 105 | CountUniqueTest = True 106 | 107 | CountUniqueTest = CountUniqueTest And CountUnique(1, 2, 2, 3) = 3 108 | CountUniqueTest = CountUniqueTest And CountUnique("a", "a", "a") = 1 109 | CountUniqueTest = CountUniqueTest And CountUnique(Array(1, 2, 4, 4, 1)) = 3 110 | 111 | End Function 112 | 113 | 114 | Private Function SortTest() As Boolean 115 | 116 | '@Example: =Sort({1,3,2}) -> {1,2,3} 117 | '@Example: =Sort({1,3,2}, True) -> {3,2,1} 118 | 119 | SortTest = True 120 | 121 | SortTest = SortTest And Sort(Array(10, 20, 30))(0) = 10 122 | SortTest = SortTest And Sort(Array(10, 20, 30))(1) = 20 123 | SortTest = SortTest And Sort(Array(10, 20, 30))(2) = 30 124 | SortTest = SortTest And Sort(Array(10, 20, 30), True)(0) = 30 125 | SortTest = SortTest And Sort(Array(10, 20, 30), True)(1) = 20 126 | SortTest = SortTest And Sort(Array(10, 20, 30), True)(2) = 10 127 | 128 | End Function 129 | 130 | 131 | Private Function ReverseTest() As Boolean 132 | 133 | '@Example: =Reverse({1,2,3}) -> {3,2,1} 134 | 135 | ReverseTest = True 136 | 137 | ReverseTest = ReverseTest And Reverse(Array(10, 20, 30))(0) = 30 138 | ReverseTest = ReverseTest And Reverse(Array(10, 20, 30))(1) = 20 139 | ReverseTest = ReverseTest And Reverse(Array(10, 20, 30))(2) = 10 140 | 141 | End Function 142 | 143 | 144 | Private Function SumHighTest() As Boolean 145 | 146 | '@Example: =SumHigh({1,2,3,4}, 2) -> 7; as 3 and 4 will be summed 147 | '@Example: =SumHigh({1,2,3,4}, 3) -> 9; as 2, 3, and 4 will be summed 148 | 149 | SumHighTest = True 150 | 151 | SumHighTest = SumHighTest And SumHigh(Array(1, 2, 3, 4), 2) = 7 152 | SumHighTest = SumHighTest And SumHigh(Array(1, 2, 3, 4), 3) = 9 153 | 154 | End Function 155 | 156 | 157 | Private Function SumLowTest() As Boolean 158 | 159 | '@Example: =SumLow({1,2,3,4}, 2) -> 3; as 1 and 2 will be summed 160 | '@Example: =SumLow({1,2,3,4}, 3) -> 6; as 1, 2, and 3 will be summed 161 | 162 | SumLowTest = True 163 | 164 | SumLowTest = SumLowTest And SumLow(Array(1, 2, 3, 4), 2) = 3 165 | SumLowTest = SumLowTest And SumLow(Array(1, 2, 3, 4), 3) = 6 166 | 167 | End Function 168 | 169 | 170 | Private Function AverageHighTest() As Boolean 171 | 172 | '@Example: =AverageHigh({1,2,3,4}, 2) -> 3.5; as 3 and 4 will be averaged 173 | '@Example: =AverageHigh({1,2,3,4}, 3) -> 3; as 2, 3, and 4 will be averaged 174 | 175 | AverageHighTest = True 176 | 177 | AverageHighTest = AverageHighTest And AverageHigh(Array(1, 2, 3, 4), 2) = 3.5 178 | AverageHighTest = AverageHighTest And AverageHigh(Array(1, 2, 3, 4), 3) = 3 179 | 180 | End Function 181 | 182 | 183 | Private Function AverageLowTest() As Boolean 184 | 185 | '@Example: =AverageLow({1,2,3,4}, 2) -> 1.5; as 1 and 2 will be averaged 186 | '@Example: =AverageLow({1,2,3,4}, 3) -> 2; as 1, 2, and 3 will be averaged 187 | 188 | AverageLowTest = True 189 | 190 | AverageLowTest = AverageLowTest And AverageLow(Array(1, 2, 3, 4), 2) = 1.5 191 | AverageLowTest = AverageLowTest And AverageLow(Array(1, 2, 3, 4), 3) = 2 192 | 193 | End Function 194 | 195 | 196 | Private Function LargeTest() As Boolean 197 | 198 | '@Example: =Large({1,2,3,4}, 1) -> 4 199 | '@Example: =Large({1,2,3,4}, 2) -> 3 200 | 201 | LargeTest = True 202 | 203 | LargeTest = LargeTest And Large(Array(1, 2, 3, 4), 1) = 4 204 | LargeTest = LargeTest And Large(Array(1, 2, 3, 4), 2) = 3 205 | 206 | End Function 207 | 208 | 209 | Private Function SmallTest() As Boolean 210 | 211 | '@Example: =Small({1,2,3,4}, 1) -> 1 212 | '@Example: =Small({1,2,3,4}, 2) -> 2 213 | 214 | SmallTest = True 215 | 216 | SmallTest = SmallTest And Small(Array(1, 2, 3, 4), 1) = 1 217 | SmallTest = SmallTest And Small(Array(1, 2, 3, 4), 2) = 2 218 | 219 | End Function 220 | 221 | 222 | Private Function IsInArrayTest() As Boolean 223 | 224 | '@Example: =IsInArray("hello", {"one", 2, "hello"}) -> True 225 | '@Example: =IsInArray("hello", {1, "two", "three"}) -> False 226 | 227 | IsInArrayTest = True 228 | 229 | IsInArrayTest = IsInArrayTest And IsInArray("hello", Array("one", 2, "hello")) = True 230 | IsInArrayTest = IsInArrayTest And IsInArray("hello", Array(1, "two", "three")) = False 231 | 232 | End Function 233 | 234 | 235 | -------------------------------------------------------------------------------- /Modules/xlibValidatorsTests.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibValidatorsTests" 2 | Option Explicit 3 | 4 | Public Function AllXlibValidatorsTests() 5 | 6 | Dim TestStatus As Boolean 7 | TestStatus = True 8 | 9 | Debug.Print "========================================" 10 | 11 | ' Begin Tests 12 | If Not IsEmailTest() Then 13 | Debug.Print "Failed: IsEmailTest" 14 | TestStatus = False 15 | Else 16 | Debug.Print "Passed: IsEmailTest" 17 | End If 18 | 19 | If Not IsPhoneTest() Then 20 | Debug.Print "Failed: IsPhoneTest" 21 | TestStatus = False 22 | Else 23 | Debug.Print "Passed: IsPhoneTest" 24 | End If 25 | 26 | If Not IsCreditCardTest() Then 27 | Debug.Print "Failed: IsCreditCardTest" 28 | TestStatus = False 29 | Else 30 | Debug.Print "Passed: IsCreditCardTest" 31 | End If 32 | 33 | If Not IsUrlTest() Then 34 | Debug.Print "Failed: IsUrlTest" 35 | TestStatus = False 36 | Else 37 | Debug.Print "Passed: IsUrlTest" 38 | End If 39 | 40 | If Not IsIPFourTest() Then 41 | Debug.Print "Failed: IsIPFourTest" 42 | TestStatus = False 43 | Else 44 | Debug.Print "Passed: IsIPFourTest" 45 | End If 46 | 47 | If Not IsMacAddressTest() Then 48 | Debug.Print "Failed: IsMacAddressTest" 49 | TestStatus = False 50 | Else 51 | Debug.Print "Passed: IsMacAddressTest" 52 | End If 53 | 54 | If Not CreditCardNameTest() Then 55 | Debug.Print "Failed: CreditCardNameTest" 56 | TestStatus = False 57 | Else 58 | Debug.Print "Passed: CreditCardNameTest" 59 | End If 60 | 61 | If Not FormatCreditCardTest() Then 62 | Debug.Print "Failed: FormatCreditCardTest" 63 | TestStatus = False 64 | Else 65 | Debug.Print "Passed: FormatCreditCardTest" 66 | End If 67 | ' End Tests 68 | 69 | Debug.Print "----------------------------------------" 70 | 71 | If TestStatus Then 72 | Debug.Print "Passed All Tests" 73 | Else 74 | Debug.Print "!!! FAILED TESTS !!!" 75 | End If 76 | 77 | Debug.Print "========================================" 78 | 79 | AllXlibValidatorsTests = TestStatus 80 | 81 | End Function 82 | 83 | 84 | 85 | Private Function IsEmailTest() As Boolean 86 | 87 | '@Example: =IsEmail("JohnDoe@testmail.com") -> TRUE 88 | '@Example: =IsEmail("JohnDoe@test/mail.com") -> FALSE 89 | '@Example: =IsEmail("not_an_email_address") -> FALSE 90 | 91 | IsEmailTest = True 92 | 93 | IsEmailTest = IsEmailTest And IsEmail("JohnDoe@testmail.com") = True 94 | IsEmailTest = IsEmailTest And IsEmail("JohnDoe@test/mail.com") = False 95 | IsEmailTest = IsEmailTest And IsEmail("not_an_email_address") = False 96 | 97 | End Function 98 | 99 | 100 | Private Function IsPhoneTest() As Boolean 101 | 102 | '@Example: =IsPhone("123 456 7890") -> TRUE 103 | '@Example: =IsPhone("1234567890") -> TRUE 104 | '@Example: =IsPhone("1-234-567-890") -> FALSE; Not enough digits 105 | '@Example: =IsPhone("1-234-567-8905") -> TRUE 106 | '@Example: =IsPhone("+1-234-567-890") -> FALSE; Not enough digits 107 | '@Example: =IsPhone("+1-234-567-8905") -> TRUE 108 | '@Example: =IsPhone("+1-(234)-567-8905") -> TRUE 109 | '@Example: =IsPhone("+1 (234) 567 8905") -> TRUE 110 | '@Example: =IsPhone("1(234)5678905") -> TRUE 111 | '@Example: =IsPhone("123-456-789") -> FALSE; Not enough digits 112 | '@Example: =IsPhone("Hello World") -> FALSE; Not a phone number 113 | 114 | IsPhoneTest = True 115 | 116 | IsPhoneTest = IsPhoneTest And IsPhone("123 456 7890") = True 117 | IsPhoneTest = IsPhoneTest And IsPhone("1234567890") = True 118 | IsPhoneTest = IsPhoneTest And IsPhone("1-234-567-890") = False 119 | IsPhoneTest = IsPhoneTest And IsPhone("1-234-567-8905") = True 120 | IsPhoneTest = IsPhoneTest And IsPhone("+1-234-567-890") = False 121 | IsPhoneTest = IsPhoneTest And IsPhone("+1-234-567-8905") = True 122 | IsPhoneTest = IsPhoneTest And IsPhone("+1-(234)-567-8905") = True 123 | IsPhoneTest = IsPhoneTest And IsPhone("+1 (234) 567 8905") = True 124 | IsPhoneTest = IsPhoneTest And IsPhone("1(234)5678905") = True 125 | IsPhoneTest = IsPhoneTest And IsPhone("123-456-789") = False 126 | IsPhoneTest = IsPhoneTest And IsPhone("Hello World") = False 127 | 128 | End Function 129 | 130 | 131 | Private Function IsCreditCardTest() As Boolean 132 | 133 | '@Example: =IsCreditCard("5111567856785678") -> TRUE; This is a valid Mastercard number 134 | '@Example: =IsCreditCard("511156785678567") -> FALSE; Not enough digits 135 | '@Example: =IsCreditCard("9999999999999999") -> FALSE; Enough digits, but not a valid card number 136 | '@Example: =IsCreditCard("Hello World") -> FALSE 137 | 138 | IsCreditCardTest = True 139 | 140 | IsCreditCardTest = IsCreditCardTest And IsCreditCard("5111567856785678") = True 141 | IsCreditCardTest = IsCreditCardTest And IsCreditCard("511156785678567") = False 142 | IsCreditCardTest = IsCreditCardTest And IsCreditCard("9999999999999999") = False 143 | IsCreditCardTest = IsCreditCardTest And IsCreditCard("Hello World") = False 144 | 145 | End Function 146 | 147 | 148 | Private Function IsUrlTest() As Boolean 149 | 150 | '@Example: =IsUrl("https://www.wikipedia.org/") -> TRUE 151 | '@Example: =IsUrl("http://www.wikipedia.org/") -> TRUE 152 | '@Example: =IsUrl("hello_world") -> FALSE 153 | 154 | IsUrlTest = True 155 | 156 | IsUrlTest = IsUrlTest And IsUrl("https://www.wikipedia.org/") = True 157 | IsUrlTest = IsUrlTest And IsUrl("http://www.wikipedia.org/") = True 158 | IsUrlTest = IsUrlTest And IsUrl("hello_world") = False 159 | 160 | End Function 161 | 162 | 163 | Private Function IsIPFourTest() As Boolean 164 | 165 | '@Example: =IsIPFour("0.0.0.0") -> TRUE 166 | '@Example: =IsIPFour("100.100.100.100") -> TRUE 167 | '@Example: =IsIPFour("255.255.255.255") -> TRUE 168 | '@Example: =IsIPFour("255.255.255.256") -> FALSE; as the final 256 makes the address outside of the bounds of IPv4 169 | '@Example: =IsIPFour("0.0.0") -> FALSE; as the fourth octet is missing 170 | 171 | IsIPFourTest = True 172 | 173 | IsIPFourTest = IsIPFourTest And IsIPFour("0.0.0.0") = True 174 | IsIPFourTest = IsIPFourTest And IsIPFour("100.100.100.100") = True 175 | IsIPFourTest = IsIPFourTest And IsIPFour("255.255.255.255") = True 176 | IsIPFourTest = IsIPFourTest And IsIPFour("255.255.255.256") = False 177 | IsIPFourTest = IsIPFourTest And IsIPFour("0.0.0") = False 178 | 179 | End Function 180 | 181 | 182 | Private Function IsMacAddressTest() As Boolean 183 | 184 | '@Example: =IsMacAddress("00:25:96:12:34:56") -> TRUE 185 | '@Example: =IsMacAddress("FF:FF:FF:FF:FF:FF") -> TRUE 186 | '@Example: =IsMacAddress("00-25-96-12-34-56") -> TRUE 187 | '@Example: =IsMacAddress("123.789.abc.DEF") -> TRUE 188 | '@Example: =IsMacAddress("Not A Mac Address") -> FALSE 189 | '@Example: =IsMacAddress("FF:FF:FF:FF:FF:FH") -> FALSE; the H at the end is not a valid Hex number 190 | 191 | IsMacAddressTest = True 192 | 193 | IsMacAddressTest = IsMacAddressTest And IsMacAddress("00:25:96:12:34:56") = True 194 | IsMacAddressTest = IsMacAddressTest And IsMacAddress("FF:FF:FF:FF:FF:FF") = True 195 | IsMacAddressTest = IsMacAddressTest And IsMacAddress("00-25-96-12-34-56") = True 196 | IsMacAddressTest = IsMacAddressTest And IsMacAddress("123.789.abc.DEF") = True 197 | IsMacAddressTest = IsMacAddressTest And IsMacAddress("Not A Mac Address") = False 198 | IsMacAddressTest = IsMacAddressTest And IsMacAddress("FF:FF:FF:FF:FF:FH") = False 199 | 200 | End Function 201 | 202 | 203 | Private Function CreditCardNameTest() As Boolean 204 | 205 | '@Example: =CreditCardName("5111567856785678") -> "MasterCard"; This is a valid Mastercard number 206 | '@Example: =CreditCardName("not_a_card_number") -> #VALUE! 207 | 208 | CreditCardNameTest = True 209 | 210 | CreditCardNameTest = CreditCardNameTest And CreditCardName("5111567856785678") = "MasterCard" 211 | 212 | End Function 213 | 214 | 215 | Private Function FormatCreditCardTest() As Boolean 216 | 217 | '@Example: =FormatCreditCard("5111567856785678") -> "5111-5678-5678-5678" 218 | 219 | FormatCreditCardTest = True 220 | 221 | FormatCreditCardTest = FormatCreditCardTest And FormatCreditCard("5111567856785678") = "5111-5678-5678-5678" 222 | 223 | End Function 224 | 225 | 226 | -------------------------------------------------------------------------------- /Modules/xlibMath.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibMath" 2 | '@Module: This module contains a set of basic mathematical functions where those functions don't already exist as base Excel functions. 3 | 4 | Option Explicit 5 | 6 | 7 | Public Function Ceil( _ 8 | ByVal number As Double) _ 9 | As Long 10 | 11 | '@Description: This function takes a number and rounds it up to the nearest whole integer 12 | '@Author: Anthony Mancini 13 | '@Version: 1.0.0 14 | '@License: MIT 15 | '@Param: number is the number that will be rounded up 16 | '@Returns: Returns the number rounded up to the nearest integer 17 | '@Example: =Ceil(1.5) -> 2 18 | '@Example: =Ceil(1.0001) -> 2 19 | '@Example: =Ceil(1.0) -> 1 20 | '@Example: =Ceil(1) -> 1 21 | 22 | If number = Fix(number) Then 23 | Ceil = number 24 | Else 25 | Ceil = Fix(number + 1) 26 | End If 27 | 28 | End Function 29 | 30 | 31 | Public Function Floor( _ 32 | ByVal number As Double) _ 33 | As Long 34 | 35 | '@Description: This function takes a number and rounds it down to the nearest whole integer 36 | '@Author: Anthony Mancini 37 | '@Version: 1.0.0 38 | '@License: MIT 39 | '@Param: number is the number that will be rounded down 40 | '@Returns: Returns the number rounded down to the nearest integer 41 | '@Example: =Floor(1.9) -> 1 42 | '@Example: =Floor(1.1) -> 1 43 | '@Example: =Floor(1.0) -> 1 44 | '@Example: =Floor(1) -> 1 45 | 46 | Floor = Fix(number) 47 | 48 | End Function 49 | 50 | 51 | Public Function InterpolateNumber( _ 52 | ByVal startingNumber As Double, _ 53 | ByVal endingNumber As Double, _ 54 | ByVal interpolationPercentage As Double) _ 55 | As Double 56 | 57 | '@Description: This function takes three numbers, a starting number, an ending number, and an interpolation percent, and linearly interpolates the number at the given percentage between the starting and ending number. 58 | '@Author: Anthony Mancini 59 | '@Version: 1.0.0 60 | '@License: MIT 61 | '@Param: startingNumber is the beginning number of the interpolation 62 | '@Param: endingNumber is the ending number of the interpolation 63 | '@Param: interpolationPercentage is the percentage that will be interpolated linearly between the startingNumber and the endingNumber 64 | '@Returns: Returns the linearly interpolated number between the two points 65 | '@Example: =InterpolateNumber(10, 20, 0.5) -> 15; Where 0.5 would be 50% between 10 and 20 66 | '@Example: =InterpolateNumber(16, 124, 0.64) -> 85.12; Where 0.64 would be 64% between 16 and 124 67 | 68 | InterpolateNumber = startingNumber + ((endingNumber - startingNumber) * interpolationPercentage) 69 | 70 | End Function 71 | 72 | 73 | Public Function InterpolatePercent( _ 74 | ByVal startingNumber As Double, _ 75 | ByVal endingNumber As Double, _ 76 | ByVal interpolationNumber As Double) _ 77 | As Double 78 | 79 | '@Description: This function takes three numbers, a starting number, an ending number, and an interpolation number, and linearly interpolates the percentage location of the interpolated number between the starting and ending number. 80 | '@Author: Anthony Mancini 81 | '@Version: 1.0.0 82 | '@License: MIT 83 | '@Param: startingNumber is the beginning number of the interpolation 84 | '@Param: endingNumber is the ending number of the interpolation 85 | '@Param: interpolationNumber is the number that will be interpolated linearly between the startingNumber and the endingNumber to calculate a percentage 86 | '@Returns: Returns the linearly interpolated percent between the two points given the interpolation number 87 | '@Example: =InterpolatePercent(10, 18, 12) -> 0.25; As 12 is 25% of the way from 10 to 18 88 | '@Example: =InterpolatePercent(10, 20, 15) -> 0.5; As 15 is 50% of the way from 10 to 20 89 | 90 | InterpolatePercent = (interpolationNumber - startingNumber) / (endingNumber - startingNumber) 91 | 92 | End Function 93 | 94 | 95 | Public Function Max( _ 96 | ParamArray numbers() As Variant) _ 97 | As Double 98 | 99 | '@Description: This function takes multiple numbers or multiple arrays of numbers and returns the max number. This function also accounts for numbers that are formatted as strings by converting them into numbers 100 | '@Author: Anthony Mancini 101 | '@Version: 1.0.0 102 | '@License: MIT 103 | '@Param: numbers is a single number, multiple numbers, or multiple arrays of numbers 104 | '@Returns: Returns the max number 105 | '@Example: =Max(1, 2, 3) -> 3 106 | '@Example: =Max(4.4, 5, "6") -> 6 107 | '@Example: =Max(x) -> 3; Where x is an array with these values [1, 2.2, "3"] 108 | '@Example: =Max(x, y, 10) -> 15; Where x = [1, 2.2, "3"] and y = [5, 15, -100] 109 | 110 | Dim individualParamArrayValue As Variant 111 | Dim individualValue As Variant 112 | Dim maxValue As Variant 113 | 114 | maxValue = Empty 115 | 116 | For Each individualParamArrayValue In numbers 117 | If IsArray(individualParamArrayValue) Then 118 | For Each individualValue In individualParamArrayValue 119 | If TypeName(individualValue) = "String" Then 120 | individualValue = CDbl(individualValue) 121 | End If 122 | 123 | If IsEmpty(maxValue) Then 124 | maxValue = individualValue 125 | ElseIf individualValue > maxValue Then 126 | maxValue = individualValue 127 | End If 128 | Next 129 | Else 130 | If TypeName(individualParamArrayValue) = "String" Then 131 | individualParamArrayValue = CDbl(individualParamArrayValue) 132 | End If 133 | 134 | If IsEmpty(maxValue) Then 135 | maxValue = individualParamArrayValue 136 | ElseIf individualParamArrayValue > maxValue Then 137 | maxValue = individualParamArrayValue 138 | End If 139 | End If 140 | Next 141 | 142 | Max = maxValue 143 | 144 | End Function 145 | 146 | 147 | Public Function Min( _ 148 | ParamArray numbers() As Variant) _ 149 | As Double 150 | 151 | '@Description: This function takes multiple numbers or multiple arrays of numbers and returns the min number. This function also accounts for numbers that are formatted as strings by converting them into numbers 152 | '@Author: Anthony Mancini 153 | '@Version: 1.0.0 154 | '@License: MIT 155 | '@Param: numbers is a single number, multiple numbers, or multiple arrays of numbers 156 | '@Returns: Returns the min number 157 | '@Example: =Min(1, 2, 3) -> 1 158 | '@Example: =Min(4.4, 5, "6") -> 4.4 159 | '@Example: =Min(-1, -2, -3) -> -3 160 | '@Example: =Min(x) -> 1; Where x is an array with these values [1, 2.2, "3"] 161 | '@Example: =Min(x, y, 10) -> -100; Where x = [1, 2.2, "3"] and y = [5, 15, -100] 162 | 163 | Dim individualParamArrayValue As Variant 164 | Dim individualValue As Variant 165 | Dim minValue As Variant 166 | 167 | minValue = Empty 168 | 169 | For Each individualParamArrayValue In numbers 170 | If IsArray(individualParamArrayValue) Then 171 | For Each individualValue In individualParamArrayValue 172 | If TypeName(individualValue) = "String" Then 173 | individualValue = CDbl(individualValue) 174 | End If 175 | 176 | If IsEmpty(minValue) Then 177 | minValue = individualValue 178 | ElseIf individualValue < minValue Then 179 | minValue = individualValue 180 | End If 181 | Next 182 | Else 183 | If TypeName(individualParamArrayValue) = "String" Then 184 | individualParamArrayValue = CDbl(individualParamArrayValue) 185 | End If 186 | 187 | If IsEmpty(minValue) Then 188 | minValue = individualParamArrayValue 189 | ElseIf individualParamArrayValue < minValue Then 190 | minValue = individualParamArrayValue 191 | End If 192 | End If 193 | Next 194 | 195 | Min = minValue 196 | 197 | End Function 198 | 199 | 200 | Public Function ModFloat( _ 201 | numerator As Double, _ 202 | denominator As Double) _ 203 | As Double 204 | 205 | '@Description: This function performs modulus operations with floats as the Mod operator in VBA does not support floats. 206 | '@Author: Anthony Mancini 207 | '@Version: 1.0.0 208 | '@License: MIT 209 | '@Todo: Find out if numerator and denominator are the correct names for Modulo operation 210 | '@Param: numerator is the left value of the Mod 211 | '@Param: denominator is the right value of the Mod 212 | '@Returns: Returns a double with ModFloat operator performed on it 213 | '@Example: =ModFloat(3.55, 2) -> 1.55 214 | 215 | Dim modValue As Double 216 | 217 | modValue = numerator - Fix(numerator / denominator) * denominator 218 | 219 | If modValue >= -2 ^ -52 Then 220 | If modValue <= 2 ^ -52 Then 221 | modValue = 0 222 | End If 223 | End If 224 | 225 | ModFloat = modValue 226 | 227 | End Function 228 | -------------------------------------------------------------------------------- /Modules/xlibUtilitiesTests.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibUtilitiesTests" 2 | Option Explicit 3 | 4 | Public Function AllXlibUtilitiesTests() 5 | 6 | Dim TestStatus As Boolean 7 | TestStatus = True 8 | 9 | Debug.Print "========================================" 10 | 11 | ' Begin Tests 12 | If Not JsonifyTest() Then 13 | Debug.Print "Failed: JsonifyTest" 14 | TestStatus = False 15 | Else 16 | Debug.Print "Passed: JsonifyTest" 17 | End If 18 | 19 | If Not UuidFourTest() Then 20 | Debug.Print "Failed: UuidFourTest" 21 | TestStatus = False 22 | Else 23 | Debug.Print "Passed: UuidFourTest" 24 | End If 25 | 26 | If Not HideTextTest() Then 27 | Debug.Print "Failed: HideTextTest" 28 | TestStatus = False 29 | Else 30 | Debug.Print "Passed: HideTextTest" 31 | End If 32 | 33 | If Not JavaScriptTest() Then 34 | Debug.Print "Failed: JavaScriptTest" 35 | TestStatus = False 36 | Else 37 | Debug.Print "Passed: JavaScriptTest" 38 | End If 39 | 40 | If Not HtmlEscapeTest() Then 41 | Debug.Print "Failed: HtmlEscapeTest" 42 | TestStatus = False 43 | Else 44 | Debug.Print "Passed: HtmlEscapeTest" 45 | End If 46 | 47 | If Not HtmlUnescapeTest() Then 48 | Debug.Print "Failed: HtmlUnescapeTest" 49 | TestStatus = False 50 | Else 51 | Debug.Print "Passed: HtmlUnescapeTest" 52 | End If 53 | 54 | If Not SpeakTextTest() Then 55 | Debug.Print "Failed: SpeakTextTest" 56 | TestStatus = False 57 | Else 58 | Debug.Print "Passed: SpeakTextTest" 59 | End If 60 | 61 | If Not Dec2HexTest() Then 62 | Debug.Print "Failed: Dec2HexTest" 63 | TestStatus = False 64 | Else 65 | Debug.Print "Passed: Dec2HexTest" 66 | End If 67 | 68 | If Not BigDec2HexTest() Then 69 | Debug.Print "Failed: BigDec2HexTest" 70 | TestStatus = False 71 | Else 72 | Debug.Print "Passed: BigDec2HexTest" 73 | End If 74 | 75 | If Not BigHexTest() Then 76 | Debug.Print "Failed: BigHexTest" 77 | TestStatus = False 78 | Else 79 | Debug.Print "Passed: BigHexTest" 80 | End If 81 | 82 | If Not Hex2DecTest() Then 83 | Debug.Print "Failed: Hex2DecTest" 84 | TestStatus = False 85 | Else 86 | Debug.Print "Passed: Hex2DecTest" 87 | End If 88 | 89 | If Not Len2Test() Then 90 | Debug.Print "Failed: Len2Test" 91 | TestStatus = False 92 | Else 93 | Debug.Print "Passed: Len2Test" 94 | End If 95 | ' End Tests 96 | 97 | Debug.Print "----------------------------------------" 98 | 99 | If TestStatus Then 100 | Debug.Print "Passed All Tests" 101 | Else 102 | Debug.Print "!!! FAILED TESTS !!!" 103 | End If 104 | 105 | Debug.Print "========================================" 106 | 107 | AllXlibUtilitiesTests = TestStatus 108 | 109 | End Function 110 | 111 | 112 | 113 | Private Function JsonifyTest() As Boolean 114 | 115 | '@Example: =Jsonify(0, "Hello", "World", "1", "2", 3, 4.5) -> "["Hello","World",1,2,3,4.5]" 116 | '@Example: =Jsonify(0, {"Hello", "World", "1", "2", 3, 4.5}, 10) -> "["Hello","World",1,2,3,4.5]" 117 | 118 | JsonifyTest = True 119 | 120 | JsonifyTest = JsonifyTest And Jsonify(0, "Hello", "World", "1", "2", 3, 4.5) = "[" & Chr(34) & "Hello" & Chr(34) & "," & Chr(34) & "World" & Chr(34) & ",1,2,3,4.5]" 121 | JsonifyTest = JsonifyTest And Jsonify(0, Array("Hello", "World", "1", "2", 3, 4.5)) = "[" & Chr(34) & "Hello" & Chr(34) & "," & Chr(34) & "World" & Chr(34) & ",1,2,3,4.5]" 122 | 123 | End Function 124 | 125 | 126 | Private Function UuidFourTest() As Boolean 127 | 128 | '@Example: =UuidFour() -> "3B4BDC26-E76E-4D6C-9E05-7AE7D2D68304" 129 | '@Example: =UuidFour() -> "D5761256-8385-4FDA-AD56-6AEF0AD6B9A5" 130 | '@Example: =UuidFour() -> "CDCAE2F5-B52F-4C90-A38A-42BD58BCED4B" 131 | 132 | Dim uuidGroups As Variant 133 | uuidGroups = Split(UuidFour(), "-") 134 | 135 | If Len(uuidGroups(0)) = 8 _ 136 | And Len(uuidGroups(1)) = 4 _ 137 | And Len(uuidGroups(2)) = 4 _ 138 | And Len(uuidGroups(3)) = 4 _ 139 | And Len(uuidGroups(4)) = 12 Then 140 | 141 | UuidFourTest = True 142 | 143 | End If 144 | 145 | End Function 146 | 147 | 148 | Private Function HideTextTest() As Boolean 149 | 150 | '@Example: =HideText("Hello World", FALSE) -> "Hello World" 151 | '@Example: =HideText("Hello World", TRUE) -> "********" 152 | '@Example: =HideText("Hello World", TRUE, "[HideText Text]") -> "[HideText Text]" 153 | '@Example: =HideText("Hello World", UserName()="Anthony") -> "********" 154 | 155 | HideTextTest = True 156 | 157 | HideTextTest = HideTextTest And HideText("Hello World", False) = "Hello World" 158 | HideTextTest = HideTextTest And HideText("Hello World", True) = "********" 159 | HideTextTest = HideTextTest And HideText("Hello World", True, "[Hidden Text]") = "[Hidden Text]" 160 | 161 | End Function 162 | 163 | 164 | Private Function JavaScriptTest() As Boolean 165 | 166 | '@Example: =JavaScript("function helloFunc(){return 'Hello World!'}", "helloFunc") -> "Hello World!" 167 | '@Example: =JavaScript("function addTwo(a, b){return a + b}","addTwo",12,24) -> 36 168 | 169 | JavaScriptTest = True 170 | 171 | JavaScriptTest = JavaScriptTest And JavaScript("function helloFunc(){return 'Hello World!'}", "helloFunc") = "Hello World!" 172 | JavaScriptTest = JavaScriptTest And JavaScript("function addTwo(a, b){return a + b}", "addTwo", 12, 24) = 36 173 | 174 | End Function 175 | 176 | 177 | Private Function HtmlEscapeTest() As Boolean 178 | 179 | '@Example: =HtmlEscape("

Hello World

") -> "<p>Hello World</p>" 180 | 181 | HtmlEscapeTest = True 182 | 183 | HtmlEscapeTest = HtmlEscapeTest And HtmlEscape("

Hello World

") = "<p>Hello World</p>" 184 | 185 | End Function 186 | 187 | 188 | Private Function HtmlUnescapeTest() As Boolean 189 | 190 | '@Example: =HtmlUnescape("<p>Hello World</p>") -> "

Hello World

" 191 | 192 | HtmlUnescapeTest = True 193 | 194 | HtmlUnescapeTest = HtmlUnescapeTest And HtmlUnescape("<p>Hello World</p>") = "

Hello World

" 195 | 196 | End Function 197 | 198 | 199 | Private Function SpeakTextTest() As Boolean 200 | 201 | '@Example: =SpeakText("Hello", "World") -> "Hello World" and the text will be spoken through the speaker 202 | 203 | SpeakTextTest = True 204 | 205 | SpeakTextTest = SpeakTextTest And SpeakText("Hello", "World") = "Hello World" 206 | 207 | End Function 208 | 209 | 210 | Private Function Dec2HexTest() As Boolean 211 | 212 | '@Example: =Dec2Hex(5) -> "5" 213 | '@Example: =Dec2Hex(5, 2) -> "05" 214 | '@Example: =Dec2Hex(255, 2) -> "FF" 215 | '@Example: =Dec2Hex(255, 8) -> "000000FF" 216 | 217 | Dec2HexTest = True 218 | 219 | Dec2HexTest = Dec2HexTest And Dec2Hex(5) = "5" 220 | Dec2HexTest = Dec2HexTest And Dec2Hex(5, 2) = "05" 221 | Dec2HexTest = Dec2HexTest And Dec2Hex(255, 2) = "FF" 222 | Dec2HexTest = Dec2HexTest And Dec2Hex(255, 8) = "000000FF" 223 | 224 | End Function 225 | 226 | 227 | Private Function BigDec2HexTest() As Boolean 228 | 229 | '@Example: =Dec2Hex(255, 8) -> "000000FF" 230 | '@Example: =Dec2Hex(3000000000, 16) -> Error; As Dec2Hex does not support integers this large 231 | '@Example: =BigDec2Hex(3000000000, 16) -> "00000000B2D05E00" 232 | 233 | BigDec2HexTest = True 234 | 235 | BigDec2HexTest = BigDec2HexTest And BigDec2Hex(3000000000#, 16) = "00000000B2D05E00" 236 | 237 | End Function 238 | 239 | 240 | Private Function BigHexTest() As Boolean 241 | 242 | '@Example: =BigHex(255) -> "FF" 243 | '@Example: =Hex(3000000000) -> Error; As hex does not support big integers 244 | '@Example: =BigHex(3000000000) -> "B2D05E00" 245 | 246 | BigHexTest = True 247 | 248 | BigHexTest = BigHexTest And BigHex(3000000000#) = "B2D05E00" 249 | 250 | End Function 251 | 252 | 253 | Private Function Hex2DecTest() As Boolean 254 | 255 | '@Example: =Hex2Dec("FF") -> 255 256 | '@Example: =Hex2Dec("FFFF") -> 65535 257 | 258 | Hex2DecTest = True 259 | 260 | Hex2DecTest = Hex2DecTest And Hex2Dec("FF") = 255 261 | Hex2DecTest = Hex2DecTest And Hex2Dec("FFFF") = 65535 262 | 263 | End Function 264 | 265 | 266 | Private Function Len2Test() As Boolean 267 | 268 | '@Example: =Len2("Hello") -> 5; As the string is 5 characters long 269 | '@Example: =Len2(arr) -> 3; Where arr is an array with {1, 2, 3} in it, and the array has 3 values in it 270 | '@Example: =Len2("100") -> 3; As the string is 3 characters long 271 | '@Example: =Len2(100) -> 3; As the integer is 3 characters long when converted to a string 272 | '@Example: =Len2(Range("A1:A3")) -> 3; As the Excel Range has 3 273 | '@Example: =Len2(col) -> 5; Where col is a Collection with 5 items in it 274 | '@Example: =Len2(dict) -> 2; Where dict is a Dictionary with 2 key/value pairs in it 275 | '@Example: =Len2(Application.Documents) -> 3; Where we currently have 3 documents open 276 | '@Example: =Len2(Application.ActivePresentation.Slides) -> 10; Where the active PowerPoint Presentation has 10 slides 277 | 278 | Len2Test = True 279 | 280 | Len2Test = Len2Test And Len2("Hello") = 5 281 | Len2Test = Len2Test And Len2(Array(1, 2, 3)) = 3 282 | Len2Test = Len2Test And Len2("100") = 3 283 | Len2Test = Len2Test And Len2(100) = 3 284 | 285 | Dim col As Collection 286 | Set col = New Collection 287 | col.Add 1 288 | col.Add 2 289 | col.Add 3 290 | col.Add 4 291 | col.Add 5 292 | Len2Test = Len2Test And Len2(col) = 5 293 | 294 | Dim dict As Object 295 | Set dict = CreateObject("Scripting.Dictionary") 296 | dict.Add "Hello", 1 297 | dict.Add "World", 2 298 | Len2Test = Len2Test And Len2(dict) = 2 299 | 300 | End Function 301 | 302 | -------------------------------------------------------------------------------- /Modules/xlibStringMetrics.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibStringMetrics" 2 | '@Module: This module contains a set of functions for performing fuzzy string matches. It can be useful when you have 2 columns containing text that is close but not 100% the same. However, since the functions in this module only perform fuzzy matches, there is no guarantee that there will be 100% accuracy in the matches. However, for small groups of string where each string is very different than the other (such as a small group of fairly dissimilar names), these functions can be highly accurate. Finally, some of the functions in this Module will take a long time to calculate for large numbers of cells, as the number of calculations for some functions will grow exponentially, but for small sets of data (such as 100 strings to compare), these functions perform fairly quickly. 3 | 4 | Option Explicit 5 | 6 | 7 | '======================================== 8 | ' Hamming Distance 9 | '======================================== 10 | 11 | Public Function Hamming( _ 12 | string1 As String, _ 13 | string2 As String) _ 14 | As Integer 15 | 16 | '@Description: This function takes two strings of the same length and calculates the Hamming Distance between them. Hamming Distance measures how close two strings are by checking how many Substitutions are needed to turn one string into the other. Lower numbers mean the strings are closer than high numbers. 17 | '@Author: Anthony Mancini 18 | '@Version: 1.0.0 19 | '@License: MIT 20 | '@Param: string1 is the first string 21 | '@Param: string2 is the second string that will be compared to the first string 22 | '@Returns: Returns an integer of the Hamming Distance between two string 23 | '@Example: =Hamming("Cat", "Bat") -> 1; Since all that is needed is 1 change (changing the "B" in Bat to "C") 24 | '@Example: =Hamming("Cat", "Bag") -> 2; 2 changes are needed, changing the "B" to "C" and the "g" to "t" 25 | '@Example: =Hamming("Cat", "Dog") -> 3; Every single character needs to be substituted in this case 26 | 27 | If Len(string1) <> Len(string2) Then 28 | Hamming = CVErr(2015) 29 | End If 30 | 31 | Dim totalDistance As Integer 32 | totalDistance = 0 33 | 34 | Dim i As Integer 35 | 36 | For i = 1 To Len(string1) 37 | If Mid(string1, i, 1) <> Mid(string2, i, 1) Then 38 | totalDistance = totalDistance + 1 39 | End If 40 | Next 41 | 42 | Hamming = totalDistance 43 | 44 | End Function 45 | 46 | 47 | 48 | '======================================== 49 | ' Levenshtein Distance 50 | '======================================== 51 | 52 | Public Function Levenshtein( _ 53 | string1 As String, _ 54 | string2 As String) _ 55 | As Long 56 | 57 | '@Description: This function takes two strings of any length and calculates the Levenshtein Distance between them. Levenshtein Distance measures how close two strings are by checking how many Insertions, Deletions, or Substitutions are needed to turn one string into the other. Lower numbers mean the strings are closer than high numbers. Unlike Hamming Distance, Levenshtein Distance works for strings of any length and includes 2 more operations. However, calculation time will be slower than Hamming Distance for same length strings, so if you know the two strings are the same length, its preferred to use Hamming Distance. 58 | '@Author: Anthony Mancini 59 | '@Version: 1.1.0 60 | '@License: MIT 61 | '@Param: string1 is the first string 62 | '@Param: string2 is the second string that will be compared to the first string 63 | '@Returns: Returns an integer of the Levenshtein Distance between two string 64 | '@Example: =Levenshtein("Cat", "Bat") -> 1; Since all that is needed is 1 change (changing the "B" in Bat to "C") 65 | '@Example: =Levenshtein("Cat", "Ca") -> 1; Since only one Insertion needs to occur (adding a "t" at the end) 66 | '@Example: =Levenshtein("Cat", "Cta") -> 2; Since the "t" in "Cta" needs to be substituted into an "a", and the final character "a" needs to be substituted into a "t" 67 | 68 | ' **Error Checking** 69 | ' Quick returns for common errors 70 | If string1 = string2 Then 71 | Levenshtein = 0 72 | Exit Function 73 | ElseIf string1 = Empty Then 74 | Levenshtein = Len(string2) 75 | Exit Function 76 | ElseIf string2 = Empty Then 77 | Levenshtein = Len(string1) 78 | Exit Function 79 | End If 80 | 81 | 82 | ' **Algorithm Code** 83 | ' Creating the distance metrix and filling it with values 84 | Dim numberOfRows As Integer 85 | Dim numberOfColumns As Integer 86 | 87 | numberOfRows = Len(string1) 88 | numberOfColumns = Len(string2) 89 | 90 | Dim distanceArray() As Integer 91 | ReDim distanceArray(numberOfRows, numberOfColumns) 92 | 93 | Dim r As Integer 94 | Dim c As Integer 95 | 96 | For r = 0 To numberOfRows 97 | For c = 0 To numberOfColumns 98 | distanceArray(r, c) = 0 99 | Next 100 | Next 101 | 102 | For r = 1 To numberOfRows 103 | distanceArray(r, 0) = r 104 | Next 105 | 106 | For c = 1 To numberOfColumns 107 | distanceArray(0, c) = c 108 | Next 109 | 110 | ' Non-recursive Levenshtein Distance matrix walk 111 | Dim operationCost As Integer 112 | 113 | For c = 1 To numberOfColumns 114 | For r = 1 To numberOfRows 115 | If Mid(string1, r, 1) = Mid(string2, c, 1) Then 116 | operationCost = 0 117 | Else 118 | operationCost = 1 119 | End If 120 | 121 | distanceArray(r, c) = Min(distanceArray(r - 1, c) + 1, distanceArray(r, c - 1) + 1, distanceArray(r - 1, c - 1) + operationCost) 122 | Next 123 | Next 124 | 125 | Levenshtein = distanceArray(numberOfRows, numberOfColumns) 126 | 127 | End Function 128 | 129 | 130 | 131 | '======================================== 132 | ' Damerau-Levenshtein Distance 133 | '======================================== 134 | 135 | Public Function Damerau( _ 136 | string1 As String, _ 137 | string2 As String) _ 138 | As Integer 139 | 140 | '@Description: This function takes two strings of any length and calculates the Damerau-Levenshtein Distance between them. Damerau-Levenshtein Distance differs from Levenshtein Distance in that it includes an additional operation, called Transpositions, which occurs when two adjacent characters are swapped. Thus, Damerau-Levenshtein Distance calculates the number of Insertions, Deletions, Substitutions, and Transpositons needed to convert string1 into string2. As a result, this function is good when it is likely that spelling errors have occured between two string where the error is simply a transposition of 2 adjacent characters. 141 | '@Author: Anthony Mancini 142 | '@Version: 1.1.0 143 | '@License: MIT 144 | '@Param: string1 is the first string 145 | '@Param: string2 is the second string that will be compared to the first string 146 | '@Returns: Returns an integer of the Damerau-Levenshtein Distance between two string 147 | '@Example: =Damerau("Cat", "Bat") -> 1; Since all that is needed is 1 change (changing the "B" in Bat to "C") 148 | '@Example: =Damerau("Cat", "Ca") -> 1; Since only one Insertion needs to occur (adding a "t" at the end) 149 | '@Example: =Damerau("Cat", "Cta") -> 1; Since the "t" and "a" can be transposed as they are adjacent to each other. Notice how LEVENSHTEIN("Cat","Cta")=2 but DAMERAU("Cat","Cta")=1 150 | 151 | ' **Error Checking** 152 | ' Quick returns for common errors 153 | If string1 = string2 Then 154 | Damerau = 0 155 | ElseIf string1 = Empty Then 156 | Damerau = Len(string2) 157 | ElseIf string2 = Empty Then 158 | Damerau = Len(string1) 159 | End If 160 | 161 | Dim inf As Long 162 | Dim da As Object 163 | inf = Len(string1) + Len(string2) 164 | Set da = CreateObject("Scripting.Dictionary") 165 | 166 | ' 35 - 38 = filling the dictionary 167 | Dim i As Integer 168 | For i = 1 To Len(string1) 169 | If da.exists(Mid(string1, i, 1)) = False Then 170 | da.Add Mid(string1, i, 1), "0" 171 | End If 172 | Next 173 | 174 | For i = 1 To Len(string2) 175 | If da.exists(Mid(string2, i, 1)) = False Then 176 | da.Add Mid(string2, i, 1), "0" 177 | End If 178 | Next 179 | 180 | ' 39 = creating h matrix 181 | Dim H() As Long 182 | ReDim H(Len(string1) + 1, Len(string2) + 1) 183 | 184 | Dim k As Integer 185 | For i = 0 To (Len(string1) + 1) 186 | For k = 0 To (Len(string2) + 1) 187 | H(i, k) = 0 188 | Next 189 | Next 190 | 191 | ' 40 - 45 = updating the matrix 192 | For i = 0 To Len(string1) 193 | H(i + 1, 0) = inf 194 | H(i + 1, 1) = i 195 | Next 196 | For k = 0 To Len(string2) 197 | H(0, k + 1) = inf 198 | H(1, k + 1) = k 199 | Next 200 | 201 | 202 | ' 46 - 60 = running the array 203 | Dim db As Long 204 | Dim i1 As Long 205 | Dim k1 As Long 206 | Dim cost As Long 207 | 208 | For i = 1 To Len(string1) 209 | db = 0 210 | For k = 1 To Len(string2) 211 | i1 = CInt(da(Mid(string2, k, 1))) 212 | k1 = db 213 | cost = 1 214 | 215 | If Mid(string1, i, 1) = Mid(string2, k, 1) Then 216 | cost = 0 217 | db = k 218 | End If 219 | 220 | H(i + 1, k + 1) = Min(H(i, k) + cost, _ 221 | H(i + 1, k) + 1, _ 222 | H(i, k + 1) + 1, _ 223 | H(i1, k1) + (i - i1 - 1) + 1 + (k - k1 - 1)) 224 | 225 | 226 | Next 227 | 228 | If da.exists(Mid(string1, i, 1)) Then 229 | da.Remove Mid(string1, i, 1) 230 | da.Add Mid(string1, i, 1), CStr(i) 231 | Else 232 | da.Add Mid(string1, i, 1), CStr(i) 233 | End If 234 | 235 | Next 236 | 237 | Damerau = H(Len(string1) + 1, Len(string2) + 1) 238 | 239 | End Function 240 | 241 | -------------------------------------------------------------------------------- /Modules/xlibDateTime.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibDateTime" 2 | '@Module: This module contains a set of functions for working with dates and times. 3 | 4 | Option Private Module 5 | Option Explicit 6 | 7 | 8 | Public Function WeekdayName2( _ 9 | Optional ByVal dayNumber As Byte) _ 10 | As String 11 | 12 | '@Description: This function takes a weekday number and returns the name of the day of the week. 13 | '@Author: Anthony Mancini 14 | '@Version: 1.0.0 15 | '@License: MIT 16 | '@Param: dayNumber is a number that should be between 1 and 7, with 1 being Sunday and 7 being Saturday. If no dayNumber is given, the value will default to the current day of the week. 17 | '@Returns: Returns the day of the week as a string 18 | '@Example: =WeekdayName2(4) -> Wednesday 19 | '@Example: To get today's weekday name: =WeekdayName2() 20 | 21 | If dayNumber = 0 Then 22 | WeekdayName2 = WeekdayName(Weekday(Now())) 23 | Else 24 | WeekdayName2 = WeekdayName(dayNumber) 25 | End If 26 | 27 | End Function 28 | 29 | 30 | Public Function MonthName2( _ 31 | Optional ByVal monthNumber As Byte) _ 32 | As String 33 | 34 | '@Description: This function takes a month number and returns the name of the month. 35 | '@Author: Anthony Mancini 36 | '@Version: 1.0.0 37 | '@License: MIT 38 | '@Param: monthNumber is a number that should be between 1 and 12, with 1 being January and 12 being December. If no monthNumber is given, the value will default to the current month. 39 | '@Returns: Returns the month name as a string 40 | '@Example: =MonthName2(1) -> "January" 41 | '@Example: =MonthName2(3) -> "March" 42 | '@Example: To get today's month name: =MonthName2() 43 | 44 | If monthNumber = 0 Then 45 | MonthName2 = MonthName(Month(Now())) 46 | Else 47 | MonthName2 = MonthName(monthNumber) 48 | End If 49 | 50 | End Function 51 | 52 | 53 | Public Function Quarter( _ 54 | Optional ByVal monthNumberOrName As Variant) _ 55 | As Byte 56 | 57 | '@Description: This function takes a month as a number and returns the Quarter of the year the month resides. 58 | '@Author: Anthony Mancini 59 | '@Version: 1.0.0 60 | '@License: MIT 61 | '@Todo: Look further into DatePart function and see if its a better choice for generating the Quarter of the year. Also look into adding the month name as well as an option for this function 62 | '@Param: monthNumberOrName is a number that should be between 1 and 12, with 1 being January and 12 being December, or the name of a Month, such as "January" or "March". 63 | '@Returns: Returns the Quarter of the month as a number 64 | '@Example: =Quarter(4) -> 2 65 | '@Example: =Quarter("April") -> 2 66 | '@Example: =Quarter(12) -> 4 67 | '@Example: =Quarter("December") -> 4 68 | '@Example: To get today's Quarter: =Quarter() 69 | 70 | If IsMissing(monthNumberOrName) Then 71 | monthNumberOrName = MonthName(Month(Now())) 72 | End If 73 | 74 | If IsNumeric(monthNumberOrName) Then 75 | monthNumberOrName = MonthName(monthNumberOrName) 76 | End If 77 | 78 | 79 | If monthNumberOrName = MonthName(1) Or monthNumberOrName = MonthName(2) Or monthNumberOrName = MonthName(3) Then 80 | Quarter = 1 81 | End If 82 | 83 | If monthNumberOrName = MonthName(4) Or monthNumberOrName = MonthName(5) Or monthNumberOrName = MonthName(6) Then 84 | Quarter = 2 85 | End If 86 | 87 | If monthNumberOrName = MonthName(7) Or monthNumberOrName = MonthName(8) Or monthNumberOrName = MonthName(9) Then 88 | Quarter = 3 89 | End If 90 | 91 | If monthNumberOrName = MonthName(10) Or monthNumberOrName = MonthName(11) Or monthNumberOrName = MonthName(12) Then 92 | Quarter = 4 93 | End If 94 | 95 | End Function 96 | 97 | 98 | Public Function TimeConverter( _ 99 | ByVal date1 As Date, _ 100 | Optional ByVal secondsInteger As Integer, _ 101 | Optional ByVal minutesInteger As Integer, _ 102 | Optional ByVal hoursInteger As Integer, _ 103 | Optional ByVal daysInteger As Integer, _ 104 | Optional ByVal monthsInteger As Integer, _ 105 | Optional ByVal yearsInteger As Integer) _ 106 | As Date 107 | 108 | '@Description: This function takes a date, and then a series of optional arguments for a number of seconds, minutes, hours, days, and years, and then converts the date given to a new date adding in the other date argument values. 109 | '@Author: Anthony Mancini 110 | '@Version: 1.0.0 111 | '@License: MIT 112 | '@Param: date1 is the original date that will be converted into a new date 113 | '@Param: secondsInteger is the number of seconds that will be added 114 | '@Param: minutesInteger is the number of minutes that will be added 115 | '@Param: hoursInteger is the number of hours that will be added 116 | '@Param: daysInteger is the number of days that will be added 117 | '@Param: monthsInteger is the number of months that will be added 118 | '@Param: yearsInteger is the number of years that will be added 119 | '@Returns: Returns a new date with all the date arguments added to it 120 | '@Note: You can skip earlier date arguments in the function by putting a 0 in place. For example, if we only wanted to change the month, which is the 5th argument, we can do =TimeConverter(A1,0,0,0,2) which will add 2 months to the date chosen 121 | '@Example: =TimeConverter(A1,60) -> 1/1/2000 1:01; Where A1 contains the date 1/1/2000 1:00 122 | '@Example: =TimeConverter(A1,0,5) -> 1/1/2000 1:05; Where A1 contains the date 1/1/2000 1:00 123 | '@Example: =TimeConverter(A1,0,0,2) -> 1/1/2000 3:00; Where A1 contains the date 1/1/2000 1:00 124 | '@Example: =TimeConverter(A1,0,0,0,4) -> 1/5/2000 1:00; Where A1 contains the date 1/1/2000 1:00 125 | '@Example: =TimeConverter(A1,0,0,0,0,1) -> 2/1/2000 1:00; Where A1 contains the date 1/1/2000 1:00 126 | '@Example: =TimeConverter(A1,0,0,0,0,0,5) -> 1/1/2005 1:00; Where A1 contains the date 1/1/2000 1:00 127 | '@Example: =TimeConverter(A1,60,5,3,10,5,15) -> 6/11/2015 4:06; Where A1 contains the date 1/1/2000 1:00 128 | 129 | secondsInteger = Second(date1) + secondsInteger 130 | minutesInteger = Minute(date1) + minutesInteger 131 | hoursInteger = Hour(date1) + hoursInteger 132 | daysInteger = Day(date1) + daysInteger 133 | monthsInteger = Month(date1) + monthsInteger 134 | yearsInteger = Year(date1) + yearsInteger 135 | 136 | TimeConverter = DateSerial(yearsInteger, monthsInteger, daysInteger) + TimeSerial(hoursInteger, minutesInteger, secondsInteger) 137 | 138 | End Function 139 | 140 | 141 | Public Function DaysOfMonth( _ 142 | Optional ByVal monthNumberOrName As Variant, _ 143 | Optional ByVal yearNumber As Integer) _ 144 | As Variant 145 | 146 | '@Description: This function takes a month number or month name and returns the number of days in the month. Optionally, a year number can be specified. If no year number is provided, the current year will be used. Finally, note that the month name or number argument is optional and if omitted will use the current month. 147 | '@Author: Anthony Mancini 148 | '@Version: 1.0.0 149 | '@License: MIT 150 | '@Param: monthNumberOrName is a number that should be between 1 and 12, with 1 being January and 12 being December, or the name of a Month, such as "January" or "March". If omitted the current month will be used. 151 | '@Param: yearNumber is the year that will be used. If omitted, the current year will be used. 152 | '@Returns: Returns the number of days in the month and year specified 153 | '@Example: =DaysOfMonth() -> 31; Where the current month is January 154 | '@Example: =DaysOfMonth(1) -> 31 155 | '@Example: =DaysOfMonth("January") -> 31 156 | '@Example: =DaysOfMonth(2, 2019) -> 28 157 | '@Example: =DaysOfMonth(2, 2020) -> 29 158 | 159 | If IsMissing(monthNumberOrName) Then 160 | monthNumberOrName = Month(Now()) 161 | End If 162 | 163 | If yearNumber = 0 Then 164 | yearNumber = Year(Now()) 165 | End If 166 | 167 | If monthNumberOrName = 1 Or monthNumberOrName = MonthName(1) Then 168 | DaysOfMonth = 31 169 | ElseIf monthNumberOrName = 2 Or monthNumberOrName = MonthName(2) Then 170 | If yearNumber Mod 4 <> 0 Then 171 | DaysOfMonth = 28 172 | Else 173 | DaysOfMonth = 29 174 | End If 175 | ElseIf monthNumberOrName = 3 Or monthNumberOrName = MonthName(3) Then 176 | DaysOfMonth = 31 177 | ElseIf monthNumberOrName = 4 Or monthNumberOrName = MonthName(4) Then 178 | DaysOfMonth = 30 179 | ElseIf monthNumberOrName = 5 Or monthNumberOrName = MonthName(5) Then 180 | DaysOfMonth = 31 181 | ElseIf monthNumberOrName = 6 Or monthNumberOrName = MonthName(6) Then 182 | DaysOfMonth = 30 183 | ElseIf monthNumberOrName = 7 Or monthNumberOrName = MonthName(7) Then 184 | DaysOfMonth = 31 185 | ElseIf monthNumberOrName = 8 Or monthNumberOrName = MonthName(8) Then 186 | DaysOfMonth = 31 187 | ElseIf monthNumberOrName = 9 Or monthNumberOrName = MonthName(9) Then 188 | DaysOfMonth = 30 189 | ElseIf monthNumberOrName = 10 Or monthNumberOrName = MonthName(10) Then 190 | DaysOfMonth = 31 191 | ElseIf monthNumberOrName = 11 Or monthNumberOrName = MonthName(11) Then 192 | DaysOfMonth = 30 193 | ElseIf monthNumberOrName = 12 Or monthNumberOrName = MonthName(12) Then 194 | DaysOfMonth = 31 195 | Else 196 | DaysOfMonth = "#NotAValidMonthNumberOrName" 197 | End If 198 | 199 | End Function 200 | 201 | 202 | Public Function WeekOfMonth( _ 203 | Optional ByVal date1 As Date) _ 204 | As Byte 205 | 206 | '@Description: This function takes a date and returns the number of the week of the month for that date. If no date is given, the current date is used. 207 | '@Author: Anthony Mancini 208 | '@Version: 1.0.0 209 | '@License: MIT 210 | '@Param: date1 is a date whose week number will be found 211 | '@Returns: Returns the number of week in the month 212 | '@Example: =WeekOfMonth() -> 5; Where the current date is 1/29/2020 213 | '@Example: =WeekOfMonth(1/29/2020) -> 5 214 | '@Example: =WeekOfMonth(1/28/2020) -> 5 215 | '@Example: =WeekOfMonth(1/27/2020) -> 5 216 | '@Example: =WeekOfMonth(1/26/2020) -> 5 217 | '@Example: =WeekOfMonth(1/25/2020) -> 4 218 | '@Example: =WeekOfMonth(1/24/2020) -> 4 219 | '@Example: =WeekOfMonth(1/1/2020) -> 1 220 | 221 | 222 | Dim weekNumber As Byte 223 | Dim currentDay As Byte 224 | Dim currentWeekday As Byte 225 | 226 | weekNumber = 1 227 | 228 | ' When year is 1899, no year was given as an input 229 | If Year(date1) = 1899 Then 230 | currentDay = Day(Now()) 231 | currentWeekday = Weekday(Now()) 232 | Else 233 | currentDay = Day(date1) 234 | currentWeekday = Weekday(date1) 235 | End If 236 | 237 | While currentDay <> 0 238 | If currentWeekday = 0 Then 239 | weekNumber = weekNumber + 1 240 | currentWeekday = 7 241 | End If 242 | 243 | currentDay = currentDay - 1 244 | currentWeekday = currentWeekday - 1 245 | Wend 246 | 247 | WeekOfMonth = weekNumber 248 | 249 | End Function 250 | -------------------------------------------------------------------------------- /Modules/xlibArray.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibArray" 2 | '@Module: This module contains a set of functions for manipulating and working with arrays. 3 | 4 | Option Explicit 5 | 6 | 7 | Public Function CountUnique( _ 8 | ParamArray array1() As Variant) _ 9 | As Integer 10 | 11 | '@Description: This function counts the number of unique occurances of values within a range or multiple ranges 12 | '@Author: Anthony Mancini 13 | '@Version: 1.0.0 14 | '@License: MIT 15 | '@Param: array1 is the group of cells we are counting the unique values of 16 | '@Returns: Returns the number of unique values 17 | '@Example: =CountUnique(1, 2, 2, 3) -> 3; 18 | '@Example: =CountUnique("a", "a", "a") -> 1; 19 | '@Example: =CountUnique(arr) -> 3; Where arr = [1, 2, 4, 4, 1] 20 | 21 | Dim individualElement As Variant 22 | Dim individualValue As Variant 23 | Dim uniqueDictionary As Object 24 | Dim uniqueCount As Integer 25 | 26 | Set uniqueDictionary = CreateObject("Scripting.Dictionary") 27 | 28 | For Each individualElement In array1 29 | If IsArray(individualElement) Then 30 | For Each individualValue In individualElement 31 | If Not uniqueDictionary.exists(individualValue) Then 32 | uniqueDictionary.Add individualValue, 0 33 | uniqueCount = uniqueCount + 1 34 | End If 35 | Next 36 | Else 37 | If Not uniqueDictionary.exists(individualElement) Then 38 | uniqueDictionary.Add individualElement, 0 39 | uniqueCount = uniqueCount + 1 40 | End If 41 | End If 42 | Next 43 | 44 | CountUnique = uniqueCount 45 | 46 | End Function 47 | 48 | 49 | Public Function Sort( _ 50 | ByVal sortableArray As Variant, _ 51 | Optional ByVal descendingFlag As Boolean) _ 52 | As Variant 53 | 54 | '@Description: This function is an implementation of Bubble Sort, allowing the user to sort an array, optionally allowing the user to specify the array to be sorted in descending order 55 | '@Author: Anthony Mancini 56 | '@Version: 1.0.0 57 | '@License: MIT 58 | '@Param: sortableArray is the array that will be sorted 59 | '@Param: descendingFlag changes the sort to descending 60 | '@Returns: Returns the a sorted array 61 | '@Example: =Sort({1,3,2}) -> {1,2,3} 62 | '@Example: =Sort({1,3,2}, True) -> {3,2,1} 63 | 64 | Dim i As Integer 65 | Dim swapOccuredBool As Boolean 66 | Dim arrayLength As Integer 67 | arrayLength = UBound(sortableArray) - LBound(sortableArray) + 1 68 | 69 | Dim sortedArray() As Variant 70 | ReDim sortedArray(arrayLength) 71 | 72 | For i = 0 To arrayLength - 1 73 | sortedArray(i) = sortableArray(i) 74 | Next 75 | 76 | Dim temporaryValue As Variant 77 | 78 | Do 79 | swapOccuredBool = False 80 | For i = 0 To arrayLength - 1 81 | If (sortedArray(i)) < sortedArray(i + 1) Then 82 | temporaryValue = sortedArray(i) 83 | sortedArray(i) = sortedArray(i + 1) 84 | sortedArray(i + 1) = temporaryValue 85 | swapOccuredBool = True 86 | End If 87 | Next 88 | Loop While swapOccuredBool 89 | 90 | If descendingFlag = True Then 91 | Sort = sortedArray 92 | Else 93 | Dim ascendingArray() As Variant 94 | ReDim ascendingArray(arrayLength) 95 | 96 | For i = 0 To arrayLength - 1 97 | ascendingArray(i) = sortedArray(arrayLength - i - 1) 98 | Next 99 | 100 | Sort = ascendingArray 101 | End If 102 | 103 | End Function 104 | 105 | 106 | Public Function Reverse( _ 107 | ByVal array1 As Variant) _ 108 | As Variant 109 | 110 | '@Description: This function takes an array and reverses all its elements 111 | '@Author: Anthony Mancini 112 | '@Version: 1.0.0 113 | '@License: MIT 114 | '@Param: array1 is the array that will be reversed 115 | '@Returns: Returns the a reversed array 116 | '@Example: =Reverse({1,2,3}) -> {3,2,1} 117 | 118 | Dim i As Integer 119 | Dim arrayLength As Integer 120 | Dim reversedArray() As Variant 121 | 122 | arrayLength = UBound(array1) - LBound(array1) 123 | ReDim reversedArray(arrayLength) 124 | 125 | For i = LBound(array1) To UBound(array1) 126 | reversedArray(arrayLength - i) = array1(i) 127 | Next 128 | 129 | Reverse = reversedArray 130 | 131 | End Function 132 | 133 | 134 | Public Function SumHigh( _ 135 | ByVal array1 As Variant, _ 136 | ByVal numberSummed As Integer) _ 137 | As Variant 138 | 139 | '@Description: This function returns the sum of the top values of the number specified in the second argument. For example, if the second argument is 3, only the top 3 values will be summed 140 | '@Author: Anthony Mancini 141 | '@Version: 1.0.0 142 | '@License: MIT 143 | '@Param: array1 is the range that will be summed 144 | '@Param: numberSummed is the number of the top values that will be summed 145 | '@Returns: Returns the sum of the top numbers specified 146 | '@Example: =SumHigh({1,2,3,4}, 2) -> 7; as 3 and 4 will be summed 147 | '@Example: =SumHigh({1,2,3,4}, 3) -> 9; as 2, 3, and 4 will be summed 148 | 149 | Dim i As Integer 150 | Dim sumValue As Double 151 | 152 | For i = 1 To numberSummed 153 | sumValue = sumValue + Large(array1, i) 154 | Next 155 | 156 | SumHigh = sumValue 157 | 158 | End Function 159 | 160 | 161 | Public Function SumLow( _ 162 | ByVal array1 As Variant, _ 163 | ByVal numberSummed As Integer) _ 164 | As Variant 165 | 166 | '@Description: This function returns the sum of the bottom values of the number specified in the second argument. For example, if the second argument is 3, only the bottom 3 values will be summed 167 | '@Author: Anthony Mancini 168 | '@Version: 1.0.0 169 | '@License: MIT 170 | '@Param: array1 is the range that will be summed 171 | '@Param: numberSummed is the number of the bottom values that will be summed 172 | '@Returns: Returns the sum of the bottom numbers specified 173 | '@Example: =SumLow({1,2,3,4}, 2) -> 3; as 1 and 2 will be summed 174 | '@Example: =SumLow({1,2,3,4}, 3) -> 6; as 1, 2, and 3 will be summed 175 | 176 | Dim i As Integer 177 | Dim sumValue As Double 178 | 179 | For i = 1 To numberSummed 180 | sumValue = sumValue + Small(array1, i) 181 | Next 182 | 183 | SumLow = sumValue 184 | 185 | End Function 186 | 187 | 188 | Public Function AverageHigh( _ 189 | ByVal array1 As Variant, _ 190 | ByVal numberAveraged As Integer) _ 191 | As Variant 192 | 193 | '@Description: This function returns the average of the top values of the number specified in the second argument. For example, if the second argument is 3, only the top 3 values will be averaged 194 | '@Author: Anthony Mancini 195 | '@Version: 1.0.0 196 | '@License: MIT 197 | '@Param: array1 is the range that will be averaged 198 | '@Param: numberAveraged is the number of the top values that will be averaged 199 | '@Returns: Returns the average of the top numbers specified 200 | '@Example: =AverageHigh({1,2,3,4}, 2) -> 3.5; as 3 and 4 will be averaged 201 | '@Example: =AverageHigh({1,2,3,4}, 3) -> 3; as 2, 3, and 4 will be averaged 202 | 203 | Dim i As Integer 204 | Dim sumValue As Double 205 | 206 | For i = 1 To numberAveraged 207 | sumValue = sumValue + Large(array1, i) 208 | Next 209 | 210 | AverageHigh = sumValue / numberAveraged 211 | 212 | End Function 213 | 214 | 215 | Public Function AverageLow( _ 216 | ByVal array1 As Variant, _ 217 | ByVal numberAveraged As Integer) _ 218 | As Variant 219 | 220 | '@Description: This function returns the average of the bottom values of the number specified in the second argument. For example, if the second argument is 3, only the bottom 3 values will be averaged 221 | '@Author: Anthony Mancini 222 | '@Version: 1.0.0 223 | '@License: MIT 224 | '@Param: array1 is the range that will be averaged 225 | '@Param: numberAveraged is the number of the bottom values that will be averaged 226 | '@Returns: Returns the average of the bottom numbers specified 227 | '@Example: =AverageLow({1,2,3,4}, 2) -> 1.5; as 1 and 2 will be averaged 228 | '@Example: =AverageLow({1,2,3,4}, 3) -> 2; as 1, 2, and 3 will be averaged 229 | 230 | Dim i As Integer 231 | Dim sumValue As Double 232 | 233 | For i = 1 To numberAveraged 234 | sumValue = sumValue + Small(array1, i) 235 | Next 236 | 237 | AverageLow = sumValue / numberAveraged 238 | 239 | End Function 240 | 241 | 242 | Public Function Large( _ 243 | ByVal array1 As Variant, _ 244 | ByVal nthNumber As Integer) _ 245 | As Variant 246 | 247 | '@Description: This function returns the nth highest number an in array, similar to Excel's LARGE function. 248 | '@Author: Anthony Mancini 249 | '@Version: 1.0.0 250 | '@License: MIT 251 | '@Param: array1 is the array that the number will be pulled from 252 | '@Param: nthNumber is the number of the top value that will be chosen. For example, a nthNumber of 1 results in the 1st highest value being chosen, when a number of 2 results in the 2nd, etc. 253 | '@Returns: Returns the nth highest number 254 | '@Example: =Large({1,2,3,4}, 1) -> 4 255 | '@Example: =Large({1,2,3,4}, 2) -> 3 256 | 257 | Large = Sort(array1)(UBound(array1) - (nthNumber - 1)) 258 | 259 | End Function 260 | 261 | 262 | Public Function Small( _ 263 | ByVal array1 As Variant, _ 264 | ByVal nthNumber As Integer) _ 265 | As Variant 266 | 267 | '@Description: This function returns the nth lowest number an in array, similar to Excel's SMALL function. 268 | '@Author: Anthony Mancini 269 | '@Version: 1.0.0 270 | '@License: MIT 271 | '@Param: array1 is the array that the number will be pulled from 272 | '@Param: nthNumber is the number of the bottom value that will be chosen. For example, a nthNumber of 1 results in the 1st smallest value being chosen, when a number of 2 results in the 2nd, etc. 273 | '@Returns: Returns the nth smallest number 274 | '@Example: =Small({1,2,3,4}, 1) -> 1 275 | '@Example: =Small({1,2,3,4}, 2) -> 2 276 | 277 | Small = Sort(array1, True)(UBound(array1) - (nthNumber - 1)) 278 | 279 | End Function 280 | 281 | Public Function IsInArray( _ 282 | ByVal value1 As Variant, _ 283 | ByVal array1 As Variant) _ 284 | As Boolean 285 | 286 | '@Description: This function checks if a value is in an array 287 | '@Author: Anthony Mancini 288 | '@Version: 1.0.0 289 | '@License: MIT 290 | '@Param: value1 is the value that will be checked if its in the array 291 | '@Param: array1 is the array 292 | '@Returns: Returns boolean True if the value is in the array, and false otherwise 293 | '@Example: =IsInArray("hello", {"one", 2, "hello"}) -> True 294 | '@Example: =IsInArray("hello", {1, "two", "three"}) -> False 295 | 296 | Dim individualElement As Variant 297 | 298 | For Each individualElement In array1 299 | If individualElement = value1 Then 300 | IsInArray = True 301 | Exit Function 302 | End If 303 | Next 304 | 305 | IsInArray = False 306 | 307 | End Function 308 | 309 | 310 | -------------------------------------------------------------------------------- /Modules/xlibValidators.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibValidators" 2 | '@Module: This module contains a set of functions for validating some commonly used string, such as validators for email addresses and phone numbers. 3 | 4 | Option Explicit 5 | 6 | 7 | Public Function IsEmail( _ 8 | ByVal string1 As String) _ 9 | As Boolean 10 | 11 | '@Description: This function checks if a string is a valid email address. 12 | '@Author: Anthony Mancini 13 | '@Version: 1.0.0 14 | '@License: MIT 15 | '@Todo: Improve regex robustness 16 | '@Param: string1 is the string we are checking if its a valid email 17 | '@Returns: Returns TRUE if the string is a valid email, and FALSE if its invalid 18 | '@Example: =IsEmail("JohnDoe@testmail.com") -> TRUE 19 | '@Example: =IsEmail("JohnDoe@test/mail.com") -> FALSE 20 | '@Example: =IsEmail("not_an_email_address") -> FALSE 21 | 22 | Dim Regex As Object 23 | Set Regex = CreateObject("VBScript.RegExp") 24 | 25 | With Regex 26 | .Global = True 27 | .IgnoreCase = True 28 | .MultiLine = True 29 | .Pattern = "^[a-zA-Z0-9_.]*?[@][a-zA-Z0-9.]*?[.][a-zA-Z]{2,15}$" 30 | End With 31 | 32 | IsEmail = Regex.Test(string1) 33 | 34 | End Function 35 | 36 | 37 | Public Function IsPhone( _ 38 | ByVal string1 As String) _ 39 | As Boolean 40 | 41 | '@Description: This function checks if a string is a phone number is valid. 42 | '@Author: Anthony Mancini 43 | '@Version: 1.0.0 44 | '@License: MIT 45 | '@Todo: Improve regex robustness 46 | '@Todo: Add a second argument that lets the user add a country code and uses a different regex for phone number formats for that country. Also make the regx more robust so it can include more common formats. 47 | '@Param: string1 is the string we are checking if its a valid phone number 48 | '@Returns: Returns TRUE if the string is a valid phone number, and FALSE if its invalid 49 | '@Example: =IsPhone("123 456 7890") -> TRUE 50 | '@Example: =IsPhone("1234567890") -> TRUE 51 | '@Example: =IsPhone("1-234-567-890") -> FALSE; Not enough digits 52 | '@Example: =IsPhone("1-234-567-8905") -> TRUE 53 | '@Example: =IsPhone("+1-234-567-890") -> FALSE; Not enough digits 54 | '@Example: =IsPhone("+1-234-567-8905") -> TRUE 55 | '@Example: =IsPhone("+1-(234)-567-8905") -> TRUE 56 | '@Example: =IsPhone("+1 (234) 567 8905") -> TRUE 57 | '@Example: =IsPhone("1(234)5678905") -> TRUE 58 | '@Example: =IsPhone("123-456-789") -> FALSE; Not enough digits 59 | '@Example: =IsPhone("Hello World") -> FALSE; Not a phone number 60 | 61 | Dim Regex As Object 62 | Set Regex = CreateObject("VBScript.RegExp") 63 | 64 | With Regex 65 | .Global = True 66 | .IgnoreCase = True 67 | .MultiLine = True 68 | .Pattern = "^\s*[+]{0,1}[0-9]{0,1}[\s-]{0,1}\({0,1}([0-9]{3})\){0,1}[\s-]{0,1}([0-9]{3})[\s-]{0,1}([0-9]{4})$" 69 | End With 70 | 71 | IsPhone = Regex.Test(string1) 72 | 73 | End Function 74 | 75 | 76 | Public Function IsCreditCard( _ 77 | ByVal string1 As String) _ 78 | As Boolean 79 | 80 | '@Description: This function checks if a string is a valid credit card from one of the major card issuing companies. 81 | '@Author: Anthony Mancini 82 | '@Version: 1.0.0 83 | '@License: MIT 84 | '@Param: string1 is the string we are checking if its a valid credit card number 85 | '@Returns: Returns TRUE if the string is a valid credit card number, and FALSE if its invalid. Currently supports these cards: Visa, MasterCard, Discover, Amex, Diners, JCB 86 | '@Example: =IsCreditCard("5111567856785678") -> TRUE; This is a valid Mastercard number 87 | '@Example: =IsCreditCard("511156785678567") -> FALSE; Not enough digits 88 | '@Example: =IsCreditCard("9999999999999999") -> FALSE; Enough digits, but not a valid card number 89 | '@Example: =IsCreditCard("Hello World") -> FALSE 90 | 91 | Dim Regex As Object 92 | Set Regex = CreateObject("VBScript.RegExp") 93 | 94 | Dim regexPattern As String 95 | 96 | ' Regex for Amex 97 | regexPattern = regexPattern & "(3[47][0-9]{13})|" 98 | 99 | ' Regex for Diners 100 | regexPattern = regexPattern & "(3(0[0-5]|[68][0-9])?[0-9]{11})|" 101 | 102 | ' Regex for Discover 103 | regexPattern = regexPattern & "(6(011|5[0-9]{2})[0-9]{12})|" 104 | 105 | ' Regex for JCB 106 | regexPattern = regexPattern & "((2131|1800|35[0-9]{3})[0-9]{11})|" 107 | 108 | ' Regex for MasterCard 109 | regexPattern = regexPattern & "(5[1-5][0-9]{14})|" 110 | 111 | ' Regex for Visa 112 | regexPattern = regexPattern & "(4[0-9]{12}([0-9]{3})?)" 113 | 114 | With Regex 115 | .Global = True 116 | .IgnoreCase = True 117 | .MultiLine = True 118 | .Pattern = regexPattern 119 | End With 120 | 121 | IsCreditCard = Regex.Test(string1) 122 | 123 | End Function 124 | 125 | 126 | Public Function IsUrl( _ 127 | ByVal string1 As String) _ 128 | As Boolean 129 | 130 | '@Description: This function checks if a string is a valid URL address. 131 | '@Author: Anthony Mancini 132 | '@Version: 1.0.0 133 | '@License: MIT 134 | '@Todo: Improve regex robustness 135 | '@Param: string1 is the string we are checking if its a valid URL 136 | '@Returns: Returns TRUE if the string is a valid URL, and FALSE if its invalid 137 | '@Example: =IsUrl("https://www.wikipedia.org/") -> TRUE 138 | '@Example: =IsUrl("http://www.wikipedia.org/") -> TRUE 139 | '@Example: =IsUrl("hello_world") -> FALSE 140 | 141 | Dim Regex As Object 142 | Set Regex = CreateObject("VBScript.RegExp") 143 | 144 | With Regex 145 | .Global = True 146 | .IgnoreCase = True 147 | .MultiLine = True 148 | .Pattern = "http(s){0,1}://www.[a-zA-Z0-9_.]*?[.][a-zA-Z]{2,15}" 149 | End With 150 | 151 | IsUrl = Regex.Test(string1) 152 | 153 | End Function 154 | 155 | 156 | Public Function IsIPFour( _ 157 | ByVal string1 As String) _ 158 | As Boolean 159 | 160 | '@Description: This function checks if a string is a valid IPv4 address. 161 | '@Author: Anthony Mancini 162 | '@Version: 1.0.0 163 | '@License: MIT 164 | '@Todo: Improve regex robustness 165 | '@Param: string1 is the string we are checking if its a valid IPv4 address 166 | '@Returns: Returns TRUE if the string is a valid IPv4, and FALSE if its invalid 167 | '@Example: =IsIPFour("0.0.0.0") -> TRUE 168 | '@Example: =IsIPFour("100.100.100.100") -> TRUE 169 | '@Example: =IsIPFour("255.255.255.255") -> TRUE 170 | '@Example: =IsIPFour("255.255.255.256") -> FALSE; as the final 256 makes the address outside of the bounds of IPv4 171 | '@Example: =IsIPFour("0.0.0") -> FALSE; as the fourth octet is missing 172 | 173 | Dim Regex As Object 174 | Set Regex = CreateObject("VBScript.RegExp") 175 | 176 | With Regex 177 | .Global = True 178 | .IgnoreCase = True 179 | .MultiLine = True 180 | .Pattern = "^((2[0-4]\d|25[0-5]|1\d\d|\d{1,2})[.]){3}(2[0-4]\d|25[0-5]|1\d\d|\d{1,2})$" 181 | End With 182 | 183 | IsIPFour = Regex.Test(string1) 184 | 185 | End Function 186 | 187 | 188 | Public Function IsMacAddress( _ 189 | ByVal string1 As String) _ 190 | As Boolean 191 | 192 | '@Description: This function checks if a string is a valid 48-bit Mac Address. 193 | '@Author: Anthony Mancini 194 | '@Version: 1.0.0 195 | '@License: MIT 196 | '@Param: string1 is the string we are checking if its a valid 48-bit Mac Address 197 | '@Returns: Returns TRUE if the string is a valid 48-bit Mac Address, and FALSE if its invalid 198 | '@Example: =IsMacAddress("00:25:96:12:34:56") -> TRUE 199 | '@Example: =IsMacAddress("FF:FF:FF:FF:FF:FF") -> TRUE 200 | '@Example: =IsMacAddress("00-25-96-12-34-56") -> TRUE 201 | '@Example: =IsMacAddress("123.789.abc.DEF") -> TRUE 202 | '@Example: =IsMacAddress("Not A Mac Address") -> FALSE 203 | '@Example: =IsMacAddress("FF:FF:FF:FF:FF:FH") -> FALSE; the H at the end is not a valid Hex number 204 | 205 | Dim Regex As Object 206 | Set Regex = CreateObject("VBScript.RegExp") 207 | 208 | With Regex 209 | .Global = True 210 | .IgnoreCase = True 211 | .MultiLine = True 212 | .Pattern = "^(([a-fA-F0-9]{2}([:]|[-])){5}[a-fA-F0-9]{2}|([a-fA-F0-9]{3}[.]){3}[a-fA-F0-9]{3})$" 213 | End With 214 | 215 | IsMacAddress = Regex.Test(string1) 216 | 217 | End Function 218 | 219 | 220 | Public Function CreditCardName( _ 221 | ByVal string1 As String) _ 222 | As String 223 | 224 | '@Description: This function checks if a string is a valid credit card from one of the major card issuing companies, and then returns the name of the credit card name. This function assumes no spaces or hyphens (if you have card numbers with spaces or hyphens you can remove these using =SUBSTITUTE("-", "") function. 225 | '@Author: Anthony Mancini 226 | '@Version: 1.0.0 227 | '@License: MIT 228 | '@Param: string1 is the credit card string 229 | '@Returns: Returns the name of the credit card. Currently supports these cards: Visa, MasterCard, Discover, Amex, Diners, JCB 230 | '@Example: =CreditCardName("5111567856785678") -> "MasterCard"; This is a valid Mastercard number 231 | '@Example: =CreditCardName("not_a_card_number") -> #VALUE! 232 | 233 | Dim Regex As Object 234 | Set Regex = CreateObject("VBScript.RegExp") 235 | 236 | Regex.Global = True 237 | Regex.IgnoreCase = True 238 | Regex.MultiLine = True 239 | 240 | ' Regex for Amex 241 | Regex.Pattern = "(3[47][0-9]{13})" 242 | If Regex.Test(string1) Then 243 | CreditCardName = "Amex" 244 | Exit Function 245 | End If 246 | 247 | ' Regex for Diners 248 | Regex.Pattern = "(3(0[0-5]|[68][0-9])?[0-9]{11})" 249 | If Regex.Test(string1) Then 250 | CreditCardName = "Diners" 251 | Exit Function 252 | End If 253 | 254 | ' Regex for Discover 255 | Regex.Pattern = "(6(011|5[0-9]{2})[0-9]{12})" 256 | If Regex.Test(string1) Then 257 | CreditCardName = "Discover" 258 | Exit Function 259 | End If 260 | 261 | ' Regex for JCB 262 | Regex.Pattern = "((2131|1800|35[0-9]{3})[0-9]{11})" 263 | If Regex.Test(string1) Then 264 | CreditCardName = "JCB" 265 | Exit Function 266 | End If 267 | 268 | ' Regex for MasterCard 269 | Regex.Pattern = "(5[1-5][0-9]{14})" 270 | If Regex.Test(string1) Then 271 | CreditCardName = "MasterCard" 272 | Exit Function 273 | End If 274 | 275 | ' Regex for Visa 276 | Regex.Pattern = "(4[0-9]{12}([0-9]{3})?)" 277 | If Regex.Test(string1) Then 278 | CreditCardName = "Visa" 279 | Exit Function 280 | End If 281 | 282 | CreditCardName = "#NotAValidCreditCardNumber!" 283 | 284 | End Function 285 | 286 | 287 | Public Function FormatCreditCard( _ 288 | ByVal string1 As String) _ 289 | As String 290 | 291 | '@Description: This function checks if a string is a valid credit card, and if it is formats it in a more readable way. The format used is XXXX-XXXX-XXXX-XXXX. 292 | '@Author: Anthony Mancini 293 | '@Version: 1.0.0 294 | '@License: MIT 295 | '@Param: string1 is credit card number 296 | '@Returns: Returns a string formatted as a more readable credit card number 297 | '@Example: =FormatCreditCard("5111567856785678") -> "5111-5678-5678-5678" 298 | 299 | If IsCreditCard(string1) Then 300 | FormatCreditCard = Left(string1, 4) & "-" & Mid(string1, 5, 4) & "-" & Mid(string1, 9, 4) & "-" & Mid(string1, 13) 301 | Else 302 | FormatCreditCard = "#NotAValidCreditCardNumber!" 303 | End If 304 | 305 | End Function 306 | -------------------------------------------------------------------------------- /Modules/xlibFileTests.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibFileTests" 2 | Option Explicit 3 | 4 | Public Function AllXlibFileTests() 5 | 6 | Dim TestStatus As Boolean 7 | TestStatus = True 8 | 9 | Debug.Print "========================================" 10 | 11 | ' Begin Tests 12 | If Not GetActivePathAndNameTest() Then 13 | Debug.Print "Failed: GetActivePathAndNameTest" 14 | TestStatus = False 15 | Else 16 | Debug.Print "Passed: GetActivePathAndNameTest" 17 | End If 18 | 19 | If Not GetActivePathTest() Then 20 | Debug.Print "Failed: GetActivePathTest" 21 | TestStatus = False 22 | Else 23 | Debug.Print "Passed: GetActivePathTest" 24 | End If 25 | 26 | If Not FileCreationTimeTest() Then 27 | Debug.Print "Failed: FileCreationTimeTest" 28 | TestStatus = False 29 | Else 30 | Debug.Print "Passed: FileCreationTimeTest" 31 | End If 32 | 33 | If Not FileLastModifiedTimeTest() Then 34 | Debug.Print "Failed: FileLastModifiedTimeTest" 35 | TestStatus = False 36 | Else 37 | Debug.Print "Passed: FileLastModifiedTimeTest" 38 | End If 39 | 40 | If Not FileDriveTest() Then 41 | Debug.Print "Failed: FileDriveTest" 42 | TestStatus = False 43 | Else 44 | Debug.Print "Passed: FileDriveTest" 45 | End If 46 | 47 | If Not FileNameTest() Then 48 | Debug.Print "Failed: FileNameTest" 49 | TestStatus = False 50 | Else 51 | Debug.Print "Passed: FileNameTest" 52 | End If 53 | 54 | If Not FileFolderTest() Then 55 | Debug.Print "Failed: FileFolderTest" 56 | TestStatus = False 57 | Else 58 | Debug.Print "Passed: FileFolderTest" 59 | End If 60 | 61 | If Not CurrentFilePathTest() Then 62 | Debug.Print "Failed: CurrentFilePathTest" 63 | TestStatus = False 64 | Else 65 | Debug.Print "Passed: CurrentFilePathTest" 66 | End If 67 | 68 | If Not FileSizeTest() Then 69 | Debug.Print "Failed: FileSizeTest" 70 | TestStatus = False 71 | Else 72 | Debug.Print "Passed: FileSizeTest" 73 | End If 74 | 75 | If Not FileTypeTest() Then 76 | Debug.Print "Failed: FileTypeTest" 77 | TestStatus = False 78 | Else 79 | Debug.Print "Passed: FileTypeTest" 80 | End If 81 | 82 | If Not FileExtensionTest() Then 83 | Debug.Print "Failed: FileExtensionTest" 84 | TestStatus = False 85 | Else 86 | Debug.Print "Passed: FileExtensionTest" 87 | End If 88 | 89 | If Not WriteFileTest() Then 90 | Debug.Print "Failed: WriteFileTest" 91 | TestStatus = False 92 | Else 93 | Debug.Print "Passed: WriteFileTest" 94 | End If 95 | 96 | If Not ReadFileTest() Then 97 | Debug.Print "Failed: ReadFileTest" 98 | TestStatus = False 99 | Else 100 | Debug.Print "Passed: ReadFileTest" 101 | End If 102 | 103 | If Not PathSeparatorTest() Then 104 | Debug.Print "Failed: PathSeparatorTest" 105 | TestStatus = False 106 | Else 107 | Debug.Print "Passed: PathSeparatorTest" 108 | End If 109 | 110 | If Not PathJoinTest() Then 111 | Debug.Print "Failed: PathJoinTest" 112 | TestStatus = False 113 | Else 114 | Debug.Print "Passed: PathJoinTest" 115 | End If 116 | 117 | If Not CountFilesTest() Then 118 | Debug.Print "Failed: CountFilesTest" 119 | TestStatus = False 120 | Else 121 | Debug.Print "Passed: CountFilesTest" 122 | End If 123 | 124 | If Not CountFilesAndFoldersTest() Then 125 | Debug.Print "Failed: CountFilesAndFoldersTest" 126 | TestStatus = False 127 | Else 128 | Debug.Print "Passed: CountFilesAndFoldersTest" 129 | End If 130 | 131 | If Not GetFileNameByNumberTest() Then 132 | Debug.Print "Failed: GetFileNameByNumberTest" 133 | TestStatus = False 134 | Else 135 | Debug.Print "Passed: GetFileNameByNumberTest" 136 | End If 137 | ' End Tests 138 | 139 | Debug.Print "----------------------------------------" 140 | 141 | If TestStatus Then 142 | Debug.Print "Passed All Tests" 143 | Else 144 | Debug.Print "!!! FAILED TESTS !!!" 145 | End If 146 | 147 | Debug.Print "========================================" 148 | 149 | AllXlibFileTests = TestStatus 150 | 151 | End Function 152 | 153 | 154 | 155 | Private Function GetActivePathAndNameTest() As Boolean 156 | 157 | '@Example: =GetActivePathAndName() -> "C:\Users\UserName\Documents\XLib.xlsm" 158 | 159 | GetActivePathAndNameTest = True 160 | 161 | If InStr(1, GetActivePathAndName(), ".") > 0 Then 162 | #If Mac Then 163 | If InStr(1, GetActivePathAndName(), "/") > 0 Then 164 | GetActivePathAndNameTest = True 165 | Else 166 | GetActivePathAndNameTest = False 167 | End If 168 | #Else 169 | If InStr(1, GetActivePathAndName(), ":\") > 0 Then 170 | GetActivePathAndNameTest = True 171 | Else 172 | GetActivePathAndNameTest = False 173 | End If 174 | #End If 175 | End If 176 | 177 | End Function 178 | 179 | 180 | Private Function GetActivePathTest() As Boolean 181 | 182 | '@Example: =GetActivePath() -> "C:\Users\UserName\Documents\" 183 | 184 | GetActivePathTest = True 185 | 186 | #If Mac Then 187 | If InStr(1, GetActivePath(), "/") > 0 Then 188 | GetActivePathTest = True 189 | Else 190 | GetActivePathTest = False 191 | End If 192 | #Else 193 | If InStr(1, GetActivePath(), ":\") > 0 Then 194 | GetActivePathTest = True 195 | Else 196 | GetActivePathTest = False 197 | End If 198 | #End If 199 | 200 | End Function 201 | 202 | 203 | Private Function FileCreationTimeTest() As Boolean 204 | 205 | '@Example: =FileCreationTime() -> "1/1/2020 1:23:45 PM" 206 | '@Example: =FileCreationTime("C:\hello\world.txt") -> "1/1/2020 5:55:55 PM" 207 | '@Example: =FileCreationTime("vba.txt") -> "12/25/2000 1:00:00 PM"; Where "vba.txt" resides in the same folder as the workbook, document, presentation, or database this function resides in 208 | 209 | FileCreationTimeTest = False 210 | 211 | If InStr(1, FileCreationTime(), " ") > 0 Then 212 | If InStr(1, FileCreationTime(), ":") > 0 Then 213 | FileCreationTimeTest = True 214 | End If 215 | End If 216 | 217 | End Function 218 | 219 | 220 | Private Function FileLastModifiedTimeTest() As Boolean 221 | 222 | '@Example: =FileLastModifiedTime() -> "1/1/2020 2:23:45 PM" 223 | '@Example: =FileLastModifiedTime("C:\hello\world.txt") -> "1/1/2020 7:55:55 PM" 224 | '@Example: =FileLastModifiedTime("vba.txt") -> "12/25/2000 3:00:00 PM"; Where "vba.txt" resides in the same folder as the workbook, document, presentation, or database this function resides in 225 | 226 | FileLastModifiedTimeTest = False 227 | 228 | If InStr(1, FileLastModifiedTime(), " ") > 0 Then 229 | If InStr(1, FileLastModifiedTime(), ":") > 0 Then 230 | FileLastModifiedTimeTest = True 231 | End If 232 | End If 233 | 234 | End Function 235 | 236 | 237 | Private Function FileDriveTest() As Boolean 238 | 239 | '@Example: =FileDrive() -> "A:"; Where the current workbook resides on the A: drive 240 | '@Example: =FileDrive("C:\hello\world.txt") -> "C:" 241 | '@Example: =FileDrive("vba.txt") -> "B:"; Where "vba.txt" resides in the same folder as the workbook, document, presentation, or database this function resides in, and where the workbook resides in the B: drive 242 | 243 | If InStr(1, FileDrive(), ":") > 0 Then 244 | FileDriveTest = True 245 | End If 246 | 247 | End Function 248 | 249 | 250 | Private Function FileNameTest() As Boolean 251 | 252 | '@Example: =FileName() -> "MyWorkbook.xlsm" 253 | '@Example: =FileName("C:\hello\world.txt") -> "world.txt" 254 | '@Example: =FileName("vba.txt") -> "vba.txt"; Where "vba.txt" resides in the same folder as the workbook, document, presentation, or database this function resides in 255 | 256 | If Len(FileName()) > 0 Then 257 | FileNameTest = True 258 | End If 259 | 260 | End Function 261 | 262 | 263 | Private Function FileFolderTest() As Boolean 264 | 265 | '@Example: =FileFolder() -> "C:\my_excel_files" 266 | '@Example: =FileFolder("C:\hello\world.txt") -> "C:\hello" 267 | '@Example: =FileFolder("vba.txt") -> "C:\my_excel_files"; Where "vba.txt" resides in the same folder as the workbook, document, presentation, or database this function resides in 268 | 269 | #If Mac Then 270 | If InStr(1, FileFolder(), "/") > 0 Then 271 | FileFolderTest = True 272 | End If 273 | #Else 274 | If InStr(1, FileFolder(), ":\") > 0 Then 275 | FileFolderTest = True 276 | End If 277 | #End If 278 | 279 | End Function 280 | 281 | 282 | Private Function CurrentFilePathTest() As Boolean 283 | 284 | '@Example: =CurrentFilePath() -> "C:\my_excel_files\MyWorkbook.xlsx" 285 | '@Example: =CurrentFilePath("C:\hello\world.txt") -> "C:\hello\world.txt" 286 | '@Example: =CurrentFilePath("vba.txt") -> "C:\hello\world.txt"; Where "vba.txt" resides in the same folder as the workbook, document, presentation, or database this function resides in 287 | 288 | #If Mac Then 289 | If InStr(1, CurrentFilePath(), "/") > 0 Then 290 | CurrentFilePathTest = True 291 | End If 292 | #Else 293 | If InStr(1, CurrentFilePath(), ":\") > 0 Then 294 | CurrentFilePathTest = True 295 | End If 296 | #End If 297 | 298 | End Function 299 | 300 | 301 | Private Function FileSizeTest() As Boolean 302 | 303 | '@Example: =FileSize() -> 1024 304 | '@Example: =FileSize(,"KB") -> 1 305 | '@Example: =FileSize("vba.txt", "KB") -> 0.25; Where "vba.txt" resides in the same folder as the workbook, document, presentation, or database this function resides in 306 | 307 | If FileSize() > 0 Then 308 | FileSizeTest = True 309 | End If 310 | 311 | End Function 312 | 313 | 314 | Private Function FileTypeTest() As Boolean 315 | 316 | '@Example: FileType() -> "Microsoft Excel Macro-Enabled Worksheet" 317 | '@Example: FileType("C:\hello\world.txt") -> "Text Document" 318 | '@Example: FileType("vba.txt") -> "Text Document"; Where "vba.txt" resides in the same folder as the workbook, document, presentation, or database this function resides in 319 | 320 | If Len(FileType()) > 0 Then 321 | FileTypeTest = True 322 | End If 323 | 324 | End Function 325 | 326 | 327 | Private Function FileExtensionTest() As Boolean 328 | 329 | '@Example: =FileExtension() = "xlsx" 330 | '@Example: =FileExtension("C:\hello\world.txt") -> "txt" 331 | '@Example: =FileExtension("vba.txt") -> "txt"; Where "vba.txt" resides in the same folder as the workbook, document, presentation, or database this function resides in 332 | 333 | If Len(FileExtension()) > 0 Then 334 | FileExtensionTest = True 335 | End If 336 | 337 | End Function 338 | 339 | 340 | Private Function WriteFileTest() As Boolean 341 | 342 | '@Example: =WriteFile("C:\MyWorkbookFolder\hello.txt", "Hello World") -> "Successfully wrote to: C:\MyWorkbookFolder\hello.txt" 343 | '@Example: =WriteFile("hello.txt", "Hello World") -> "Successfully wrote to: C:\MyWorkbookFolder\hello.txt"; Where the Workbook resides in "C:\MyWorkbookFolder\" 344 | 345 | If WriteFile("TempTestFile.txt", "Hello World") Then 346 | WriteFileTest = True 347 | End If 348 | 349 | End Function 350 | 351 | 352 | Private Function ReadFileTest() As Boolean 353 | 354 | '@Example: =ReadFile("C:\hello\world.txt") -> "Hello" World 355 | '@Example: =ReadFile("vba.txt") -> "This is my VBA text file"; Where "vba.txt" resides in the same folder as the workbook, document, presentation, or database this function resides in 356 | '@Example: =ReadFile("multline.txt", 1) -> "This is line 1"; 357 | '@Example: =ReadFile("multline.txt", 2) -> "This is line 2"; 358 | 359 | ReadFileTest = IIf(ReadFile("TempTestFile.txt") = "Hello World", True, False) 360 | Kill (GetActivePath() & "TempTestFile.txt") 361 | 362 | End Function 363 | 364 | 365 | Private Function PathSeparatorTest() As Boolean 366 | 367 | '@Example: =PathSeparator() -> "\"; When running this code on Windows 368 | '@Example: =PathSeparator() -> "/"; When running this code on Mac 369 | 370 | If PathSeparator() = "\" Or PathSeparator() = "/" Then 371 | PathSeparatorTest = True 372 | End If 373 | 374 | End Function 375 | 376 | 377 | Private Function PathJoinTest() As Boolean 378 | 379 | '@Example: =PathJoin("C:", "hello", "world.txt") -> "C:\hello\world.txt"; On Windows 380 | '@Example: =PathJoin("hello", "world.txt") -> "/hello/world.txt"; On Mac 381 | 382 | If PathJoin("hello", "world") = "hello/world" Or PathJoin("hello", "world") = "hello\world" Then 383 | PathJoinTest = True 384 | End If 385 | 386 | End Function 387 | 388 | 389 | Private Function CountFilesTest() As Boolean 390 | 391 | '@Example: =CountFiles() -> 6 392 | '@Example: =CountFiles("C:\hello") -> 10 393 | 394 | If CountFiles() > 0 Then 395 | CountFilesTest = True 396 | End If 397 | 398 | End Function 399 | 400 | 401 | Private Function CountFilesAndFoldersTest() As Boolean 402 | 403 | '@Example: =CountFilesAndFolders() -> 8 404 | '@Example: =CountFilesAndFolders("C:\hello") -> 30 405 | 406 | If CountFilesAndFolders() > 0 Then 407 | CountFilesAndFoldersTest = True 408 | End If 409 | 410 | End Function 411 | 412 | 413 | Private Function GetFileNameByNumberTest() As Boolean 414 | 415 | '@Example: =GetFileName(,1) -> "hello.txt" 416 | '@Example: =GetFileName(,1) -> "world.txt" 417 | '@Example: =GetFileName("C:\hello", 1) -> "one.txt" 418 | '@Example: =GetFileName("C:\hello", 1) -> "two.txt" 419 | '@Example: =GetFileName("C:\hello", 1) -> "three.txt" 420 | 421 | If Len(GetFileNameByNumber()) > 0 Then 422 | GetFileNameByNumberTest = True 423 | End If 424 | 425 | End Function 426 | 427 | 428 | -------------------------------------------------------------------------------- /Modules/xlibNetwork.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibNetwork" 2 | '@Module: This module contains a set of functions for performing networking tasks such as performing HTTP requests and parsing HTML. 3 | 4 | Option Explicit 5 | 6 | 7 | Public Function Http( _ 8 | ByVal url As String, _ 9 | Optional ByVal httpMethod As String = "GET", _ 10 | Optional ByVal headers As Variant, _ 11 | Optional ByVal postData As Variant = "", _ 12 | Optional ByVal asyncFlag As Boolean, _ 13 | Optional ByVal statusErrorHandlerFlag As Boolean, _ 14 | Optional ByVal parseArguments As Variant) _ 15 | As String 16 | 17 | '@Description: This function performs an HTTP request to the web and returns the response as a string. It provides many options to change the http method, provide data for a POST request, change the headers, handle errors for non-successful requests, and parse out text from a request using a light parsing language. 18 | '@Author: Anthony Mancini 19 | '@Version: 1.0.0 20 | '@License: MIT 21 | '@Param: url is a string of the URL of the website you want to fetch data from 22 | '@Param: httpMethod is a string with the http method, with the default being a GET request. For POST requests, use "POST", for PUT use "PUT", and for DELETE use "DELETE" 23 | '@Param: headers is either an array or a Scripting Dictionary of headers that will be used in the request. For an array, the 1st, 3rd, 5th... will be used as the key and the 2nd, 4th, 6th... will be used as the values. For a Scripting Dictionary, the dictionary keys will be used as header keys, and the values as values. Finally, in the case when no headers are set, the User-Agent will be set to "XPlus" as a courtesy to the web server. 24 | '@Param: postData is a string that will contain data for a POST request 25 | '@Param: asyncFlag is a Boolean value that if set to TRUE will make the request asynchronous. By default requests will be synchronous, which will lock Excel while fetching but will also prevent errors when performing calculations based on fetched data. 26 | '@Param: statusErrorHandlerFlag is a Boolean value that if set to TRUE will result in a User-Defined Error String being returned for all non 200 requests that tells the user the status code that occured. This flag is useful in cases where requests need to be successful and if not errors should be thrown. 27 | '@Param: parseArguments is an array of arguments that perform string parsing on the response. It uses a light scripting language that includes commands similar to the Excel Built-in LEFT(), RIGHT(), and MID() that allow you to parse the request before it gets returned. See the Note on the scripting language, and the Warning on why this argument should be used. 28 | '@Returns: Returns the parsed HTTP response as a string 29 | '@Note: The parseArguments parameter uses a light scripting language to perform string manipulations on the HTTP response text that allows you to parse out the relevant information to you. The language contains 5 commands that can be used for parsing. Please check out the examples as well below for a better understanding of how to use the parsing language:

{"ID", "idOfAnElement"} -> HTML inside of the element with the specified ID
{"TAG", "div", 2} -> HTML inside of the second div tag found
{"LEFT", 100} -> The 100 leftmost characters
{"LEFT", "Hello World"} -> All characters left of the first "Hello World" found in the HTML
{"RIGHT", 100} -> The 100 rightmost characters
{"RIGHT", "Hello World"} -> All characters right of the last "Hello World" found in the HTML
{"MID", 100} -> All character to the right of the 100th character in the string
{"MID", "Hello World"} -> All characters right of the first "Hello World" found in the HTML 30 | '@Warning: Excel has a limit on the number of characters that can be placed within a cell. This limit is a max of 32767 characters. If the request returns any more than this, a #VALUE! error will be returned. Most webpages surpass this number of characters, which makes the Excel Built-in function WEBSERVICE() not very useful. However, internally VBA can handle around 2,000,000,000 characters, which more characters that found on virtually every single webpage. As a result, parsing arguments should be used with this function so that you can parse out the relevant information for a request without this function failing. See the Note on the syntax of the light parsing language. 31 | '@Example: =Http("https://httpbin.org/uuid") -> "{"uuid: "41416bcf-ef11-4256-9490-63853d14e4e8"}" 32 | '@Example: =Http("https://httpbin.org/user-agent", "GET", {"User-Agent","MicrosoftExcel"}) -> "{"user-agent": "MicrosoftExcel"}" 33 | '@Example: =Http("https://httpbin.org/status/404",,,,,TRUE) -> "#RequestFailedStatusCode404!"; Since the status error handler flag is set and since this URL returns a 404 status code. Also note that this formula is easier to construct using the Excel Formula Builder 34 | '@Example: =Http("https://en.wikipedia.org/wiki/Visual_Basic_for_Applications",,{"User-Agent","MicrosoftExcel"},,,,{"ID","mw-content-text","LEFT",3000}) -> Returning a string with the leftmost 3000 characters found within the element with the ID "mw-content-text" (we are trying to get the release date of VBA from the VBA wikipedia page, but we need to do more parsing first) 35 | '@Example: =Http("https://en.wikipedia.org/wiki/Visual_Basic_for_Applications",,{"User-Agent","MicrosoftExcel"},,,,{"ID","mw-content-text","LEFT",3000,"MID","appeared"}) -> Returns the prior string, but now with all characters right of the first occurance of the word "appeared" in the HTML (getting closer to parsing the VBA creation date) 36 | '@Example: =Http("https://en.wikipedia.org/wiki/Visual_Basic_for_Applications",,{"User-Agent","MicrosoftExcel"},,,,{"ID","mw-content-text","LEFT",3000,"MID","appeared","MID",""}) -> From the prior result, now returning everything after the first occurance of the "" in the prior string 37 | '@Example: =Http("https://en.wikipedia.org/wiki/Visual_Basic_for_Applications",,{"User-Agent","MicrosoftExcel"},,,,{"ID","mw-content-text","LEFT",3000,"MID","appeared","MID","","LEFT"," "1993"; Finally this is all the parsing needed to be able to return the date 1993 that we were looking for 38 | 39 | Dim WinHttpRequest As Object 40 | Set WinHttpRequest = CreateObject("WinHttp.WinHttpRequest.5.1") 41 | 42 | WinHttpRequest.Open httpMethod, url, asyncFlag 43 | 44 | ' Setting the request headers 45 | ' Case where headers come in the form of an Array 46 | If IsArray(headers) Then 47 | Dim i As Integer 48 | 49 | For i = 0 To UBound(headers) - LBound(headers) Step 2 50 | WinHttpRequest.SetRequestHeader headers(i), headers(i + 1) 51 | Next 52 | 53 | ' Case where headers come in the form of a Dictionary 54 | ElseIf TypeName(headers) = "Dictionary" Then 55 | Dim dictKey As Variant 56 | 57 | For Each dictKey In headers.Keys() 58 | WinHttpRequest.SetRequestHeader dictKey, headers(dictKey) 59 | Next 60 | 61 | ' In cases where no headers are given by the user, set a base User-Agent to 62 | ' "XPlus" as a courtesy to the webserver 63 | Else 64 | WinHttpRequest.SetRequestHeader "User-Agent", "XLib" 65 | End If 66 | 67 | ' Sending the HTTP request 68 | If postData = "" Then 69 | WinHttpRequest.Send 70 | Else 71 | WinHttpRequest.Send postData 72 | End If 73 | 74 | ' If the status error handler flag is set to True, then enable error returns 75 | ' in cases where the status code is not a 200 76 | If statusErrorHandlerFlag Then 77 | If WinHttpRequest.Status = 200 Then 78 | Http = WinHttpRequest.ResponseText 79 | Else 80 | Http = "#RequestFailedStatusCode" & WinHttpRequest.Status & "!" 81 | End If 82 | 83 | ' Case when the status code error handler is not used 84 | Else 85 | Http = WinHttpRequest.ResponseText 86 | End If 87 | 88 | ' Parsing Html Response 89 | If IsArray(parseArguments) Then 90 | Dim reorderedParseArguments() As Variant 91 | i = UBound(parseArguments) - LBound(parseArguments) 92 | ReDim reorderedParseArguments(i) 93 | 94 | ' Reordering here, as possibly had some name collision with the name parseArguments somewhere 95 | 96 | For i = 0 To UBound(parseArguments) - LBound(parseArguments) 97 | reorderedParseArguments(i) = parseArguments(i) 98 | Next 99 | 100 | Http = ParseHtmlString(Http, reorderedParseArguments) 101 | 102 | End If 103 | 104 | End Function 105 | 106 | 107 | Public Function SimpleHttp( _ 108 | ByVal url As String, _ 109 | ParamArray parseArguments() As Variant) _ 110 | As String 111 | 112 | '@Description: This function performs an HTTP request to the web and returns the response as a string, similar to the HTTP() function, except that only requires one parameter, the URL, and then takes an infinite number of strings after it as the parsing arguments instead of requiring an Array to use. Essentially, this function is a little cleaner to set up when performing very basic GET requests. 113 | '@Author: Anthony Mancini 114 | '@Version: 1.0.0 115 | '@License: MIT 116 | '@Param: url is a string of the URL of the website you want to fetch data from 117 | '@Param: parseArguments is an array of arguments that perform string parsing on the response. It uses a light scripting language that includes commands similar to the Excel Built-in LEFT(), RIGHT(), and MID() that allow you to parse the request before it gets returned. See the Note on the HTTP() function, and the Warning on the HTTP() function on why this argument should be used. 118 | '@Returns: Returns the parsed HTTP response as a string 119 | '@Example: =SimpleHttp("https://en.wikipedia.org/wiki/Visual_Basic_for_Applications","ID","mw-content-text","LEFT",3000,"MID","appeared","MID","","LEFT"," "1993"; See the examples in the HTTP() function, as this example has the same result as the example in the HTTP() function. You can see that this function is cleaner and easier to set up than the corresponding HTTP() function. 120 | 121 | ' Case where parse arguments are provided 122 | If UBound(parseArguments) > 0 Then 123 | ' Need to reorder the arguments of the Array since when the caller is a 124 | ' Range, the Array is 1-based, where as when the caller is another VBA function, 125 | ' the Array is 0-based 126 | Dim i As Integer 127 | Dim reorderedParseArguments() As Variant 128 | i = UBound(parseArguments) - LBound(parseArguments) 129 | ReDim reorderedParseArguments(i) 130 | 131 | ' Reordering for Range 132 | For i = 0 To UBound(parseArguments) - LBound(parseArguments) 133 | reorderedParseArguments(i) = parseArguments(i) 134 | Next 135 | 136 | SimpleHttp = ParseHtmlString(Http(url), reorderedParseArguments) 137 | 138 | ' In case of no parse arguments, simply perform an HTTP request 139 | Else 140 | SimpleHttp = Http(url) 141 | End If 142 | 143 | End Function 144 | 145 | 146 | Public Function ParseHtmlString( _ 147 | ByVal htmlString As String, _ 148 | ByVal parseArguments As Variant) _ 149 | As Variant 150 | 151 | '@Description: This function parses an HTML string using the same parsing language that the HTTP() function uses. See the HTTP() function for more information on how to use this function. 152 | '@Author: Anthony Mancini 153 | '@Version: 1.0.0 154 | '@License: MIT 155 | '@Param: htmlString is a string of the HTML 156 | '@Param: parseArguments is an array of arguments that perform string parsing on the response. It uses a light scripting language that includes commands similar to the Excel Built-in LEFT(), RIGHT(), and MID() that allow you to parse the request before it gets returned. See the Note on the HTTP() function, and the Warning on the HTTP() function on why this argument should be used. 157 | '@Returns: Returns the parsed HTTP response as a string 158 | '@Example: =ParseHtmlString("HTML String from the webpage: https://en.wikipedia.org/wiki/Visual_Basic_for_Applications","ID","mw-content-text","LEFT",3000,"MID","appeared","MID","","LEFT"," "1993" 159 | 160 | Dim partialHtml As String 161 | Dim html As Object 162 | Set html = CreateObject("HtmlFile") 163 | 164 | ' Setting the HTML Document 165 | html.body.innerHTML = htmlString 166 | 167 | ' Parsing out info from the HTML Document 168 | Dim i As Integer 169 | 170 | For i = LBound(parseArguments) To UBound(parseArguments) 171 | ' Note that id and tag will truncate poorly formatted HTML 172 | ' Works with late bindings 173 | If LCase(parseArguments(i)) = "id" Then 174 | If partialHtml <> "" Then 175 | html.body.innerHTML = partialHtml 176 | End If 177 | partialHtml = html.getElementById(parseArguments(i + 1)).innerHTML 178 | html.body.innerHTML = partialHtml 179 | i = i + 1 180 | 181 | ' Requires early bindings. Don't include in final code, but potentially consider for future updates 182 | 'ElseIf LCase(parseArguments(i)) = "class" Then 183 | ' partialHtml = html.getElementsByClassName(parseArguments(i + 1))(i + 2).innerHTML 184 | ' i = i + 2 185 | 186 | ' Works with late bindings 187 | ElseIf LCase(parseArguments(i)) = "tag" Then 188 | If partialHtml <> "" Then 189 | html.body.innerHTML = partialHtml 190 | End If 191 | partialHtml = html.getElementsByTagName(parseArguments(i + 1))(i + 2).innerHTML 192 | html.body.innerHTML = partialHtml 193 | i = i + 2 194 | 195 | ' Left string manipulation 196 | ElseIf LCase(parseArguments(i)) = "left" Then 197 | If IsNumeric(parseArguments(i + 1)) And TypeName(parseArguments(i + 1)) <> "String" Then 198 | partialHtml = Left(partialHtml, parseArguments(i + 1)) 199 | Else 200 | partialHtml = Left(partialHtml, InStr(1, partialHtml, CStr(parseArguments(i + 1)), vbTextCompare) - 1) 201 | End If 202 | i = i + 1 203 | 204 | ' Right string manipulation 205 | ElseIf LCase(parseArguments(i)) = "right" Then 206 | If IsNumeric(parseArguments(i + 1)) And TypeName(parseArguments(i + 1)) <> "String" Then 207 | partialHtml = Right(partialHtml, parseArguments(i + 1)) 208 | Else 209 | partialHtml = Right(partialHtml, Len(partialHtml) - Len(parseArguments(i + 1)) + 1 - InStrRev(partialHtml, CStr(parseArguments(i + 1)), Compare:=vbTextCompare)) 210 | End If 211 | i = i + 1 212 | 213 | ' Mid string manipulation. Possibly update this to allow Mid length argument 214 | ElseIf LCase(parseArguments(i)) = "mid" Then 215 | If IsNumeric(parseArguments(i + 1)) And TypeName(parseArguments(i + 1)) <> "String" Then 216 | partialHtml = Mid(partialHtml, parseArguments(i + 1)) 217 | Else 218 | partialHtml = Mid(partialHtml, Len(parseArguments(i + 1)) + InStr(1, partialHtml, CStr(parseArguments(i + 1)), vbTextCompare)) 219 | End If 220 | i = i + 1 221 | End If 222 | Next 223 | 224 | ParseHtmlString = partialHtml 225 | 226 | End Function 227 | 228 | 229 | -------------------------------------------------------------------------------- /Modules/xlibUtilities.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibUtilities" 2 | '@Module: This module contains a set of basic miscellaneous utility functions 3 | 4 | Option Explicit 5 | 6 | 7 | Public Function Jsonify( _ 8 | ByVal indentLevel As Byte, _ 9 | ParamArray stringArray() As Variant) _ 10 | As String 11 | 12 | '@Description: This function takes an array of strings and numbers and returns the array as a JSON string. This function takes into account formatting for numbers, and supports specifying the indentation level. 13 | '@Author: Anthony Mancini 14 | '@Version: 1.0.0 15 | '@License: MIT 16 | '@Param: indentLevel is an optional number that specifying the indentation level. Leaving this argument out will result in no indentation 17 | '@Param: stringArray() is an array of strings and number in the following format: {"Hello", "World"} 18 | '@Returns: Returns a JSON valid string of all elements in the array 19 | '@Example: =Jsonify(0, "Hello", "World", "1", "2", 3, 4.5) -> "["Hello","World",1,2,3,4.5]" 20 | '@Example: =Jsonify(0, {"Hello", "World", "1", "2", 3, 4.5}, 10) -> "["Hello","World",1,2,3,4.5]" 21 | 22 | Dim i As Byte 23 | Dim jsonString As String 24 | Dim individualTextItem As Variant 25 | Dim individualValue As Variant 26 | Dim indentString As String 27 | 28 | ' Setting up some base JSON features and the indenting 29 | jsonString = "[" 30 | 31 | For i = 1 To indentLevel 32 | indentString = indentString & " " 33 | Next 34 | 35 | If indentLevel > 0 Then 36 | jsonString = jsonString & Chr(10) 37 | End If 38 | 39 | 40 | ' Creating the contents of the JSON string 41 | For Each individualTextItem In stringArray 42 | 43 | ' In cases of ranges 44 | If IsArray(individualTextItem) Then 45 | For Each individualValue In individualTextItem 46 | jsonString = jsonString & indentString 47 | 48 | If IsNumeric(individualValue) Then 49 | jsonString = jsonString & individualValue & "," 50 | Else 51 | jsonString = jsonString & Chr(34) & individualValue & Chr(34) & "," 52 | End If 53 | 54 | If indentLevel > 0 Then 55 | jsonString = jsonString & Chr(10) 56 | End If 57 | Next 58 | 59 | ' In cases of text 60 | Else 61 | jsonString = jsonString & indentString 62 | 63 | If IsNumeric(individualTextItem) Then 64 | jsonString = jsonString & individualTextItem & "," 65 | Else 66 | jsonString = jsonString & Chr(34) & individualTextItem & Chr(34) & "," 67 | End If 68 | 69 | If indentLevel > 0 Then 70 | jsonString = jsonString & Chr(10) 71 | End If 72 | End If 73 | 74 | Next 75 | 76 | jsonString = Left(jsonString, InStrRev(jsonString, ",") - 1) 77 | 78 | If indentLevel > 0 Then 79 | jsonString = jsonString & Chr(10) 80 | End If 81 | 82 | jsonString = jsonString & "]" 83 | 84 | Jsonify = jsonString 85 | 86 | End Function 87 | 88 | 89 | Public Function UuidFour() As String 90 | 91 | '@Description: This function generates a unique ID based on the UUID V4 specification. This function is useful for generating unique IDs of a fixed character length. 92 | '@Author: Anthony Mancini 93 | '@Version: 1.0.0 94 | '@License: MIT 95 | '@Returns: Returns a string unique ID based on UUID V4. The format of the string will always be in the form of "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx" where each x is a hex digit, and y is either 8, 9, A, or B. 96 | '@Example: =UuidFour() -> "3B4BDC26-E76E-4D6C-9E05-7AE7D2D68304" 97 | '@Example: =UuidFour() -> "D5761256-8385-4FDA-AD56-6AEF0AD6B9A5" 98 | '@Example: =UuidFour() -> "CDCAE2F5-B52F-4C90-A38A-42BD58BCED4B" 99 | 100 | Dim firstGroup As String 101 | Dim secondGroup As String 102 | Dim thirdGroup As String 103 | Dim fourthGroup As String 104 | Dim fifthGroup As String 105 | Dim sixthGroup As String 106 | 107 | firstGroup = BigDec2Hex(BigRandBetween(0, 4294967295#), 8) & "-" 108 | secondGroup = Dec2Hex(RandBetween(0, 65535), 4) & "-" 109 | thirdGroup = Dec2Hex(RandBetween(16384, 20479), 4) & "-" 110 | fourthGroup = Dec2Hex(RandBetween(32768, 49151), 4) & "-" 111 | fifthGroup = Dec2Hex(RandBetween(0, 65535), 4) 112 | sixthGroup = BigDec2Hex(BigRandBetween(0, 4294967295#), 8) 113 | 114 | UuidFour = firstGroup & secondGroup & thirdGroup & fourthGroup & fifthGroup & sixthGroup 115 | 116 | End Function 117 | 118 | 119 | Public Function HideText( _ 120 | ByVal string1 As String, _ 121 | ByVal hiddenFlag As Boolean, _ 122 | Optional ByVal hideString As String) _ 123 | As String 124 | 125 | '@Description: This function takes the value in a cell and visibly hides it if the HideText flag set to TRUE. If TRUE, the value will appear as "********", with the option to set the HideText characters to a different set of text. 126 | '@Author: Anthony Mancini 127 | '@Version: 1.0.0 128 | '@License: MIT 129 | '@Param: string1 is the string that will be HideText 130 | '@Param: hiddenFlag if set to TRUE will hide string1 131 | '@Param: hideString is an optional string that if set will be used instead of "********" 132 | '@Returns: Returns a string to hide string1 if hideFlag is TRUE 133 | '@Example: =HideText("Hello World", FALSE) -> "Hello World" 134 | '@Example: =HideText("Hello World", TRUE) -> "********" 135 | '@Example: =HideText("Hello World", TRUE, "[Hidden Text]") -> "[Hidden Text]" 136 | '@Example: =HideText("Hello World", UserName()="Anthony") -> "********" 137 | 138 | If hiddenFlag Then 139 | If hideString = "" Then 140 | HideText = "********" 141 | Else 142 | HideText = hideString 143 | End If 144 | Else 145 | HideText = string1 146 | End If 147 | 148 | End Function 149 | 150 | 151 | Public Function JavaScript( _ 152 | ByVal jsFuncCode As String, _ 153 | ByVal jsFuncName As String, _ 154 | Optional ByVal argument1 As Variant, _ 155 | Optional ByVal argument2 As Variant, _ 156 | Optional ByVal argument3 As Variant, _ 157 | Optional ByVal argument4 As Variant, _ 158 | Optional ByVal argument5 As Variant, _ 159 | Optional ByVal argument6 As Variant, _ 160 | Optional ByVal argument7 As Variant, _ 161 | Optional ByVal argument8 As Variant, _ 162 | Optional ByVal argument9 As Variant, _ 163 | Optional ByVal argument10 As Variant, _ 164 | Optional ByVal argument11 As Variant, _ 165 | Optional ByVal argument12 As Variant, _ 166 | Optional ByVal argument13 As Variant, _ 167 | Optional ByVal argument14 As Variant, _ 168 | Optional ByVal argument15 As Variant, _ 169 | Optional ByVal argument16 As Variant) _ 170 | As Variant 171 | 172 | '@Description: This function executes JavaScript code using Microsoft's JScript scripting language. It takes 3 arguments, the JavaScript code that will be executed, the name of the JavaScript function that will be executed, and up to 16 optional arguments to be used in the JavaScript function that is called. One thing to note is that ES5 syntax should be used in the JavaScript code, as ES6 features are unlikely to be supported. 173 | '@Author: Anthony Mancini 174 | '@Version: 1.0.0 175 | '@License: MIT 176 | '@Param: jsFuncCode is a string of the JavaScript source code that will be executed 177 | '@Param: jsFuncName is the name of the JavaScript function that will be called 178 | '@Param: argument1 - argument16 are optional arguments used in the JScript function call 179 | '@Returns: Returns the result of the JavaScript function that is called 180 | '@Example: =JavaScript("function helloFunc(){return 'Hello World!'}", "helloFunc") -> "Hello World!" 181 | '@Example: =JavaScript("function addTwo(a, b){return a + b}","addTwo",12,24) -> 36 182 | 183 | Dim ScriptContoller As Object 184 | Set ScriptContoller = CreateObject("ScriptControl") 185 | 186 | ScriptContoller.Language = "JScript" 187 | ScriptContoller.addCode jsFuncCode 188 | 189 | JavaScript = ScriptContoller.Run(jsFuncName, _ 190 | argument1, argument2, argument3, argument4, _ 191 | argument5, argument6, argument7, argument8, _ 192 | argument9, argument10, argument11, argument12, _ 193 | argument13, argument14, argument15, argument16) 194 | 195 | End Function 196 | 197 | Public Function HtmlEscape( _ 198 | ByVal string1 As String) _ 199 | As String 200 | 201 | '@Description: This function takes a string and escapes the HTML characters in it. For example, the character ">" will be escaped into "%gt;" 202 | '@Author: Anthony Mancini 203 | '@Version: 1.0.0 204 | '@License: MIT 205 | '@Param: string1 is the string that will have its characters HTML escaped 206 | '@Returns: Returns an HTML escaped string 207 | '@Example: =HtmlEscape("

Hello World

") -> "<p>Hello World</p>" 208 | 209 | string1 = Replace(string1, "&", "&") 210 | string1 = Replace(string1, Chr(34), """) 211 | string1 = Replace(string1, "'", "'") 212 | string1 = Replace(string1, "<", "<") 213 | string1 = Replace(string1, ">", ">") 214 | 215 | HtmlEscape = string1 216 | 217 | End Function 218 | 219 | 220 | Public Function HtmlUnescape( _ 221 | ByVal string1 As String) _ 222 | As String 223 | 224 | '@Description: This function takes a string and unescapes the HTML characters in it. For example, the character "%gt;" will be escaped into ">" 225 | '@Author: Anthony Mancini 226 | '@Version: 1.0.0 227 | '@License: MIT 228 | '@Param: string1 is the string that will have its characters HTML unescaped 229 | '@Returns: Returns an HTML unescaped string 230 | '@Example: =HtmlUnescape("<p>Hello World</p>") -> "

Hello World

" 231 | 232 | string1 = Replace(string1, "&", "&") 233 | string1 = Replace(string1, """, Chr(34)) 234 | string1 = Replace(string1, "'", "'") 235 | string1 = Replace(string1, "<", "<") 236 | string1 = Replace(string1, ">", ">") 237 | 238 | HtmlUnescape = string1 239 | 240 | End Function 241 | 242 | 243 | Private Sub CallTextToSpeech(combinedString) 244 | 245 | '@Description: This subroutine simply calls the text-to-speech API 246 | '@Author: Anthony Mancini 247 | '@Version: 1.0.0 248 | '@License: MIT 249 | '@Param: combinedString is the string that will be spoken 250 | 251 | Application.Speech.Speak combinedString, True 252 | 253 | End Sub 254 | 255 | 256 | Public Function SpeakText( _ 257 | ParamArray textArray() As Variant) _ 258 | As String 259 | 260 | '@Description: This function takes the range of the cell that this function resides, and then an array of text, and when this function is recalculated manually by the user (for example when pressing the F2 key while on the cell) this function will use Microsoft's text-to-speech to speak out the text through the speakers or microphone. 261 | '@Author: Anthony Mancini 262 | '@Version: 1.0.0 263 | '@License: MIT 264 | '@Param: textArray() is an array of ranges, strings, or number that will be displayed 265 | '@Note: Note that text-to-speech is only available on Microsoft Excel. This function will still return the combined string from the text array, but will only result in speech through the speakers in Microsoft Excel 266 | '@Returns: Returns all the strings in the text array combined as well as displays all the text in the text array 267 | '@Example: =SpeakText("Hello", "World") -> "Hello World" and the text will be spoken through the speaker 268 | 269 | Dim combinedString As String 270 | Dim individualTextItem As Variant 271 | 272 | For Each individualTextItem In textArray 273 | combinedString = combinedString & individualTextItem & " " 274 | Next 275 | 276 | If Application.Name = "Microsoft Excel" Then 277 | CallTextToSpeech combinedString 278 | End If 279 | 280 | SpeakText = Trim(combinedString) 281 | 282 | End Function 283 | 284 | 285 | Public Function Dec2Hex( _ 286 | ByVal number As Long, _ 287 | Optional ByVal zeroFillAmount As Integer) _ 288 | As String 289 | 290 | '@Description: This function takes an integer and converts it to a hex string, with the option to specify the number of leading zeros for the hex string returned 291 | '@Author: Anthony Mancini 292 | '@Version: 1.0.0 293 | '@License: MIT 294 | '@Param: number is the integer that will be converted to a hex string 295 | '@Returns: Returns the number rounded down to the nearest integer 296 | '@Example: =Dec2Hex(5) -> "5" 297 | '@Example: =Dec2Hex(5, 2) -> "05" 298 | '@Example: =Dec2Hex(255, 2) -> "FF" 299 | '@Example: =Dec2Hex(255, 8) -> "000000FF" 300 | 301 | Dim i As Integer 302 | Dim hexString As String 303 | 304 | hexString = Hex(number) 305 | 306 | If zeroFillAmount > 0 Then 307 | While Len(hexString) < zeroFillAmount 308 | hexString = "0" & hexString 309 | Wend 310 | End If 311 | 312 | Dec2Hex = hexString 313 | 314 | End Function 315 | 316 | 317 | Public Function BigDec2Hex( _ 318 | ByVal number As Variant, _ 319 | Optional ByVal zeroFillAmount As Integer) _ 320 | As String 321 | 322 | '@Description: This function is an implementation of Dec2Hex that allows big integers up to 14-byte to be used 323 | '@Author: Anthony Mancini 324 | '@Version: 1.0.0 325 | '@License: MIT 326 | '@Param: number is the integer that will be converted to a hex string 327 | '@Returns: Returns the number rounded down to the nearest integer 328 | '@Example: =Dec2Hex(255, 8) -> "000000FF" 329 | '@Example: =Dec2Hex(3000000000, 16) -> Error; As Dec2Hex does not support integers this large 330 | '@Example: =BigDec2Hex(3000000000, 16) -> "00000000B2D05E00" 331 | 332 | Dim i As Integer 333 | Dim hexString As String 334 | 335 | hexString = BigHex(number) 336 | 337 | If zeroFillAmount > 0 Then 338 | While Len(hexString) < zeroFillAmount 339 | hexString = "0" & hexString 340 | Wend 341 | End If 342 | 343 | BigDec2Hex = hexString 344 | 345 | End Function 346 | 347 | 348 | Public Function BigHex( _ 349 | ByVal number As Variant) _ 350 | As String 351 | 352 | '@Description: This function is an implementation of the Hex() function that allows for 14-byte integers to be used 353 | '@Author: Anthony Mancini 354 | '@Version: 1.0.0 355 | '@License: MIT 356 | '@Param: number is the number that will be converted to hex 357 | '@Returns: Returns a string of the number converted to hex 358 | '@Example: =BigHex(255) -> "FF" 359 | '@Example: =Hex(3000000000) -> Error; As hex does not support big integers 360 | '@Example: =BigHex(3000000000) -> "B2D05E00" 361 | 362 | Dim integerString As String 363 | Dim decimalString As String 364 | Dim hexString As String 365 | 366 | While number > 0 367 | number = number / 16 368 | If InStr(1, CStr(number), ".") > 0 Then 369 | integerString = Split(CStr(number), ".")(0) 370 | decimalString = Split(CStr(number), ".")(1) 371 | Else 372 | integerString = CStr(number) 373 | decimalString = "0" 374 | End If 375 | 376 | Select Case decimalString 377 | Case "0" 378 | hexString = "0" & hexString 379 | Case "0625" 380 | hexString = "1" & hexString 381 | Case "125" 382 | hexString = "2" & hexString 383 | Case "1875" 384 | hexString = "3" & hexString 385 | Case "25" 386 | hexString = "4" & hexString 387 | Case "3125" 388 | hexString = "5" & hexString 389 | Case "375" 390 | hexString = "6" & hexString 391 | Case "4375" 392 | hexString = "7" & hexString 393 | Case "5" 394 | hexString = "8" & hexString 395 | Case "5625" 396 | hexString = "9" & hexString 397 | Case "625" 398 | hexString = "A" & hexString 399 | Case "6875" 400 | hexString = "B" & hexString 401 | Case "75" 402 | hexString = "C" & hexString 403 | Case "8125" 404 | hexString = "D" & hexString 405 | Case "875" 406 | hexString = "E" & hexString 407 | Case "9375" 408 | hexString = "F" & hexString 409 | End Select 410 | 411 | number = Fix(number) 412 | Wend 413 | 414 | BigHex = hexString 415 | 416 | End Function 417 | 418 | Public Function Hex2Dec( _ 419 | ByVal hexNumber As String) _ 420 | As Long 421 | 422 | '@Description: This function takes a hex number as a string and converts it to a decimal long 423 | '@Author: Anthony Mancini 424 | '@Version: 1.0.0 425 | '@License: MIT 426 | '@Param: hexNumber is the hex number that will be converted to a long 427 | '@Returns: Returns a decimal base number converted from the hex number 428 | '@Example: =Hex2Dec("FF") -> 255 429 | '@Example: =Hex2Dec("FFFF") -> 65535 430 | 431 | Hex2Dec = CLng("&H" & hexNumber) 432 | 433 | End Function 434 | 435 | 436 | Public Function Len2( _ 437 | ByVal val As Variant) _ 438 | As Integer 439 | 440 | '@Description: This function is an extension on the Len() function by returning the length of strings, arrays, numbers, and many other objects in Excel, Word, PowerPoint, and Access, including Objects such as Dictionaries. Internally, any Object that implements a .Count property will have a length returned by this function. Also, any number used within this function will be converted to a string and then its length returned. 441 | '@Author: Anthony Mancini 442 | '@Version: 1.0.0 443 | '@License: MIT 444 | '@Param: val is the value you want the length from 445 | '@Returns: Returns an integer of the length of the value specified 446 | '@Example: =Len2("Hello") -> 5; As the string is 5 characters long 447 | '@Example: =Len2(arr) -> 3; Where arr is an array with {1, 2, 3} in it, and the array has 3 values in it 448 | '@Example: =Len2("100") -> 3; As the string is 3 characters long 449 | '@Example: =Len2(100) -> 3; As the integer is 3 characters long when converted to a string 450 | '@Example: =Len2(Range("A1:A3")) -> 3; As the Excel Range has 3 451 | '@Example: =Len2(col) -> 5; Where col is a Collection with 5 items in it 452 | '@Example: =Len2(dict) -> 2; Where dict is a Dictionary with 2 key/value pairs in it 453 | '@Example: =Len2(Application.Documents) -> 3; Where we currently have 3 documents open 454 | '@Example: =Len2(Application.ActivePresentation.Slides) -> 10; Where the active PowerPoint Presentation has 10 slides 455 | 456 | If IsArray(val) And Right(TypeName(val), 2) = "()" Then 457 | Len2 = UBound(val) - LBound(val) + 1 458 | ElseIf TypeName(val) = "String" Then 459 | Len2 = Len(val) 460 | ElseIf IsNumeric(val) Then 461 | Len2 = Len(CStr(val)) 462 | Else 463 | Len2 = val.Count 464 | End If 465 | 466 | End Function 467 | 468 | -------------------------------------------------------------------------------- /Modules/xlibStringManipulationTests.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "xlibStringManipulationTests" 2 | Option Explicit 3 | 4 | Public Function AllXlibStringManipulationTests() 5 | 6 | Dim TestStatus As Boolean 7 | TestStatus = True 8 | 9 | Debug.Print "========================================" 10 | 11 | ' Begin Tests 12 | If Not CapitalizeTest() Then 13 | Debug.Print "Failed: CapitalizeTest" 14 | TestStatus = False 15 | Else 16 | Debug.Print "Passed: CapitalizeTest" 17 | End If 18 | 19 | If Not LeftFindTest() Then 20 | Debug.Print "Failed: LeftFindTest" 21 | TestStatus = False 22 | Else 23 | Debug.Print "Passed: LeftFindTest" 24 | End If 25 | 26 | If Not RightFindTest() Then 27 | Debug.Print "Failed: RightFindTest" 28 | TestStatus = False 29 | Else 30 | Debug.Print "Passed: RightFindTest" 31 | End If 32 | 33 | If Not LeftSearchTest() Then 34 | Debug.Print "Failed: LeftSearchTest" 35 | TestStatus = False 36 | Else 37 | Debug.Print "Passed: LeftSearchTest" 38 | End If 39 | 40 | If Not RightSearchTest() Then 41 | Debug.Print "Failed: RightSearchTest" 42 | TestStatus = False 43 | Else 44 | Debug.Print "Passed: RightSearchTest" 45 | End If 46 | 47 | If Not SubstrTest() Then 48 | Debug.Print "Failed: SubstrTest" 49 | TestStatus = False 50 | Else 51 | Debug.Print "Passed: SubstrTest" 52 | End If 53 | 54 | If Not SubstrFindTest() Then 55 | Debug.Print "Failed: SubstrFindTest" 56 | TestStatus = False 57 | Else 58 | Debug.Print "Passed: SubstrFindTest" 59 | End If 60 | 61 | If Not SubstrSearchTest() Then 62 | Debug.Print "Failed: SubstrSearchTest" 63 | TestStatus = False 64 | Else 65 | Debug.Print "Passed: SubstrSearchTest" 66 | End If 67 | 68 | If Not RepeatTest() Then 69 | Debug.Print "Failed: RepeatTest" 70 | TestStatus = False 71 | Else 72 | Debug.Print "Passed: RepeatTest" 73 | End If 74 | 75 | If Not FormatterTest() Then 76 | Debug.Print "Failed: FormatterTest" 77 | TestStatus = False 78 | Else 79 | Debug.Print "Passed: FormatterTest" 80 | End If 81 | 82 | If Not ZfillTest() Then 83 | Debug.Print "Failed: ZfillTest" 84 | TestStatus = False 85 | Else 86 | Debug.Print "Passed: ZfillTest" 87 | End If 88 | 89 | If Not SplitTextTest() Then 90 | Debug.Print "Failed: SplitTextTest" 91 | TestStatus = False 92 | Else 93 | Debug.Print "Passed: SplitTextTest" 94 | End If 95 | 96 | If Not CountWordsTest() Then 97 | Debug.Print "Failed: CountWordsTest" 98 | TestStatus = False 99 | Else 100 | Debug.Print "Passed: CountWordsTest" 101 | End If 102 | 103 | If Not CamelCaseTest() Then 104 | Debug.Print "Failed: CamelCaseTest" 105 | TestStatus = False 106 | Else 107 | Debug.Print "Passed: CamelCaseTest" 108 | End If 109 | 110 | If Not KebabCaseTest() Then 111 | Debug.Print "Failed: KebabCaseTest" 112 | TestStatus = False 113 | Else 114 | Debug.Print "Passed: KebabCaseTest" 115 | End If 116 | 117 | If Not RemoveCharactersTest() Then 118 | Debug.Print "Failed: RemoveCharactersTest" 119 | TestStatus = False 120 | Else 121 | Debug.Print "Passed: RemoveCharactersTest" 122 | End If 123 | 124 | If Not CompanyCaseTest() Then 125 | Debug.Print "Failed: CompanyCaseTest" 126 | TestStatus = False 127 | Else 128 | Debug.Print "Passed: CompanyCaseTest" 129 | End If 130 | 131 | If Not ReverseTextTest() Then 132 | Debug.Print "Failed: ReverseTextTest" 133 | TestStatus = False 134 | Else 135 | Debug.Print "Passed: ReverseTextTest" 136 | End If 137 | 138 | If Not ReverseWordsTest() Then 139 | Debug.Print "Failed: ReverseWordsTest" 140 | TestStatus = False 141 | Else 142 | Debug.Print "Passed: ReverseWordsTest" 143 | End If 144 | 145 | If Not IndentTextTest() Then 146 | Debug.Print "Failed: IndentTextTest" 147 | TestStatus = False 148 | Else 149 | Debug.Print "Passed: IndentTextTest" 150 | End If 151 | 152 | If Not DedentTextTest() Then 153 | Debug.Print "Failed: DedentTextTest" 154 | TestStatus = False 155 | Else 156 | Debug.Print "Passed: DedentTextTest" 157 | End If 158 | 159 | If Not ShortenTextTest() Then 160 | Debug.Print "Failed: ShortenTextTest" 161 | TestStatus = False 162 | Else 163 | Debug.Print "Passed: ShortenTextTest" 164 | End If 165 | 166 | If Not InSplitTest() Then 167 | Debug.Print "Failed: InSplitTest" 168 | TestStatus = False 169 | Else 170 | Debug.Print "Passed: InSplitTest" 171 | End If 172 | 173 | If Not EliteCaseTest() Then 174 | Debug.Print "Failed: EliteCaseTest" 175 | TestStatus = False 176 | Else 177 | Debug.Print "Passed: EliteCaseTest" 178 | End If 179 | 180 | If Not ScrambleCaseTest() Then 181 | Debug.Print "Failed: ScrambleCaseTest" 182 | TestStatus = False 183 | Else 184 | Debug.Print "Passed: ScrambleCaseTest" 185 | End If 186 | 187 | If Not LeftSplitTest() Then 188 | Debug.Print "Failed: LeftSplitTest" 189 | TestStatus = False 190 | Else 191 | Debug.Print "Passed: LeftSplitTest" 192 | End If 193 | 194 | If Not RightSplitTest() Then 195 | Debug.Print "Failed: RightSplitTest" 196 | TestStatus = False 197 | Else 198 | Debug.Print "Passed: RightSplitTest" 199 | End If 200 | 201 | If Not TrimCharTest() Then 202 | Debug.Print "Failed: TrimCharTest" 203 | TestStatus = False 204 | Else 205 | Debug.Print "Passed: TrimCharTest" 206 | End If 207 | 208 | If Not TrimLeftTest() Then 209 | Debug.Print "Failed: TrimLeftTest" 210 | TestStatus = False 211 | Else 212 | Debug.Print "Passed: TrimLeftTest" 213 | End If 214 | 215 | If Not TrimRightTest() Then 216 | Debug.Print "Failed: TrimRightTest" 217 | TestStatus = False 218 | Else 219 | Debug.Print "Passed: TrimRightTest" 220 | End If 221 | 222 | If Not CountUppercaseCharactersTest() Then 223 | Debug.Print "Failed: CountUppercaseCharactersTest" 224 | TestStatus = False 225 | Else 226 | Debug.Print "Passed: CountUppercaseCharactersTest" 227 | End If 228 | 229 | If Not CountLowercaseCharactersTest() Then 230 | Debug.Print "Failed: CountLowercaseCharactersTest" 231 | TestStatus = False 232 | Else 233 | Debug.Print "Passed: CountLowercaseCharactersTest" 234 | End If 235 | 236 | If Not TextJoinTest() Then 237 | Debug.Print "Failed: TextJoinTest" 238 | TestStatus = False 239 | Else 240 | Debug.Print "Passed: TextJoinTest" 241 | End If 242 | ' End Tests 243 | 244 | Debug.Print "----------------------------------------" 245 | 246 | If TestStatus Then 247 | Debug.Print "Passed All Tests" 248 | Else 249 | Debug.Print "!!! FAILED TESTS !!!" 250 | End If 251 | 252 | Debug.Print "========================================" 253 | 254 | AllXlibStringManipulationTests = TestStatus 255 | 256 | End Function 257 | 258 | 259 | 260 | Private Function CapitalizeTest() As Boolean 261 | 262 | '@Example: =Capitalize("hello World") -> "Hello world" 263 | 264 | CapitalizeTest = True 265 | 266 | CapitalizeTest = CapitalizeTest And Capitalize("hello World") = "Hello world" 267 | 268 | End Function 269 | 270 | 271 | Private Function LeftFindTest() As Boolean 272 | 273 | '@Example: =LeftFind("Hello World", "r") -> "Hello Wo" 274 | '@Example: =LeftFind("Hello World", "R") -> "#VALUE!"; Since string1 does not contain "R" in it. 275 | 276 | LeftFindTest = True 277 | 278 | LeftFindTest = LeftFindTest And LeftFind("Hello World", "r") = "Hello Wo" 279 | 280 | End Function 281 | 282 | 283 | Private Function RightFindTest() As Boolean 284 | 285 | '@Example: =RightFind("Hello World", "o") -> "rld" 286 | '@Example: =RightFind("Hello World", "O") -> "#VALUE!"; Since string1 does not contain "O" in it. 287 | 288 | RightFindTest = True 289 | 290 | RightFindTest = RightFindTest And RightFind("Hello World", "o") = "rld" 291 | 292 | End Function 293 | 294 | 295 | Private Function LeftSearchTest() As Boolean 296 | 297 | '@Example: =LeftSearch("Hello World", "r") -> "Hello Wo" 298 | '@Example: =LeftSearch("Hello World", "R") -> "Hello Wo" 299 | 300 | LeftSearchTest = True 301 | 302 | LeftSearchTest = LeftSearchTest And LeftSearch("Hello World", "r") = "Hello Wo" 303 | LeftSearchTest = LeftSearchTest And LeftSearch("Hello World", "R") = "Hello Wo" 304 | 305 | End Function 306 | 307 | 308 | Private Function RightSearchTest() As Boolean 309 | 310 | '@Example: =RightSearch("Hello World", "o") -> "rld" 311 | '@Example: =RightSearch("Hello World", "O") -> "rld" 312 | 313 | RightSearchTest = True 314 | 315 | RightSearchTest = RightSearchTest And RightSearch("Hello World", "o") = "rld" 316 | RightSearchTest = RightSearchTest And RightSearch("Hello World", "O") = "rld" 317 | 318 | End Function 319 | 320 | 321 | Private Function SubstrTest() As Boolean 322 | 323 | '@Example: =Substr("Hello World", 2, 6) -> "ello" 324 | 325 | SubstrTest = True 326 | 327 | SubstrTest = SubstrTest And Substr("Hello World", 2, 6) = "ello" 328 | 329 | End Function 330 | 331 | 332 | Private Function SubstrFindTest() As Boolean 333 | 334 | '@Example: =SubstrFind("Hello World", "e", "o") -> "ello Wo" 335 | '@Example: =SubstrFind("Hello World", "e", "o", TRUE) -> "llo W" 336 | '@Example: =SubstrFind("One Two Three", "ne ", " Thr") -> "ne Two Thr" 337 | '@Example: =SubstrFind("One Two Three", "NE ", " THR") -> "#VALUE!"; Since SubstrFind() is case-sensitive 338 | '@Example: =SubstrFind("One Two Three", "ne ", " Thr", TRUE) -> "Two" 339 | '@Example: =SubstrFind("Country Code: +51; Area Code: 315; Phone Number: 762-5929;", "Area Code: ", "; Phone", TRUE) -> 315 340 | '@Example: =SubstrFind("Country Code: +313; Area Code: 423; Phone Number: 284-2468;", "Area Code: ", "; Phone", TRUE) -> 423 341 | '@Example: =SubstrFind("Country Code: +171; Area Code: 629; Phone Number: 731-5456;", "Area Code: ", "; Phone", TRUE) -> 629 342 | 343 | SubstrFindTest = True 344 | 345 | SubstrFindTest = SubstrFindTest And SubstrFind("Hello World", "e", "o") = "ello Wo" 346 | SubstrFindTest = SubstrFindTest And SubstrFind("Hello World", "e", "o", True) = "llo W" 347 | SubstrFindTest = SubstrFindTest And SubstrFind("One Two Three", "ne ", " Thr") = "ne Two Thr" 348 | SubstrFindTest = SubstrFindTest And SubstrFind("One Two Three", "ne ", " Thr", True) = "Two" 349 | 350 | End Function 351 | 352 | 353 | Private Function SubstrSearchTest() As Boolean 354 | 355 | '@Example: =SubstrSearch("Hello World", "e", "o") -> "ello Wo" 356 | '@Example: =SubstrSearch("Hello World", "e", "o", TRUE) -> "llo W" 357 | '@Example: =SubstrSearch("One Two Three", "ne ", " Thr") -> "ne Two Thr" 358 | '@Example: =SubstrSearch("One Two Three", "NE ", " THR") -> "ne Two Thr"; No error, since SubstrSearch is case-insensitive 359 | '@Example: =SubstrSearch("One Two Three", "ne ", " Thr", TRUE) -> "Two" 360 | '@Example: =SubstrSearch("Country Code: +51; Area Code: 315; Phone Number: 762-5929;", "Area Code: ", "; Phone", TRUE) -> 315 361 | '@Example: =SubstrSearch("Country Code: +313; Area Code: 423; Phone Number: 284-2468;", "Area Code: ", "; Phone", TRUE) -> 423 362 | '@Example: =SubstrSearch("Country Code: +171; Area Code: 629; Phone Number: 731-5456;", "Area Code: ", "; Phone", TRUE) -> 629 363 | 364 | SubstrSearchTest = True 365 | 366 | SubstrSearchTest = SubstrSearchTest And SubstrSearch("Hello World", "e", "o") = "ello Wo" 367 | SubstrSearchTest = SubstrSearchTest And SubstrSearch("Hello World", "e", "o", True) = "llo W" 368 | SubstrSearchTest = SubstrSearchTest And SubstrSearch("One Two Three", "ne ", " Thr") = "ne Two Thr" 369 | SubstrSearchTest = SubstrSearchTest And SubstrSearch("One Two Three", "NE ", " THR") = "ne Two Thr" 370 | SubstrSearchTest = SubstrSearchTest And SubstrSearch("One Two Three", "ne ", " Thr", True) = "Two" 371 | 372 | End Function 373 | 374 | 375 | Private Function RepeatTest() As Boolean 376 | 377 | '@Example: =Repeat("Hello", 2) -> HelloHello" 378 | '@Example: =Repeat("=", 10) -> "==========" 379 | 380 | RepeatTest = True 381 | 382 | RepeatTest = RepeatTest And Repeat("Hello", 2) = "HelloHello" 383 | RepeatTest = RepeatTest And Repeat("=", 10) = "==========" 384 | 385 | End Function 386 | 387 | 388 | Private Function FormatterTest() As Boolean 389 | 390 | '@Example: =Formatter("Hello {1}", "World") -> "Hello World" 391 | '@Example: =Formatter("{1} {2}", "Hello", "World") -> "Hello World" 392 | '@Example: =Formatter("{1}.{2}@{3}", "FirstName", "LastName", "email.com") -> "FirstName.LastName@email.com" 393 | '@Example: =Formatter("{1}.{2}@{3}", A1:A3) -> "FirstName.LastName@email.com"; where A1="FirstName", A2="LastName", and A3="email.com" 394 | '@Example: =Formatter("{1}.{2}@{3}", A1, A2, A3) -> "FirstName.LastName@email.com"; where A1="FirstName", A2="LastName", and A3="email.com" 395 | 396 | FormatterTest = True 397 | 398 | FormatterTest = FormatterTest And Formatter("Hello {1}", "World") = "Hello World" 399 | FormatterTest = FormatterTest And Formatter("{1} {2}", "Hello", "World") = "Hello World" 400 | FormatterTest = FormatterTest And Formatter("{1}.{2}@{3}", "FirstName", "LastName", "email.com") = "FirstName.LastName@email.com" 401 | FormatterTest = FormatterTest And Formatter("{1}.{2}@{3}", Array("FirstName", "LastName", "email.com")) = "FirstName.LastName@email.com" 402 | 403 | End Function 404 | 405 | 406 | Private Function ZfillTest() As Boolean 407 | 408 | '@Example: =Zfill(123, 5) -> "00123" 409 | '@Example: =Zfill(5678, 5) -> "05678" 410 | '@Example: =Zfill(12345678, 5) -> "12345678" 411 | '@Example: =Zfill(123, 5, "X") -> "XX123" 412 | '@Example: =Zfill(123, 5, "X", TRUE) -> "123XX" 413 | 414 | ZfillTest = True 415 | 416 | ZfillTest = ZfillTest And Zfill(123, 5) = "00123" 417 | ZfillTest = ZfillTest And Zfill(5678, 5) = "05678" 418 | ZfillTest = ZfillTest And Zfill(12345678, 5) = "12345678" 419 | ZfillTest = ZfillTest And Zfill(123, 5, "X") = "XX123" 420 | ZfillTest = ZfillTest And Zfill(123, 5, "X", True) = "123XX" 421 | 422 | End Function 423 | 424 | 425 | Private Function SplitTextTest() As Boolean 426 | 427 | '@Example: =SplitText("Hello World", 1) -> "Hello" 428 | '@Example: =SplitText("Hello World", 2) -> "World" 429 | '@Example: =SplitText("One Two Three", 2) -> "Two" 430 | '@Example: =SplitText("One-Two-Three", 2, "-") -> "Two" 431 | 432 | SplitTextTest = True 433 | 434 | SplitTextTest = SplitTextTest And SplitText("Hello World", 1) = "Hello" 435 | SplitTextTest = SplitTextTest And SplitText("Hello World", 2) = "World" 436 | SplitTextTest = SplitTextTest And SplitText("One Two Three", 2) = "Two" 437 | SplitTextTest = SplitTextTest And SplitText("One-Two-Three", 2, "-") = "Two" 438 | 439 | End Function 440 | 441 | 442 | Private Function CountWordsTest() As Boolean 443 | 444 | '@Example: =CountWords("Hello World") -> 2 445 | '@Example: =CountWords("One Two Three") -> 3 446 | '@Example: =CountWords("One-Two-Three", "-") -> 3 447 | 448 | CountWordsTest = True 449 | 450 | CountWordsTest = CountWordsTest And CountWords("Hello World") = 2 451 | CountWordsTest = CountWordsTest And CountWords("One Two Three") = 3 452 | CountWordsTest = CountWordsTest And CountWords("One-Two-Three", "-") = 3 453 | 454 | End Function 455 | 456 | 457 | Private Function CamelCaseTest() As Boolean 458 | 459 | '@Example: =CamelCase("Hello World") -> "helloWorld" 460 | '@Example: =CamelCase("One Two Three") -> "oneTwoThree" 461 | 462 | CamelCaseTest = True 463 | 464 | CamelCaseTest = CamelCaseTest And CamelCase("Hello World") = "helloWorld" 465 | CamelCaseTest = CamelCaseTest And CamelCase("One Two Three") = "oneTwoThree" 466 | 467 | End Function 468 | 469 | 470 | Private Function KebabCaseTest() As Boolean 471 | 472 | '@Example: =KebabCase("Hello World") -> "hello-world" 473 | '@Example: =KebabCase("One Two Three") -> "one-two-three" 474 | 475 | KebabCaseTest = True 476 | 477 | KebabCaseTest = KebabCaseTest And KebabCase("Hello World") = "hello-world" 478 | KebabCaseTest = KebabCaseTest And KebabCase("One Two Three") = "one-two-three" 479 | 480 | End Function 481 | 482 | 483 | Private Function RemoveCharactersTest() As Boolean 484 | 485 | '@Example: =RemoveCharacters("Hello World", "l") -> "Heo Word" 486 | '@Example: =RemoveCharacters("Hello World", "lo") -> "He Wrd" 487 | '@Example: =RemoveCharacters("Hello World", "l", "o") -> "He Wrd" 488 | '@Example: =RemoveCharacters("Hello World", "lod") -> "He Wr" 489 | '@Example: =RemoveCharacters("One Two Three", "o", "t") -> "One Two Three"; Nothing is replaced since this function is case sensitive 490 | '@Example: =RemoveCharacters("One Two Three", "O", "T") -> "ne wo hree" 491 | 492 | RemoveCharactersTest = True 493 | 494 | RemoveCharactersTest = RemoveCharactersTest And RemoveCharacters("Hello World", "l") = "Heo Word" 495 | RemoveCharactersTest = RemoveCharactersTest And RemoveCharacters("Hello World", "lo") = "He Wrd" 496 | RemoveCharactersTest = RemoveCharactersTest And RemoveCharacters("Hello World", "l", "o") = "He Wrd" 497 | RemoveCharactersTest = RemoveCharactersTest And RemoveCharacters("Hello World", "lod") = "He Wr" 498 | RemoveCharactersTest = RemoveCharactersTest And RemoveCharacters("Two Three Four", "f", "t") = "Two Three Four" 499 | RemoveCharactersTest = RemoveCharactersTest And RemoveCharacters("Two Three Four", "F", "T") = "wo hree our" 500 | 501 | End Function 502 | 503 | 504 | Private Function CompanyCaseTest() As Boolean 505 | 506 | '@Example: =CompanyCase("hello world") -> "Hello World" 507 | '@Example: =CompanyCase("x.y.z company & co.") -> "X.Y.Z Company & Co." 508 | '@Example: =CompanyCase("x.y.z plc") -> "X.Y.Z PLC" 509 | '@Example: =CompanyCase("one company gmbh") -> "One Company GmbH" 510 | '@Example: =CompanyCase("three company s. en n.c.") -> "Three Company S. en N.C." 511 | '@Example: =CompanyCase("FOUR COMPANY SPOL S.R.O.") -> "Four Company spol s.r.o." 512 | '@Example: =CompanyCase("five company bvba") -> "Five Company BVBA" 513 | 514 | CompanyCaseTest = True 515 | 516 | CompanyCaseTest = CompanyCaseTest And CompanyCase("hello world") = "Hello World" 517 | CompanyCaseTest = CompanyCaseTest And CompanyCase("x.y.z company & co.") = "X.Y.Z Company & Co." 518 | CompanyCaseTest = CompanyCaseTest And CompanyCase("x.y.z plc") = "X.Y.Z PLC" 519 | CompanyCaseTest = CompanyCaseTest And CompanyCase("one company gmbh") = "One Company GmbH" 520 | CompanyCaseTest = CompanyCaseTest And CompanyCase("three company s. en n.c.") = "Three Company S. en N.C." 521 | CompanyCaseTest = CompanyCaseTest And CompanyCase("FOUR COMPANY SPOL S.R.O.") = "Four Company spol s.r.o." 522 | CompanyCaseTest = CompanyCaseTest And CompanyCase("five company bvba") = "Five Company BVBA" 523 | 524 | End Function 525 | 526 | 527 | Private Function ReverseTextTest() As Boolean 528 | 529 | '@Example: =ReverseText("Hello World") -> "dlroW olleH" 530 | 531 | ReverseTextTest = True 532 | 533 | ReverseTextTest = ReverseTextTest And ReverseText("Hello World") = "dlroW olleH" 534 | 535 | End Function 536 | 537 | 538 | Private Function ReverseWordsTest() As Boolean 539 | 540 | '@Example: =ReverseWords("Hello World") -> "World Hello" 541 | '@Example: =ReverseWords("One Two Three") -> "Three Two One" 542 | '@Example: =ReverseWords("One-Two-Three", "-") -> "Three-Two-One" 543 | 544 | ReverseWordsTest = True 545 | 546 | ReverseWordsTest = ReverseWordsTest And ReverseWords("Hello World") = "World Hello" 547 | ReverseWordsTest = ReverseWordsTest And ReverseWords("One Two Three") = "Three Two One" 548 | ReverseWordsTest = ReverseWordsTest And ReverseWords("One-Two-Three", "-") = "Three-Two-One" 549 | 550 | End Function 551 | 552 | 553 | Private Function IndentTextTest() As Boolean 554 | 555 | '@Example: =IndentText("Hello") -> " Hello" 556 | '@Example: =IndentText("Hello", 4) -> " Hello" 557 | '@Example: =IndentText("Hello", 3) -> " Hello" 558 | '@Example: =IndentText("Hello", 2) -> " Hello" 559 | '@Example: =IndentText("Hello", 1) -> " Hello" 560 | 561 | IndentTextTest = True 562 | 563 | IndentTextTest = IndentTextTest And IndentText("Hello") = " Hello" 564 | IndentTextTest = IndentTextTest And IndentText("Hello", 4) = " Hello" 565 | IndentTextTest = IndentTextTest And IndentText("Hello", 3) = " Hello" 566 | IndentTextTest = IndentTextTest And IndentText("Hello", 2) = " Hello" 567 | IndentTextTest = IndentTextTest And IndentText("Hello", 1) = " Hello" 568 | 569 | End Function 570 | 571 | 572 | Private Function DedentTextTest() As Boolean 573 | 574 | '@Example: =DedentText(" Hello") -> "Hello" 575 | 576 | DedentTextTest = True 577 | 578 | DedentTextTest = DedentTextTest And DedentText(" Hello") = "Hello" 579 | 580 | End Function 581 | 582 | 583 | Private Function ShortenTextTest() As Boolean 584 | 585 | '@Example: =ShortenText("Hello World One Two Three", 20) -> "Hello World [...]"; Only the first two words and the placeholder will result in a string that is less than or equal to 20 in length 586 | '@Example: =ShortenText("Hello World One Two Three", 15) -> "Hello [...]"; Only the first word and the placeholder will result in a string that is less than or equal to 15 in length 587 | '@Example: =ShortenText("Hello World One Two Three") -> "Hello World One Two Three"; Since this string is shorter than the default 80 shorten width value, no placeholder will be used and the string wont be shortened 588 | '@Example: =ShortenText("Hello World One Two Three", 15, "-->") -> "Hello World -->"; A new placeholder is used 589 | '@Example: =ShortenText("Hello_World_One_Two_Three", 15, "-->", "_") -> "Hello_World_-->"; A new placeholder andd delimiter is used 590 | 591 | ShortenTextTest = True 592 | 593 | ShortenTextTest = ShortenTextTest And ShortenText("Hello World One Two Three", 20) = "Hello World [...]" 594 | ShortenTextTest = ShortenTextTest And ShortenText("Hello World One Two Three", 15) = "Hello [...]" 595 | ShortenTextTest = ShortenTextTest And ShortenText("Hello World One Two Three") = "Hello World One Two Three" 596 | ShortenTextTest = ShortenTextTest And ShortenText("Hello World One Two Three", 15, "-->") = "Hello World -->" 597 | ShortenTextTest = ShortenTextTest And ShortenText("Hello_World_One_Two_Three", 15, "-->", "_") = "Hello_World_-->" 598 | 599 | End Function 600 | 601 | 602 | Private Function InSplitTest() As Boolean 603 | 604 | '@Example: =InSplit("Hello", "Hello World One Two Three") -> TRUE; Since "Hello" is found within the searchString after being split 605 | '@Example: =InSplit("NotInString", "Hello World One Two Three") -> FALSE; Since "NotInString" is not found within the searchString after being split 606 | '@Example: =InSplit("Hello", "Hello-World-One-Two-Three", "-") -> TRUE; Since "Hello" is found and since the delimiter is set to "-" 607 | 608 | InSplitTest = True 609 | 610 | InSplitTest = InSplitTest And InSplit("Hello", "Hello World One Two Three") = True 611 | InSplitTest = InSplitTest And InSplit("NotInString", "Hello World One Two Three") = False 612 | InSplitTest = InSplitTest And InSplit("Hello", "Hello-World-One-Two-Three", "-") = True 613 | 614 | End Function 615 | 616 | 617 | Private Function EliteCaseTest() As Boolean 618 | 619 | '@Example: =EliteCase("Hello World") -> "H3110 W0r1d" 620 | 621 | EliteCaseTest = True 622 | 623 | EliteCaseTest = EliteCaseTest And EliteCase("Hello World") = "H3110 W0r1d" 624 | 625 | End Function 626 | 627 | 628 | Private Function ScrambleCaseTest() As Boolean 629 | 630 | '@Example: =ScrambleCase("Hello World") -> "helLo WORlD" 631 | '@Example: =ScrambleCase("Hello World") -> "HElLo WorLD" 632 | '@Example: =ScrambleCase("Hello World") -> "hELlo WOrLd" 633 | 634 | ScrambleCaseTest = True 635 | 636 | Dim testString As String 637 | testString = "a" 638 | 639 | ScrambleCaseTest = ScrambleCaseTest And (testString = "a" Or testString = "A") 640 | 641 | End Function 642 | 643 | 644 | Private Function LeftSplitTest() As Boolean 645 | 646 | '@Example: =LeftSplit("Hello World One Two Three", 1) -> "Hello" 647 | '@Example: =LeftSplit("Hello World One Two Three", 2) -> "Hello World" 648 | '@Example: =LeftSplit("Hello World One Two Three", 3) -> "Hello World One" 649 | '@Example: =LeftSplit("Hello World One Two Three", 10) -> "Hello World One Two Three" 650 | '@Example: =LeftSplit("Hello-World-One-Two-Three", 2, "-") -> "Hello-World" 651 | 652 | LeftSplitTest = True 653 | 654 | LeftSplitTest = LeftSplitTest And LeftSplit("Hello World One Two Three", 1) = "Hello" 655 | LeftSplitTest = LeftSplitTest And LeftSplit("Hello World One Two Three", 2) = "Hello World" 656 | LeftSplitTest = LeftSplitTest And LeftSplit("Hello World One Two Three", 3) = "Hello World One" 657 | LeftSplitTest = LeftSplitTest And LeftSplit("Hello World One Two Three", 10) = "Hello World One Two Three" 658 | LeftSplitTest = LeftSplitTest And LeftSplit("Hello-World-One-Two-Three", 2, "-") = "Hello-World" 659 | 660 | End Function 661 | 662 | 663 | Private Function RightSplitTest() As Boolean 664 | 665 | '@Example: =RightSplit("Hello World One Two Three", 1) -> "Three" 666 | '@Example: =RightSplit("Hello World One Two Three", 2) -> "Two Three" 667 | '@Example: =RightSplit("Hello World One Two Three", 3) -> "One Two Three" 668 | '@Example: =RightSplit("Hello World One Two Three", 10) -> "Hello World One Two Three" 669 | '@Example: =RightSplit("Hello-World-One-Two-Three", 2, "-") -> "Two-Three" 670 | 671 | RightSplitTest = True 672 | 673 | RightSplitTest = RightSplitTest And RightSplit("Hello World One Two Three", 1) = "Three" 674 | RightSplitTest = RightSplitTest And RightSplit("Hello World One Two Three", 2) = "Two Three" 675 | RightSplitTest = RightSplitTest And RightSplit("Hello World One Two Three", 3) = "One Two Three" 676 | RightSplitTest = RightSplitTest And RightSplit("Hello World One Two Three", 10) = "Hello World One Two Three" 677 | RightSplitTest = RightSplitTest And RightSplit("Hello-World-One-Two-Three", 2, "-") = "Two-Three" 678 | 679 | End Function 680 | 681 | 682 | Private Function TrimCharTest() As Boolean 683 | 684 | '@Example: =TrimChar(" Hello World ") -> "Hello World" 685 | '@Example: =TrimChar("---Hello World---", "-") -> "Hello World" 686 | 687 | TrimCharTest = True 688 | 689 | TrimCharTest = TrimCharTest And TrimChar(" Hello World ") = "Hello World" 690 | TrimCharTest = TrimCharTest And TrimChar("---Hello World---", "-") = "Hello World" 691 | 692 | End Function 693 | 694 | 695 | Private Function TrimLeftTest() As Boolean 696 | 697 | '@Example: =TrimLeft(" Hello World ") -> "Hello World " 698 | '@Example: =TrimLeft("---Hello World---", "-") -> "Hello World---" 699 | 700 | TrimLeftTest = True 701 | 702 | TrimLeftTest = TrimLeftTest And TrimLeft(" Hello World ") = "Hello World " 703 | TrimLeftTest = TrimLeftTest And TrimLeft("---Hello World---", "-") = "Hello World---" 704 | 705 | End Function 706 | 707 | 708 | Private Function TrimRightTest() As Boolean 709 | 710 | '@Example: =TrimRight(" Hello World ") -> " Hello World" 711 | '@Example: =TrimRight("---Hello World---", "-") -> "---Hello World" 712 | 713 | TrimRightTest = True 714 | 715 | TrimRightTest = TrimRightTest And TrimRight(" Hello World ") = " Hello World" 716 | TrimRightTest = TrimRightTest And TrimRight("---Hello World---", "-") = "---Hello World" 717 | 718 | End Function 719 | 720 | 721 | Private Function CountUppercaseCharactersTest() As Boolean 722 | 723 | '@Example: =CountUppercaseCharacters("Hello World") -> 2; As the "H" and the "E" are the only 2 uppercase characters in the string 724 | 725 | CountUppercaseCharactersTest = True 726 | 727 | CountUppercaseCharactersTest = CountUppercaseCharactersTest And CountUppercaseCharacters("Hello World") = 2 728 | 729 | End Function 730 | 731 | 732 | Private Function CountLowercaseCharactersTest() As Boolean 733 | 734 | '@Example: =CountLowercaseCharacters("Hello World") -> 8; As the "ello" and the "orld" are lowercase 735 | 736 | CountLowercaseCharactersTest = True 737 | 738 | CountLowercaseCharactersTest = CountLowercaseCharactersTest And CountLowercaseCharacters("Hello World") = 8 739 | 740 | End Function 741 | 742 | 743 | Private Function TextJoinTest() As Boolean 744 | 745 | '@Example: =TextJoin(A1:A3) -> "123"; Where A1:A3 contains ["1", "2", "3"] 746 | '@Example: =TextJoin(A1:A3, "--") -> "1--2--3"; Where A1:A3 contains ["1", "2", "3"] 747 | '@Example: =TextJoin(A1:A3, "--") -> "1----3"; Where A1:A3 contains ["1", "", "3"] 748 | '@Example: =TextJoin(A1:A3, "-") -> "1--3"; Where A1:A3 contains ["1", "", "3"] 749 | '@Example: =TextJoin(A1:A3, "-", TRUE) -> "1-3"; Where A1:A3 contains ["1", "", "3"] 750 | 751 | TextJoinTest = True 752 | 753 | TextJoinTest = TextJoinTest And TextJoin(Array("1", "2", "3")) = "123" 754 | TextJoinTest = TextJoinTest And TextJoin(Array("1", "2", "3"), "--") = "1--2--3" 755 | TextJoinTest = TextJoinTest And TextJoin(Array("1", "", "3"), "--") = "1----3" 756 | TextJoinTest = TextJoinTest And TextJoin(Array("1", "", "3"), "-") = "1--3" 757 | TextJoinTest = TextJoinTest And TextJoin(Array("1", "", "3"), "-", True) = "1-3" 758 | 759 | End Function 760 | 761 | 762 | --------------------------------------------------------------------------------