Sub jsInit() ' JavaScript Setup probably called at open_worksheet gJSEnabled = False If FileExists(gLibsPath & "jsdb.dll") Then llib = LoadLibraryW(StrPtr(gLibsPath & "jsdb.dll")) If llib Then gJSEnabled = True End If lJSPath = Replace(gJSPath, "\", "\\") If Right$(lJSPath, 2) = "\\" Then lJSPath = Left(lJSPath, Len(lJSPath) - 2) End If If JSOut <> "" Then gJSOut = JSOut Else gJSOut = lJSPath & "\\JSDB_out.log" End If ' out will collect any debug print()s or writeln()s 'Stop JSScriptOut = gJSOut ' Let JSSSetup = "JSShellExe" - determines the load path not just for the Exe but for all Load()s JSSetup = Replace(gJSPath & "jsdb.exe", "\", "\\") ' In this case I initialise a "global" XLITE for use later lJSScript = "XLITE={};XLITE.ok='OK';XLITE.appDB=null;XLITE.helperDB=null;XLITE.argc=0;XLITE.p=[];XLITE.ok" If JSScript(lJSScript) <> "OK" Then gJSEnabled = False Dim lRet As String lRet = JSScript(lJSScript) End If end sub ' xLiteJSScript Public Function xLiteJSScript(inJSScript As Variant, ParamArray inVarArgs() As Variant) Dim varArgs Dim lLoc As String Dim lerr As Long Dim lScript As String Dim lQScript As String Dim lP As String Dim inFunc As String Dim returnVal Dim lCnt As Long Dim lPCnt As Long Dim i As Long Dim lInP As String Dim lPs As String Dim lInPCnt As Long Dim varArg As Variant Dim rngCell As Range Dim isEmptyCells As Boolean Dim isFunction As Boolean Dim lArray As Variant Dim lRows As Long Dim lCols As Long Dim lRow As Long Dim lCol As Long Dim lStartRow As Long Dim lStartCol As Long Dim lValue As String Dim lText As String Dim lRet As String Dim lScriptSource As Variant If isFuncLocked Then xLiteJSScript = False Exit Function End If If IsMissing(inJSScript) Then xLiteJSScript = False Exit Function End If ' if called from another function passing on an array ' then inVarargs will be an array holding an array varArgs = inVarArgs On Error Resume Next varArg = inVarArgs(LBound(inVarArgs)) ' If inVarArgs(0) = "Variant()" Then If TypeName(varArg) = "Variant()" Then varArgs = inVarArgs(0) End If On Error GoTo 0 If isUDF Then If TypeName(inJSScript) = "Range" Then lScriptSource = xLiteRangeToText(inJSScript) Else lScriptSource = inJSScript End If Else lScriptSource = inJSScript End If isEmptyCells = True lPCnt = 0 For Each varArg In varArgs If Not isEmptyCells Then Exit For If Not IsMissing(varArg) Then ' ' if not a range skip the check ' If TypeName(varArg) = "Range" Then For Each rngCell In varArg lPCnt = lPCnt + 1 If Not isEmptyCells Then Exit For If Not IsEmpty(rngCell) Then isEmptyCells = False Exit For End If Next rngCell Else lPCnt = lPCnt + 1 If Not IsEmpty(varArg) Then isEmptyCells = False End If End If Next varArg ' ' exit function if all input cells are empty ' If isEmptyCells And lPCnt > 0 Then Exit Function End If '1st check if range of named range ' 3rd para of true, indicates only take visible (non filtered) rows lScript = "" If TypeName(lScriptSource) = "Variant()" Then lArray = lScriptSource Else lArray = getArray(lScriptSource, deSQLite, True) End If lRows = UBound(lArray, 1) lStartRow = LBound(lArray, 1) lCols = UBound(lArray, 2) lStartCol = LBound(lArray, 2) 'if still not an array assume script is being passed in the string para 'if a single value assume full script in (1,1) 'otherwise built indented script If lScript <> "" Then ' script provided ElseIf lRows = lStartRow And lCols = lStartCol Then lScript = CStr(lArray(lStartRow, lStartCol)) Else lScript = "" For lRow = lStartRow To lRows i = 0 For lCol = lStartCol To lCols lValue = lArray(lRow, lCol) lValue = Trim$(lValue) If lValue = "" Then lScript = lScript & vbTab Else lScript = lScript & lValue ' stop once an non empty cell found lCol = lCols End If i = i + 1 Next lCol lScript = lScript & vbLf Next lRow End If If lScript = "" Then Exit Function End If ' this allows run & loads to operate in the working folder of the add-in rather than the PATH lScript = Replace(lScript, ":xLiteRun(""", "run(""" & Replace(gJSPath, "\", "\\")) lScript = Replace(lScript, ":xLiteRun('", "run('" & Replace(gJSPath, "\", "\\")) lScript = Replace(lScript, ":xLiteLoad(""", "load(""" & Replace(gJSPath, "\", "\\")) lScript = Replace(lScript, ":xLiteLoad('", "load('" & Replace(gJSPath, "\", "\\")) If Left$(LTrim(lScript), 8) = "function" Then isFunction = True Else isFunction = False End If ' if a function (i.e. will no execute now) then offer token replacement ' otherwise build up XLITE.p[] args If isFunction Then ' replace tokens in script with args i.e :1 replaced with 1st argument, :2 with 2nd and so on lText = Replace(lScript, ":", ">" & vbLf & ">") lInPCnt = 0 For Each varArg In varArgs If Not IsMissing(varArg) Then If TypeName(varArg) = "Range" Then For Each rngCell In varArg lInPCnt = lInPCnt + 1 lInP = CStr(rngCell.value) lText = textItemBinder(lText, lInPCnt, lInP) Next rngCell Else lInPCnt = lInPCnt + 1 lInP = CStr(varArg) lText = textItemBinder(lText, lInPCnt, lInP) End If End If Next varArg lScript = Replace(lText, ">" & vbLf & ">", ":") Else lPs = "XLITE.p=[];" lInPCnt = 0 For Each varArg In varArgs If Not IsMissing(varArg) Then If TypeName(varArg) = "Range" Then For Each rngCell In varArg lInPCnt = lInPCnt + 1 lInP = CStr(rngCell.value) If Not IsNumeric(lInP) Then lInP = """" & lInP & """" lPs = lPs & "XLITE.p[" & CStr(lInPCnt) & "]=" & lInP & ";" Next rngCell Else lInPCnt = lInPCnt + 1 lInP = CStr(varArg) If Not IsNumeric(lInP) Then lInP = """" & lInP & """" lPs = lPs & "XLITE.p[" & CStr(lInPCnt) & "]=" & lInP & ";" End If End If Next varArg lPs = lPs & "XLITE.p[0]=" & CStr(lInPCnt) & ";XLITE.ok;" & vbCrLf ' Discovered 'delete', no longer needed ' MAXjsUID is in effect the maximum depth of xLiteJSScipt recursion 'If jsUID > MAXJSUID Then ' jsUID = 1 'Else ' jsUID = jsUID + 1 'End If jsUID = jsUID + 1 If (jsUID Mod JSGCEVERY) = 0 Then ' a null script forces the JS Garbage Collector to run lRet = JSScript("") End If End If lScript = lScript & ";" If isFunction Then ' if pre compile set If jsPreCompile Then lRet = "var err=system.compile(""" & Replace(Replace(lScript, """", "\"""), vbCrLf, "") & """);err;" lRet = JSScript(lRet) If lRet <> "" Then xLiteJSScript = "ABEND - error in JS Script Function " & lRet Exit Function End If End If lRet = JSScript(lScript) If lRet <> "OK" Then xLiteJSScript = "ABEND - error in JS Script Function see " & gJSOut Else xLiteJSScript = lRet End If Exit Function Else lRet = JSScript(lPs) If lRet <> "OK" Then xLiteJSScript = "ABEND - bad arguments " & lPs Exit Function End If lScript = "xLiteAnonFunc_" & CStr(jsUID) & "=function (xLite) {" & vbCrLf & lScript & vbCrLf & "};XLITE.ok;" & vbCrLf If jsPreCompile Then lRet = "var err=system.compile(""" & Replace(Replace(lScript, """", "\"""), vbCrLf, "") & """);err;" & vbCrLf lRet = JSScript(lRet) If lRet <> "" Then xLiteJSScript = "ABEND - error in JS Script Function " & lRet Exit Function End If End If lRet = JSScript(lScript) If lRet <> "OK" Then xLiteJSScript = "ABEND - error in JS Script see " & gJSOut Exit Function Else lRet = JSScript("xLiteAnonFunc_" & CStr(jsUID) & "(XLITE);") If IsNumeric(lRet) Then xLiteJSScript = CDbl(lRet) Else xLiteJSScript = lRet End If ' finished with it, use delete to recover memory lRet = JSScript("delete xLiteAnonFunc_" & CStr(jsUID) & ";") End If End If End Function Public Function textItemBinder(inText As String, inBind As Long, inItem As Variant) As String Dim lPlace As String Dim lReplace As String Dim lText As String Dim lbind As Long On Error GoTo FuncFail: lText = inText lbind = inBind ' replace :1: first , these are quoted lPlace = ">" & vbLf & ">" & CStr(lbind) & ">" & vbLf & ">" lReplace = CStr(inItem) lReplace = Replace(lReplace, """", """""") lReplace = """" & lReplace & """" lText = Replace(lText, lPlace, lReplace) lPlace = ">" & vbLf & ">" & CStr(lbind) lReplace = CStr(inItem) lText = Replace(lText, lPlace, lReplace) textItemBinder = lText Exit Function FuncFail: textItemBinder = "" End Function ' Public Function xLiteJSDebugOn() jsPreCompile = True End Function Public Function xLiteJSDebugOff() jsPreCompile = False End Function