From fd6c3f1eef41b6c13553ef6f6aed6d508230437c Mon Sep 17 00:00:00 2001 From: yuriy Date: Wed, 1 Mar 2023 23:08:24 -0500 Subject: [PATCH] Added extra error loggint to chrome tab switchin, moved functions to proper libs script --- General-Shared-Functions.ahk | 152 -------------- Selenium-Shared-Functions.ahk | 361 +++++++++++++++++++++++++++------- 2 files changed, 293 insertions(+), 220 deletions(-) diff --git a/General-Shared-Functions.ahk b/General-Shared-Functions.ahk index ce3a62f..126fca8 100644 --- a/General-Shared-Functions.ahk +++ b/General-Shared-Functions.ahk @@ -152,157 +152,6 @@ CheckIfUpdateAvailable(Filepath, CurrentVersion){ } - -CheckSeleniumDriver(){ - try Driver := SChrome_Get("", ChromeProfile := "") ; open new tab page with with specified profile - catch e { - ShowSeleniumErrorMsgbox() - ; Message = Failed to Make Connection to Chrome. Check for Any Open Dialogue Boxes or out of date ChromeDriver - ; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging") - Return "Failed" - } - ; Driver := SChrome_Get("https://www.bitchute.com/", ChromeProfile) ; open new tab page with with specified profile - ; driver.executeScript("return document.readyState").equals("complete") ; wait until page loads completely before proceeding - try driver.executeScript("return document.readyState").equals("complete") ; wait until page loads completely before proceeding - catch e { - ShowSeleniumErrorMsgbox() - ; Message = Failed to send command to Chrome. Check for an Open Dialogue Box. - ; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging") - Return "Failed" - } - DriverStatus := 1 - - if(ReuseTabs) - CreateArrayOfChromeTabs() - - -} - -SeleniumConnectToActiveTab(IP_Port := "127.0.0.1:9222"){ - Driver := ComObjCreate("Selenium.ChromeDriver") - Driver.SetCapability("debuggerAddress", IP_Port) - try Driver.Start() - catch e { - Message = Failed to Connect to Chrome. Showing Error Msgbox - SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging") - ShowSeleniumErrorMsgbox() - ; msgbox, failed to connect to Chrome for some reason. - ; Message = Failed to Connect to Chrome for some reason. - ; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging") - } - return Driver -} - -/* -*/ - -CreateArrayOfChromeTabs() { - Message = Creating an Array of All Chrome Tabs - SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile") - - ; Create an arrays - DriverTitleArray := [] - ChromeTabsURLArray := [] - - try TotalTabsFound := Driver.Windows.Count - ; Message = TotalTabsFound: %TotalTabsFound% - ; DevModeMsgBox(Message) - ; DevModeMsgBox(TotalTabsFound) - -/* ; if only 1 tab exists, grab info, push to array and return - if(TotalTabsFound = 1){ - try Title := Driver.Title - try URL := Driver.URL - - if(Title != "") - DriverTitleArray.Push(Title) - if(URL != "") - ChromeTabsURLArray.Push(URL) - return - } - - */ - ; Msgbox % "TotalTabsFound: " TotalTabsFound - ; if(DevMode) - ; Msgbox % "TotalTabsFound: " TotalTabsFound - ; msgbox % "total Tabs:" Driver.Windows.Count - ; Message = Creating an Array of Chrome Tabs - ; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile") - - ; StartTime := A_TickCount - ; Sleep, 1000 - StartTime := A_TickCount - - - - ; 5 is arbitrary number to do some extra loops to make sure all tabs are gone through - ; most likely not necessary because unloaded tabs cannot be activated - TotalTabLoops := TotalTabsFound + 5 - ; Message = TotalTabLoops: %TotalTabLoops% - ; DevModeMsgBox(message) - - Loop % TotalTabLoops { - Message = Creating an Array of All Chrome Tabs`nCurrent Loop: %A_index%/%TotalTabLoops% (Cannot check on unloaded tabs)`nSometimes might get stuck for a short while if there is something loading in active tab - TooltipThis(Message) - - ; exit after looping through 1 tab, if only 1 tab found in count - if(TotalTabsFound = 1 AND A_index > TotalTabsFound){ - Message = Exiting Early after 1 loop - ; DevModeMsgBox(message) - break - } - - - TabEndTime := A_TickCount - TabFoundStartTime - TabEndTimeArray .= TabEndTime . "," - - - ; Message = Time to switch to new tab: %TabEndTime%`nCurrent Loop: %A_index%/%TotalTabsFound% - ; SaveOrPostProgress(Message:=Message,PostType:="ErrorLoggingTextFile,DiscordErrorLogging") - - TabFoundStartTime := A_TickCount - - ; TimeToGrabCurrentTab := A_TickCount - StartTime - ; Msgbox % "TimeToGrabCurrentTab: " TimeToGrabCurrentTab - - ; Stop page refresh if it's happening - ; try driver.executeScript("return window.stop") - - try Title := Driver.Title - try URL := Driver.URL - - ; TimeToGrabCurrentTab := A_TickCount - StartTime - ; Msgbox % "TimeToGrabCurrentTab: " TimeToGrabCurrentTab - ; VAR := HasVal(ChromeTabsURLArray, STRINGVAR) ; returns position of value in array - -/* - if(HasVal(ChromeTabsURLArray, URL)){ ; returns position of value in array - DevModeMsgBox("Skipping rest of loop and continuing") - Continue - } - - */ - - - if(Title != "") - DriverTitleArray.Push(Title) - if(URL != "") - ChromeTabsURLArray.Push(URL) - - - try driver.SwitchToNextWindow ;Focuses Selenium on the newly opened/next window. - ; DevModeMsgBox("switching to next tab") - } ; end of loop - - ; TimeToLoopThroughAllTabs := A_TickCount - StartTime - ; Message = Time to Loop through all tabs: %TimeToLoopThroughAllTabs% - ; SaveOrPostProgress(Message:=Message,PostType:="ErrorLoggingTextFile,DiscordErrorLogging") - ; DevModeMsgBox(Message) - - return - - } - /* */ @@ -577,4 +426,3 @@ SaveDriverURLOFErrorPage(){ ; save the url of the result page. That way if a tab - diff --git a/Selenium-Shared-Functions.ahk b/Selenium-Shared-Functions.ahk index 95059ef..78b3f87 100644 --- a/Selenium-Shared-Functions.ahk +++ b/Selenium-Shared-Functions.ahk @@ -1,7 +1,215 @@ ; Functions ;------------------------------------------------ + + +ShowSeleniumErrorMsgbox(){ + GetChromeVersionCommand = powershell (Get-Item '%ChromeFilepath%').VersionInfo.ProductVersion + Chromeversion := RunCMD(GetChromeVersionCommand) + ChromeVersion := StrReplace(ChromeVersion, "`n", "") + + ; Clipboard := ChromeVersion + ; Msgbox % "Chromeversion: " Chromeversion + IniRead, PreviousWorkingChromeVersion, Settings.ini, Misc, ChromeVersion, %A_Space% + ; IniWrite, %ChromeVersion%, Settings.ini, Misc, ChromeVersion + ; msgbox, failed to connect to Chrome for some reason. + ; Message = Failed to Connect to Chrome. Most likely problem is either Chrome has some sort of dialogue box open or ChromeDriver needs to be updated. + ; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging") + + OnMessage(0x44, "OnMsgBoxChromeDriverFailed") + MsgBox 0x40043, Error, Failed to Connect to Chrome. `nMost likely issue is either Chrome has some sort of dialogue box open or ChromeDriver needs to be updated.`n`nClick "Reload" to reload the script to try again`nClick "ChromeDriver" to open up the ChromeDriver download page. `n`nClick "Instructions" to open up the instructions website for updating Chromedriver.`n`nPossibly Helpful Info:`nCurrent Chrome Version: %Chromeversion%Chrome Version of Last Successfull Upload: %PreviousWorkingChromeVersion% + OnMessage(0x44, "") + + IfMsgBox Yes, { + ; Reload script + Reload + } Else IfMsgBox No, { + run, https://chromedriver.chromium.org/downloads + ExitApp + ; open chromedriver site + } Else IfMsgBox Cancel, { + URL = https://git.freedomainplaylists.com/yuriy/Freedomain-Social-Media-Poster#installation + run, %url% + } + ExitApp + + } + + + + + +/* +*/ + + ; -------------------------------Tab Navigation & Activation------------------------------- + +CheckSeleniumDriver(){ + try Driver := SChrome_Get("", ChromeProfile := "") ; open new tab page with with specified profile + catch e { + ShowSeleniumErrorMsgbox() + ; Message = Failed to Make Connection to Chrome. Check for Any Open Dialogue Boxes or out of date ChromeDriver + ; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging") + Return "Failed" + } + ; Driver := SChrome_Get("https://www.bitchute.com/", ChromeProfile) ; open new tab page with with specified profile + ; driver.executeScript("return document.readyState").equals("complete") ; wait until page loads completely before proceeding + try driver.executeScript("return document.readyState").equals("complete") ; wait until page loads completely before proceeding + catch e { + ShowSeleniumErrorMsgbox() + ; Message = Failed to send command to Chrome. Check for an Open Dialogue Box. + ; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging") + Return "Failed" + } + DriverStatus := 1 + + if(ReuseTabs) + CreateArrayOfChromeTabs() + + +} + +SeleniumConnectToActiveTab(IP_Port := "127.0.0.1:9222"){ + Driver := ComObjCreate("Selenium.ChromeDriver") + Driver.SetCapability("debuggerAddress", IP_Port) + try Driver.Start() + catch e { + Message = Failed to Connect to Chrome. Showing Error Msgbox + SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging") + ShowSeleniumErrorMsgbox() + ; msgbox, failed to connect to Chrome for some reason. + ; Message = Failed to Connect to Chrome for some reason. + ; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging") + } + return Driver +} + +/* +*/ + +CreateArrayOfChromeTabs() { + Message = Creating an Array of All Chrome Tabs + SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile") + + ; Create an arrays + DriverTitleArray := [] + ChromeTabsURLArray := [] + + try TotalTabsFound := Driver.Windows.Count + ; Message = TotalTabsFound: %TotalTabsFound% + ; DevModeMsgBox(Message) + ; DevModeMsgBox(TotalTabsFound) + +/* ; if only 1 tab exists, grab info, push to array and return + if(TotalTabsFound = 1){ + try Title := Driver.Title + try URL := Driver.URL + + if(Title != "") + DriverTitleArray.Push(Title) + if(URL != "") + ChromeTabsURLArray.Push(URL) + return + } + + */ + ; Msgbox % "TotalTabsFound: " TotalTabsFound + ; if(DevMode) + ; Msgbox % "TotalTabsFound: " TotalTabsFound + ; msgbox % "total Tabs:" Driver.Windows.Count + ; Message = Creating an Array of Chrome Tabs + ; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile") + + ; StartTime := A_TickCount + ; Sleep, 1000 + StartTime := A_TickCount + + + + ; 5 is arbitrary number to do some extra loops to make sure all tabs are gone through + ; most likely not necessary because unloaded tabs cannot be activated + TotalTabLoops := TotalTabsFound + 5 + ; Message = TotalTabLoops: %TotalTabLoops% + ; DevModeMsgBox(message) + + + Message = Creating an Array of All Chrome Tabs`n(Sometimes might get stuck for a short while if there is something loading in a tab) + SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging") + + ; TooltipThis(Message) + + Message = Total Times looping through tabs: %TotalTabLoops% + SaveOrPostProgress(Message:=Message,PostType:="ErrorLoggingTextFile,DiscordErrorLogging") + + Loop % TotalTabLoops { + + + try Title := Driver.Title + try URL := Driver.URL + + + if(Title != "") + DriverTitleArray.Push(Title) + if(URL != "") + ChromeTabsURLArray.Push(URL) + + ; exit after looping through 1 tab, if only 1 tab found in count + if(TotalTabsFound = 1 AND A_index > TotalTabsFound){ + Message = Exiting Early after 1 loop. Only 1 tab found + SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging") + ; DevModeMsgBox(message) + break + } + + + TabEndTime := A_TickCount - TabFoundStartTime + TabEndTimeArray .= TabEndTime . "," + + + ; Message = Time to switch to new tab: %TabEndTime%`nCurrent Loop: %A_index%/%TotalTabsFound% + ; SaveOrPostProgress(Message:=Message,PostType:="ErrorLoggingTextFile,DiscordErrorLogging") + + TabFoundStartTime := A_TickCount + + ; TimeToGrabCurrentTab := A_TickCount - StartTime + ; Msgbox % "TimeToGrabCurrentTab: " TimeToGrabCurrentTab + + ; Stop page refresh if it's happening + ; try driver.executeScript("return window.stop") + + + + ; TimeToGrabCurrentTab := A_TickCount - StartTime + ; Msgbox % "TimeToGrabCurrentTab: " TimeToGrabCurrentTab + ; VAR := HasVal(ChromeTabsURLArray, STRINGVAR) ; returns position of value in array + +/* + if(HasVal(ChromeTabsURLArray, URL)){ ; returns position of value in array + DevModeMsgBox("Skipping rest of loop and continuing") + Continue + } + + */ + + + try driver.SwitchToNextWindow ;Focuses Selenium on the newly opened/next window. + ; DevModeMsgBox("switching to next tab") + } ; end of loop + + ; TimeToLoopThroughAllTabs := A_TickCount - StartTime + ; Message = Time to Loop through all tabs: %TimeToLoopThroughAllTabs% + ; SaveOrPostProgress(Message:=Message,PostType:="ErrorLoggingTextFile,DiscordErrorLogging") + ; DevModeMsgBox(Message) + + return + + } + + +/* +*/ + CheckCurrentTabForCurrentSite(){ try CurrentTabURL := GetCurrentTabURlBase() @@ -17,7 +225,7 @@ CheckCurrentTabForCurrentSite(){ */ -GetCurrentTabURlBase(){ +GetCurrentTabURLBase(){ try, TabURL := driver.url TabURL := ExtractBaseURL(TabURL) return TabURL @@ -55,6 +263,10 @@ NavigateFromBaseURLTo(URL,PageTitle := "TodoDeleteme"){ ; DevModeMsgBox("Creating new tab") Message = Tab for %urlBase% does not exist. Creating new tab with URL: %URL% try, run "%ChromeFilepath%" "%URL%" + catch e { + Message = Trying to Run Chrome with URL failed for some reason. Wrong Chrome filepath? + SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging") + } ChromeTabsURLArray.Push(URL) ; Append the new url to the array NewTabCreated := 1 sleep, 1000 @@ -70,23 +282,27 @@ NavigateFromBaseURLTo(URL,PageTitle := "TodoDeleteme"){ status := ActivateChromeTab(URLBase) if(Status = "Failed"){ - try currentURL := driver.url + try currentURL := GetCurrentTabURLBase() Message = Failed to switch active tab to %URLBase%. Current tab is: %currentURL% SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging") CheckForAlerts() ; create a new tab and try to switch to it again - Message = Creating new tab with URL: %URL% + Message = Creating new Chrome tab with URL: %URL% SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging") try, run "%ChromeFilepath%" "%URL%" + catch e { + Message = Trying to Run Chrome with URL failed for some reason. Wrong Chrome filepath? + SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging") + } ChromeTabsURLArray.Push(URL) ; Append the new url to the array NewTabCreated := 1 sleep, 1000 status := ActivateChromeTab(URL) if(Status = "Failed"){ - Message = Failed to activate tab for %urlBase% after 2 atteppts. Chrome stuck on a dialog box of some sort? + Message = Failed to activate tab for %urlBase% after 2 seperate attempts. Chrome stuck on a dialog box of some sort? SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging") Return "Failed" } @@ -157,27 +373,70 @@ ActivateChromeTab(URL){ TabFoundSuccessfully := - NumberOfTabActivationLoops := ChromeTabsURLArray.Length() + NumberOfTabActivationLoops := ChromeTabsURLArray.Length() + 3 + + Message = Looping through tabs -> %NumberOfTabActivationLoops% <- times to find tab with URL: %urlBase% + SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging") + + try, StartingTabURL := driver.url + ; Message := "NumberOfTabActivationLoops: " NumberOfTabActivationLoops ; DevModeMsgBox(Message) ; NumberOfTabLoops := Driver.Windows.Count + 2 - Message = Looping through tabs to activate with: %URLBase% - SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging") + ; Message = Looping through tabs to activate with: %URLBase% + ; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging") + + ; create empty variable for loop + LastActiveTab := loop % NumberOfTabActivationLoops { ; loop through tabs to find matching tab + UStartTime := A_TickCount ; start time try driver.SwitchToNextWindow() + ; calculate run time and convert to seconds + URunTime := round(((A_TickCount - UStartTime) / 1000), 2) + + + if(URunTime > 5){ + + Message = Time to switch Tabs took %URunTime% seconds + SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging") + } + ; Msgbox % "URunTime: " URunTime + ; sleep, 1000 ; msgbox, looping through tabs try CurrentTabTitle := driver.window.title try CurrentTabURL := driver.Url + if(A_index < 3){ + if(CurrentTabURL = StartingTabURL){ + Message = Current Tab URL is THE SAME as Starting URL after %A_index% tab switches`nStuck on this tab? + SaveOrPostProgress(Message:=Message,PostType:="ErrorLoggingTextFile,DiscordErrorLogging") + CheckForAlerts() + } + else, { + Message = Current Tab URL is DIFFERENT from starting URL after %A_index% tab switches + SaveOrPostProgress(Message:=Message,PostType:="ErrorLoggingTextFile,DiscordErrorLogging") + } + + if(LastActiveTab = CurrentTabURL){ + Message = Chrome is on same tab URL after calling SwitchToNextWindow() function + SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging") + CheckForAlerts() + } + + } + if(InStr(CurrentTabURL, URLBase)){ + TabURL := GetCurrentTabURLBase() + Message = Successfully Found and Activated Tab. URLBase: %urlBase% and currentTabURL: %TabURL% + ; Message = Found Tab:.`n%CurrentTabTitle% = %PageTitle%`n%CurrentTabURL% = %URLBase% ; DevModeMsgBox(message) @@ -187,6 +446,8 @@ ActivateChromeTab(URL){ return } + try, LastActiveTab := driver.URL + ; / loop through tabs } Message = ActivateChromeTab function failed to activate tab for %urlBase% after looping through %NumberOfTabActivationLoops% tabs @@ -289,7 +550,7 @@ SChrome_Get(URL := "", Profile := "Profile 1", IP_Port := "127.0.0.1:9222"){ if(ChromeFilepath = ""){ Message = Failed to find chrome.exe in the usual locations. SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,DiscordErrorLogging") - MsgBox 0x30, Error!, Unable to find Chrome.exe in the usual locations. `nScript Exiting. + MsgBox 0x30, Error!, Unable to find Chrome.exe in the usual locations. `nProgram Exiting. ExitApp } @@ -313,70 +574,34 @@ SChrome_Get(URL := "", Profile := "Profile 1", IP_Port := "127.0.0.1:9222"){ ; -------------------------------/SChrome_Get------------------------------- /* */ -ShowSeleniumErrorMsgbox(){ - GetChromeVersionCommand = powershell (Get-Item '%ChromeFilepath%').VersionInfo.ProductVersion - Chromeversion := RunCMD(GetChromeVersionCommand) - ChromeVersion := StrReplace(ChromeVersion, "`n", "") - ; Clipboard := ChromeVersion - ; Msgbox % "Chromeversion: " Chromeversion - IniRead, PreviousWorkingChromeVersion, Settings.ini, Misc, ChromeVersion, %A_Space% - ; IniWrite, %ChromeVersion%, Settings.ini, Misc, ChromeVersion - ; msgbox, failed to connect to Chrome for some reason. - ; Message = Failed to Connect to Chrome. Most likely problem is either Chrome has some sort of dialogue box open or ChromeDriver needs to be updated. - ; SaveOrPostProgress(Message:=Message,PostType:="Tooltip,ErrorLoggingTextFile,ErrorSummaryVar,DiscordErrorLogging") - OnMessage(0x44, "OnMsgBoxChromeDriverFailed") - MsgBox 0x40043, Error, Failed to Connect to Chrome. `nMost likely issue is either Chrome has some sort of dialogue box open or ChromeDriver needs to be updated.`n`nClick "Reload" to reload the script to try again`nClick "ChromeDriver" to open up the ChromeDriver download page. `n`nClick "Instructions" to open up .pdf file with instructions for updating chromedriver.exe`n`nPossibly Helpful Info:`nCurrent Chrome Version: %Chromeversion%Chrome Version of Last Successfull Upload: %PreviousWorkingChromeVersion% - OnMessage(0x44, "") - - IfMsgBox Yes, { - ; Reload script - Reload - } Else IfMsgBox No, { - run, https://chromedriver.chromium.org/downloads - ExitApp - ; open chromedriver site - } Else IfMsgBox Cancel, { - URL = https://freedomainplaylists.com/wp-content/FreedomainScripts/Update`%20Selenium`%20ChromeDriver.pdf - Filepath = %A_ScriptDir%\Lib\Update Selenium ChromeDriver.pdf - if(!FileExist(Filepath)){ - UrlDownloadToFile, %URL%, %Filepath% - - run, %Filepath% - } - ExitApp - - } - } - - - ; -------------------------------HasVal------------------------------- - ; Function needed for finding a value in an array - HasVal(haystack, needle) - { - if !(IsObject(haystack)) || (haystack.Length() = 0) - return 0 - for index, value in haystack - if (value = needle) - return index - return 0 - } - ; -------------------------------/HasVal------------------------------- - - HasSubstringVal(haystack, needle) - { - if !(IsObject(haystack)) || (haystack.Length() = 0) - return 0 - for index, value in haystack - if (InStr(value, Needle)) - return index - return 0 - } +; -------------------------------HasVal------------------------------- +; Function needed for finding a value in an array +HasVal(haystack, needle) +{ + if !(IsObject(haystack)) || (haystack.Length() = 0) + return 0 + for index, value in haystack + if (value = needle) + return index + return 0 +} +; -------------------------------/HasVal------------------------------- + +HasSubstringVal(haystack, needle) +{ + if !(IsObject(haystack)) || (haystack.Length() = 0) + return 0 + for index, value in haystack + if (InStr(value, Needle)) + return index + return 0 +} - ; SubStr(String, StartingPos [, Length]) +; SubStr(String, StartingPos [, Length]) - ; InStr(value, Needle) +; InStr(value, Needle) /* */