├── #ID.calc ├── #IDExclude.calc ├── #IDReplace.calc ├── #IDUpdate.calc ├── #IDValue.calc ├── #Merge.calc ├── .gitignore ├── AppleScriptArrayFinal.calc ├── AppleScriptChooseColor.calc ├── AppleScriptChooseDir.calc ├── AppleScriptCreateEventInICal.fmfn ├── AppleScriptDirPath.calc ├── AppleScriptFilePaths.calc ├── AppleScriptFilePathsInDir.calc ├── AppleScriptFilePathsInDirPrompt.calc ├── AppleScriptGetPageSource.calc ├── AppleScriptLDAPLookup.calc ├── AppleScriptMakeDirOnDesktop.calc ├── AppleScriptMountVolume.calc ├── AppleScriptMoveFiles.calc ├── AppleScriptMoveFiles_ShellMethod.calc ├── AppleScriptOpenInSafari.calc ├── AppleScriptPerformScript.calc ├── AppleScriptPerformScripts.calc ├── AppleScriptReadFile.calc ├── AppleScriptSendEmail.calc ├── AppleScriptSort.calc ├── AppleScriptSortFull.calc ├── AppleScriptSystemProfiler ├── ArrayCell.calc ├── ArrayColumn.calc ├── ArrayColumnLoop.calc ├── ArrayCountInColumn.calc ├── ArrayRow.calc ├── ArrayRowLoop.calc ├── ArrayToHTMLTable.calc ├── ArrayToHash.calc ├── ArrayTranspose.calc ├── ArrayTransposeLoop.calc ├── ArrayValueNext.calc ├── Borrowed ├── ListApplyToValues.calc ├── ListCustom.calc ├── ListCustomCombined.calc ├── ListFilterCustom.calc ├── ListFilterValuesByTest ├── ListSort.calc ├── ListSortDates.calc ├── ListSortDatesLoop.calc ├── ListSortDesc.calc ├── ListSortDescLoop.calc ├── ListSortLoop.calc ├── ListUniqueValues.calc ├── ListUniqueValuesCustom.calc ├── TabActive.calc ├── TabFrontMost.calc ├── TabFrontMostLoop.calc ├── TextAsDate.calc ├── TextRandom.calc ├── app.growlMessage.calc ├── date.weekOfYearFiscal.calc ├── domain.formatPhone.calc ├── layout.tabsSelected.calc ├── num.applyToRange.calc ├── text.ascii.fmfn ├── text.maskReplace.calc └── text.trimCR ├── CodeMerge.calc ├── CodeMergeLinks.calc ├── CommaDelimit.calc ├── ContainerFileName.calc ├── ContainerStorageType.calc ├── DateBuildRangeHeaders.calc ├── DateBuildSearchRange.calc ├── DateMinusMonths.calc ├── DateMonthDays.calc ├── DateMonthName.calc ├── DateMonthNumber.calc ├── DatePadded.calc ├── DateRangeFromLabel.calc ├── DateShortHand.calc ├── DateWeekStart.calc ├── DateWeekdaysInRange.calc ├── DateWorkdaysInMonth.calc ├── DatesFrom.calc ├── DatesFromFull.calc ├── DatesFromLoop.calc ├── DatesHolidayList.calc ├── DatesInRange.calc ├── DatesInRangeFull.calc ├── DatesInRangeLoop.calc ├── Deprecated ├── VarInvalid.calc └── VarInvalidLoop.calc ├── DialogDataInputs.calc ├── DialogDataInputsLoop.calc ├── EmailCSSForTable.calc ├── ErrorSuppressionOff.calc ├── ErrorSuppressionOffGlobal.calc ├── ErrorSuppressionOn.calc ├── ErrorText.calc ├── ErrorText11.calc ├── ErrorTextAppleScript.calc ├── ErrorTextAutoUpdate.calc ├── ErrorTextSDialog.calc ├── ErrorsAreSuppressed.calc ├── FOCUS-Specific ├── #DialogResult.calc ├── DialogResultsChecked.calc ├── ExtractTableName.calc ├── IDCreate.calc ├── LayoutBasetable.calc ├── MessageDelete.calc ├── MessageRemove.calc ├── ParamQuery.calc ├── ParamQueryRequest.calc ├── TableIDRemove.calc ├── TableIDRemoveLoop.calc └── dialog.inputCheckboxes.calc ├── FieldIsQualified.calc ├── FieldNameShort.calc ├── FieldNotEmpty.calc ├── FieldOccurrences.calc ├── FieldRepMatch.calc ├── FieldSortValue.calc ├── FieldSortValues.calc ├── FieldSortValuesLoop.calc ├── FieldsEmpty.calc ├── FileNameEncodeForPath.calc ├── FileNameFromPaths.calc ├── FileNameFromPathsLoop.calc ├── FileNameWithExtension.calc ├── FilePathConvert.txt ├── FileSlash.calc ├── FileView.calc ├── FileViewConditional.calc ├── FileViewRaw.calc ├── GetAsBooleanCustom.calc ├── GetRelatedByValue.calc ├── IsMac.calc ├── IsServer.calc ├── IsWebPublished.calc ├── IsWindows.calc ├── JSONArray.calc ├── JSONArrayGet ├── JSONArrayLoop.calc ├── JSONArrayPosition.calc ├── JSONArrayToVariables.calc ├── JSONArrayValue.calc ├── JSONDecode.calc ├── JSONEncode.calc ├── JSONEncodeStringOnly.calc ├── JSONFromHash.calc ├── JSONFromHashNames ├── JSONObject.calc ├── JSONObjectLoop.calc ├── JSONPair.calc ├── JSONPath.calc ├── JSONValue.calc ├── JSONValueNth.calc ├── JSONWhitespace ├── JavaVersion.calc ├── JsonEscapeChars.calc ├── JsonPretty.calc ├── LibField.calc ├── LibText.calc ├── ListAddOrRemove.calc ├── ListAddUnique.calc ├── ListAggregateNthRecordValues.calc ├── ListAggregateRelatedSets.calc ├── ListAppendPrecedingValues.calc ├── ListAppendUnique.calc ├── ListChartRelatedValues.calc ├── ListChunk.calc ├── ListChunkLoop.calc ├── ListContains.calc ├── ListDateFromNumber.calc ├── ListDateToNumber.calc ├── ListFilter.calc ├── ListFilterSub.calc ├── ListFoundValues.calc ├── ListGetValueIndexes.fmfn ├── ListIndex.calc ├── ListIndexContaining.calc ├── ListIndexLoop.calc ├── ListJoin.calc ├── ListModifyValues.calc ├── ListPrependBOM.calc ├── ListRemoveEmptyValues.calc ├── ListRemoveSuccessiveDuplicates.calc ├── ListRemoveSuccessiveDuplicatesLoop.calc ├── ListReplaceValue.calc ├── ListSortByList.calc ├── ListSortByListLoop.calc ├── ListSortByValueList.calc ├── ListSortDates.calc ├── ListStrip.calc ├── ListToggleValue.calc ├── ListTrimAndJoin.calc ├── ListTrimValues.calc ├── ListTrimValuesLoop.calc ├── ListUnique_v2.calc ├── ListWithNull.calc ├── ListWithNullLoop.calc ├── LogAdd.calc ├── LogDelimiter.calc ├── LogExtract.calc ├── LogFormat.calc ├── MVLSet.calc ├── MVLSetList.calc ├── MVLSetListSorted.calc ├── MapRouteURL.calc ├── MenuRevealIsOn.calc ├── MessageInvalidVar.calc ├── NavLayoutRank.calc ├── NavViewLayout.calc ├── NumberAsDollars.calc ├── ParamAssign.calc ├── ParamValidate.calc ├── ParamValidateMessage.calc ├── PathDir.calc ├── PathFileName.calc ├── PathForAppleScript.calc ├── PathForFMP.calc ├── PathForImport.calc ├── PathForOpenURL.calc ├── PathForScriptMaster.calc ├── PathForShell.calc ├── PathForWebViewer.calc ├── PathFromHome.calc ├── PathPosix.calc ├── PathSet.calc ├── PathStripDisk.calc ├── PathStripPrefix.calc ├── PositionIgnoring.calc ├── PositionUnescaped.calc ├── Project-Specific ├── AmountProratedForMonth.calc ├── CodeLabel.calc ├── ConvertFieldContext.calc ├── CriterionDecode.calc ├── DatabaseModule.calc ├── DateFromString.calc ├── EncodeForHTMLScript.calc ├── FieldNameReadable.calc ├── FilePathForWebViewer.calc ├── FilterIsCustom.calc ├── FocusLocationTab.txt ├── GenerateRange.calc ├── LogForField.calc ├── ParamLogForField.calc ├── ParamLogForRelatedField.calc ├── ResourceData.calc ├── ResourceInclude.calc ├── ScriptTriggersAreOff.calc ├── ScriptTriggersOff.calc ├── ScriptTriggersOn.calc ├── TemplateMerge.calc ├── TimeIncrement.calc ├── TooltipQueryTips.calc ├── WebBubbleButtons.calc ├── WeekdaysOffset.calc ├── text.getBetweenAll.calc └── time.getMicro.calc ├── PythonSendMailScript.calc ├── README ├── RGBToCSS.calc ├── RGBToHex.calc ├── SQLDate.calc ├── SQLDebug.calc ├── SQLField.calc ├── SQLFieldSeparator.calc ├── SQLFunctions.zip ├── SQLResponse.calc ├── SQLRowSeparator.calc ├── SQLString.calc ├── SQLTable.calc ├── ScriptMasterDependent ├── HTMLGetCellRight.calc ├── HTMLGetRow.calc └── HTMLGetRowCell.calc ├── ScriptTraceAdd.calc ├── ScriptTraceIsOn.calc ├── ScriptTraceOff.calc ├── ScriptTraceOn.calc ├── SecondsAsString.calc ├── SetIfEmpty.calc ├── SetNotEmpty.calc ├── SqFieldListLoop.calc ├── SqGet.calc ├── SqGetByID.calc ├── SqGetColumn.calc ├── SqGetFields.calc ├── SqGetLike ├── SqGetLiteral ├── SqListLoop ├── SqResponseAsDate.calc ├── SqResponseAsDateNumber.calc ├── SqStringSmart.calc ├── StringRepeat.calc ├── StringRepeatLoop.calc ├── StringToList.calc ├── SuperContainerGetFile.calc ├── SuperContainerViewRawTypes.calc ├── SystemProperties.calc ├── TextAsBoolean.calc ├── TextAsDate.calc ├── TextAsDateSub.calc ├── TextBeginsWith.calc ├── TextBetween.calc ├── TextCapitalizeFirstLetters.calc ├── TextCleanQuotes.calc ├── TextClosePosition.fmfn ├── TextEncodeForAppleScript.calc ├── TextEncodeForFilePath.calc ├── TextEncodeForHTML.calc ├── TextEncodeUTF8Hex.calc ├── TextEscapeForCSV.calc ├── TextEscapeSearchChars.calc ├── TextFilterResult.calc ├── TextFilterResult_subA.calc ├── TextFilterToText.calc ├── TextFormatBullets.calc ├── TextFormatLoop.calc ├── TextInjected?.calc ├── TextInsertAtCursor.calc ├── TextIsDate.calc ├── TextMergeTags.calc ├── TextNthNodePosition.calc ├── TextOmitChars.calc ├── TextPadColumn.calc ├── TextPrependWithTimestamp.calc ├── TextProperLines.calc ├── TextRandom.calc ├── TextRepeatWithIncrement.calc ├── TextReplaceString.calc ├── TextReplaceString_sub.calc ├── TextSplit.calc ├── TextStripLeft.calc ├── TextStripRight.calc ├── TextWrapString.calc ├── TimeDurationAsText.calc ├── TimeStampAsZulu.calc ├── TimeStampMicroUTC.calc ├── TimeZone.calc ├── TimestampFromText.calc ├── TimestampFromUnix.calc ├── TimestampMicro.calc ├── TraceAdd.calc ├── TraceAddSQL.calc ├── TraceClear.calc ├── TraceIsOn.calc ├── TraceLog.calc ├── TraceOff.calc ├── TraceOn.calc ├── TrimCR.calc ├── TrimCRLF.calc ├── TrimCRLeft.calc ├── TrimCRRight.calc ├── TrimChar.calc ├── TrimWhitespace.calc ├── TrimWhitespaceLeft.calc ├── URLDecoded.calc ├── URLEncode ├── URLHash.calc ├── URLParam.calc ├── URLSelf.calc ├── UserIsFullAccess.calc ├── VarAssign.calc ├── VarAssign.fmfn ├── VarAssignLoop.calc ├── VarAssignMan.calc ├── VarAssignWithLog.fmfn ├── VarInvalid.calc ├── VarInvalidLoop.calc ├── VarSet.fmfn ├── VarSetFull.calc ├── VarUpdate.fmfn ├── VarValidate.calc ├── VarValidate2.calc ├── VarValidateLoop.calc ├── WebGif.calc ├── WebNavHeader.calc ├── WebNavHeaderSub.calc ├── WebProgressBar.calc ├── WebSpinningIcon.calc ├── WebViewerFieldDisplay.calc ├── Weekdays.calc ├── WindowGetMeasurements.calc ├── WindowSetMeasurements.calc ├── WindowSetMeasurementsSub.calc ├── WorkHoursOffset.calc ├── calc.hideInvalid.calc ├── calc_Let#Assign.calc ├── calc_PortalSelections.calc ├── calc_PythonSendMail.calc ├── calc_StripDisk.calc ├── calc_getApplicationVersion.calc ├── dev.getScriptName.txt ├── dev.layoutNamesPrefixed.calc ├── domain.convertState.calc ├── domain.formatAddress.calc ├── nav.measureWindow.fmfn ├── nav.setWindowSettings.fmfn ├── plugin.dialogResults.calc ├── rec.getValidRelationships.fmfn ├── rec.hasValidRelationships.fmfn ├── rec.sortFieldValue.calc ├── script.logError.calc ├── sqlList.calc ├── test.compareFields.calc ├── test.sortDisplay.calc ├── web.bubbleButtons.calc ├── web.bubbleButtons_pure.calc ├── web.dataStore.calc ├── xml.select.fmfn ├── xml.select_subA.fmfn ├── xml.select_subB.fmfn ├── xml.transform.fmfn ├── xml.update.fmfn ├── xml.verify.fmfn └── zJSHighlight.calc /#ID.calc: -------------------------------------------------------------------------------- 1 | "<:" & table & ":=¶" & 2 | listOfIDs & ¶ & 3 | ":>" 4 | 5 | /* __________________________________________________ 6 | 7 | NAME: #ID ( table ; listOfIDs ) 8 | PURPOSE: Wraps an encoding tag around a list of IDs. When used in conjunction with decoding functions, allows large groups of IDs from the same table to be stuffed into a field containing IDs from many tables, and the quick extraction of just those IDs, or all IDS but those IDs. 9 | EXAMPLES: 10 | #ID ( "PERSON"; "ID1¶ID2¶ID3" ) = "<:PERSON¶ID1¶ID2¶ID3¶:>" 11 | HISTORY: 12 | Created: 2010-02-08 15:54 PT - Will M. Baker 13 | Modified: 2012-09-24 13:33 PT - Donovan Chandler : Made compatible with normal #Value(). 14 | */ -------------------------------------------------------------------------------- /#IDExclude.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | tag = "<:" & table & ":=¶" ; 3 | tagStart = Position ( listOfIDs ; tag ; 1 ; 1 ) ; 4 | tagEnd = Position ( listOfIDs ; "¶:>" ; tagStart ; 1 ) + 2 ; 5 | listLength = Length ( listOfIDs ) 6 | ] ; 7 | 8 | Case ( 9 | PatternCount ( listOfIDs ; tag ) = 0 ; listOfIDs ; 10 | tagEnd ≥ listLength ; Left ( listOfIDs ; tagStart - 2 ) ; 11 | Left ( listOfIDs ; tagStart - 1 ) & Middle ( listOfIDs ; tagEnd + 1 ; listLength ) 12 | ) 13 | 14 | ) 15 | 16 | /* __________________________________________________ 17 | 18 | NAME: #IDExclude ( listOfIDs ; table ) 19 | PURPOSE: Retrieves a set of IDs from a table-encoded list, excluding the chunk of IDs corresponding to the specified table. 20 | EXAMPLES: 21 | 22 | HISTORY: 23 | Created: 2010-02-08 15:54 PT - Will M. Baker 24 | Modified: 2012-09-24 13:37 PT - Donovan Chandler : Formatting; made compatible with #( ) 25 | */ 26 | -------------------------------------------------------------------------------- /#IDReplace.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | all = listOfIDs ; 3 | allFiltered = #IDExclude ( all ; table ) ; 4 | tableOrig = TrimCR ( # ( all ; table ) ) 5 | ] ; 6 | List ( 7 | #ID ( table ; newValue ) ; 8 | allFiltered 9 | ) 10 | ) 11 | 12 | /* __________________________________________________ 13 | 14 | NAME: #IDReplace ( listOfIDs ; table ; newValue ) 15 | PURPOSE: Adds or replaces list of ID's for given table. 16 | Modifies order of name-value pairs in favor of using existing functions. 17 | EXAMPLES: 18 | 19 | HISTORY: 20 | Created: 2012-09-24 14:01 PT - Donovan Chandler 21 | Modified: 22 | */ -------------------------------------------------------------------------------- /#IDUpdate.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | all = listOfIDs ; 3 | allFiltered = #IDExclude ( all ; table ) ; 4 | tableOrig = #IDValue ( all ; table ) ; 5 | tableNew = 6 | Case( 7 | /*-- Multiple selection allowed */ 8 | multipleSelectionEnabled ; 9 | ListAddOrRemove ( tableOrig ; selectedID ); 10 | 11 | /*-- Add or remove single selection */ 12 | tableOrig = selectedID ; "" ; 13 | 14 | selectedID 15 | ) 16 | ] ; 17 | List ( 18 | #ID ( table ; tableNew ) ; 19 | allFiltered 20 | ) 21 | ) 22 | 23 | /* __________________________________________________ 24 | 25 | NAME: #IDUpdate ( listOfIDs ; table ; selectedID ; multipleSelectionEnabled ) 26 | PURPOSE: Updates existing list of ID's for given table. 27 | Used to add/remove a single id value. 28 | Modifies order of name-value pairs in favor of using existing functions. 29 | EXAMPLES: 30 | 31 | HISTORY: 32 | Created: 2012-09-24 14:01 PT - Donovan Chandler 33 | Modified: 34 | */ -------------------------------------------------------------------------------- /#IDValue.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | tag = "<:" & table & ":=¶" ; 3 | dataStart = Position ( listOfIDs ; tag ; 1 ; 1 ) + Length ( tag ) ; 4 | dataEnd = Position ( listOfIDs ; "¶:>" ; dataStart ; 1 ) 5 | ] ; 6 | 7 | Case ( 8 | Position ( listOfIDs ; tag ; 1 ; 1 ) = 0 ; "" ; 9 | Middle ( listOfIDs ; dataStart ; dataEnd - dataStart ) 10 | ) 11 | 12 | ) 13 | 14 | /* __________________________________________________ 15 | 16 | NAME: #IDValue ( listOfIDs ; table ) 17 | PURPOSE: Retrieves a set of IDs from an encoded list of tables. 18 | EXAMPLES: 19 | 20 | HISTORY: 21 | Created: 2010-02-08 15:54 PT - Will M. Baker 22 | Modified: 2012-09-24 14:40 PT - Donovan Chandler : Formatting; switched parameter order. 23 | */ 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Private/ -------------------------------------------------------------------------------- /AppleScriptArrayFinal.calc: -------------------------------------------------------------------------------- 1 | "{" & 2 | Substitute ( TextStripRight ( unenclosedArray ; "," ) ; 3 | [ "}, ¶{" ; "},{" ] ; 4 | [ "},¶{" ; "},{" ] ; 5 | [ "}¶}" ; "}}" ] ; 6 | [ "{¶{" ; "{{"] 7 | ) 8 | & "}" 9 | 10 | /* __________________________________________________ 11 | 12 | NAME: AppleScriptArrayFinal ( unenclosedArray ) 13 | PURPOSE: Formats array for use in AppleScript 14 | Removes carriage returns and extraneous commas 15 | EXAMPLES: 16 | AppleScriptArrayFinal ( "{foo:123},¶{bar:345}," ) 17 | = "{{foo:123},{bar:345}}" 18 | HISTORY: 19 | 2014-07-24 08:09 PT - Donovan Chandler 20 | */ -------------------------------------------------------------------------------- /AppleScriptMakeDirOnDesktop.calc: -------------------------------------------------------------------------------- 1 | "tell application \"Finder\"¶ 2 | set dirPath to path to desktop¶ 3 | make new folder at dirPath with properties {name:\"" & folderName & "\"}¶ 4 | end tell" 5 | 6 | /* —————————————————————————————— // 7 | NAME: 8 | AppleScriptMakeDirOnDesktop ( folderName ) 9 | 10 | PURPOSE: 11 | Creates file on user's desktop 12 | 13 | EXAMPLES: 14 | 15 | 16 | HISTORY: 17 | Created: 2011-Jul-22 10h17 PST — Donovan A. Chandler 18 | */ -------------------------------------------------------------------------------- /AppleScriptSort.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | field = sortField ; 3 | order = 4 | Case ( 5 | sortDescending ; "descending" ; 6 | "ascending" 7 | ) ; 8 | doc = Get ( FileName ) 9 | ] ; 10 | 11 | "tell current layout of document " & "\"" & doc & "\"¶ 12 | sort by field " & "\"" & field & "\"" & " in order " & order & "¶ 13 | end tell" 14 | 15 | ) 16 | 17 | /* —————————————————————————————— // 18 | NAME: 19 | AppleScriptSort ( sortField ; sortDescending ) 20 | 21 | PURPOSE: 22 | Provides dynamic sort on Mac OS using AppleScript. 23 | 24 | EXAMPLES: 25 | 26 | 27 | HISTORY: 28 | Created: 2010-May-25 18h16 PST — Donovan A. Chandler 29 | 30 | NOTES: 31 | BEWARE, sortField must be visible on layout! 32 | */ -------------------------------------------------------------------------------- /ArrayCell.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | row = 3 | TextBetween ( rowDelimiter & array & rowDelimiter ; 4 | rowDelimiter ; 5 | rowDelimiter ; 6 | rowIndex 7 | ) ; 8 | cell = 9 | TextBetween ( columnDelimiter & row & columnDelimiter ; 10 | columnDelimiter ; 11 | columnDelimiter ; 12 | columnIndex 13 | ) 14 | ] ; 15 | cell 16 | ) 17 | 18 | /* __________________________________________________ 19 | 20 | NAME: ArrayCell ( array ; columnIndex ; columnDelimiter ; rowIndex ; rowDelimiter ) 21 | PURPOSE: Returns cell value from 2-dimensional array 22 | EXAMPLES: 23 | ArrayCell ( "City|State¶Oakland|CA¶Portland|OR" ; 2 ; "|" ; 2 ; ¶ ) = "CA" 24 | HISTORY: 25 | Created: 2012-10-12 19:06 PT - Donovan Chandler 26 | Modified: 2012-05-25 11:27 PT - Donovan Chandler : Added rowDelimiter param; now uses TextBetween( ). 27 | */ -------------------------------------------------------------------------------- /ArrayColumn.calc: -------------------------------------------------------------------------------- 1 | ArrayColumnLoop ( array ; columnIndex ; columnDelimiter ; rowDelimiter ; "" ) 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: ArrayColumn ( array ; columnIndex ; columnDelimiter ; rowDelimiter ) 6 | PURPOSE: Returns entire row from 2-dimensional array. 7 | TESTS: 8 | 9 | HISTORY: 10 | Created: 2011-10-24 19:40 PST — Donovan Chandler 11 | Modified: 2014-03-20 12:22 PDT - Donovan Chandler : Added rowDelimiter parameter. 12 | */ -------------------------------------------------------------------------------- /ArrayCountInColumn.calc: -------------------------------------------------------------------------------- 1 | ValueCount ( 2 | FilterValues ( ArrayColumn ( array ; columnIndex ; columnDelimiter ) ; searchString ) 3 | ) 4 | 5 | /* —————————————————————————————— // 6 | NAME: 7 | ArrayCountInColumn ( array ; searchString ; columnIndex ; columnDelimiter ) 8 | 9 | PURPOSE: 10 | Returns number of cells in specified column of a 2-dimensional array that match 'searchString' 11 | 12 | DEPENDENCIES: 13 | Custom Functions: ArrayColumn ( ) 14 | 15 | HISTORY: 16 | Created: 2011-Oct-24 20h03 PST — Donovan A. Chandler 17 | */ -------------------------------------------------------------------------------- /ArrayRow.calc: -------------------------------------------------------------------------------- 1 | ArrayRowLoop ( array; searchValue; searchColumn; 1 ) 2 | 3 | /*--------------------------------------------------------------------------------------- 4 | NAME: 5 | ArrayRow ( array; searchValue; searchColumn ) 6 | 7 | PURPOSE: 8 | Wrapper for RowValueSearchLoop(). See that function documentation for details. 9 | 10 | HISTORY: 11 | Created 2010-Mar-22 11h52 PT donovan_c@beezwax.net 12 | ---------------------------------------------------------------------------------------*/ -------------------------------------------------------------------------------- /ArrayToHTMLTable.calc: -------------------------------------------------------------------------------- 1 | "¶¶¶
" & 2 | Substitute ( 3 | array ; 4 | [ rowDelimiter ; "
" ] ; 5 | [ columnDelimiter ; "" ] 6 | ) & 7 | "
" 8 | 9 | 10 | /* __________________________________________________ 11 | 12 | NAME: ArrayToHTMLTable ( array ; rowDelimiter ; columnDelimiter ) 13 | PURPOSE: Converts tabular array into HTML table 14 | EXAMPLES: 15 | ArrayToHTMLTable ( "Animal|Food¶Dragon|livestock" ; "¶" ; "|" ) 16 | //= " 17 | 18 | 19 |
AnimalFood
Dragonlivestock
" 20 | HISTORY: 21 | Created: 2013-01-10 11:00 PT - Donovan Chandler 22 | Modified: 23 | */ -------------------------------------------------------------------------------- /ArrayTranspose.calc: -------------------------------------------------------------------------------- 1 | ArrayTransposeLoop ( array ; columnDelimiter ; "" ) 2 | 3 | /* —————————————————————————————— // 4 | NAME: 5 | ArrayTranspose ( array ; columnDelimiter ) 6 | 7 | PURPOSE: 8 | Inverts axis of tabular array by moving first row to first column and so forth. 9 | 10 | EXAMPLES: 11 | ArrayTranspose ( "A-B-C¶1-2-3" ; "-" ) 12 | = "A-1¶B-2¶C-3" 13 | 14 | HISTORY: 15 | Created: 2011-Oct-24 20h21 PST — Donovan A. Chandler 16 | */ -------------------------------------------------------------------------------- /ArrayTransposeLoop.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | column = ArrayColumn ( array ; 1 ; columnDelimiter ) ; 3 | newRow = Substitute ( column ; columnDelimiter ; ¶ ) ; 4 | newArray = If ( not IsEmpty ( previousResults ) ; previousResults & ¶ ) & newRow 5 | ] ; 6 | ArrayTransposeLoop ( 7 | RightValues ( array ; ValueCount ( array ) - 1 ) ) ; 8 | columnDelimiter ; 9 | newArray 10 | ) 11 | ) 12 | 13 | /* —————————————————————————————— // 14 | NAME: 15 | ArrayTranspose ( array ; columnDelimiter ; previousResults ) 16 | 17 | PURPOSE: 18 | Perform recursion for ArrayTranspose() 19 | 20 | HISTORY: 21 | Created: 2011-Oct-24 20h14 PST — Donovan A. Chandler 22 | */ -------------------------------------------------------------------------------- /ArrayValueNext.calc: -------------------------------------------------------------------------------- 1 | Let([ 2 | _row = ArrayRow ( array; rowHeader; headerColumn ); 3 | _rowNum = ListValueRowNum( Substitute( _row; Tab; ¶ ); searchValue ); 4 | _rowNumNext = If( _rowNum > 0; _rowNum + 1; "" ) 5 | ]; 6 | Case( 7 | //-- Column is valid 8 | _rowNum > 0; 9 | RowValue( _row; _rowNumNext ); 10 | 11 | //-- Column not found 12 | "" 13 | ) 14 | ) 15 | 16 | /*--------------------------------------------------------------------------------------- 17 | NAME: 18 | ArrayValueNext ( array ; rowHeader ; headerColumn ; searchValue ) 19 | 20 | PURPOSE: 21 | Finds row in array (tab-delimited) that corresponds to rowHeader in headerColumn. 22 | Then returns value from column following searchValue. 23 | 24 | HISTORY: 25 | Created 2010-Mar-22 12h44 donovan_c@beezwax.net 26 | 27 | EXAMPLE: 28 | If $_array = 29 | "A » pear » apple¶ 30 | B » ball » bat¶ 31 | C » dog » cat¶ 32 | B » can » bottle¶" 33 | 34 | where " » " represents tab character, then : 35 | 36 | ArrayValueNext ( $_array ; "B" ; 1 ; "ball" ) returns "bat". 37 | ---------------------------------------------------------------------------------------*/ -------------------------------------------------------------------------------- /Borrowed/ListSortDescLoop.calc: -------------------------------------------------------------------------------- 1 | Case( 2 | (ValueCount( list1 ) < 1) or (ValueCount( list2 ) < 1); 3 | Case( ValueCount( list1 ) < 1; list2; list1 ); 4 | 5 | GetValue( list1; 1 ) > GetValue( list2; 1 ); 6 | GetValue( list1; 1 ) & "¶" & 7 | ListSortDescLoop( RightValues( list1; ValueCount( list1 ) - 1 ); list2); 8 | 9 | GetValue( list2; 1 ) & "¶" & 10 | ListSortDescLoop( list1; RightValues( list2; ValueCount( list2 ) - 1 ) ) 11 | 12 | ) 13 | 14 | /* —————————————————————————————— // 15 | NAME: 16 | ListSortDescLoop( list1; list2 ) 17 | v1.1 18 | 19 | PURPOSE: 20 | Merges two sorted lists into a single sorted list. Used by list.sort(). 21 | 22 | HISTORY: 23 | Created by Soliant Consulting (See below or FM 8 Functions p. 229) 24 | Modified 2008.06.17 by DChandler for formatting/commenting preference 25 | 26 | INPUT: 27 | Two sorted, return-delimited lists 28 | 29 | OUTPUT: 30 | A single sorted return-delimited list 31 | 32 | Function created by Soliant Consulting 33 | www.soliantconsulting.com 34 | 35 | Released under the Creative Commons Attribution 2.5 License 36 | http://creativecommons.org/licenses/by/2.5/ 37 | */ -------------------------------------------------------------------------------- /Borrowed/ListSortLoop.calc: -------------------------------------------------------------------------------- 1 | Case( 2 | (ValueCount( list1 ) < 1) or (ValueCount( list2 ) < 1); 3 | Case( ValueCount( list1 ) < 1; list2; list1 ); 4 | 5 | GetValue( list1; 1 ) < GetValue( list2; 1 ); 6 | GetValue( list1; 1 ) & "¶" & 7 | ListSortLoop( RightValues( list1; ValueCount( list1 ) - 1 ); list2); 8 | 9 | GetValue( list2; 1 ) & "¶" & 10 | ListSortLoop( list1; RightValues( list2; ValueCount( list2 ) - 1 ) ) 11 | 12 | ) 13 | 14 | /* —————————————————————————————— // 15 | NAME: 16 | ListSortLoop( list1; list2 ) 17 | v1.1 18 | 19 | PURPOSE: 20 | Merges two sorted lists into a single sorted list. Used by list.sort(). 21 | 22 | HISTORY: 23 | Created by Soliant Consulting (See below or FM 8 Functions p. 229) 24 | Modified 2008.06.17 by DChandler for formatting/commenting preference 25 | 26 | INPUT: 27 | Two sorted, return-delimited lists 28 | 29 | OUTPUT: 30 | A single sorted return-delimited list 31 | 32 | Function created by Soliant Consulting 33 | www.soliantconsulting.com 34 | 35 | Released under the Creative Commons Attribution 2.5 License 36 | http://creativecommons.org/licenses/by/2.5/ 37 | */ -------------------------------------------------------------------------------- /Borrowed/TabFrontMost.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | objectList = LayoutObjectNames ( Get ( FileName ) ; Get ( LayoutName ) ) 3 | ] ; 4 | 5 | TrimCR ( TabFrontMostLoop ( objectList ; ValueCount ( objectList ) ) ) 6 | 7 | ) 8 | 9 | /* __________________________________________________ 10 | 11 | NAME: TabFrontMost ( ) 12 | PURPOSE: Returns a list of front-most tab panels on the layout, according to FileMaker's definition of 'active' (i.e. that every tab object always has exactly one active tab panel). 13 | HISTORY: 14 | Created: 2010-A08-27 12:00 PT - Will M. Baker 15 | Modified: 2012-10-17 10:28 PT - Donovan Chandler : Reformatted. 16 | */ -------------------------------------------------------------------------------- /Borrowed/date.weekOfYearFiscal.calc: -------------------------------------------------------------------------------- 1 | Let( 2 | [ 3 | TheDate = GetAsDate ( TheDate ) ; 4 | d = Date(MonthOfYearStart; DayOfYearStart; Year(TheDate)) ; 5 | dp = Date(MonthOfYearStart; DayOfYearStart; Year(TheDate) - 1) ; 6 | s = d + Mod(DayOfWeekStart - DayOfWeek( d ) + 3; 7) - 3 ; 7 | sp = dp + Mod(DayOfWeekStart - DayOfWeek( dp ) + 3; 7) - 3 ; 8 | FY_Start = Case( TheDate >= s ; s ; sp ) 9 | ] ; 10 | Int( (TheDate - FY_Start)/7) + 1 11 | ) 12 | 13 | /* —————————————————————————————— // 14 | NAME: 15 | WeekOfYearFiscalCustom ( TheDate ; DayOfWeekStart ; MonthOfYearStart ; DayOfYearStart ) 16 | 17 | PURPOSE: 18 | Returns week number of fiscal year (as defined by user) 19 | 20 | EXAMPLES: 21 | WeekOfYearFiscalCustom ( 22 | "10/01/2010" ; 23 | 1 ; 24 | 10 ; 25 | 7 26 | ) => 52 27 | 28 | HISTORY: 29 | Created by Jason L. DeLooze, http://www.briandunning.com/cf/147 30 | Modified: 2010-May-18 11h42 PST — Donovan A. Chandler 31 | */ -------------------------------------------------------------------------------- /Borrowed/text.ascii.fmfn: -------------------------------------------------------------------------------- 1 | Let ( ascii = Mod ( Abs ( GetAsNumber ( ascii ) ) ; 256 ) ; 2 | If ( ascii = 0 ; "" ; 3 | Middle ( "☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕" & 4 | "‼\¶§▬↨↑↓→←∟↔▲▼ !\"#$%&'()*+,-./" & 5 | "0123456789|;<=>?@ABCDEFGHIJKLMNOPQ" & 6 | "RSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz" & 7 | "{|}~⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜø" & 8 | "£Ø×ƒáíóúñѪº¿®¬½¼¡«»░▒▓│┤ÁÂÀ©╣" & 9 | "║╗╝¢¥┐ü┴┬├─┼ãÃ╚╔╩╦╠═╬¤ðÐÊ" & 10 | "ËÈıÍÎÏ┘┌█▄¦Ì▀ÓßÔÒõÕµþÞÚÛÙýݯ´­±‗¾¶§" & 11 | "÷¸°¨·¹³²■ " ; ascii ; 1 ) 12 | ) 13 | ) 14 | 15 | /* —————————————————————————————— // 16 | NAME: 17 | text.ascii ( ascii ) 18 | 19 | PURPOSE: 20 | Returns the character for the given ascii value 0-255 21 | 22 | EXAMPLES: 23 | 24 | 25 | HISTORY: 26 | Created by Theo Ros. http://www.briandunning.com/cf/285 27 | Adapted: 2010-Aug-20 12h14 PST — Donovan A. Chandler 28 | 29 | NOTE: 30 | Not all fonts are able to display all characters. 31 | These characters show up as square. 32 | */ -------------------------------------------------------------------------------- /Borrowed/text.trimCR: -------------------------------------------------------------------------------- 1 | Let([ 2 | _delimiter = "::‡::" 3 | ]; 4 | 5 | Substitute( 6 | Trim( 7 | Substitute( textString; 8 | [ " " ; _delimiter ]; 9 | [ ¶ ; " " ] 10 | ) 11 | ); 12 | [ " " ; ¶ ]; 13 | [ _delimiter ; " " ] 14 | ) 15 | ) 16 | 17 | /* —————————————————————————————— // 18 | NAME: 19 | text.trimCR( textString ) 20 | 21 | PURPOSE: 22 | Trims leading and trailing carriage returns from textString 23 | 24 | HISTORY: 25 | Created by Charlie (see below) 26 | Modified: 2010-Aug-09 10h17 PST — Donovan A. Chandler for formatting 27 | 28 | ORIGINAL DOCUMENTATION: 29 |     This function is published on FileMaker Custom Functions 30 |     to check for updates and provide feedback and bug reports 31 |     please visit http://www.fmfunctions.com/fid/185 32 | 33 |     Prototype: TrimCR( pText ) 34 |     Function Author: Charlie (http://www.fmfunctions.com/mid/132) 35 |     Last updated: 13 January 2009 36 |     Version: 1 37 | */ -------------------------------------------------------------------------------- /CodeMergeLinks.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | linked = CodeMerge ( Substitute ( text ; "‡‡CODE[" ; "‡‡CODE_LINK[" ) ) 3 | ] ; 4 | CodeMerge ( Substitute ( linked ; "‡‡*CODE[" ; "‡‡CODE[" ) ) 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: CodeMergeLinks ( text ) 10 | PURPOSE: Merges value from LIBRARY_CODE table into text, 11 | ensuring that links to values are included instead of merging in entire text. 12 | Useful when exporting code from a table. 13 | EXAMPLES: 14 | // Where FOCUS::LIBRARY_CODE_INCLUDE[index] = "Beezwax!" 15 | // Where FOCUS::LIBRARY_CODE_LINK[index] = "http://beezwax.net" 16 | CodeMergeLoop ( "Hello ‡‡CODE[1]‡‡" ) = "http://beezwax.net" 17 | CodeMergeLoop ( "Hello ‡‡CODE_LINK[1]‡‡" ) = "http://beezwax.net" 18 | 19 | HISTORY: 20 | Created: 2012-06-21 12:14 PT - Donovan Chandler 21 | Modified: 22 | */ -------------------------------------------------------------------------------- /CommaDelimit.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | ~listEncoded = Substitute ( ¶ & theList & ¶ ; ¶ ; "¶|" ) ; 3 | ~listCulled = 4 | Substitute ( ~listEncoded ; 5 | [ "|¶" ; "" ] ; 6 | [ "¶|" ; ¶ ] 7 | ) ; 8 | ~listNew = Middle ( ~listCulled ; 2 ; Length ( ~listCulled ) - 2 ) 9 | ]; 10 | Substitute ( ~listNew ; "¶" ; ", " ) 11 | ) 12 | 13 | /* __________________________________________________ 14 | 15 | NAME: CommaDelimit ( theList ) 16 | PURPOSE: Replaces returns with commas 17 | EXAMPLES: 18 | List ( 19 | CommaDelimit ( "" ) = "" 20 | ; CommaDelimit ( "¶" ) = "" 21 | ; CommaDelimit ( "¶¶" ) = "" 22 | ; CommaDelimit ( "foo¶fum" ) = "foo, fum" 23 | ; CommaDelimit ( "foo¶fum¶" ) = "foo, fum" 24 | ; CommaDelimit ( "¶foo¶fum" ) = "foo, fum" 25 | ; CommaDelimit ( "foo¶¶fum" ) = "foo, fum" 26 | ; CommaDelimit ( "¶¶foo" ) = "foo" 27 | ; CommaDelimit ( "foo¶¶" ) = "foo" 28 | ) 29 | HISTORY: 30 | 2014-08-18 15:13 PDT - Donovan Chandler 31 | */ -------------------------------------------------------------------------------- /ContainerFileName.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | type = ContainerStorageType ( containerAsText ) 3 | ] ; 4 | Case ( 5 | type = "external" ; TextBetween ( containerAsText ; ":" ; "¶" ; 1 ) ; 6 | type = "reference" ; GetValue ( containerAsText ; 1 ) ; 7 | containerAsText 8 | ) 9 | ) 10 | 11 | /* __________________________________________________ 12 | 13 | NAME: ContainerFileName ( containerAsText ) 14 | PURPOSE: Returns file name from container field. 15 | EXAMPLES: 16 | ContainerFileName ( GetAsText ( table::file ) ) 17 | HISTORY: 18 | Created: 2012-11-20 17:24 PT - Donovan Chandler 19 | Modified: 20 | */ -------------------------------------------------------------------------------- /ContainerStorageType.calc: -------------------------------------------------------------------------------- 1 | Case ( 2 | Left ( containerAsText ; 7 ) = "remote:" ; "external" ; 3 | ValueCount ( containerAsText ) ≥ 2 ; "reference" ; 4 | "local" 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: ContainerStorageType ( containerAsText ) 10 | PURPOSE: Determines how container data is being stored. 11 | EXAMPLES: 12 | ContainerStorageType ( GetAsText ( table::file ) ) 13 | HISTORY: 14 | Created: 2012-11-20 17:22 PT - Donovan Chandler 15 | Modified: 16 | */ -------------------------------------------------------------------------------- /DateMinusMonths.calc: -------------------------------------------------------------------------------- 1 | Date( 2 | Month( theDate ) - monthsToSubtract; 3 | 1; 4 | Year( theDate ) 5 | ) 6 | 7 | /* —————————————————————————————— // 8 | NAME: 9 | DateMinusMonths( theDate; monthsToSubtract ) 10 | 11 | PURPOSE: 12 | Returns first day of month x number of months prior to date provided. 13 | 14 | EXAMPLES: 15 | DateMinusMonths( "8/5/09"; 3 ) = "5/1/09" 16 | 17 | HISTORY: 18 | Created: 2010-Sep-14 17h45 PST — Donovan A. Chandler 19 | */ -------------------------------------------------------------------------------- /DateMonthDays.calc: -------------------------------------------------------------------------------- 1 | Day ( 2 | Date ( 3 | Month ( GetAsDate ( theDate ) ) + 1 ; 4 | 0 ; 5 | Year ( GetAsDate ( theDate ) ) 6 | ) 7 | ) 8 | 9 | /* —————————————————————————————— // 10 | NAME: 11 | DateMonthDays ( theDate ) 12 | 13 | PURPOSE: 14 | Returns count of days in month 15 | 16 | EXAMPLES: 17 | DateMonthDays ( "12/1/2010" ) = 31 18 | 19 | HISTORY: 20 | Created: 2010-Dec-20 14h08 PST — Donovan A. Chandler 21 | */ -------------------------------------------------------------------------------- /DateMonthName.calc: -------------------------------------------------------------------------------- 1 | Let([ 2 | _name_long = 3 | Choose( monthNum; 4 | ""; 5 | "January"; 6 | "February"; 7 | "March"; 8 | "April"; 9 | "May"; 10 | "June"; 11 | "July"; 12 | "August"; 13 | "September"; 14 | "October"; 15 | "November"; 16 | "December" 17 | ) 18 | ]; 19 | Case( 20 | shortFormat; Left( _name_long; 3 ); 21 | _name_long 22 | ) 23 | ) 24 | 25 | /* —————————————————————————————— // 26 | NAME: 27 | DateMonthName ( monthNum; shortFormat ) 28 | 29 | PURPOSE: 30 | Converts month number to full name 31 | 32 | EXAMPLES: 33 | DateMonthName ( 1 ; False ) = "January" 34 | DateMonthName ( 1 ; True ) = "Jan" 35 | 36 | HISTORY: 37 | Created: 2010-Aug-06 19h22 PST — Donovan A. Chandler 38 | */ -------------------------------------------------------------------------------- /DateMonthNumber.calc: -------------------------------------------------------------------------------- 1 | Position ( 2 | "xxJanFebMarAprMayJunJulAugSepOctNovDec" 3 | ; Left ( mnthName; 3 ) 4 | ; 1 5 | ; 1 6 | ) / 3 7 | 8 | /* —————————————————————————————— // 9 | NAME: 10 | DateMonthNumber ( mnthName ) 11 | 12 | PURPOSE: 13 | Returns month name corresponding to month number. 14 | 15 | EXAMPLES: 16 | DateMonthName ( "February" ) = 2 17 | DateMonthName ( "feb" ) = 2 18 | 19 | HISTORY: 20 | Source: http://www.briandunning.com/cf/805 21 | Author: David Head, uLearnIT .... http://www.ulearnit.com.au/ 22 | Adopted: 2011-Mar-25 12h16 PST — Donovan A. Chandler ; with formatting modifications 23 | */ -------------------------------------------------------------------------------- /DatePadded.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | ~date = GetAsDate ( "1/2/14" ) ; 3 | ~month = Month ( ~date ) ; 4 | ~day = Day ( ~date ) ; 5 | ~year = Year ( ~date ) 6 | ] ; 7 | Right ( "0" & ~month ; 2 ) & "/" & 8 | Right ( "0" & ~day ; 2 ) & "/" & 9 | ~year 10 | ) 11 | 12 | /* __________________________________________________ 13 | 14 | NAME: DatePadded ( theDate ) 15 | PURPOSE: Pads month and day with zero for single-digit numbers 16 | EXAMPLES: 17 | DatePadded ( "1/2/14" ) = "01/02/2014" 18 | HISTORY: 19 | Created: 2014-02-26 12:21 PT - Donovan Chandler 20 | Modified: 21 | */ -------------------------------------------------------------------------------- /DateShortHand.calc: -------------------------------------------------------------------------------- 1 | Let([ 2 | _month_full = 3 | Choose( Month( theDate ) 4 | ; "" 5 | ; "January" 6 | ; "February" 7 | ; "March" 8 | ; "April" 9 | ; "May" 10 | ; "June" 11 | ; "July" 12 | ; "August" 13 | ; "September" 14 | ; "October" 15 | ; "November" 16 | ; "December" 17 | ); 18 | _month_short = Left( _month_full; 3 ); 19 | _year_short = Right( Year( theDate ); 2) 20 | ]; 21 | Case ( 22 | //-- Future tests for format type go here 23 | True; 24 | _month_short & " " & _year_short 25 | ) 26 | ) 27 | 28 | /* —————————————————————————————— // 29 | NAME: 30 | date.shorthand( theDate ; format ) 31 | 32 | PURPOSE: 33 | Returns shorthand format of date 34 | 35 | EXAMPLES: 36 | date.shorthand ( "3/4/10"; "" ) = "Apr 10" 37 | 38 | HISTORY: 39 | Created: 2010-Aug-04 16h27 PST — Donovan A. Chandler 40 | */ -------------------------------------------------------------------------------- /DateWeekStart.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | yearStart = GetAsNumber ( Date ( 1 ; 1 ; yr ) ) ; 3 | weekStart = yearStart + ( weekNum - 2 ) * 7 + 1 4 | ] ; 5 | GetAsDate ( weekStart ) 6 | ) 7 | 8 | /* —————————————————————————————— // 9 | NAME: 10 | DateWeekStart ( weekNum ; yr ) 11 | 12 | PURPOSE: 13 | Returns date of beginning of week (on Sunday). 14 | 15 | EXAMPLES: 16 | DayWeekStart ( 2011 ; WeekOfYear ( "1/1/2011" ) ) 17 | = "12/26/2010" 18 | 19 | DayWeekStart ( 2011 ; WeekOfYear ( "1/2/2011" ) ) 20 | = "1/2/2011" 21 | 22 | HISTORY: 23 | Created: 2011-Jul-14 14h31 PST — Donovan A. Chandler 24 | */ -------------------------------------------------------------------------------- /DateWeekdaysInRange.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | dayTotal = 3 | GetAsNumber ( GetAsDate ( dateEnd ) ) 4 | - GetAsNumber ( GetAsDate ( dateStart ) ) + 1 ; 5 | workWeeks = Int ( dayTotal / 7 ) ; 6 | workLeftover = Mod ( dayTotal ; 7 ) - 1 ; 7 | workLeftover = If ( workLeftover < 1 ; 0 ; workLeftover ) ; 8 | workLeftover = workLeftover + If ( workWeeks ≥ 1 ; 1 ) 9 | ] ; 10 | workWeeks*5 + workLeftover 11 | ) 12 | 13 | /* __________________________________________________ 14 | 15 | NAME: DateWeekdaysInRange ( dateStart ; dateEnd ) 16 | PURPOSE: Returns number of weekdays in given range 17 | EXAMPLES/TESTS: 18 | List ( 19 | DateWeekdaysInRange ( "7/1/2013" ; "7/8/2013" ) = 6 /* Mon - Mon */ 20 | ; DateWeekDaysInRange ( "2/14/14" ; "2/18/14" ) = 4 /* Tue - Sat */ 21 | ) 22 | HISTORY: 23 | Created: 2011-03-25 12:52 PT - Donovan Chandler 24 | Modified: 2013-07-09 17:11 PT - Donovan Chandler: Now includes last day in range. 25 | Modified: 2014-02-04 15:45 PT - Donovan Chandler: Fixed bug with ranges less than a week. 26 | */ -------------------------------------------------------------------------------- /DateWorkdaysInMonth.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | dte = GetAsDate ( theDate ) ; 3 | mnth = Month ( dte ) ; 4 | yr = Year ( dte ) 5 | ]; 6 | DatesInRange ( 7 | Date ( mnth ; 1 ; yr ) ; 8 | Date ( mnth + 1 ; 1 ; yr ) - 1 ; 9 | 1 ; 10 | omitDateList 11 | ) 12 | ) 13 | 14 | /* —————————————————————————————— // 15 | NAME: 16 | DateWorkdaysInMonth ( theDate ; omitDateList ) 17 | 18 | PURPOSE: 19 | Returns workdays for month of given date 20 | 21 | EXAMPLES: 22 | ValueCount ( DateWorkdaysInMonth ( "12/20/10" ; "12/20/10" ) ) = 22 23 | 24 | HISTORY: 25 | Created: 2010-Dec-20 14h41 PST — Donovan A. Chandler 26 | */ -------------------------------------------------------------------------------- /DatesFrom.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | //-- Build list of valid dates 3 | list_new = 4 | Case ( 5 | numberOfDaysToReturn ≠ 0 ; 6 | DatesFromLoop ( 7 | GetAsDate ( startDate ) ; 8 | numberOfDaysToReturn ; 9 | omitWeekends ; 10 | ListDateToNumber ( omitDateList ) ; 11 | "" 12 | ) 13 | ) 14 | ]; 15 | //-- Ensure list is sorted ascending 16 | Case ( 17 | IsEmpty ( list_new ) ; 18 | "" ; 19 | numberOfDaysToReturn < 0 ; 20 | ListSortDates ( list_new ; 0 ) ; 21 | list_new 22 | ) 23 | ) 24 | 25 | /* —————————————————————————————— // 26 | NAME: 27 | DatesFrom ( startDate ; numberOfDaysToReturn ; omitWeekends ; omitDateList ) 28 | 29 | PURPOSE: 30 | Returns list of dates in range. Excludes weekends and/or holidays if specified. 31 | Pass negative number into numberOfDaysToReturn to end range on startDate. 32 | 33 | EXAMPLES: 34 | DatesFrom ( "10/1/2010" ; 2 ; 1 ; "10/1/2010" ) = "10/4/2010¶10/5/2010" 35 | DatesFrom ( "10/1/2010" ; -2 ; 1 ; "" ) = "9/29/2010¶9/30/2010" 36 | 37 | HISTORY: 38 | Created: 2010-Oct-15 12h06 PST — Donovan A. Chandler 39 | 40 | NOTE: 41 | 42 | */ -------------------------------------------------------------------------------- /DatesFromFull.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | omitDateList = If ( omitHolidays ; DatesHolidayList ) 3 | ]; 4 | DatesFrom ( 5 | startDate ; numberOfDaysToReturn ; 6 | omitWeekends ; 7 | omitDateList 8 | ) 9 | ) 10 | 11 | /* —————————————————————————————— // 12 | NAME: 13 | DatesFromFull ( 14 | startDate ; numberOfDaysToReturn ; 15 | omitWeekends ; 16 | omitHolidays 17 | ) 18 | 19 | PURPOSE: 20 | Wrapper for DatesFrom() providing better support for toggling multiple sets of omit dates 21 | 22 | EXAMPLES: 23 | 24 | 25 | HISTORY: 26 | Created: 2010-Nov-19 15h07 PST — Donovan Chandler 27 | */ -------------------------------------------------------------------------------- /DatesHolidayList.calc: -------------------------------------------------------------------------------- 1 | FOCUS::HOLIDAY_LIST 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: DatesHolidayList 6 | PURPOSE: Returns list of dates considered to be holidays 7 | EXAMPLES: 8 | 9 | HISTORY: 10 | Created: 2010-10-19 14:11 PST - Donovan A. Chandler 11 | */ -------------------------------------------------------------------------------- /DatesInRange.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | start = GetAsDate ( startDate ) ; 3 | end = GetAsDate ( endDate ) 4 | ] ; 5 | Case ( 6 | start ≤ end ; 7 | DatesInRangeLoop ( 8 | start ; 9 | end ; 10 | omitWeekends ; 11 | ListDateToNumber ( omitDateList ) ; 12 | "" 13 | ) 14 | ) 15 | ) 16 | 17 | /* __________________________________________________ 18 | 19 | NAME: DatesInRange ( startDate ; endDate ; omitWeekends ; omitDateList ) 20 | PURPOSE: Returns list of dates in range. Excludes weekends and/or holidays if specified. 21 | EXAMPLES: 22 | DatesInRange ( "10/1/2010" ; "10/4/2010" ; 1 ; "10/4/2010" ) = "10/1/2010¶10/5/2010" 23 | HISTORY: 24 | Created: 2010-10-15 12:06 PT - Donovan Chandler 25 | Modified: 2010-11-30 12:07 PT - Donovan Chandler : replaced "omitHoliday" param with "omitDateList" 26 | */ -------------------------------------------------------------------------------- /DatesInRangeFull.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | omitDateListFull = 3 | List ( 4 | If ( omitHolidays ; DatesHolidayList ) ; 5 | omitDateList 6 | ) 7 | ]; 8 | DatesInRange ( 9 | startDate ; endDate ; 10 | omitWeekends ; 11 | omitDateListFull 12 | ) 13 | ) 14 | 15 | /* __________________________________________________ 16 | 17 | NAME: DatesInRangeFull ( startDate ; endDate ; 18 | omitWeekends ; 19 | omitHolidays ; 20 | omitDateList 21 | ) 22 | PURPOSE: Wrapper for DatesInRange() providing better support for toggling multiple sets of omit dates 23 | EXAMPLES: 24 | 25 | HISTORY: 26 | Created: 2010-11-30 12:15 PT - Donovan Chandler 27 | */ -------------------------------------------------------------------------------- /Deprecated/VarInvalid.calc: -------------------------------------------------------------------------------- 1 | VarInvalidLoop ( listOfVariableNames ; requireAll ; 1 ; "" ) 2 | 3 | /* —————————————————————————————— // 4 | NAME: 5 | VarInvalid ( listOfVariableNames ; requireAll ) 6 | 7 | PURPOSE: 8 | Returns list of variables with invalid data. 9 | 10 | USAGE: 11 | Supply variable names as text strings (in quotes). 12 | Each line of the parameter must evaluate to a valid value. 13 | To require one of several vars, place them on one line separated by "|". 14 | 15 | EXAMPLES: 16 | Where $_table = "CONTACT", $_id_contact = "?", $_id_student = "" 17 | 18 | VarInvalid ( "$_table" ) = "" 19 | 20 | VarInvalid ( 21 | List ( "$_table" ; "$_id_contact | $_id_student" ) 22 | ) = "$_id_contact | $_id_student" 23 | 24 | VarInvalid ( 25 | "$_table | $_id_student" ) 26 | ) = "" 27 | 28 | HISTORY: 29 | Created: 2010-Oct-28 08h04 PST — Donovan Chandler 30 | */ -------------------------------------------------------------------------------- /DialogDataInputs.calc: -------------------------------------------------------------------------------- 1 | DialogDataInputsLoop ( dialogHashContents ; 1 ; "" ) 2 | 3 | /* —————————————————————————————— // 4 | NAME: 5 | DialogDataInputs ( dialogHashContents ) 6 | 7 | PURPOSE: 8 | Returns DIALOG hash omitting INPUT elements that don't accept data entry. 9 | Built for use with dialog script supporting SimpleDialog. 10 | 11 | EXAMPLES: 12 | 13 | 14 | HISTORY: 15 | Created: 2010-Nov-11 17h43 PST — Donovan A. Chandler 16 | */ -------------------------------------------------------------------------------- /DialogDataInputsLoop.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | input = #NthValue ( dialogHashContents ; "INPUT" ; rep ) ; 3 | type = #Value (input ; "TYPE" ) ; 4 | invalidTypes = "separator¶image¶link¶caption" ; 5 | isValid = not ListContains ( invalidTypes ; type ) 6 | ] ; 7 | Case ( 8 | IsEmpty ( input ) ; previousResults ; 9 | 10 | DialogDataInputsLoop ( 11 | dialogHashContents ; 12 | rep + 1 ; 13 | List ( previousResults ; If ( isValid ; # ( "INPUT" ; input ) ) ) 14 | ) 15 | ) 16 | ) 17 | 18 | /* —————————————————————————————— // 19 | NAME: 20 | DialogDataInputsLoop ( dialogHashContents ; rep ; previousResults ) 21 | 22 | PURPOSE: 23 | Returns DIALOG hash omitting INPUT elements that don't accept data entry. 24 | Built for use with dialog script supporting SimpleDialog. 25 | 26 | EXAMPLES: 27 | 28 | 29 | HISTORY: 30 | Created: 2010-Nov-11 15h21 PST — Donovan A. Chandler 31 | */ -------------------------------------------------------------------------------- /EmailCSSForTable.calc: -------------------------------------------------------------------------------- 1 | " 12 | " 13 | 14 | // Trailing lines to leave space before attachment 15 | 16 | 17 | /* —————————————————————————————— // 18 | NAME: 19 | EmailCSSForTable ( ) 20 | 21 | PURPOSE: 22 | Returns style element for generic tables used in HTML emails. 23 | 24 | EXAMPLES: 25 | "¶ 26 | " & EmailCSSForTable & "¶ 27 | ¶ 28 | ¶ 29 |

Dear person. Please see table below.

¶ 30 | ¶ 31 | ¶ 32 |
Name" & CONTACT::NAME & "
¶ 33 | "" 34 | 35 | HISTORY: 36 | Created: 2011-Nov-23 14h12 PST — Donovan Chandler 37 | */ -------------------------------------------------------------------------------- /ErrorSuppressionOff.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | $$_errors_suppressed = If ( $$_errors_suppressed = Get ( ScriptName ) ; False ; $$_errors_suppressed ) 3 | ] ; 4 | $$_errors_suppressed 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: ErrorSuppressionOff ( ) 10 | PURPOSE: Causes error suppression to be disabled if it was enabled by the same script. 11 | EXAMPLES: 12 | 13 | HISTORY: 14 | Created: 2011-10-07 09:47 PST - Donovan A. Chandler 15 | */ -------------------------------------------------------------------------------- /ErrorSuppressionOffGlobal.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | $$_errors_suppressed = False 3 | ] ; 4 | $$_errors_suppressed 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: ErrorSuppressionOffGlobal ( ) 10 | PURPOSE: Causes error suppression to be disabled regardless of which script enabled it. 11 | HISTORY: 12 | Created: 2011-10-07 09:47 PST - Donovan A. Chandler 13 | */ -------------------------------------------------------------------------------- /ErrorSuppressionOn.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | $$_errors_suppressed = If ( ErrorsAreSuppressed ; $$_errors_suppressed ; Get ( ScriptName ) ) 3 | ] ; 4 | $$_errors_suppressed 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: ErrorSuppressionOn ( ) 10 | PURPOSE: Causes error suppression to be enabled. 11 | HISTORY: 12 | Created: 2011-10-07 09:47 PST - Donovan A. Chandler 13 | */ -------------------------------------------------------------------------------- /ErrorsAreSuppressed.calc: -------------------------------------------------------------------------------- 1 | not 2 | ( 3 | IsEmpty ( $$_errors_suppressed ) 4 | or $$_errors_suppressed = 0 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: ErrorsAreSuppressed ( ) 10 | PURPOSE: Returns 1 (True) if error handling is disabled for file. 11 | For example, if you are looping through records and building a temp error log instead of showing a dialog for each error. 12 | HISTORY: 13 | Created: 2011-10-07 09:44 PST - Donovan A. Chandler 14 | */ -------------------------------------------------------------------------------- /FOCUS-Specific/#DialogResult.calc: -------------------------------------------------------------------------------- 1 | #Value ( 2 | #NthResult ( "RESULT" ; resultNumber ) ; 3 | resultType 4 | ) 5 | 6 | /* —————————————————————————————— // 7 | NAME: 8 | #DialogResult ( resultNumber ; resultType ) 9 | 10 | PURPOSE: 11 | Retrieves result from dialog script 12 | 13 | EXAMPLES: 14 | 15 | 16 | HISTORY: 17 | Created: 2010-Jun-28 16h45 PST — Donovan A. Chandler 18 | */ -------------------------------------------------------------------------------- /FOCUS-Specific/DialogResultsChecked.calc: -------------------------------------------------------------------------------- 1 | Let([ 2 | _result_cur = #NthValue ( dialogResults; "RESULT"; startIndex ); 3 | _result_cur_value = #Value ( _result_cur; "VALUE" ); 4 | _result_cur_menu = #Value ( _result_cur; "TEXT" ); 5 | _is_checked = ( _result_cur_value = 1 ); 6 | 7 | _result_next = #NthValue ( dialogResults; "RESULT"; startIndex + 1 ); 8 | _result_next_value = #Value ( _result_next; "VALUE" ) 9 | ]; 10 | If ( _is_checked; _result_cur_menu ) & 11 | If ( startIndex < endIndex; 12 | If ( _result_next_value = 1; ¶ ) & 13 | DialogResultsChecked ( dialogResults; startIndex + 1; endIndex ) 14 | ) 15 | ) 16 | 17 | /* —————————————————————————————— // 18 | NAME: 19 | dialog.resultsChecked ( dialogResults; startIndex; endIndex ) 20 | 21 | PURPOSE: 22 | Returns return-delimited list of all checkboxes that were checked in the specified dialog results. 23 | 24 | EXAMPLES: 25 | 26 | 27 | HISTORY: 28 | Created: 2010-Jun-23 11h36 PST — Donovan A. Chandler 29 | */ -------------------------------------------------------------------------------- /FOCUS-Specific/LayoutBasetable.calc: -------------------------------------------------------------------------------- 1 | Let([ 2 | _to = layoutTableOccurrence; 3 | _delim = "_"; 4 | _sName = Position ( _to; _delim; 1; 1 ) + 1; 5 | _eName = Position ( _to; _delim; 1; 2 ) - 1 6 | ]; 7 | Case ( 8 | _sName = 0; _to; 9 | _eName ≤ 0; Middle ( _to; _sName; 9999 ); 10 | Middle ( _to; _sName; _eName - _sName + 1 ) 11 | ) 12 | ) 13 | 14 | /* —————————————————————————————— // 15 | NAME: 16 | LayoutBasetable ( layoutTableOccurrence ) 17 | 18 | PURPOSE: 19 | Returns name of basetable corresponding to current layout. Used with table array. 20 | 21 | EXAMPLES: 22 | 23 | 24 | HISTORY: 25 | Created: 2010-Jul-13 13h33 PST — Donovan A. Chandler 26 | */ -------------------------------------------------------------------------------- /FOCUS-Specific/MessageDelete.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | name = itemFieldOrName ; 3 | field = GetFieldName ( name ) ; 4 | field = 5 | If ( 6 | not IsEmpty ( field ) and field ≠ "?"; 7 | TableOccurrenceBaseTable ( FieldTableOccurrence ( field ) ) 8 | ) ; 9 | reference = 10 | Case ( 11 | not IsEmpty ( name ) ; name ; 12 | not IsEmpty ( field ) ; Proper ( field ) ; 13 | "record" 14 | ) 15 | ] ; 16 | "Delete " & reference & "?" & ¶ & ¶ & 17 | "There is no undo for this action." 18 | ) 19 | 20 | /* —————————————————————————————— // 21 | NAME: 22 | MessageDelete ( itemFieldOrName ) 23 | 24 | PURPOSE: 25 | Returns text message for use in deletion dialogs. 26 | 27 | EXAMPLES: 28 | MessageDelete ( CONTACT_FOCUS::NAME ) 29 | 30 | HISTORY: 31 | Created: 2010-Sep-07 12h00 PST — Donovan A. Chandler 32 | */ -------------------------------------------------------------------------------- /FOCUS-Specific/MessageRemove.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | name = itemFieldOrName ; 3 | field = GetFieldName ( name ) ; 4 | field = 5 | If ( 6 | not IsEmpty ( field ) and field ≠ "?"; 7 | TableOccurrenceBaseTable ( FieldTableOccurrence ( field ) ) 8 | ) ; 9 | reference = 10 | Case ( 11 | not IsEmpty ( name ) ; name ; 12 | not IsEmpty ( field ) ; Proper ( field ) ; 13 | "record" 14 | ) 15 | ] ; 16 | "Remove " & reference & "?" & ¶ & ¶ & 17 | "There is no undo for this action." 18 | ) 19 | 20 | /* —————————————————————————————— // 21 | NAME: 22 | MessageRemove ( itemFieldOrName ) 23 | 24 | PURPOSE: 25 | Returns text message for use in dialogs when deleting join records. 26 | 27 | EXAMPLES: 28 | MessageRemove ( CONTACT_FOCUS::NAME ) 29 | 30 | HISTORY: 31 | Created: 2010-Sep-07 12h00 PST — Donovan A. Chandler 32 | */ -------------------------------------------------------------------------------- /FOCUS-Specific/ParamQuery.calc: -------------------------------------------------------------------------------- 1 | # ( "QUERY" ; 2 | # ( "REQUEST" ; 3 | # ( "OMIT" ; omit ) & 4 | # ( "CRITERION" ; 5 | # ( "FIELD" ; fieldName ) & 6 | # ( "VALUE" ; searchValue ) 7 | ) 8 | ) 9 | ) 10 | 11 | /* —————————————————————————————— // 12 | NAME: 13 | ParamQuery ( fieldName ; searchValue ; omit ) 14 | 15 | PURPOSE: 16 | Constructs QUERY parameter using inputs. 17 | Used with "t filter" and related scripts. 18 | 19 | EXAMPLES: 20 | ParamQuery ( "CONTACT::TYPE" ; "Client" ; 0 ) 21 | 22 | HISTORY: 23 | Created: 2011-Jan-06 11h58 PST — Donovan A. Chandler 24 | */ -------------------------------------------------------------------------------- /FOCUS-Specific/ParamQueryRequest.calc: -------------------------------------------------------------------------------- 1 | # ( "REQUEST" ; 2 | # ( "OMIT" ; omit ) & 3 | # ( "CRITERION" ; 4 | # ( "FIELD" ; fieldName ) & 5 | # ( "VALUE" ; searchValue ) 6 | ) 7 | ) 8 | 9 | /* —————————————————————————————— // 10 | NAME: 11 | ParamQueryRequest ( fieldName ; searchValue ; omit ) 12 | 13 | PURPOSE: 14 | Constructs REQUEST of QUERY parameter using inputs. 15 | Used with "t filter" and related scripts. 16 | 17 | EXAMPLES: 18 | ParamQueryRequest ( "CONTACT::TYPE" ; "Client" ; 0 ) 19 | 20 | HISTORY: 21 | Created: 2011-Jan-06 11h58 PST — Donovan A. Chandler 22 | */ -------------------------------------------------------------------------------- /FOCUS-Specific/TableIDRemove.calc: -------------------------------------------------------------------------------- 1 | TableIDRemoveLoop ( table ; FocusList ) 2 | 3 | /* —————————————————————————————— // 4 | NAME: 5 | TableIDRemove ( table ) 6 | 7 | PURPOSE: 8 | Returns the list of focused IDs, but without the ID for the specified table. If the ID is not present, the list will be returned as is. Note that each row must be parsed, because we only know the table we are looking for, not a specific ID. 9 | DISABLED -> We assume that only one ID is in focus for the specified table, and thus only attempt to remove the first ID we find. 10 | 11 | EXAMPLES: 12 | 13 | HISTORY: 14 | Created: 2010-Jan-29 17h00 PST — Will M. Baker 15 | Modified: 2010-Sep-22 16h25 PST — Donovan Chandler : Now removes multiple ID's 16 | */ -------------------------------------------------------------------------------- /FOCUS-Specific/TableIDRemoveLoop.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | #_list = listOfIDs ; 3 | #_id = TableIDRetrieve ( table ) ; 4 | #_row = ListValueRowNum ( #_list ; #_id ) ; 5 | #_list_new = 6 | Case ( 7 | #_row > 0 ; 8 | LeftValues ( #_list ; #_row - 1 ) & RightValues ( #_list ; ValueCount ( #_list ) - #_row ) ; 9 | #_list 10 | ) 11 | ] ; 12 | Case ( 13 | ListValueRowNum ( #_list_new ; #_id ) > 0 ; 14 | TableIDRemoveLoop ( table ; #_list_new ) ; 15 | 16 | #_list_new 17 | ) 18 | ) 19 | 20 | /* —————————————————————————————— // 21 | NAME: 22 | TableIDRemoveLoop ( table ; listOfIDs ) 23 | 24 | PURPOSE: 25 | Returns the list of focused IDs, but without the ID for the specified table. If the ID is not present, the list will be returned as is. Note that each row must be parsed, because we only know the table we are looking for, not a specific ID. 26 | DISABLED -> We assume that only one ID is in focus for the specified table, and thus only attempt to remove the first ID we find. 27 | 28 | EXAMPLES: 29 | 30 | HISTORY: 31 | Created: 2010-Jan-29 17h00 PST — Will M. Baker 32 | Modified: 2010-Sep-22 16h25 PST — Donovan Chandler : Modified into recursive subscript 33 | */ -------------------------------------------------------------------------------- /FOCUS-Specific/dialog.inputCheckboxes.calc: -------------------------------------------------------------------------------- 1 | Let([ 2 | _label_list = listOfLabels; 3 | _value_list = listOfValues; 4 | _label_cur = GetValue ( _label_list; 1 ); 5 | _value_cur = GetValue ( _value_list; 1 ); 6 | _label_count = ValueCount ( _label_list ) 7 | ]; 8 | Case ( 9 | not IsEmpty ( _label_cur ); 10 | # ( "INPUT" ; 11 | # ( "TYPE" ; "checkbox" ) & 12 | # ( "LABEL" ; _label_cur ) & 13 | # ( "DEFAULT_VALUE" ; _value_cur ) & 14 | # ( "DEFAULT_IS_VALID" ; 1 ) 15 | ) 16 | ) 17 | & Case ( 18 | _label_count > 1; 19 | ¶ & DialogInputCheckboxes ( 20 | RightValues ( _label_list; _label_count - 1 ); 21 | RightValues ( _value_list; _label_count - 1 ) 22 | ) 23 | ) 24 | ) 25 | 26 | /* —————————————————————————————— // 27 | NAME: 28 | DialogInputCheckboxes ( listOfLabels ; listOfValues ) 29 | 30 | PURPOSE: 31 | Constructs input parameter for creating a checkbox set within a dialog. 32 | 33 | EXAMPLES: 34 | 35 | 36 | HISTORY: 37 | Created: 2010-Jun-23 11h04 PST — Donovan A. Chandler 38 | 39 | NOTES: 40 | listOfValues parameter may contain empty or missing values so long as the existing values correlate in position to their respective labels. 41 | */ -------------------------------------------------------------------------------- /FieldIsQualified.calc: -------------------------------------------------------------------------------- 1 | PatternCount ( fieldName ; "::" ) > 0 2 | 3 | /* —————————————————————————————— // 4 | NAME: 5 | FieldIsQualified ( fieldName ) 6 | 7 | PURPOSE: 8 | Returns True if field name is fully qualified (contains table name) 9 | 10 | EXAMPLES: 11 | FieldIsQualified ( GetFieldName ( CONTACT::NAME ) ) = 1 12 | FieldIsQualified ( "NAME" ) = 0 13 | FieldIsQualified ( "" ) = 0 14 | 15 | HISTORY: 16 | Created: 2011-Jan-25 14h59 PST — Donovan A. Chandler 17 | */ -------------------------------------------------------------------------------- /FieldNameShort.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | tableEnd = Position ( fieldName ; "::" ; 1 ; 1 ) ; 3 | field = 4 | Case ( 5 | tableEnd = 0 ; 6 | fieldName ; 7 | Middle ( fieldName ; tableEnd + 2 ; 999 ) 8 | ) 9 | ] ; 10 | Trim ( field ) 11 | ) 12 | 13 | /* __________________________________________________ 14 | 15 | NAME: FieldNameShort ( fieldName ) 16 | PURPOSE: Returns name of field without table name 17 | EXAMPLES: 18 | FieldNameShort ( "CONTACT::NAME" ) = "NAME" 19 | HISTORY: 20 | Created: 2010-11-02 08:59 PST - Donovan A. Chandler 21 | */ 22 | -------------------------------------------------------------------------------- /FieldNotEmpty.calc: -------------------------------------------------------------------------------- 1 | Let ( [ $fields = listOfFieldNames ; ex = "Let ( [ value = GetField ( GetValue ( $fields ; [n] ) ) ] ; If ( value = \"?\" ; \"?\" ; not IsEmpty ( value ) ) )" ; result = ListCustom ( 1 ; ValueCount ( $fields ) ; ex ) ] ; If ( Position ( result ; "?" ; 1 ; 1 ) ; "?" ; Evaluate ( Substitute ( result ; ¶ ; "+" ) ) ) ) /* —————————————————————————————— // NAME: FieldNotEmpty ( listOfFieldNames ) PURPOSE: Given list of field names, returns count of fields that contain a value. EXAMPLES: FieldNotEmpty ( List ( GetFieldName ( CONTACT::NAME_FIRST ) ; GetFieldName ( CONTACT::NAME_LAST ) ; GetFieldName ( CONTACT::TITLE ) ) ) = 1 if NAME_FIRST is the only field with a value = "?" if fields are not related HISTORY: Created: 2011-Sep-30 13h55 PST — Donovan A. Chandler */ -------------------------------------------------------------------------------- /FieldOccurrences.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | ~tableEnd = Position ( fieldName ; "::" ; 1 ; 1 ) ; 3 | ~fieldName = Middle ( fieldName ; If ( ~tableEnd ; ~tableEnd + 2 ; 1 ) ; 99 ) ; 4 | ~query = 5 | "SELECT TableName FROM filemaker_fields" & 6 | "¶WHERE FieldName = ?" & 7 | //-- Remove all tables with "__" in name 8 | "¶AND TableName NOT LIKE '%\_\_%'" 9 | ] ; 10 | ExecuteSQL ( ~query ; "" ; "¶" ; ~fieldName ) 11 | ) 12 | 13 | /* __________________________________________________ 14 | 15 | NAME: FieldOccurrences ( fieldName ) 16 | PURPOSE: Returns list of tables containing specified field. 17 | Contains additional logic to filter out all but "anchor" table occurrences. 18 | EXAMPLES: 19 | FieldOccurrences ( "ID_COMPANY" ) //= "CONTACT¶INVOICE" where those tables have ID_COMPANY field 20 | HISTORY: 21 | Created: 2013-05-09 14:26 PT - Donovan Chandler 22 | Modified: 23 | */ -------------------------------------------------------------------------------- /FieldRepMatch.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | /* 3 | rep = 1 ; 4 | repeatingField = FOCUS::NAV_SUB_LAYOUT_LIST_REP ; 5 | matchValue = "Equipment List" ; 6 | */ 7 | ~repContent = GetRepetition ( repeatingField ; startingRep ) ; 8 | ~repMatched = ListContains ( ~repContent ; matchValue ) 9 | ] ; 10 | Case ( 11 | //-- Exceeded rep range 12 | ~repContent = "?" ; "" ; 13 | 14 | //-- Matched, return repetition/index 15 | ~repMatched ; startingRep ; 16 | 17 | //-- Iterate to next repetition, if still within permitted rep range 18 | startingRep < repMax ; FieldRepMatch ( repeatingField ; matchValue ; startingRep + 1 ; repMax ) 19 | ) 20 | ) 21 | 22 | /* __________________________________________________ 23 | 24 | NAME: FieldRepMatch ( repeatingField ; matchValue ; startingRep ; maxRep ) 25 | PURPOSE: Returns repetition of field containing a line that matches matchValue 26 | EXAMPLES: 27 | 28 | HISTORY: 29 | Created: 2013-05-16 09:40 PT - Donovan Chandler 30 | Modified: 31 | */ -------------------------------------------------------------------------------- /FieldSortValues.calc: -------------------------------------------------------------------------------- 1 | FieldSortValuesLoop ( fieldList ; useForDescSort ; ValueCount ( fieldList ) ; 1 ) 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: FieldSortValues ( fieldList ; useForDescSort ) 6 | PURPOSE: Given list of field names, returns list of values that are sortable as text. 7 | EXAMPLES: 8 | 9 | HISTORY: 10 | Created: 2013-03-04 08:13 PT - Donovan Chandler 11 | Modified: 12 | */ -------------------------------------------------------------------------------- /FieldSortValuesLoop.calc: -------------------------------------------------------------------------------- 1 | If ( 2 | rep > repMax ; "" ; 3 | Let ( [ 4 | field = GetValue ( fieldList ; rep ) ; 5 | tableIndex = TableIndex ( FieldTableOccurrence ( field ) ) ; 6 | descSortIsOn = GetValue ( $$_sort_desc[tableIndex] ; rep ) 7 | ] ; 8 | List ( 9 | FieldSortValue ( field ; useForDescSort ; descSortIsOn ) ; 10 | FieldSortValuesLoop ( fieldList ; useForDescSort ; repMax ; rep + 1 ) 11 | ) 12 | ) 13 | ) 14 | 15 | /* __________________________________________________ 16 | 17 | NAME: FieldSortValuesLoop ( fieldList ; useForDescSort ; repMax ; rep ) 18 | PURPOSE: Given list of field names, returns list of field values that are sortable as text. 19 | EXAMPLES: 20 | 21 | NOTES: Be sure that the table occurrence of the fieldList values matches the evaluation context calculation in the sort field. 22 | HISTORY: 23 | Created: 2013-03-04 08:13 PT - Donovan Chandler 24 | Modified: 25 | */ -------------------------------------------------------------------------------- /FieldsEmpty.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | $fields = listOfFieldNames ; 3 | ex = 4 | "Let ( [ name = GetValue ( $fields ; [n] ) 5 | ; value = GetField ( name ) 6 | ] ; If ( IsEmpty ( value ) or value = \"?\" ; name ) 7 | )" ; 8 | result = ListCustom ( 1 ; ValueCount ( $fields ) ; ex ) 9 | ] ; 10 | result 11 | ) 12 | 13 | /* —————————————————————————————— // 14 | NAME: 15 | FieldsEmpty ( listOfFieldNames ) 16 | 17 | PURPOSE: 18 | Given list of field names, returns list of fields that are empty or unrelated. 19 | 20 | EXAMPLES: 21 | Given that NAME_FIRST is the only field containing a value... 22 | 23 | FieldsEmpty ( List ( 24 | GetFieldName ( CONTACT::NAME_FIRST ) ; 25 | GetFieldName ( CONTACT::NAME_LAST ) ; 26 | GetFieldName ( CONTACT::TITLE ) 27 | ) ) 28 | = "CONTACT::NAME_LAST¶CONTACT::TITLE" 29 | 30 | HISTORY: 31 | Created: 2011-Nov-23 11h59 PST — Donovan Chandler 32 | */ -------------------------------------------------------------------------------- /FileNameEncodeForPath.calc: -------------------------------------------------------------------------------- 1 | Substitute ( 2 | text ; 3 | [ "/" ; "-" ] ; 4 | [ ¶ ; " " ] ; 5 | [ "|" ; " " ] ; 6 | [ "<" ; " " ] ; 7 | [ ">" ; " " ] ; 8 | [ "..." ; "." ] ; 9 | [ "\"" ; "" ] ; 10 | [ "," ; "" ] 11 | ) 12 | 13 | /* __________________________________________________ 14 | 15 | NAME: FileNameEncodeForPath ( text ) 16 | PURPOSE: Ensures file name is valid for use in a path 17 | EXAMPLES: 18 | FileNameEncodeForPath ( "in/out values.pdf" ) 19 | // Returns "in-out values.pdf" 20 | HISTORY: 21 | Created: 2013-10-04 12:06 PT - Donovan Chandler 22 | Modified: 23 | */ -------------------------------------------------------------------------------- /FileNameFromPaths.calc: -------------------------------------------------------------------------------- 1 | FileNameFromPathsLoop ( filePaths ; "" ) 2 | 3 | /* —————————————————————————————— // 4 | NAME: 5 | FileNameFromPaths ( filePaths ) 6 | 7 | PURPOSE: 8 | Extracts file names from list of paths, return list of names 9 | 10 | EXAMPLES: 11 | FileNameFromPaths ( "dir/fileName.txt/¶otherFile.tab" ) = "fileName.txt¶otherFile.tab" 12 | 13 | HISTORY: 14 | Created: 2011-Oct-06 13h19 PST — Donovan A. Chandler 15 | */ -------------------------------------------------------------------------------- /FileNameFromPathsLoop.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | path = GetValue ( filePaths ; 1 ) ; 3 | dirList = Substitute ( path ; "/" ; ¶ ) ; 4 | count = ValueCount ( dirList ) ; 5 | file = GetValue ( dirList ; count ) ; 6 | file = 7 | Case ( 8 | IsEmpty ( file ) ; 9 | GetValue ( dirList ; count - 1 ) ; 10 | file 11 | ) ; 12 | newResult = List ( previousResults ; file ) 13 | ] ; 14 | Case ( 15 | ValueCount ( filePaths ) > 0 ; 16 | FileNameFromPathsLoop ( 17 | RightValues ( filePaths ; ValueCount ( filePaths ) - 1 ) ; 18 | newResult 19 | ) ; 20 | newResult 21 | ) 22 | ) 23 | 24 | /* —————————————————————————————— // 25 | NAME: 26 | FileNameFromPathsLoop ( filePaths ; previousResults ) 27 | 28 | PURPOSE: 29 | Performs recursion for FileNameFromPaths 30 | 31 | EXAMPLES: 32 | 33 | 34 | HISTORY: 35 | Created: 2011-Oct-06 13h09 PST — Donovan A. Chandler 36 | */ -------------------------------------------------------------------------------- /FileNameWithExtension.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | path = Get ( FilePath ) ; 3 | sName = Position ( path ; "/" ; Length ( path ) ; -1 ) + 1 4 | ] ; 5 | Middle ( path ; sName ; 999 ) 6 | ) 7 | 8 | /* —————————————————————————————— // 9 | NAME: 10 | FileNameWithExtension 11 | 12 | PURPOSE: 13 | Returns file name including extension. 14 | Keeps design functions from being fooled by periods in file name. 15 | 16 | EXAMPLES: 17 | 18 | 19 | HISTORY: 20 | Created: 2012-Jan-12 14h06 PST — Donovan A. Chandler 21 | */ -------------------------------------------------------------------------------- /FileSlash.calc: -------------------------------------------------------------------------------- 1 | If ( 2 | Abs ( Get ( SystemPlatform ) ) = 2 ; "\\" ; 3 | "/" 4 | ) 5 | 6 | /* —————————————————————————————— // 7 | NAME: 8 | FileSlash () 9 | 10 | PURPOSE: 11 | Returns slash character used for current operating system 12 | 13 | EXAMPLES: 14 | 15 | 16 | HISTORY: 17 | Created: 2012-Feb-03 23h29 PST — Donovan A. Chandler 18 | */ -------------------------------------------------------------------------------- /FileView.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | path = folder ; 3 | id = recID ; 4 | nullMessage = "Data:text/html,Please select a file to view" ; 5 | nullPathMessage = "Data:text/html,Path to file on server is invalid" 6 | ]; 7 | Case ( 8 | IsEmpty ( id ) ; nullMessage ; 9 | IsEmpty ( path ) ; nullPathMessage ; 10 | 11 | SuperContainerGetFile ( 12 | SuperContainerUser ; 13 | SuperContainerPassword ; 14 | path ; 15 | height ; 16 | width ; 17 | resolution ; // resolution 18 | style ; // style 19 | backgroundColor ; // bckgndColor 20 | False 21 | ) 22 | ) 23 | 24 | ) 25 | 26 | /* —————————————————————————————— // 27 | NAME: 28 | FileView ( recID ; folder ; height ; width ; resolution ; style ; backgroundcolor ) 29 | 30 | PURPOSE: 31 | Fetches file from SuperContainer for viewing in solution. 32 | This is a wrapper for the core function, adding extra validation for record selection, etc. 33 | 34 | EXAMPLES: 35 | 36 | 37 | HISTORY: 38 | Created: 2011-Apr-14 09h52 PST — Donovan A. Chandler 39 | */ -------------------------------------------------------------------------------- /FileViewConditional.calc: -------------------------------------------------------------------------------- 1 | Case ( //-- If PDF, display page preview ListContains ( typesToShowRaw ; Filter ( fileType ; "abcdefghijklmnopqrstuvwxyz" ) ) ; FileViewRaw ( FILE::RECORD_ID ; FILE::FILE_PATH_FROM_BASE_EU ) ; FileView ( recID ; folder ; height ; width ; resolution ; style ; backgroundcolor ) ) /* —————————————————————————————— // NAME: FileViewConditional ( recID ; folder ; height ; width ; resolution ; style ; backgroundcolor ; fileType ; typesToShowRaw ) PURPOSE: Fetches file from SuperContainer for viewing in solution. Shows raw data view if file type is in specified list of types. This allows for centering of images (applet view) and browsing of PDF's (raw data view). This is a wrapper for the core function, adding extra validation for record selection, etc. EXAMPLES: HISTORY: Created: 2011-Apr-14 09h52 PST — Donovan A. Chandler */ -------------------------------------------------------------------------------- /FileViewRaw.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | path = folder ; 3 | id = recID ; 4 | nullMessage = "Data:text/html,Please select a file to view" ; 5 | nullPathMessage = "Data:text/html,Path to file on server is invalid" 6 | ]; 7 | Case ( 8 | IsEmpty ( id ) ; nullMessage ; 9 | IsEmpty ( path ) ; nullPathMessage ; 10 | 11 | SuperContainerGetFile ( 12 | SuperContainerUser ; 13 | SuperContainerPassword ; 14 | path ; 15 | "" ; 16 | "" ; 17 | "" ; // resolution 18 | "" ; // style 19 | "" ; // bckgndColor 20 | True 21 | ) 22 | ) 23 | 24 | ) 25 | 26 | /* —————————————————————————————— // 27 | NAME: 28 | FileViewRaw ( recID ; folder ) 29 | 30 | PURPOSE: 31 | Fetches file from SuperContainer for viewing in solution. 32 | Shows raw file instead of applet. 33 | This is a wrapper for the core function, adding extra validation for record selection, etc. 34 | 35 | EXAMPLES: 36 | 37 | 38 | HISTORY: 39 | Created: 2011-May-13 13h16 PST — Donovan Chandler 40 | */ -------------------------------------------------------------------------------- /GetAsBooleanCustom.calc: -------------------------------------------------------------------------------- 1 | Case ( 2 | string = "no" or string = "N"; 0; 3 | string = "yes" or string = "Y"; 1; 4 | GetAsBoolean( string ) 5 | ) 6 | 7 | /* —————————————————————————————— // 8 | NAME: 9 | GetAsBooleanCustom ( string ) 10 | 11 | PURPOSE: 12 | Returns boolean result from text string 13 | 14 | EXAMPLES: 15 | GetAsBooleanCustom ( "yes" ) = 1 16 | 17 | HISTORY: 18 | Created: 2010-Aug-09 19h21 PST — Donovan A. Chandler 19 | */ -------------------------------------------------------------------------------- /GetRelatedByValue.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | ex = 3 | "Let ( [ check = GetNthRecord ( " & compareField & " ; [n] ) " & 4 | "] ; " & 5 | "If ( " & 6 | "check = " & Quote ( compareValue ) & " ; " & 7 | "GetNthRecord ( " & targetField & " ; [n] ) " & 8 | ") )" 9 | ] ; 10 | ListCustom ( 1 ; Count ( GetField ( targetField ) ) ; ex ) 11 | ) 12 | 13 | /* __________________________________________________ 14 | 15 | NAME: GetRelatedByValue ( targetField ; compareField ; compareValue ) 16 | PURPOSE: Returns related values from field where compareField = compareValue 17 | EXAMPLES: 18 | GetRelatedByValue ( "CONTACT::NAME_FIRST" ; "CONTACT::NAME_LAST" ; "Simpson" ) 19 | //= "Bart¶Homer¶Lisa¶Maggie¶Marge" 20 | HISTORY: 21 | Created: 2012-03-20 15:44 PST - Donovan Chandler 22 | Modified: 23 | */ -------------------------------------------------------------------------------- /IsMac.calc: -------------------------------------------------------------------------------- 1 | Abs ( Get ( SystemPlatform ) ) = 1 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: IsMac () 6 | PURPOSE: Returns 1 (True) if operating system is Mac OS. 7 | HISTORY: 8 | Created: 2011-05-13 18:18 PST - Donovan A. Chandler 9 | */ -------------------------------------------------------------------------------- /IsServer.calc: -------------------------------------------------------------------------------- 1 | PatternCount ( Get ( ApplicationVersion ) ; "server" ) > 0 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: IsServer ( ) 6 | PURPOSE: Returns 1 (True) if current user is the server (scheduled script) 7 | NOTES: 8 | For reference on Get ( ApplicationVersion ), see 9 | http://www.filemaker.com/12help/html/func_ref2.32.17.html#1028783 10 | HISTORY: 11 | Created: 2012-03-09 16:04 PT - Donovan Chandler 12 | Modified: 13 | */ -------------------------------------------------------------------------------- /IsWebPublished.calc: -------------------------------------------------------------------------------- 1 | PatternCount ( Get ( ApplicationVersion ) ; "Web Publishing" ) > 0 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: IsWebPublished ( ) 6 | PURPOSE: Returns TRUE if user is using Instant Web Publishing, otherwise FALSE. 7 | EXAMPLES: 8 | 9 | NOTES: 10 | For reference on Get ( ApplicationVersion ), see 11 | http://www.filemaker.com/12help/html/func_ref2.32.17.html#1028783 12 | HISTORY: 13 | Created: 2012-05-18 15:48 PT - Donovan Chandler 14 | */ -------------------------------------------------------------------------------- /IsWindows.calc: -------------------------------------------------------------------------------- 1 | Abs ( Get ( SystemPlatform ) ) = 2 2 | 3 | /* —————————————————————————————— // 4 | NAME: 5 | IsWindows () 6 | 7 | PURPOSE: 8 | Returns true if operating system is Windows 9 | 10 | EXAMPLES: 11 | 12 | 13 | HISTORY: 14 | Created: 2012-Feb-03 22h32 PST — Donovan A. Chandler 15 | */ -------------------------------------------------------------------------------- /JSONArray.calc: -------------------------------------------------------------------------------- 1 | "[" & JSONArrayLoop ( listOfValues ; ValueCount ( listOfValues ) ; "" ) & "]" 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: JSONArray ( listOfValues ) 6 | PURPOSE: Converts return-delimited list into JSON array. 7 | Escapes each value, unless it appears to be a JSON object or array. 8 | EXAMPLES: 9 | #Array ( "Oakland¶[\"a\",\"b\"]" ) = "[\"Oakland\",[\"a\",\"b\"]]" 10 | #Array ( "" ) = "[]" 11 | HISTORY: 12 | Created: 2012-05-29 12:18 PT - Donovan Chandler 13 | Modified: 14 | */ -------------------------------------------------------------------------------- /JSONArrayGet: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | inner = Trim ( Middle ( jsonArray ; 2 ; Length ( jsonArray ) - 2 ) ) 3 | ] ; 4 | TextBetweenNth ( "," & inner & "," ; "," ; "," ; index ) 5 | ) 6 | 7 | /* —————————————————————————————— // 8 | NAME: 9 | JSONArrayGet ( jsonArray ; index ) 10 | 11 | PURPOSE: 12 | Returns value from JSON-style array 13 | 14 | EXAMPLES: 15 | JSONArrayGet ( "[9,"b","c"]" ; 1 ) // = 9 16 | JSONArrayGet ( "[1,"b","c"]" ; 2 ) // = "\"b\"" 17 | 18 | HISTORY: 19 | Created: 2012-Mar-01 09h03 PST — Donovan A. Chandler 20 | */ -------------------------------------------------------------------------------- /JSONArrayLoop.calc: -------------------------------------------------------------------------------- 1 | Case ( 2 | repMax < 1 or IsEmpty ( listOfValues ) ; previousResults ; 3 | Let ( [ 4 | value = JSONEncodeStringOnly ( GetValue ( listOfValues ; 1 ) ) ; 5 | listNew = If ( not IsEmpty ( previousResults ) ; previousResults & "," ) & value ; 6 | listRemaining = MiddleValues ( listOfValues ; 2 ; repMax ) 7 | ] ; 8 | JSONArrayLoop ( listRemaining ; repMax - 1 ; listNew ) 9 | ) 10 | ) 11 | 12 | /* __________________________________________________ 13 | 14 | NAME: JSONArrayLoop ( listOfValues ; repMax ; previousResults ) 15 | PURPOSE: Performs recursion for JSONArray( ) 16 | EXAMPLES: 17 | 18 | HISTORY: 19 | Created: 2012-05-29 12:23 PT - Donovan Chandler 20 | Modified: 21 | */ -------------------------------------------------------------------------------- /JSONArrayToVariables.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | array = jsonObject ; 3 | name = TextBetween ( array ; "\"" ; ":" ; 1 ) ; 4 | name = TrimChars ( Trim ( name ) ; "\"" ) ; 5 | eName = Position ( array ; name ; 1 ; 1 ) + Length ( name ) ; 6 | value = TextBetween ( array ; ":" ; "," ; 1 ) ; 7 | value = TrimChars ( Trim ( value ) ; "\"" ) ; 8 | sValue = Position ( array ; value ; eName ; 1 ) ; 9 | eValue = If ( sValue > 0 ; Position ( array ; "," ; sValue ; 1 ) ) ; 10 | arrayRemaining = Middle ( array ; eValue ; Length ( array ) + 1 ) ; 11 | arrayRemaining = TrimChars ( Trim ( arrayRemaining ) ; "\"" ) 12 | ] ; 13 | VarSet ( name ; value ; useGlobalVars ) + 14 | If ( eValue > 0 and not IsEmpty ( arrayRemaining ) ; 15 | JSONObjectToVariables ( arrayRemaining ; useGlobalVars ) 16 | ) 17 | ) 18 | 19 | /* —————————————————————————————— // 20 | NAME: 21 | JSONObjectToVariables ( jsonObject ; useGlobalVars ) 22 | 23 | PURPOSE: 24 | Sets each value of associative array to a variable of same name. 25 | 26 | EXAMPLES: 27 | JSONObjectToVariables ( "\"name\":\"Bob\"" ; true ) 28 | // instantiates variable $$_name with value "Bob" 29 | 30 | HISTORY: 31 | Created: 2012-Jan-04 13h33 PST — Donovan Chandler 32 | */ -------------------------------------------------------------------------------- /JSONDecode.calc: -------------------------------------------------------------------------------- 1 | Substitute ( encodedText ; 2 | [ Backslash & QuotationMark ; QuotationMark ] ; 3 | [ Backslash & Backslash ; Backslash ] ; 4 | [ "\¶" ; ¶ ] 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: JSONDecode ( encodedText ) 10 | PURPOSE: Returns unquoted form of string encoded using JSONEncode( ) function. 11 | EXAMPLES: 12 | 13 | HISTORY: 14 | Created: 2012-02-13 13:00 PT - Will M. Baker 15 | Modified: 16 | */ -------------------------------------------------------------------------------- /JSONEncodeStringOnly.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | char1 = Left ( Trim ( text ) ; 1 ) ; 3 | isEscaped = ( char1 = "[" or char1 = "{" ) 4 | ] ; 5 | If ( isEscaped ; text ; JSONEncode ( text ) ) 6 | ) 7 | 8 | /* __________________________________________________ 9 | 10 | NAME: JSONEncodeStringOnly ( text ) 11 | PURPOSE: Creates quoted string for use in JSON, escaping characters as necessary. 12 | Leaves string in tact if it appears to be a JSON object or array. 13 | EXAMPLES: 14 | #EncodeStringOnly ( "Oakland" ) = "\"Oakland\"" 15 | #EncodeStringOnly ( " [\"a\",\"b\"]") = "[\"a\",\"b\"]" 16 | #EncodeStringOnly ( "{\"city\":\"Oakland\"}") = "{\"city\":\"Oakland\"}" 17 | HISTORY: 18 | Created: 2012-05-29 12:54 PT - Donovan Chandler 19 | Modified: 20 | */ -------------------------------------------------------------------------------- /JSONFromHash.calc: -------------------------------------------------------------------------------- 1 | JSONFromHashNames ( text ; #NameAll ( text ) ) 2 | 3 | /* —————————————————————————————— // 4 | NAME: 5 | JSONFromHash ( text ) 6 | 7 | PURPOSE: 8 | Converts text from hash to JSON 9 | 10 | EXAMPLES: 11 | 12 | 13 | HISTORY: 14 | Created: 2011-Nov-18 13h34 PST — Donovan Chandler 15 | */ -------------------------------------------------------------------------------- /JSONFromHashNames: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | _name = GetValue ( listOfNames ; 1 ) ; 3 | _valueRaw = #Value ( text ; _name ) ; 4 | _value = 5 | Case ( 6 | Position ( _valueRaw ; ¶ ; 1 ; 1 ) > 0 ; 7 | JSONArray ( _valueRaw ) ; 8 | _valueRaw 9 | ) ; 10 | _listCount = ValueCount ( listOfNames ) 11 | ] ; 12 | Case ( 13 | not IsEmpty ( _value ) ; 14 | JSONSet ( Lower ( _name ) ; _value ) 15 | ) & 16 | Case ( 17 | _listCount - 1 > 0 ; 18 | JSONFromHashNames ( text ; 19 | RightValues ( listOfNames ; _listCount - 1 ) 20 | ) 21 | ) 22 | ) 23 | 24 | /* —————————————————————————————— // 25 | NAME: 26 | JSONFromHashNames ( text ; listOfNames ) 27 | 28 | PURPOSE: 29 | Converts text from hash to JSON for named nodes at top level. 30 | 31 | EXAMPLES: 32 | 33 | HISTORY: 34 | Created: 2010-Aug-18 21h51 PST — Donovan A. Chandler 35 | 36 | NOTES: 37 | Names with empty values will be skipped. 38 | */ -------------------------------------------------------------------------------- /JSONObject.calc: -------------------------------------------------------------------------------- 1 | "{" & JSONObjectLoop ( listOfPairs ; ValueCount ( listOfPairs ) ; "" ) & "}" 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: #Object ( listOfPairs ) 6 | PURPOSE: Converts return-delimited list of encoded pairs into JSON object. 7 | Assumes each value is already encoded propertly. 8 | EXAMPLES: 9 | Where $_text = "\"city\":\"Oakland\"¶\"\"tags\":[\"bikes\"]" 10 | 11 | #Object ( $_text ) = "{\"city\":\"Oakland\"¶\"\"tags\":[\"bikes\"]}" 12 | #Array ( "" ) = "{}" 13 | HISTORY: 14 | Created: 2012-05-29 13:34 PT - Donovan Chandler 15 | Modified: 16 | */ -------------------------------------------------------------------------------- /JSONObjectLoop.calc: -------------------------------------------------------------------------------- 1 | Case ( 2 | repMax < 1 or IsEmpty ( listOfPairs ) ; previousResults ; 3 | Let ( [ 4 | value = GetValue ( listOfPairs ; 1 ) ; 5 | listNew = If ( not IsEmpty ( previousResults ) ; previousResults & "," ) & value ; 6 | listRemaining = MiddleValues ( listOfPairs ; 2 ; repMax ) 7 | ] ; 8 | JSONObjectLoop ( listRemaining ; repMax - 1 ; listNew ) 9 | ) 10 | ) 11 | 12 | /* __________________________________________________ 13 | 14 | NAME: JSONObjectLoop ( listOfPairs ; repMax ; previousResults ) 15 | PURPOSE: Performs recursion for #Object( ) 16 | EXAMPLES: 17 | 18 | HISTORY: 19 | Created: 2012-05-29 13:39 PT - Donovan Chandler 20 | Modified: 21 | */ -------------------------------------------------------------------------------- /JSONPair.calc: -------------------------------------------------------------------------------- 1 | JSONEncode ( name ) & ":" & JSONEncodeStringOnly ( value ) 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: JSONPair ( name ; value ) 6 | PURPOSE: Creates name-value pair in JSON format. 7 | EXAMPLES: 8 | # ( "name" ; "Oakland" ) = "\"name\":\"Oakland\"" 9 | # ( "array" ; " [\"a\",\"b\"]") = "\"array\":[\"a\",\"b\"]" 10 | # ( "object" ; "{\"city\":\"Oakland\"}") = "\"object\":{\"city\":\"Oakland\"}" 11 | HISTORY: 12 | Created: 2012-02-13 13:00 PT - Will M. Baker 13 | Modified: 2012-05-29 12:59 PT - Donovan Chandler : Now preserves pre-encoded values. 14 | */ -------------------------------------------------------------------------------- /JSONWhitespace: -------------------------------------------------------------------------------- 1 | List ( 2 | Char ( 32 ) // space 3 | ; Char ( 9 ) // horizontal tab 4 | ; Char ( 10 ) // line feed 5 | ; Char ( 11 ) // vertical tab 6 | ; Char ( 12 ) // form feed 7 | ; Char ( 13 ) // carriate return 8 | ) 9 | 10 | /* __________________________________________________ 11 | 12 | NAME: JSONWhitespace ( ) 13 | PURPOSE: Returns list of characters to ignore when searching for JSON values. 14 | HISTORY: 15 | Created: 2013-11-03 22:50 PT - Donovan Chandler 16 | Modified: 17 | */ -------------------------------------------------------------------------------- /JsonEscapeChars.calc: -------------------------------------------------------------------------------- 1 | Case ( 2 | GetAsNumber ( text ) = text ; text ; 3 | 4 | Substitute ( Quote ( text ) ; 5 | [ Char ( "/" ) ; "\\/" ] // forward slash 6 | ; [ Char ( 147 ) ; "\"" ] // left curly quote 7 | ; [ Char ( 148 ) ; "\"" ] // right curly quote 8 | ; [ Char ( 8220 ) ; "\"" ] // left curly quote 9 | ; [ Char ( 8221 ) ; "\"" ] // right curly quote 10 | 11 | //-- Collapse lines for efficiency 12 | // ; [ "\¶" ; ":‡:" ] 13 | // ; [ "¶" ; Char ( 32 ) ] // CR to space 14 | // ; [ ":‡:" ; "¶" ] 15 | ) 16 | ) 17 | 18 | /* __________________________________________________ 19 | 20 | NAME: JSONEncode ( text ) 21 | PURPOSE: Escapes or removes invalid characters in JSON 22 | EXAMPLES: 23 | JSONEncode ( "Jim said \"what's that \ / ?\"" ) 24 | // returns "Jim said \"what's that \\ \/ ?\"" 25 | HISTORY: 26 | Created: 2011-07-22 14:14 PT - Donovan Chandler 27 | Modified: 2013-10-20 16:53 PT - Donovan Chandler : Doesn't quote numbers. 28 | NOTES: 29 | Code ( " 30 | " ) = 32 31 | Code ( "¶" ) = 13 32 | */ -------------------------------------------------------------------------------- /JsonPretty.calc: -------------------------------------------------------------------------------- 1 | TextFormatLoop ( 2 | text ; 3 | "[¶{" ; // Open chars 4 | "]¶}" ; // Close chars 5 | "," ; // Delimiter chars 6 | "\"¶'" ; // Boundary chars 7 | 0 ; // Indent level 8 | 1 ; // Repetition 9 | Length ( text ) 10 | ) 11 | 12 | // TextFormatLoop ( text ; openChars ; closeChars ; delimiterChars ; boundaryChars ; indentLevel ; rep ; repMax ) 13 | 14 | /* —————————————————————————————— // 15 | NAME: 16 | JSONPretty ( text ) 17 | 18 | PURPOSE: 19 | Formats JSON text in readable format 20 | 21 | EXAMPLES: 22 | 23 | 24 | HISTORY: 25 | Created: 2011-Feb-08 11h11 PST — Donovan A. Chandler 26 | */ -------------------------------------------------------------------------------- /LibField.calc: -------------------------------------------------------------------------------- 1 | GetFieldName ( FOCUS::LIBRARY_CODE_REP ) & "[" & index & "]" 2 | 3 | /* —————————————————————————————— // 4 | NAME: 5 | LibField ( index ) 6 | 7 | PURPOSE: 8 | Returns name of field from LIBRARY record with specified index value. 9 | 10 | EXAMPLES: 11 | LibField ( 1 ) = "FOCUS::LIBRARY_CODE_REP[1]" 12 | 13 | HISTORY: 14 | Created: 2010-Aug-24 12h12 PST — Donovan A. Chandler 15 | */ -------------------------------------------------------------------------------- /LibText.calc: -------------------------------------------------------------------------------- 1 | FOCUS::LIBRARY_CODE_REP[index] 2 | 3 | /* —————————————————————————————— // 4 | NAME: 5 | LibText ( index ) 6 | 7 | PURPOSE: 8 | Returns text from LIBRARY record with specified index value. 9 | 10 | HISTORY: 11 | Created: 2010-Aug-24 12h12 PST — Donovan A. Chandler 12 | */ -------------------------------------------------------------------------------- /ListAddUnique.calc: -------------------------------------------------------------------------------- 1 | List ( 2 | lst ; 3 | If ( not ListContains ( lst ; value ) ; value ) 4 | ) 5 | 6 | /* —————————————————————————————— // 7 | NAME: 8 | ListAddUnique ( lst ; value ) 9 | 10 | PURPOSE: 11 | Appends value to a return-delimited list if it does not already exist. 12 | Compares entire value (case-insensitive) to determine match. 13 | 14 | EXAMPLES: 15 | ListAddUnique ( "dog¶cat" ; "mouse" ) = "dog¶cat¶mouse" 16 | ListAddUnique ( "dog¶cat" ; "dog" ) = "dog¶cat" 17 | ListAddUnique ( "Dog¶cat" ; "dog" ) = "dog¶cat" 18 | ListAddUnique ( "doggie¶cat" ; "dog" ) = "dog¶cat¶doggie" 19 | ListAddUnique ( "dog¶cat" ; "dog¶doggie" ) = "dog¶cat¶dog¶doggie" 20 | 21 | HISTORY: 22 | Created: 2011-June-27 1h00 PDT — L. Allen Poole 23 | Modified: 2012-Jan-09 17h05 PST — Donovan Chandler ; Now uses List() for handling empty lines. 24 | */ -------------------------------------------------------------------------------- /ListAggregateRelatedSets.calc: -------------------------------------------------------------------------------- 1 | Let([ 2 | _field = relatedFieldContainingLists ; 3 | _ex = "list.aggregateNthRecordValues ( " & GetFieldName(_field) & "; [n]; " & Quote ( aggregationType ) & " )" 4 | ]; 5 | CustomList ( 6 | 1 ; 7 | ValueCount ( _field ) ; 8 | _ex 9 | ) 10 | ) 11 | 12 | /* —————————————————————————————— // 13 | NAME: 14 | list.aggregateRelatedSets ( relatedFieldContainingLists ; aggregationType ) 15 | 16 | PURPOSE: 17 | If a related field has lists of values, this function will take value one from each list and aggregate it (see list.aggregateNthRecordValues). Then it will do the same for the second value, etc. 18 | 19 | EXAMPLES: 20 | list.aggregateNthRecordValues ( 21 | "STUDENT_CLASS::ListOfMonthlyTotals"; 22 | "Average" 23 | ) 24 | = "80.345¶90¶75¶60¶78.113456¶80¶90.09875¶75¶60¶78¶50¶90.01" 25 | = Average totals for January thru December 26 | 27 | HISTORY: 28 | Created: 2010-Jun-11 15h02 PST — Donovan A. Chandler 29 | */ -------------------------------------------------------------------------------- /ListAppendPrecedingValues.calc: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------- 2 | NAME: 3 | list.appendPrecedingValues( text; searchString ) 4 | 5 | PURPOSE: 6 | Returns searchString and all values preceding it in text 7 | 8 | HISTORY: 9 | Created 2010.02.10 by Donovan Chandler 10 | 11 | DEPENDENCIES: 12 | list.getValueIndex() 13 | 14 | ---------------------------------------------------------------------------------------*/ 15 | //Show checked value as well as preceding values// 16 | 17 | Let([ 18 | lisValues = text; 19 | vValueSel = searchString; 20 | indexValueSel = list.getValueIndex( lisValues; vValueSel; False ); 21 | lisValuesResult = LeftValues( lisValues; indexValueSel ) 22 | ]; 23 | lisValuesResult 24 | ) -------------------------------------------------------------------------------- /ListAppendUnique.calc: -------------------------------------------------------------------------------- 1 | Let ( 2 | [ 3 | value_exists = Position ( "¶" & currentList & "¶" ; "¶" & value & "¶" ) 4 | ] ; 5 | Case ( 6 | value_exists ; 7 | currentList ; 8 | 9 | IsEmpty ( value ) ; 10 | currentList ; 11 | 12 | currentList & 13 | If ( Right ( currentList ; 1 ) ≠ ¶ and Length ( currentList ) ; ¶ ) & value 14 | ) 15 | ) 16 | 17 | 18 | /* —————————————————————————————— // 19 | NAME: 20 | list.appendUnique ( currentList ; value ) 21 | 22 | PURPOSE: 23 | Appends value to list if it does not already exist in the list 24 | 25 | EXAMPLES: 26 | 27 | 28 | HISTORY: 29 | Created: 2010-Jul-20 15h18 PST — Donovan A. Chandler 30 | */ -------------------------------------------------------------------------------- /ListChartRelatedValues.calc: -------------------------------------------------------------------------------- 1 | Let([ 2 | _field = relatedFieldContainingLists ; 3 | _ex = "list.aggregateNthRecordValues ( " & GetFieldName(_field) & "; [n]; " & Quote ( aggregationType ) & " )" 4 | ]; 5 | CustomList ( 6 | 1 ; 7 | ValueCount ( _field ) ; 8 | _ex 9 | ) 10 | ) 11 | 12 | /* —————————————————————————————— // 13 | NAME: 14 | list.aggregateRelatedSets ( relatedFieldContainingLists ; aggregationType ) 15 | 16 | PURPOSE: 17 | If a related field has lists of values, this function will take value one from each list and aggregate it (see list.aggregateNthRecordValues). Then it will do the same for the second value, etc. 18 | 19 | EXAMPLES: 20 | list.aggregateNthRecordValues ( 21 | "STUDENT_CLASS::ListOfMonthlyTotals"; 22 | "Average" 23 | ) 24 | = "80.345¶90¶75¶60¶78.113456¶80¶90.09875¶75¶60¶78¶50¶90.01" 25 | = Average totals for January thru December 26 | 27 | HISTORY: 28 | Created: 2010-Jun-11 15h02 PST — Donovan A. Chandler 29 | */ -------------------------------------------------------------------------------- /ListChunk.calc: -------------------------------------------------------------------------------- 1 | ListChunkLoop ( completeList ; chunkSize ; chunkName ; 1 ; "" ) 2 | 3 | /* —————————————————————————————— // 4 | NAME: 5 | ListChunk ( completeList ; chunkSize ; chunkName ) 6 | 7 | PURPOSE: 8 | Breaks list into series of named values. 9 | 10 | EXAMPLES: 11 | ListChunk ( "1¶2¶3¶4¶5" ; 2 ; "SET" ) 12 | = "<:SET:=1¶2:>¶<:SET:=3¶4:>¶<:SET:=5:>" 13 | 14 | HISTORY: 15 | Created: 2011-Mar-24 17h14 PST — Donovan A. Chandler 16 | */ -------------------------------------------------------------------------------- /ListChunkLoop.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | startCur = ( rep - 1 ) * chunkSize + 1 ; 3 | listCur = MiddleValues ( completeList ; startCur ; chunkSize ) ; 4 | listHash = # ( chunkName ; TrimCarriageReturns ( listCur ) ) ; 5 | result = List ( previousResults ; listHash ) 6 | ]; 7 | Case ( 8 | IsEmpty ( listCur ) ; previousResults ; 9 | ListChunkLoop ( completeList ; chunkSize ; chunkName ; rep + 1 ; result ) 10 | ) 11 | ) 12 | 13 | /* —————————————————————————————— // 14 | NAME: 15 | ListChunkLoop ( completeList ; chunkSize ; chunkName ; rep ; previousResults ) 16 | 17 | PURPOSE: 18 | Performs recursion for ListChunk. 19 | 20 | EXAMPLES: 21 | 22 | 23 | HISTORY: 24 | Created: 2011-Mar-24 16h54 PST — Donovan A. Chandler 25 | */ -------------------------------------------------------------------------------- /ListContains.calc: -------------------------------------------------------------------------------- 1 | not IsEmpty ( FilterValues ( searchValue ; listOfValues ) ) 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: ListContains ( listOfValues ; searchValue ) 6 | PURPOSE: Returns true if listOfValues contains match for searchValue 7 | EXAMPLES: 8 | List ( 9 | ListContains ( "foo¶fum¶fap" ; "FOO" ) = 1 10 | ; ListContains ( "foo¶fum¶fap" ; "FOG" ) = 0 11 | ; ListContains ( "foo¶fum¶fap" ; "fu" ) = 0 12 | ; ListContains ( "foo¶fum¶fap" ; "fum¶fap" ) = 1 13 | ) 14 | HISTORY: 15 | Created: 2012-03-15 21:59 PST - Donovan Chandler 16 | Modified: 2014-04-09 12:25 PDT - Jeremy Bante : Improving performance 17 | NOTES: 18 | For case sensitive search, use ListFilterCustom() 19 | */ -------------------------------------------------------------------------------- /ListDateFromNumber.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | listCount = ValueCount ( listOfNumbers ) 3 | ]; 4 | 5 | GetAsDate ( GetAsNumber ( GetValue( listOfNumbers; 1 ) ) ) & 6 | Case ( 7 | listCount > 1; 8 | ¶ & ListDateFromNumber ( RightValues ( listOfNumbers; listCount - 1 )) 9 | ) 10 | 11 | ) 12 | 13 | /* —————————————————————————————— // 14 | NAME: 15 | ListDateFromNumber ( listOfNumbers ) 16 | 17 | PURPOSE: 18 | Converts a list of numbers into a list of dates. Useful when sorting a list of dates. 19 | 20 | EXAMPLES: 21 | 22 | 23 | HISTORY: 24 | Created: 2010-Sep-07 17h18 PST — Donovan A. Chandler 25 | */ -------------------------------------------------------------------------------- /ListDateToNumber.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | listCount = ValueCount ( listOfDates ) 3 | ] ; 4 | GetAsNumber ( GetAsDate ( GetValue( listOfDates; 1 ) ) ) & 5 | Case ( 6 | listCount > 1; 7 | ¶ & ListDateToNumber ( RightValues ( listOfDates; listCount - 1 ) ) 8 | ) 9 | ) 10 | 11 | /* __________________________________________________ 12 | 13 | NAME: ListDateToNumber ( listOfDates ) 14 | PURPOSE: Converts a list of dates into a list of numbers. Useful when sorting a list of dates. 15 | EXAMPLES: 16 | 17 | HISTORY: 18 | Created: 2010-09-07 17:18 PT - Donovan Chandler 19 | */ 20 | -------------------------------------------------------------------------------- /ListFilter.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | valueCur = GetValue ( valuesToRemove ; 1 ) ; 3 | valueCnt = ValueCount ( valuesToRemove ) ; 4 | listNew = ListFilterSub ( listOfValues ; valueCur ) 5 | ] ; 6 | If ( 7 | valueCnt ≤ 1 ; listNew ; 8 | ListFilter ( listNew ; RightValues ( valuesToRemove ; valueCnt - 1 ) ) 9 | ) 10 | ) 11 | 12 | /* __________________________________________________ 13 | 14 | NAME: ListFilter ( listOfValues ; valuesToRemove ) 15 | PURPOSE: Returns list with designated value(s) removed. 16 | Preserves all empty lines. 17 | EXAMPLES: 18 | ListFilter ( "Do¶Dog¶¶Cat" ; "Do" ) = "Dog¶¶Cat" 19 | ListFilter ( "Do¶Dog¶Cat" ; "Do¶Cat" ) = "Dog" 20 | ListFilter ( "Do¶Dog¶Cat¶" ; "Dog¶Cat" ) = "Do¶" 21 | HISTORY: 22 | Created: 2012-11-30 10:40 PT - Donovan Chandler 23 | Modified: 24 | */ -------------------------------------------------------------------------------- /ListFilterSub.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | match = ¶ & valueToRemove & ¶ ; 3 | matchStart = Position ( ¶ & listOfValues & ¶ ; match ; 1 ; 1 ) ; 4 | matchStart = matchStart + If ( matchStart > 1 ; -1 ) // Subtract to offset the leading ¶ 5 | ] ; 6 | If ( 7 | matchStart = 0 ; listOfValues ; 8 | Let ( [ 9 | lead = Left ( listOfValues ; matchStart - 1 ) ; 10 | trail = Middle ( listOfValues ; matchStart + Length ( match ) - 1 ; Length ( listOfValues ) ) 11 | ] ; 12 | lead & ListFilterSub ( trail ; valueToRemove ) 13 | ) 14 | ) 15 | ) 16 | 17 | /* __________________________________________________ 18 | 19 | NAME: ListFilterSub ( listOfValues ; valueToRemove ) 20 | PURPOSE: Returns list with designated value removed. 21 | Preserves empty lines. 22 | EXAMPLES: 23 | ListFilterSub ( "Do¶Dog¶¶Cat" ; "Do" ) = "Dog¶¶Cat" 24 | ListFilterSub ( "Do¶Dog¶Cat" ; "Do¶Cat" ) = "Do¶Dog¶Cat" 25 | ListFilterSub ( "Do¶Dog¶Cat¶" ; "Dog¶Cat" ) = "Do¶" 26 | HISTORY: 27 | Created: 2012-11-29 21:47 PT - Donovan Chandler 28 | Modified: 29 | */ -------------------------------------------------------------------------------- /ListFoundValues.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | $_field_name = fieldName ; 3 | listFull = ListCustom ( 1 ; Get ( FoundCount ) ; "GetNthRecord ( GetField ( $_field_name ) ; [n])" ) 4 | ] ; 5 | Case ( 6 | uniqueValuesOnly ; 7 | ListUniqueValues ( listFull ) ; 8 | listFull 9 | ) 10 | ) 11 | 12 | /* —————————————————————————————— // 13 | NAME: 14 | ListFoundValues ( fieldName ; uniqueValuesOnly ) 15 | 16 | PURPOSE: 17 | Returns values from field for current found set. Not for use on large data sets! 18 | 19 | EXAMPLES: 20 | 21 | 22 | HISTORY: 23 | Created: 2011-Jun-07 15h40 PST — Donovan A. Chandler 24 | */ -------------------------------------------------------------------------------- /ListIndex.calc: -------------------------------------------------------------------------------- 1 | ListIndexLoop ( listOfValues ; matchValue ; 1 ; ValueCount ( listOfValues ) ; False ) 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: ListIndex ( listOfValues ; matchValue ) 6 | PURPOSE: Searches return-delimited list, returning index/value number of first value matching matchValue. 7 | TESTS: 8 | List ( 9 | ListIndex ( "lemur¶sky bison¶bear" ; "sky" ) = 0 ; 10 | ListIndex ( "lemur¶sky bison¶bear" ; "bear" ) = 3 ; 11 | ListIndex ( "lemur¶sky bison¶bear" ; "Lemur" ) = 1 12 | ) 13 | HISTORY: 14 | Created: 2013-12-09 21:43 PT - Donovan Chandler 15 | Modified: 16 | */ -------------------------------------------------------------------------------- /ListIndexLoop.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | ~value = GetValue ( listOfValues ; startIndex ) 3 | ] ; 4 | Case ( 5 | startIndex > indexCount ; 6 | 0 ; 7 | matchCase ; 8 | If ( Exact ( ~value ; matchValue ) ; startIndex ; 0 ) ; 9 | ~value = matchValue ; 10 | startIndex ; 11 | ListIndexLoop ( listOfValues ; matchValue ; startIndex + 1 ; indexCount ; matchCase ) 12 | ) 13 | ) 14 | 15 | /* __________________________________________________ 16 | 17 | NAME: ListIndexLoop ( listOfValues ; matchValue ; startIndex ; indexCount ; matchCase ) 18 | PURPOSE: Searches return-delimited list, returning index/value number of first value matching matchValue. 19 | TESTS: 20 | List ( 21 | ListIndexLoop ( "lemur¶sky bison¶bear" ; "sky" ; 1 ; 3 ; 0 ) = 0 ; 22 | ListIndexLoop ( "lemur¶sky bison¶bear" ; "bear" ; 1 ; 2 ; 0 ) = 0 ; 23 | ListIndexLoop ( "lemur¶sky bison¶bear" ; "bear" ; 1 ; 3 ; 0 ) = 3 ; 24 | ListIndexLoop ( "lemur¶sky bison¶bear" ; "Lemur" ; 1 ; 3 ; 0 ) = 1 ; 25 | ListIndexLoop ( "lemur¶sky bison¶bear" ; "Lemur" ; 1 ; 3 ; 1 ) = 0 26 | ) 27 | HISTORY: 28 | Created: 2010-01-29 17:00 PT - Will M. Baker 29 | */ 30 | -------------------------------------------------------------------------------- /ListJoin.calc: -------------------------------------------------------------------------------- 1 | Case ( IsEmpty ( lastDelimiter ) ; Substitute ( theList ; ¶ ; delimiter ) ; Let ( [ sLast = Position ( theList ; ¶ ; Length ( theList ) ; -1 ) ; rough = Replace ( theList ; sLast ; 1 ; lastDelimiter ) ] ; Substitute ( rough ; ¶ ; delimiter ) ) ) /* —————————————————————————————— // NAME: ListJoin ( theList ; delimiter ; lastDelimiter ) PURPOSE: Collapses list into string delimited by provided characters. EXAMPLES: ListJoin ( "dog¶cat¶mouse" ; ", " ; " or " ) = "dog, cat or mouse" ListJoin ( "dog¶cat¶mouse" ; ", " ; "" ) = "dog, cat, mouse" HISTORY: Created: 2011-Nov-30 16h43 PST — Donovan A. Chandler */ -------------------------------------------------------------------------------- /ListModifyValues.calc: -------------------------------------------------------------------------------- 1 | Case ( 2 | 3 | ValueCount ( text ) > 0; 4 | Let ([ 5 | vValueCur = LeftValues ( Substitute ( text ; [ "\“" ; "\"" ] ; [ "\”" ; "\"" ] ; [ "\"" ; "\\\""] ) ; 1) ; 6 | exComplete = 7 | Substitute ( expression ; 8 | [ valuePlaceholder ; "\"" & Substitute ( vValueCur ; ¶ ; "" ) & "\"" ] 9 | ) ; 10 | vValEvaluated = Evaluate ( exComplete ) ; 11 | numValuesRem = ValueCount ( text ) - 1 12 | ] ; 13 | Substitute ( vValEvaluated ; "\\\"" ; "\"" ) 14 | & If ( numValuesRem > 0 ; ¶ ) 15 | & ListModifyValues ( 16 | RightValues ( text ; numValuesRem ) ; 17 | valuePlaceholder ; 18 | expression 19 | ) 20 | ) 21 | 22 | ) 23 | 24 | /* __________________________________________________ 25 | 26 | NAME: ListModifyValues ( text ; valuePlaceholder ; expression ) 27 | PURPOSE: Applies expression to each return-delimited value in text. 28 | EXAMPLES: 29 | ListModifyValues ( "dog¶cat¶mouse"; "[v]"; "Left( [v]; 2 )" ) = "do¶ca¶mo" 30 | HISTORY: 31 | Compliments to Fabrice Nordmann of BH&A for example of this expression evaluation technique 32 | Created: 2010-02-10 00:00 PT - Donovan Chandler 33 | Modified: 2013-04-22 09:39 PT - Donovan Chandler : Updated formatting. 34 | */ -------------------------------------------------------------------------------- /ListPrependBOM.calc: -------------------------------------------------------------------------------- 1 | List ( 2 | 3 | If ( startIndex > 1 ; StringRepeat ( Char ( 65279 ) ; startIndex ) ) 4 | & GetValue ( theList ; startIndex ) 5 | 6 | ; If ( ValueCount ( theList ) > startindex ; ListPrependBOM ( theList ; startIndex + 1 ) ) 7 | 8 | ) 9 | 10 | /* __________________________________________________ 11 | 12 | NAME: ListPrependBOM ( theList ; startIndex ) 13 | PURPOSE: Prepends each line with byte order marks. Used to create sorted value lists. 14 | EXAMPLES: 15 | 16 | HISTORY: 17 | Thanks to Lon Cook for pointing me to BOM an Char ( 65279 ). 18 | Created: 2013-08-07 14:42 PT - Donovan Chandler 19 | Modified: 20 | */ -------------------------------------------------------------------------------- /ListRemoveEmptyValues.calc: -------------------------------------------------------------------------------- 1 | Case ( 2 | //-- Iterate until all empty rows are removed 3 | PatternCount ( text ; "¶¶" ) > 0 ; 4 | ListRemoveEmptyValues ( 5 | Substitute ( text ; 6 | [ "¶¶¶" ; "¶" ] ; 7 | [ "¶¶" ; "¶" ] 8 | ) 9 | ) ; 10 | 11 | //-- If list is clean, remove leading/trailing returns 12 | TrimCR ( text ) 13 | ) 14 | 15 | /* —————————————————————————————— // 16 | NAME: 17 | ListRemoveEmptyValues ( text ) 18 | 19 | PURPOSE: 20 | Removes all empty values from list 21 | 22 | EXAMPLES: 23 | ListRemoveEmptyValues ( "¶foo¶¶bar" ) = "foo¶bar" 24 | 25 | HISTORY: 26 | Created: 2010-Sep-06 08h26 PST — Donovan A. Chandler 27 | */ -------------------------------------------------------------------------------- /ListRemoveSuccessiveDuplicates.calc: -------------------------------------------------------------------------------- 1 | ListRemoveSuccessiveDuplicatesLoop ( text ; 1 ; "" ) 2 | 3 | /* —————————————————————————————— // 4 | NAME: 5 | ListRemoveSuccessiveDuplicates ( text ) 6 | 7 | PURPOSE: 8 | Returns list of values with neighboring duplicates removed. 9 | 10 | EXAMPLES: 11 | ListRemoveNeighboringDuplicates ( "1¶2¶2¶1¶2" ) = "1¶2¶1¶2" 12 | 13 | HISTORY: 14 | Created: 2010-Nov-09 10h17 PST — Donovan A. Chandler 15 | */ -------------------------------------------------------------------------------- /ListRemoveSuccessiveDuplicatesLoop.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | value_cur = GetValue ( text ; repetition ) ; 3 | value_prev = GetValue ( previousResults ; ValueCount ( previousResults ) ) ; 4 | result_new = 5 | Case ( 6 | value_cur ≠ value_prev ; 7 | previousResults & ¶ & value_cur ; 8 | previousResults 9 | ) 10 | ]; 11 | 12 | Case ( 13 | repetition ≥ ValueCount ( text ) ; 14 | ListTrimCR ( result_new ) ; 15 | 16 | ListRemoveSuccessiveDuplicatesLoop ( text ; repetition + 1 ; result_new ) 17 | ) 18 | 19 | ) 20 | 21 | /* —————————————————————————————— // 22 | NAME: 23 | ListRemoveSuccessiveDuplicates ( text ; repetition ) 24 | 25 | PURPOSE: 26 | Returns list of values with neighboring duplicates removed. 27 | 28 | EXAMPLES: 29 | ListRemoveSuccessiveDuplicatesLoop ( "1¶2¶2¶1¶2" ; 3 ; "1¶2" ) = "1¶2¶1¶2" 30 | 31 | HISTORY: 32 | Created: 2010-Nov-09 10h17 PST — Donovan A. Chandler 33 | */ -------------------------------------------------------------------------------- /ListReplaceValue.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | lstLen = ValueCount ( lst ) ; 3 | lstGap = index - lstLen ; 4 | padding = If ( lstGap > 0 ; StringRepeatLoop ( "¶" ; 1 ; lstGap ) ) ; 5 | lead = LeftValues ( lst & padding ; index - 1 ) ; 6 | trail = RightValues ( lst ; lstLen - index ) 7 | ] ; 8 | lead & newValue & If ( not IsEmpty ( trail ) ; ¶ & trail ) 9 | ) 10 | 11 | /* __________________________________________________ 12 | 13 | NAME: ListReplaceValue ( lst ; index ; newValue ) 14 | PURPOSE: Replaces value at given index in list. 15 | EXAMPLES: 16 | 17 | HISTORY: 18 | Created: 2013-03-03 22:33 PT - Donovan Chandler 19 | Modified: 20 | */ -------------------------------------------------------------------------------- /ListSortByList.calc: -------------------------------------------------------------------------------- 1 | ListSortByListLoop ( 2 | listToSort ; 3 | ListUniqueValues ( sortedList ) ; 4 | 1 ; 5 | ValueCount ( sortedList ) ; 6 | "" 7 | ) 8 | 9 | /* __________________________________________________ 10 | 11 | NAME: ListSortByList ( listToSort ; sortedList ) 12 | PURPOSE: Sorts list in order designated by another list 13 | EXAMPLES: 14 | NOTES: 15 | Omits values that do not appear in sorted list. 16 | HISTORY: 17 | Created: 2011-05-24 16:07 PT - Donovan A. Chandler 18 | */ -------------------------------------------------------------------------------- /ListSortByListLoop.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | val = GetValue ( sortedList ; rep ) 3 | ]; 4 | Case ( 5 | rep ≤ rep_max ; 6 | ListSortByListLoop ( 7 | listToSort ; 8 | sortedList ; 9 | rep + 1 ; 10 | rep_max ; 11 | TrimCR ( List ( previousResults ; FilterValues ( listToSort ; val ) ) ) 12 | ) ; 13 | previousResults 14 | ) 15 | ) 16 | 17 | /* __________________________________________________ 18 | 19 | NAME: ListSortByListLoop ( listToSort ; sortedList ; rep ; rep_max ; previousResults ) 20 | PURPOSE: Performs recursive operations for ListSortByList() 21 | EXAMPLES: 22 | 23 | HISTORY: 24 | Created: 2011-05-24 16:02 PT - Donovan A. Chandler 25 | */ -------------------------------------------------------------------------------- /ListSortByValueList.calc: -------------------------------------------------------------------------------- 1 | ListSortByList ( 2 | listToSort ; 3 | ValueListItems ( Get ( FileName ) ; valueListName ) 4 | ) 5 | 6 | /* —————————————————————————————— // 7 | NAME: 8 | ListSortByValueList ( listToSort ; valueListName ) 9 | 10 | PURPOSE: 11 | Sorts list by order of values in value list. 12 | 13 | EXAMPLES: 14 | 15 | 16 | HISTORY: 17 | Created: 2011-May-24 16h22 PST — Donovan A. Chandler 18 | */ -------------------------------------------------------------------------------- /ListSortDates.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | numberList = ListDateToNumber ( listOfDates ) ; 3 | numberSorted = 4 | Case ( 5 | sortDescending ; 6 | ListSortDesc ( numberList) ; 7 | ListSort ( numberList ) 8 | ) 9 | ]; 10 | ListDateFromNumber ( numberSorted ) 11 | ) 12 | 13 | /* —————————————————————————————— // 14 | NAME: 15 | ListSortDates ( listOfDates ; sortDescending ) 16 | 17 | PURPOSE: 18 | Returns a sorted list of dates. 19 | 20 | EXAMPLES: 21 | ListSortDates ( "9/1/10¶10/1/10" ; 1 ) = "10/1/10¶9/1/10" 22 | 23 | HISTORY: 24 | Created: 2010-Sep-07 17h45 PST — Donovan A. Chandler 25 | */ -------------------------------------------------------------------------------- /ListToggleValue.calc: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------- 2 | NAME: 3 | list.toggleValue( listOfValues ; valueAddOrRemove ) 4 | 5 | PURPOSE: 6 | Adds or removes value from theList 7 | 8 | HISTORY: 9 | Created 2010-Mar-31 by Donovan Chandler 10 | 11 | ---------------------------------------------------------------------------------------*/ 12 | 13 | Let([ 14 | _list = listOfValues; 15 | _string = valueAddOrRemove 16 | 17 | ]; 18 | 19 | Case( 20 | //-- If value exists, remove it 21 | ValueCount( FilterValues( _list; _string )) > 0; 22 | list.remove( _list; _string ); 23 | 24 | //-- Else, append value 25 | If( IsEmpty( _list ); ""; _list & ¶ ) & _string 26 | ) 27 | 28 | ) -------------------------------------------------------------------------------- /ListTrimAndJoin.calc: -------------------------------------------------------------------------------- 1 | Substitute ( 2 | ListTrimValues ( text ) ; 3 | ¶ ; 4 | newDelimiter 5 | ) 6 | 7 | /* —————————————————————————————— // 8 | NAME: 9 | ListTrimAndJoin ( text ; newDelimiter ) 10 | 11 | PURPOSE: 12 | Replaces carriage returns in return-delimited list with new delimiter. 13 | Also strips whitespace from ends of each line. 14 | 15 | EXAMPLES: 16 | ListTrimAndJoin ( "dog¶ cat ¶¶mouse¶" ; ", " ) = "dog,cat,mouse" 17 | 18 | HISTORY: 19 | Created: 2011-Mar-08 09h33 PST — Donovan A. Chandler 20 | */ -------------------------------------------------------------------------------- /ListTrimValues.calc: -------------------------------------------------------------------------------- 1 | ListTrimValuesLoop ( theList ; 1 ; ValueCount ( theList ) ) 2 | 3 | /* —————————————————————————————— // 4 | NAME: 5 | ListTrimValues ( theList ) 6 | 7 | PURPOSE: 8 | Removes leading and trailing spaces from each value in a list. 9 | 10 | EXAMPLES: 11 | 12 | 13 | HISTORY: 14 | Created: 2011-Feb-02 12h11 PST — Donovan Chandler 15 | */ -------------------------------------------------------------------------------- /ListTrimValuesLoop.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | valueTrimmed = Trim ( GetValue ( theList ; rep ) ) ; 3 | listNew = 4 | List ( 5 | ListTrimCR ( LeftValues ( theList ; rep - 1 ) ) ; 6 | valueTrimmed ; 7 | MiddleValues ( theList ; rep + 1 ; 50000 ) 8 | ) 9 | ] ; 10 | Case ( 11 | rep < repMax ; 12 | ListTrimValuesLoop ( listNew ; rep + 1 ; repMax ) ; 13 | 14 | listNew 15 | ) 16 | ) 17 | 18 | /* —————————————————————————————— // 19 | NAME: 20 | ListTrimValuesLoop ( theList ; rep ; repMax ) 21 | 22 | PURPOSE: 23 | Peforms recursion for ListTrimValues 24 | 25 | EXAMPLES: 26 | 27 | 28 | HISTORY: 29 | Created: 2011-Feb-02 12h04 PST — Donovan A. Chandler 30 | */ -------------------------------------------------------------------------------- /ListUnique_v2.calc: -------------------------------------------------------------------------------- 1 | //---- UNDER DEVELOPMENT ---- 2 | Let([ 3 | _list = theList; 4 | $$_uniqueList_list = 5 | If ( not IsEmpty ( $$_uniqueList_list ) 6 | ; $$_uniqueList_list 7 | ; _list 8 | ); 9 | $$_uniqueList_rep = $$_uniqueList_rep + 1; 10 | 11 | _list_rev = $$_uniqueList_list; 12 | _rep = $$_uniqueList_rep; 13 | _valueCur = GetValue ( _list) 14 | 15 | 16 | ]; 17 | //Replace all subsequent values with null and continue down list 18 | ) 19 | 20 | /*--------------------------------------------------------------------------------------- 21 | NAME: 22 | list.uniqueValues ( theList ) 23 | 24 | PURPOSE: 25 | Returns return-delimited list containing only unique values in the order that they first appear. 26 | 27 | HISTORY: 28 | Created 2010.04.27 by Donovan Chandler 29 | 30 | EXAMPLE: 31 | 32 | 33 | ---------------------------------------------------------------------------------------*/ -------------------------------------------------------------------------------- /ListWithNull.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | rep_max = Count ( GetField ( relatedIDFieldName ) ) 3 | ] ; 4 | Case ( 5 | rep_max > 0 ; 6 | ListWithNullLoop ( relatedIDFieldName ; relatedValueFieldName ; nullPlaceholder ; 1 ; rep_max ; "" ) 7 | ) 8 | ) 9 | 10 | 11 | /* —————————————————————————————— // 12 | NAME: 13 | ListWithNull ( relatedIDFieldName ; relatedValueFieldName ; nullPlaceholder ) 14 | 15 | PURPOSE: 16 | Returns list of related values, accounting for empty values. 17 | (FileMaker's native List function omits empty values.) 18 | 19 | EXAMPLES: 20 | ListWithNull ( 21 | GetFieldName ( contact::id ) ; 22 | GetFieldName ( contact::name ) ; 23 | $_null 24 | ) 25 | = "Fred¶¶Cindy" // where $_null = "" 26 | = "Fred¶¶Cindy" // where $_null = "" 27 | 28 | HISTORY: 29 | Created: 2011-Sep-29 09h50 PST — Donovan A. Chandler 30 | */ -------------------------------------------------------------------------------- /ListWithNullLoop.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | value = GetNthRecord ( GetField ( relatedValueFieldName ) ; rep ) ; 3 | result = If ( IsEmpty ( value ) ; nullPlaceholder ; value ) ; 4 | resultFull = If ( rep = 1 ; result ; previousResults & ¶ & result ) 5 | ] ; 6 | Case ( 7 | rep < rep_max ; 8 | ListWithNullLoop ( relatedIDFieldName ; relatedValueFieldName ; nullPlaceholder ; rep + 1 ; rep_max ; resultFull ) ; 9 | resultFull 10 | ) 11 | ) 12 | 13 | /* —————————————————————————————— // 14 | NAME: 15 | ListWithNullLoop ( relatedIDFieldName ; relatedValueFieldName ; nullPlaceholder ; rep ; rep_max ; previousResults ) 16 | 17 | PURPOSE: 18 | Performs recursion for ListWithNull () 19 | 20 | NOTES: 21 | nullPlaceholder cannot contain only carriage returns. 22 | 23 | HISTORY: 24 | Created: 2011-Sep-29 09h50 PST — Donovan A. Chandler 25 | */ -------------------------------------------------------------------------------- /LogDelimiter.calc: -------------------------------------------------------------------------------- 1 | "|" 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: LogDelimiter 6 | PURPOSE: Stores delimiter used between audit log columns. Enables easy parsing of logs. 7 | HISTORY: 8 | Created: 2012-04-17 13:00 PST - Donovan Chandler 9 | Modified: 10 | */ -------------------------------------------------------------------------------- /LogExtract.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | labelDelim = "%" ; 3 | columnDelim = LogDelimiter ; 4 | row = GetValue ( logText ; 1 ) ; 5 | sFormatNode = Position ( format ; label ; 1 ; 1 ) ; 6 | index = PatternCount ( Left ( format ; sFormatNode ) ; labelDelim ) 7 | ] ; 8 | TextBetween ( columnDelim & row & columnDelim ; columnDelim ; columnDelim ; index ) 9 | ) 10 | 11 | /* __________________________________________________ 12 | 13 | NAME: LogExtract ( logText ; format ; label ) 14 | PURPOSE: Extracts value from delimited text block according to where label resides in format. 15 | EXAMPLES: 16 | LogExtract ( "4/17/12|dchandler" ; "%Date%Account" ; "%Account" ) = "dchandler" 17 | HISTORY: 18 | Created: 2012-04-17 12:49 PST - Donovan Chandler 19 | Modified: 20 | */ -------------------------------------------------------------------------------- /LogFormat.calc: -------------------------------------------------------------------------------- 1 | "%Date%Time%Account%Field%Before%After" 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: LogFormat 6 | PURPOSE: Stores order of columns for audit logs. Enables easy parsing of logs. 7 | HISTORY: 8 | Created: 2012-04-17 13:00 PST - Donovan Chandler 9 | Modified: 10 | */ -------------------------------------------------------------------------------- /MVLSet.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | $$_MVL[column] = valueListValues 3 | ] ; 4 | $$_MVL[column] ≠ "?" and not IsEmpty ( $$_MVL[column] ) 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: MVLSetVar ( column ; valueListValues ) 10 | PURPOSE: Sets values to global variable used for value lists using Magic Value List technique. 11 | EXAMPLES: 12 | 13 | HISTORY: 14 | Created: 2013-02-01 09:52 PT - Donovan Chandler 15 | Modified: 2013-02-14 11:53 PT - Donovan Chandler : returns 0 for empty or invalid value. 16 | */ -------------------------------------------------------------------------------- /MapRouteURL.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | points = listOfCoordinates ; 3 | remaining = TrimCR ( MiddleValues ( points ; 2 ; 999 ) ) ; 4 | daddr = Substitute ( remaining ; ¶ ; "+to:" ) 5 | ] ; 6 | "http://maps.google.com/?" 7 | & "saddr=" & GetValue ( points ; 1 ) 8 | & If ( NotEmpty ( remaining ) ; "&daddr=" & daddr ) 9 | & "&output=embed" 10 | ) 11 | 12 | /* —————————————————————————————— // 13 | NAME: 14 | MapPointsURL ( listOfCoordinates ) 15 | 16 | PURPOSE: 17 | Generates url for displaying group of waypoints on a Google map. 18 | 19 | EXAMPLES: 20 | MapPointsURL ( "37.3371,-122.0021¶37.3371,-122.0028" ) 21 | = "http://maps.google.com/?q=37.3371,-122.0021&daddr=37.3371,-122.0028&output=embed" 22 | 23 | NOTES: 24 | URL syntax: http://mapki.com/wiki/Google_Map_Parameters 25 | 26 | HISTORY: 27 | Created: 2012-Mar-01 10h34 PST — Donovan A. Chandler 28 | */ -------------------------------------------------------------------------------- /MenuRevealIsOn.calc: -------------------------------------------------------------------------------- 1 | ListContains ( FOCUS::MENU_REVEALED_LIST ; menu ) 2 | 3 | /* —————————————————————————————— // 4 | NAME: 5 | MenuRevealIsOn ( menu ) 6 | 7 | PURPOSE: 8 | Returns True if specified menu is supposed to be revealed. 9 | You can hide menus and menu items in FMP 11 by setting the name to null. This function helps leverage that feature for items that are more often than note hidden. 10 | 11 | EXAMPLES: 12 | 13 | 14 | HISTORY: 15 | Created: 2011-Feb-18 11h35 PST — Donovan A. Chandler 16 | */ -------------------------------------------------------------------------------- /MessageInvalidVar.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | objectString = 3 | Substitute ( 4 | listOfObjects ; 5 | [ "&" ; "or" ] ; 6 | [ ¶ ; ", " ] 7 | ) 8 | ]; 9 | "Error: Missing Data" & ¶ & 10 | "Script: " & Get ( ScriptName ) & ¶ & 11 | "Objects: " & objectString 12 | ) 13 | 14 | /* —————————————————————————————— // 15 | NAME: 16 | MessageInvalidVar ( listOfObjects ) 17 | 18 | PURPOSE: 19 | Returns error message for list of objects that failed previous validation. 20 | Used to keep messages uniform and modifiable across solution. 21 | 22 | EXAMPLES: 23 | MessageInvalidVar ( "$_field & $_object" ) 24 | = "The following objects are missing required data:¶$_field or $_object" 25 | 26 | HISTORY: 27 | Created: 2011-Jan-31 13h40 PST — Donovan A. Chandler 28 | */ -------------------------------------------------------------------------------- /NavLayoutRank.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | //layoutToMatch = "System List" ; 3 | 4 | ~navLayouts = FOCUS::NAV_LAYOUT_LIST_REP ; 5 | ~navRepMax = 8 ; 6 | ~navIndex = FieldRepMatch ( ~navLayouts ; layoutToMatch ; 1 ; ~navRepMax ) ; 7 | 8 | ~subnavLayouts = FOCUS::NAV_SUB_LAYOUT_LIST_REP ; 9 | ~subnavRepMax = 5 ; 10 | ~subnavIndex = FieldRepMatch ( ~subnavLayouts ; layoutToMatch ; 1 ; ~subnavRepMax ) 11 | ] ; 12 | ~navIndex & If ( ~subnavIndex ; "." & ~subnavIndex ) 13 | ) 14 | 15 | /* __________________________________________________ 16 | 17 | NAME: NavLayoutRank ( layoutToMatch ) 18 | PURPOSE: Returns rank of current layout as specified in nav_layout record of active nav_set. 19 | EXAMPLES: 20 | 21 | HISTORY: 22 | Created: 2013-05-16 10:02 PT - Donovan Chandler 23 | Modified: 24 | */ -------------------------------------------------------------------------------- /NavViewLayout.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | /* 3 | rank = 2.1 ; 4 | targetView = "list" ; 5 | */ 6 | ~rank = If ( not IsEmpty ( rank ) ; rank ; navLayoutrank ( Get ( LayoutName ) ) ) ; 7 | ~rankInt = Int ( ~rank ) ; 8 | ~layouts = 9 | Case ( 10 | ~rankInt = ~rank ; FOCUS::NAV_LAYOUT_LIST_REP[ ~rank ] ; 11 | FOCUS::NAV_SUB_LAYOUT_LIST_REP[ ~rank ] 12 | ) 13 | ] ; 14 | #IDValue ( ~layouts ; targetView ) 15 | ) 16 | 17 | /* __________________________________________________ 18 | 19 | NAME: NavViewLayout ( rank ; targetView ) 20 | PURPOSE: Returns layout corresponding to view for rank. 21 | If rank is empty, uses current layout's rank. 22 | EXAMPLES: 23 | NavViewLayout ( 2.1 ; "list" ) //= "Contact List" 24 | NavViewLayout ( 2.1 ; "table" ) //= "Contact Table" 25 | NavViewLayout ( "" ; "table" ) //= "Contact Table" where current layout has rank of 2.1 26 | HISTORY: 27 | Created: 2013-05-16 10:08 PT - Donovan Chandler 28 | Modified: 29 | */ -------------------------------------------------------------------------------- /NumberAsDollars.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | int = Int ( number ) ; 3 | dec = Abs ( number - int ) 4 | ] ; 5 | 6 | If ( number < 0 ; "-" ) & 7 | "$" & 8 | TextInsertSeparator ( int ; "," ; 3 ) & 9 | If ( dec ≠ 0 ; Right ( dec ; 3 ) ) 10 | 11 | ) 12 | 13 | /* —————————————————————————————— // 14 | NAME: 15 | NumberAsDollars ( number ) 16 | 17 | PURPOSE: 18 | Formats number or text string as dollar value. 19 | 20 | EXAMPLES: 21 | NumberAsDollars ( "5000.12" ) = "$5,000.12" 22 | NumberAsDollars ( "5000.1" ) = "$5,000.1" 23 | NumberAsDollars ( "5000" ) = "$5,000" 24 | 25 | HISTORY: 26 | Created: 2011-Jun-01 16h25 PST — Donovan Chandler based on function by Will Baker 27 | */ -------------------------------------------------------------------------------- /ParamAssign.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | names = VarAssignLoop ( Get ( ScriptParameter ) ; listOfParams ) ; 3 | error = If ( IsEmpty ( names ) ; 0 ; 10 ) 4 | ] ; 5 | If ( 6 | error ≠ 0 ; 7 | Let ( [ 8 | count = ValueCount ( names ) ; 9 | str = Substitute ( names ; ¶ ; ", " ) ; 10 | msg = "Missing/invalid parameter" & If ( count > 1 ; "s" ) 11 | & ": " & str ; 12 | v = VarSet ( "_invalid_params" ; names ; "t" ; False ) ; 13 | v = VarSet ( "_error_message" ; msg ; "t" ; False ) 14 | ] ; 15 | "" 16 | ) 17 | ) 18 | & error 19 | ) 20 | 21 | /* __________________________________________________ 22 | 23 | NAME: ParamAssign ( listOfParams ) 24 | PURPOSE: Instantiates named parameters, with optional type casting and validation. 25 | EXAMPLES: See ManParamAssign() for documentation. 26 | HISTORY: 27 | Created: 2012-03-16 09:15 PST - Donovan Chandler 28 | Modified: 29 | */ -------------------------------------------------------------------------------- /ParamValidate.calc: -------------------------------------------------------------------------------- 1 | Case ( 2 | not IsEmpty ( VarInvalid ( listOfVariableNames ) ) ; 3 | 10 ; 4 | 0 5 | ) 6 | 7 | /* —————————————————————————————— // 8 | NAME: 9 | ParamValidate ( listOfVariableNames ) 10 | 11 | PURPOSE: 12 | Returns 10 if parameters are invalid, else returns 0 13 | 14 | EXAMPLES: 15 | See subfunction, VarInvalid() for details. 16 | 17 | HISTORY: 18 | Created: 2010-Sep-07 08h51 PST — Donovan A. Chandler 19 | */ -------------------------------------------------------------------------------- /ParamValidateMessage.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | vars = VarInvalid ( listOfVariables ; 1 ) ; 3 | varsPretty = Substitute ( vars ; ¶ ; ", " ) 4 | ] ; 5 | Case ( 6 | ValueCount ( vars ) ; 7 | "Internal Error: Invalid parameters" & ¶ & 8 | ¶ & 9 | "Script: " & Get ( ScriptName ) & ¶ & 10 | "Missing Parameters: " & varsPretty 11 | ) 12 | ) 13 | 14 | /* —————————————————————————————— // 15 | NAME: 16 | ParamValidateMessage ( listOfVariables ) 17 | 18 | PURPOSE: 19 | Returns dialog error message for missing parameters 20 | 21 | EXAMPLES: 22 | 23 | 24 | HISTORY: 25 | Created: 2010-Nov-08 11h48 PST — Donovan A. Chandler 26 | */ -------------------------------------------------------------------------------- /PathDir.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | len = Length ( path ) ; 3 | pos = Position ( path ; "/" ; len ; -1 ) 4 | ] ; 5 | Left ( path ; pos ) 6 | ) 7 | 8 | /* __________________________________________________ 9 | 10 | NAME: PathDir ( path ) 11 | PURPOSE: Strips file name from path. 12 | EXAMPLES: 13 | PathDir ( "filemac:/HD/Users/Shared/text.xml" ) 14 | = "filemac:/HD/Users/Shared/" 15 | HISTORY: 16 | Created: 2012-02-03 22:00 PST - Donovan A. Chandler 17 | */ -------------------------------------------------------------------------------- /PathFileName.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | dirList = Substitute ( path ; "/" ; ¶ ) ; 3 | count = ValueCount ( dirList ) ; 4 | file = GetValue ( dirList ; count ) 5 | ] ; 6 | Case ( 7 | IsEmpty ( file ) ; 8 | GetValue ( dirList ; count - 1 ) ; 9 | file 10 | ) 11 | ) 12 | 13 | /* __________________________________________________ 14 | 15 | NAME: PathFileName ( path ) 16 | PURPOSE: Returns name of file referenced in path 17 | EXAMPLES: 18 | PathFileName ( "dir/fileName.txt/" ) = "fileName.txt" 19 | HISTORY: 20 | Created: 2011-10-06 13:09 PST - Donovan A. Chandler 21 | */ -------------------------------------------------------------------------------- /PathForAppleScript.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | pathList = Substitute ( posixPath ; ":/" ; ¶ ) ; 3 | path = GetValue ( pathList ; ValueCount ( pathList ) ) 4 | ]; 5 | Substitute ( path ; "/" ; ":" ) 6 | ) 7 | 8 | /* —————————————————————————————— // 9 | NAME: 10 | FilePathForAppleScript ( posixPath ) 11 | 12 | PURPOSE: 13 | Converts POSIX path into an AppleScript file reference. 14 | This is to avoid converting the POSIX path to a valid file reference in AppleScript, which I was having trouble with. 15 | 16 | EXAMPLES: 17 | 18 | 19 | HISTORY: 20 | Created: 2011-Apr-29 18h13 PST — Donovan A. Chandler 21 | */ -------------------------------------------------------------------------------- /PathForFMP.calc: -------------------------------------------------------------------------------- 1 | Let([ 2 | path = GetValue ( pathList ; 1 ) ; 3 | pathCount = ValueCount ( pathList ) ; 4 | hdName = Get ( SystemDrive ) ; 5 | 6 | //-- Add disk name 7 | pathNew = 8 | If ( 9 | Position ( "/" & path & "/" ; hdName ; 1 ; 1 ) = 0 ; 10 | hdName & TextStripLeft ( path ; "/" ) ; 11 | path 12 | ) ; 13 | 14 | //-- Undo shell escapes 15 | pathNew = 16 | Substitute ( pathNew ; 17 | [ "\ " ; " " ] 18 | ) 19 | ]; 20 | List ( 21 | If ( not IsEmpty ( pathNew ) ; pathNew ) ; 22 | If ( pathCount > 1 ; 23 | FilePathForFMP ( RightValues ( pathList ; pathCount - 1 ) ) 24 | ) 25 | ) 26 | ) 27 | 28 | /* —————————————————————————————— // 29 | NAME: 30 | FilePathForFMP ( pathList ) 31 | 32 | PURPOSE: 33 | Returns path usable in FileMaker. 34 | Adds system drive to shell paths. 35 | 36 | EXAMPLES: 37 | FilePathForShell ( "/Library/FileMaker\ Server/Data" ) 38 | = "HD/Library/FileMaker Server/Data" 39 | 40 | HISTORY: 41 | Created: 2011-Nov-04 14h28 PST — Donovan Chandler 42 | */ -------------------------------------------------------------------------------- /PathFromHome.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | //-- Remove prefixes 3 | posColon = Position ( path ; ":" ; 1 ; 1 ) ; 4 | path = If ( posColon = 0 ; path ; Middle ( path ; posColon + 1 ; 999 ) ) ; 5 | path = If ( Left ( path ; 1 ) ≠ "/" ; path ; Middle ( path ; 2 ; 999 ) ) ; 6 | 7 | //-- Remove disk name 8 | hdName = 9 | GetValue ( 10 | Substitute ( Get ( DesktopPath ) ; "/" ; ¶ ) ; 11 | 2 12 | ) ; 13 | hdNameLen = Length ( hdName ) ; 14 | path = 15 | If ( 16 | Left ( path ; hdNameLen + 1 ) = hdName & "/" ; 17 | Middle ( path ; hdNameLen + 2 ; 999 ) ; 18 | path 19 | ) 20 | ]; 21 | path 22 | ) 23 | 24 | /* —————————————————————————————— // 25 | NAME: 26 | FilePathFromHome ( path ) 27 | 28 | PURPOSE: 29 | Removes prefix and hard drive name from path 30 | 31 | EXAMPLES: 32 | FilePathFromHome ( "filemac:/HD/Users/Donovan/Desktop" ) 33 | = "Users/Donovan/Desktop" 34 | 35 | HISTORY: 36 | Created: 2011-Jun-29 15h39 PST — Donovan A. Chandler 37 | */ -------------------------------------------------------------------------------- /PathPosix.calc: -------------------------------------------------------------------------------- 1 | If ( 2 | Abs ( Get ( SystemPlatform ) ) = 1 ; PathStripDisk ( path ) ; 3 | PathStripPrefix ( path ) 4 | ) 5 | 6 | /* 7 | Let([ 8 | 9 | //-- Remove prefixes 10 | posColon = Position ( path ; ":" ; 1 ; 1 ) ; 11 | path = If ( posColon = 0 ; path ; Middle ( path ; posColon + 1 ; 999 ) ) ; 12 | path = If ( Left ( path ; 1 ) ≠ "/" ; "/" ) & path ; 13 | 14 | //-- Remove name of system drive 15 | disk = Get ( SystemDrive ) ; 16 | posDrive = Position ( path ; disk ; 1 ; 1 ) ; 17 | path = 18 | If ( 19 | posDrive = 0 ; path ; 20 | Middle ( path ; Position ( path ; "/" ; posDrive + 1 ; 1 ) ; 999 ) 21 | ) 22 | ] ; 23 | Case ( 24 | IsEmpty ( path ) ; 25 | "" ; 26 | path 27 | ) 28 | ) 29 | */ 30 | 31 | /* __________________________________________________ 32 | 33 | NAME: PathPosix ( path ) 34 | PURPOSE: Converts path to POSIX style for use in plug-ins, etc. 35 | EXAMPLES: 36 | PathPosix ( "/Macintosh HD/Users/Admin/Desktop/text.txt" ) 37 | // (Mac OS) = "/Macintosh HD/Users/Admin/Desktop/text.txt" 38 | // (Windows) = "C:/Users/Admin/Desktop/text.txt" 39 | HISTORY: 40 | Created: 2010-03-27 14:30 PT - Donovan Chandler 41 | Modified: 2013-01-24 12:46 PT - Donovan Chandler 42 | */ -------------------------------------------------------------------------------- /PositionIgnoring.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | char1 = Middle ( text ; start ; 1 ) 3 | ] ; 4 | Case ( 5 | Position ( charactersToIgnore ; char1 ; 1 ; 1 ) = 0 ; 6 | start ; 7 | PositionIgnoring ( text ; charactersToIgnore ; start + 1 ) 8 | ) 9 | ) 10 | 11 | /* __________________________________________________ 12 | 13 | NAME: PositionIgnoring ( text ; charactersToIgnore ; start ) 14 | PURPOSE: Returns position of first character not included in charactersToIgnore. 15 | EXAMPLES: 16 | PositionIgnoring ( "123Dog" ; "D321 " ; 1 ) = 5 17 | HISTORY: 18 | Created: 2012-02-13 13:00 PT - Will M. Baker 19 | Modified: 20 | */ -------------------------------------------------------------------------------- /PositionUnescaped.calc: -------------------------------------------------------------------------------- 1 | Case ( 2 | rep > repMax or start > Length ( text ) ; "" ; 3 | Let ( [ 4 | Backslash = Char ( 92 ) ; 5 | rawStart = Position ( text ; character ; start ; 1 ) ; 6 | previousCharacter = If ( rawStart > 1 ; Middle ( text ; rawStart - 1 ; 1 ) ) ; 7 | isEscaped = ( previousCharacter = Backslash and rawStart ≠ Length ( text ) ) 8 | ] ; 9 | Case ( 10 | isEscaped ; PositionUnescaped ( text ; character ; rawStart + 1 ; repMax ; rep ) ; 11 | rawStart 12 | ) 13 | ) 14 | ) 15 | 16 | /* __________________________________________________ 17 | 18 | NAME: PositionUnescaped ( text ; character ; start ; repMax ; rep ) 19 | PURPOSE: Finds position of first unescaped occurrence of character. 20 | EXAMPLES: 21 | Where $_text = "[ \[ \] ]" 22 | PositionUnescaped ( $_text ; 1 ; Length ( $_text ) ; 1 ) = 9 23 | HISTORY: 24 | Created: 2012-02-13 13:00 PT - Will M. Baker 25 | Modified: 2012-05-29 12:05 PT - Donovan Chandler : Added character param; more concise; renamed from #QuotePosition() to PositionUnescaped(); removed Backslash() 26 | Modified: 2012-10-17 11:40 PT - Donovan Chandler : Fixed final Case statement to return result. 27 | */ -------------------------------------------------------------------------------- /Project-Specific/AmountProratedForMonth.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | dte = GetAsDate ( dateOfAmount ) ; 3 | amount = amountSoFar ; 4 | 5 | month = Month ( dte ) ; 6 | yr = Year ( dte ) ; 7 | days_past = dte - Date ( month ; 1 ; yr ) + 1 ; 8 | days_ahead = Date ( month + 1 ; 0 ; yr ) - dte ; 9 | amount_daily = amount / days_past ; 10 | amount_prorated = amount + amount_daily * days_ahead 11 | ]; 12 | amount_prorated 13 | ) 14 | 15 | /* —————————————————————————————— // 16 | NAME: 17 | AmountProratedForMonth ( amountSoFar ; dateOfAmount ) 18 | 19 | PURPOSE: 20 | Returns prorated amount for month 21 | 22 | EXAMPLES: 23 | AmountProratedForMonth ( 100 ; "2/14/10" ) = 200 24 | 25 | HISTORY: 26 | Created: 2010-Oct-11 12h09 PST — Donovan A. Chandler 27 | */ -------------------------------------------------------------------------------- /Project-Specific/CodeLabel.calc: -------------------------------------------------------------------------------- 1 | Case( 2 | linkOnly; "‡‡CODE_LINK[" & index & "]‡‡"; 3 | "‡‡CODE[" & index & "]‡‡" 4 | ) 5 | 6 | /* __________________________________________________ 7 | 8 | NAME: CodeLabel ( index ; linkOnly ) 9 | PURPOSE: Returns merge placeholder for LIBRARY_CODE record of specified index. 10 | EXAMPLES: 11 | //-- Merge value from LIBRARY_CODE::CODE 12 | CodeMergeLabel ( 1 ; False ) = "‡‡CODE[1]‡‡" 13 | //-- Merge value from LIBRARY_CODE::NAME 14 | CodeMergeLabel ( 1 ; True ) = "‡‡CODE_LINK[1]‡‡" 15 | HISTORY: 16 | Created: 2010-08-27 20:32 PST - Donovan A. Chandler 17 | */ 18 | -------------------------------------------------------------------------------- /Project-Specific/ConvertFieldContext.calc: -------------------------------------------------------------------------------- 1 | Let([ 2 | _lis = Substitute( fieldName; "::"; ¶ ); 3 | _table = GetValue( _lis; 1 ); 4 | _table_num = contextNum - 1; 5 | _table_new = _table & "_OF_" & _table & "_" & _table_num 6 | ]; 7 | _table_new & "::" & GetValue( _lis; 2 ) 8 | ) 9 | 10 | /* —————————————————————————————— // 11 | NAME: 12 | ConvertFieldContext( fieldName; contextNum ) 13 | 14 | PURPOSE: 15 | Replaces name of table occurrence in fieldName to alternative TO. 16 | Applied when using GTRR to an alternative TO instead of opening a new window. (Preserves original context without the overhead of rendering a new window.) 17 | 18 | EXAMPLES: 19 | ConvertFieldContext ( 20 | GetFieldName( CONTACT::NAME ); 21 | 2 22 | ) = "CONTACT_OF_CONTACT_1::NAME" 23 | 24 | HISTORY: 25 | Created: 2010-Aug-23 13h34 PST — Donovan A. Chandler 26 | */ -------------------------------------------------------------------------------- /Project-Specific/CriterionDecode.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | tag = TextBetween ( queryString ; "<" ; ">" ; 1 ) ; 3 | number = Filter ( tag ; "0123456789" ) ; 4 | merged = 5 | Case ( 6 | Left ( tag ; 12 ) = "date-months:" ; 7 | DateMinusMonths ( Get ( CurrentDate ) ; number ) ; 8 | Left ( tag ; 4 ) = "date" ; 9 | Get ( CurrentDate ) ; 10 | tag = "account_name" ; 11 | Get ( AccountName ) 12 | ) ; 13 | text = Substitute ( queryString ; "<" & tag & ">" ; merged ) 14 | ] ; 15 | Case ( 16 | PatternCount ( text ; "<" ) and PatternCount ( text ; ">" ) ; 17 | CriterionDecode ( Substitute ( text ; tag ; merged ) ) ; 18 | text 19 | ) 20 | ) 21 | 22 | /* —————————————————————————————— // 23 | NAME: 24 | CriterionDecode ( queryString ) 25 | 26 | PURPOSE: 27 | Translates merge tag into searchable string 28 | 29 | EXAMPLES: 30 | (Where today = "1/1/10" ) 31 | CriterionDecode ( "" ) = "1/1/2008" 32 | CriterionDecode ( "6/1/10..." ) = "6/1/09...7/19/2011" 33 | 34 | HISTORY: 35 | Created: 2010-Sep-14 17h36 PST — Donovan A. Chandler 36 | */ -------------------------------------------------------------------------------- /Project-Specific/DatabaseModule.calc: -------------------------------------------------------------------------------- 1 | 2 | Let([ 3 | _privilege = Get ( AccountPrivilegeSetName ) 4 | 5 | ]; 6 | Case ( 7 | PatternCount ( _privilege ; "Lester" ); 8 | "LESTER"; 9 | PatternCount ( _privilege ; "Haas" ); 10 | "HAAS" 11 | ) 12 | ) 13 | 14 | /* —————————————————————————————— // 15 | NAME: 16 | DatabaseModule ( ) 17 | 18 | PURPOSE: 19 | Returns name of module corresponding to the active user role 20 | 21 | EXAMPLES: 22 | DatabaseModule ( ) = "LESTER" 23 | 24 | HISTORY: 25 | Created: 2010-Jul-12 11h44 PST — Donovan A. Chandler 26 | */ -------------------------------------------------------------------------------- /Project-Specific/DateFromString.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | _string = dateAsString 3 | ] ; 4 | Case ( 5 | Position ( _string ; "." ; 1 ; 1 ) 6 | + Position ( _string ; "-" ; 1 ; 1 ) ; 7 | Let ( [ 8 | _list = Substitute ( _string ; 9 | [ "." ; ¶ ] ; 10 | [ " " ; ¶ ] ; 11 | [ "-" ; ¶ ] 12 | ) 13 | ] ; 14 | Date ( 15 | GetValue ( _list ; 2 ) ; 16 | GetValue ( _list ; 3 ) ; 17 | GetValue ( _list ; 1 ) 18 | ) 19 | ) 20 | ) 21 | ) 22 | 23 | /* —————————————————————————————— // 24 | NAME: 25 | DateFromString ( dateAsString ) 26 | 27 | PURPOSE: 28 | Converts strings into FileMaker-recognized dates. 29 | Formats accepted: yyyy.mm.dd or yyyy-mm-dd 30 | 31 | EXAMPLES: 32 | DateFromString ( "2008.01.07 ( 1.5 ) " ) = 01/07/2008 33 | 34 | HISTORY: 35 | Created: 2010-Jul-21 12h48 PST — Donovan A. Chandler 36 | */ -------------------------------------------------------------------------------- /Project-Specific/EncodeForHTMLScript.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | br = "
" 3 | ] ; 4 | Substitute ( 5 | text ; 6 | [ Char ( 10 ) ; br ] ; // Line feed 7 | [ Char ( 11 ) ; br ] ; // Vertical tab 8 | [ Char ( 12 ) ; br ] ; // Form feed 9 | [ Char ( 13 ) ; br ] // Carriage return 10 | ) 11 | ) 12 | 13 | /* __________________________________________________ 14 | 15 | NAME: EncodeForHTMLScript ( text ) 16 | PURPOSE: Encodes block of text for use in "html . p" and related scripts. 17 | EXAMPLES: 18 | 19 | HISTORY: 20 | Created: 2012-09-06 16:26 PST - Donovan Chandler 21 | Modified: 22 | */ -------------------------------------------------------------------------------- /Project-Specific/FieldNameReadable.calc: -------------------------------------------------------------------------------- 1 | Let([ 2 | field_name_full = Substitute ( fieldName ; "::" ; ¶ ) ; 3 | field_name = GetValue ( field_name_full ; ValueCount ( field_name_full ) ) 4 | ] ; 5 | Proper ( 6 | Substitute ( 7 | field_name ; 8 | [ "_FLAGGED" ; "‡FLAGGED" ] ; 9 | [ "_FLAG" ; "" ] ; 10 | [ "‡FLAGGED" ; "_FLAGGED" ] ; 11 | [ "ID_" ; "" ] ; 12 | [ "_CT" ; "" ] ; 13 | [ "_CN" ; "" ] ; 14 | [ "_AT" ; "" ] ; 15 | [ "_" ; " " ] 16 | ) 17 | ) 18 | ) 19 | 20 | /* —————————————————————————————— // 21 | NAME: 22 | FieldNameReadable ( fieldName ) 23 | 24 | PURPOSE: 25 | 26 | 27 | EXAMPLES: 28 | FieldNameReadable ( GetFieldName ( CONTACT::FIRST_NAME )) = "First Name" 29 | 30 | HISTORY: 31 | Created: 2011-Jan-12 14h12 PST — Donovan A. Chandler 32 | */ -------------------------------------------------------------------------------- /Project-Specific/FilePathForWebViewer.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | isMac = Abs ( Get ( SystemPlatform ) ) = 1 ; 3 | pathPlain = PathStripPrefix ( path ) ; 4 | prefix = "file://" & If ( isMac ; "/Volumes/" ) 5 | ] ; 6 | prefix & pathPlain 7 | ) 8 | 9 | /* __________________________________________________ 10 | 11 | NAME: PathForWebViewer ( path ) 12 | PURPOSE: Encodes file path for use in web viewer. 13 | EXAMPLES: 14 | 15 | NOTES: 16 | On Mac, prepend with "file:///Volumes/" 17 | On Win, prepend with "file:///" 18 | HISTORY: 19 | Created: 2010-06-23 16:39 PT - Donovan A. Chandler 20 | */ -------------------------------------------------------------------------------- /Project-Specific/FilterIsCustom.calc: -------------------------------------------------------------------------------- 1 | Left ( filterText ; 1 ) = "<" and 2 | Right ( filterText ; 1 ) = ">" 3 | 4 | /* —————————————————————————————— // 5 | NAME: 6 | FilterIsCustom ( filterText ) 7 | 8 | PURPOSE: 9 | Returns True if filterText is a custom message intended for display rather than searching. Used when pre-defined sets of records are placed in a filter portal. 10 | 11 | EXAMPLES: 12 | FilterIsCustom ( "" ) = 1 13 | FilterIsCustom ( "Roger" ) = 0 14 | 15 | HISTORY: 16 | Created: 2010-Jul-19 14h19 PST — Donovan A. Chandler 17 | */ -------------------------------------------------------------------------------- /Project-Specific/FocusLocationTab.txt: -------------------------------------------------------------------------------- 1 | Case ( 2 | locationType = "PHONE" ; "tab_phone_entry" ; 3 | locationType = "EMAIL" ; "tab_email_entry" ; 4 | locationType = "ADDRESS" ; "tab_address_entry" ; 5 | locationType = "WEBSITE" ; "tab_website_entry" 6 | ) 7 | 8 | /* —————————————————————————————— // 9 | NAME: 10 | FocusLocationTab ( locationType ) 11 | 12 | PURPOSE: 13 | Returns name of tab to display when record of designated locationType is focussed 14 | 15 | EXAMPLES: 16 | FocusLocationTab ( "PHONE" ) = "tab_phone_entry" 17 | 18 | HISTORY: 19 | Created: 2010-Jun-08 09h21 PST — Donovan A. Chandler 20 | */ -------------------------------------------------------------------------------- /Project-Specific/GenerateRange.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | valPrev = GetValue ( start ; ValueCount ( start ) ) ; 3 | val = valPrev + interval ; 4 | weekEnd = WeekOfYear ( "12/31/" & Left ( valPrev ; 4 ) ) ; 5 | val = 6 | Case ( 7 | type = "wom" ; 8 | If ( Right ( val ; 2 ) ≤ weekEnd ; val ; val + 100 - weekEnd ) ; 9 | val 10 | ) ; 11 | result = List ( start ; val ) 12 | ] ; 13 | Case ( 14 | val < end ; 15 | GenerateRange ( type ; result ; end ; interval ) ; 16 | result 17 | ) 18 | ) 19 | 20 | /* —————————————————————————————— // 21 | NAME: 22 | GenerateRange ( type ; start ; end ; interval ) 23 | 24 | PURPOSE: 25 | Generates return-delimited list per logic of specified type. 26 | 27 | EXAMPLES: 28 | GenerateRange ( "wom" ; 200551 ; 200602 ; 1 ) 29 | = "200551¶200552¶200601¶200602" 30 | 31 | HISTORY: 32 | Created: 2011-Oct-13 12h56 PST — Donovan A. Chandler 33 | */ -------------------------------------------------------------------------------- /Project-Specific/LogForField.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | incidentID = 3 | If ( 4 | not IsEmpty ( incidentID ) ; incidentID ; 5 | INCIDENT__FOCUS::ID 6 | ) ; 7 | action = 8 | If ( 9 | not IsEmpty ( action ) ; action ; 10 | "MODIFY" 11 | ) 12 | ]; 13 | # ( "ID_INCIDENT" ; incidentID ) & 14 | # ( "ACTION" ; action ) & 15 | # ( "FIELD_NAME" ; Get ( ActiveFieldName ) ) & 16 | # ( "VALUE" ; Get ( ActiveFieldContents ) ) & 17 | # ( "BOOLEAN" ; isBoolean ) & 18 | # ( "ID_CHILD" ; childID ) & 19 | # ( "CHILD_CODE" ; childCode ) 20 | ) 21 | 22 | /* —————————————————————————————— // 23 | NAME: 24 | ParamLogForRelatedField ( incidentID ; action ; isBoolean ; childID ; childCode ) 25 | 26 | PURPOSE: 27 | Creates parameter for script that logs field modifications, etc. 28 | 29 | EXAMPLES: 30 | ParamLogForRelatedField ( ) 31 | 32 | NOTES: 33 | action, childID and childCode are only required for related records 34 | 35 | HISTORY: 36 | Created: 2011-Jan-21 15h02 PST — Donovan A. Chandler 37 | */ -------------------------------------------------------------------------------- /Project-Specific/ParamLogForField.calc: -------------------------------------------------------------------------------- 1 | # ( "ID_INCIDENT" ; 2 | If ( 3 | not IsEmpty ( incidentID ) ; incidentID ; 4 | INCIDENT__FOCUS::ID 5 | ) 6 | ) & 7 | # ( "ACTION" ; "MODIFY" ) & 8 | # ( "FIELD_NAME" ; Get ( ActiveFieldName ) ) & 9 | # ( "VALUE" ; Get ( ActiveFieldContents ) ) & 10 | # ( "BOOLEAN" ; isBoolean ) 11 | 12 | /* —————————————————————————————— // 13 | NAME: 14 | ParamLogForField ( incidentID ; isBoolean ) 15 | 16 | PURPOSE: 17 | Creates parameter for script that logs field modifications, etc. 18 | 19 | EXAMPLES: 20 | ParamLogForField ( ) 21 | 22 | HISTORY: 23 | Created: 2011-Jan-21 15h02 PST — Donovan A. Chandler 24 | */ -------------------------------------------------------------------------------- /Project-Specific/ParamLogForRelatedField.calc: -------------------------------------------------------------------------------- 1 | # ( "ID_INCIDENT" ; 2 | If ( 3 | not IsEmpty ( incidentID ) ; incidentID ; 4 | INCIDENT__FOCUS::ID 5 | ) 6 | ) & 7 | # ( "ACTION" ; "MODIFY" ) & 8 | # ( "FIELD_NAME" ; Get ( ActiveFieldTableName ) & "::" & Get ( ActiveFieldName ) ) & 9 | # ( "VALUE" ; Get ( ActiveFieldContents ) ) & 10 | # ( "BOOLEAN" ; isBoolean ) & 11 | # ( "ID_CHILD" ; childID ) & 12 | # ( "CHILD_CODE" ; childCode ) 13 | 14 | /* —————————————————————————————— // 15 | NAME: 16 | ParamLogForField ( incidentID ; action ; childID ; childCode ; isBoolean ) 17 | 18 | PURPOSE: 19 | Creates parameter for script that logs field modifications, etc. 20 | 21 | EXAMPLES: 22 | ParamLogForField ( ) 23 | 24 | HISTORY: 25 | Created: 2011-Jan-21 15h02 PST — Donovan A. Chandler 26 | */ -------------------------------------------------------------------------------- /Project-Specific/ResourceData.calc: -------------------------------------------------------------------------------- 1 | Case( 2 | dataType = "text" ; FOCUS::LIBRARY_CODE_REP[index] ; 3 | dataType = "name" ; "FOCUS::LIBRARY_CODE_REP[" & index & "]" 4 | ) 5 | 6 | /* —————————————————————————————— // 7 | NAME: 8 | ResourceData( index; dataType ) 9 | 10 | PURPOSE: 11 | Returns specified data from RESOURCE record. 12 | 13 | EXAMPLES: 14 | Where RESOURCE record has index 1... 15 | 16 | ResourceData( 1; "text" ) returns record text 17 | ResourceData( 1; "name" ) = "FOCUS::LIBRARY_CODE_REP[1]" 18 | 19 | HISTORY: 20 | Created: 2010-Aug-24 12h12 PST — Donovan A. Chandler 21 | */ -------------------------------------------------------------------------------- /Project-Specific/ResourceInclude.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | language = FOCUS::LIBRARY_LANGUAGE_REP[index] ; 3 | text = Case ( not urlOnly ; FOCUS::LIBRARY_CODE_REP[index] ) ; 4 | url = text //Case ( urlOnly ; FOCUS::LIBRARY_URL_REP[index] ) 5 | ] ; 6 | Case ( 7 | language = "CSS" ; 8 | Case ( 9 | urlOnly ; 10 | "" ; 11 | "" 12 | ) ; 13 | language = "JavaScript" ; 14 | Case ( 15 | urlOnly ; 16 | "" ; 17 | "" 18 | ) 19 | ) 20 | ) 21 | 22 | /* —————————————————————————————— // 23 | NAME: 24 | ResourceInclude ( index ; urlOnly ) 25 | 26 | PURPOSE: 27 | Wraps text or url from Resource record with specified index in HTML include statement. 28 | 29 | EXAMPLES: 30 | 31 | 32 | DEPENDENCIES: 33 | Custom Functions: PathEncodeForWebViewer ( ) 34 | Fields: FOCUS fields that store RESOURCE data 35 | 36 | HISTORY: 37 | Created: 2010-Aug-28 16h24 PST — Donovan A. Chandler 38 | */ -------------------------------------------------------------------------------- /Project-Specific/ScriptTriggersAreOff.calc: -------------------------------------------------------------------------------- 1 | $$_script_triggers_disabled 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: ScriptTriggersAreOff ( ) 6 | PURPOSE: Returns True if script triggers are being suppressed. 7 | EXAMPLES: 8 | 9 | HISTORY: 10 | Created: 2010-11-23 09:20 PST - Donovan A. Chandler 11 | */ 12 | -------------------------------------------------------------------------------- /Project-Specific/ScriptTriggersOff.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | $$_script_triggers_disabled = 1 3 | ]; 4 | $$_script_triggers_disabled 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: ScriptTriggersOff ( ) 10 | PURPOSE: Sets boolean flag to True that prevents triggered scripts from executing. 11 | EXAMPLES: 12 | ScriptTriggersOff() = 1 13 | HISTORY: 14 | Created: 2010-11-23 09:20 PST - Donovan A. Chandler 15 | */ 16 | -------------------------------------------------------------------------------- /Project-Specific/ScriptTriggersOn.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | $$_script_triggers_disabled = "" 3 | ]; 4 | $$_script_triggers_disabled 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: ScriptTriggersOn ( ) 10 | PURPOSE: Sets boolean flag to False, allowing triggered scripts to execute. 11 | EXAMPLES: 12 | ScriptTriggersOn() 13 | HISTORY: 14 | Created: 2010-11-23 09:20 PST - Donovan A. Chandler 15 | */ 16 | -------------------------------------------------------------------------------- /Project-Specific/TemplateMerge.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | isHot = GetAsBoolean ( CAR_CONTENT::Hot_Flag ) ; 3 | comment = If ( not IsEmpty ( $_template_comment ) ; $_template_comment ; "N/A" ) 4 | ]; 5 | Substitute ( text ; 6 | [ "::CAR_ProjectNo::" ; CAR_CONTENT::ProjectNo_ct ] ; 7 | [ "::CAR_ProjectNoAndCO::" ; CAR_CONTENT::ProjectNoDisplay_ct ] ; 8 | [ "::CAR_ProjectName::" ; CAR_CONTENT::ProjectName_ct ] ; 9 | [ "::CAR_ProjectManager::" ; CAR::ProjectMgr_ct ] ; 10 | [ "::Comment::" ; comment ] ; 11 | [ ":: (HOT!)::" ; If ( isHot ; " (HOT!)" ) ] ; 12 | [ "::ExpeditedMessage::" ; If ( isHot ; " Your immediate response is requested." ) ] 13 | ) 14 | ) 15 | 16 | /* —————————————————————————————— // 17 | NAME: 18 | TemplateMerge ( text ) 19 | 20 | PURPOSE: 21 | Replaces labels in text with field values. 22 | 23 | EXAMPLES: 24 | Where CAR::ProjectMgr_ct = "Bill Banks" 25 | 26 | TemplateMerge ( "Dear ::CAR_ProjectManager::" ) 27 | = "Dear Bill Banks" 28 | 29 | HISTORY: 30 | Created: 2011-Feb-25 10h47 PST — Donovan A. Chandler 31 | */ -------------------------------------------------------------------------------- /Project-Specific/TimeIncrement.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | max = GetAsTime ( maxTime ) 3 | ; max = If ( max = "?" or IsEmpty ( max ) ; GetAsTime ( "24:00:00" ) ; max ) 4 | ; new = GetAsTime ( startTime ) + incrementSeconds 5 | ; new = If ( new > max ; max ; new ) 6 | ; new = RightWords ( GetAsTimestamp ( new ) ; 2 ) 7 | ; hour = Hour ( new ) 8 | ] ; 9 | If ( hour < 10 ; 0 ) 10 | & new 11 | ) 12 | 13 | /* —————————————————————————————— // 14 | NAME: 15 | TimeIncrement ( startTime ; incrementSeconds ; maxTime ) 16 | 17 | PURPOSE: 18 | Returns time + provided seconds in AM/PM format. 19 | 20 | EXAMPLES: 21 | TimeIncrememt ( "7:15 AM" ; 2*60*60 ; "8:00 PM" ) //= "09:15 AM" 22 | 23 | HISTORY: 24 | Created: 2012-Feb-24 14h42 PST — Donovan A. Chandler 25 | */ -------------------------------------------------------------------------------- /Project-Specific/TooltipQueryTips.calc: -------------------------------------------------------------------------------- 1 | "Special characters to use in your search:¶ 2 | ¶ 3 | ... range (\"1/1/2011...2/1/2011\")¶ 4 | // today's date (\"1/1/2010...//\")¶ 5 | @ any one character¶ 6 | # any one digit (number)¶ 7 | * zero or more characters¶ 8 | \ escape next character (to match a special char literally)¶ 9 | \"\" match phrase (from word start)¶ 10 | *\"\" match phrase (from anywhere)¶ 11 | ¶ 12 | today minus N months" 13 | 14 | /* —————————————————————————————— // 15 | NAME: 16 | TooltipQueryTips 17 | 18 | PURPOSE: 19 | Stores text describing tips for for building queries. 20 | 21 | HISTORY: 22 | Created: 2011-Apr-22 15h12 PST — Donovan A. Chandler 23 | */ -------------------------------------------------------------------------------- /Project-Specific/text.getBetweenAll.calc: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------- 2 | NAME: 3 | text.getBetweenAll ( text; from; to ) 4 | 5 | PURPOSE: 6 | Returns return-delimited list of all text strings between 'from' and 'to' in 'text' 7 | 8 | HISTORY: 9 | Created 2010.04.20 by Donovan Chandler 10 | 11 | ---------------------------------------------------------------------------------------*/ 12 | 13 | Let([ 14 | _occurrenceCount = PatternCount ( text ; from ); 15 | 16 | _rep = $$_text.getBetween_rep + 1; 17 | $$_text.getBetween_rep = _rep; 18 | 19 | _textBetween = text.getBetween ( text; from; to; _rep ); 20 | 21 | _resultList = $$_text.getBetween_result; 22 | $$_text.getBetween_result = 23 | If ( not IsEmpty ( _resultList ); _resultList & ¶ ) 24 | & _textBetween 25 | ]; 26 | Case ( 27 | //-- Continue 28 | _rep < _occurrenceCount; 29 | text.getBetweenAll ( text; from; to ); 30 | 31 | //-- Return result 32 | _resultList 33 | & Let([ $$_text.getBetween_result = "" 34 | ; $$_text.getBetween_rep = "" 35 | ]; "" ) 36 | ) 37 | 38 | ) -------------------------------------------------------------------------------- /Project-Specific/time.getMicro.calc: -------------------------------------------------------------------------------- 1 | Case ( 2 | accuracy = 2 ; TimeMillis / 1000 ; 3 | TimeNano / 1000000000 4 | ) 5 | 6 | /* —————————————————————————————— // 7 | NAME: 8 | time.getMicro ( accuracy ) 9 | 10 | PURPOSE: 11 | Returns time in milliseconds or nanoseconds but with the decimal moved so that it can be calculated as seconds. 12 | 13 | EXAMPLES: 14 | time.getMicro ( "" ) = 1276879058.526657 15 | time.getMicro ( 2 ) = 1276879058.529 16 | 17 | HISTORY: 18 | Created: 2010-Jun-17 20h54 PST — Donovan A. Chandler 19 | 20 | DEPENDECIES: 21 | Uses external function created with ScriptMaster plug-in by 360Works. 22 | 23 | To create these functions: 24 | 1. Register the ScriptMaster plug-in. Download their plug-in for more details. 25 | 2. Set variables to the following calculations: 26 | 27 | RegisterGroovy( "TimeMillis" ; "System.currentTimeMillis()" ) 28 | 29 | RegisterGroovy( "TimeNano" ; "System.nanoTime()" ) 30 | */ -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DonovanChan/fmfunctions/7917c203b8c51c7ff00f94d6036ea36f117d5e2a/README -------------------------------------------------------------------------------- /RGBToCSS.calc: -------------------------------------------------------------------------------- 1 | Substitute ( 2 | TrimAll ( RGBString ; True ; 3 ) ; 3 | ";" ; 4 | "," 5 | ) 6 | 7 | /* —————————————————————————————— // 8 | NAME: 9 | RGBToCSS ( RGBString ) 10 | 11 | PURPOSE: 12 | Converts RGB statement to CSS format 13 | 14 | EXAMPLES: 15 | RGBToCSS ( "RGB ( 255 ; 0 ; 0 )" ) 16 | = "rgb(255;0;0)" 17 | 18 | HISTORY: 19 | Created: 2011-Apr-29 10h23 PST — Donovan A. Chandler 20 | */ -------------------------------------------------------------------------------- /RGBToHex.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | Hex = "0123456789ABCDEF" ; 3 | RedHex = 4 | Middle ( Hex ; ( R - Mod ( R ; 16 ) ) / 16 + 1 ; 1 ) 5 | & Middle ( Hex ; Mod ( R ; 16 ) + 1 ; 1 ) ; 6 | GreenHex = 7 | Middle ( Hex ; ( G - Mod ( G ; 16 ) ) / 16 + 1 ; 1 ) 8 | & Middle ( Hex ; Mod ( G ; 16 ) + 1 ; 1 ) ; 9 | BlueHex = Middle ( Hex ; ( B - Mod ( B ; 16 ) ) / 16 + 1 ; 1 ) & Middle ( Hex ; Mod ( B ; 16 ) + 1 ; 1 ) 10 | ] ; 11 | RedHex & GreenHex & BlueHex 12 | ) 13 | 14 | /* __________________________________________________ 15 | 16 | NAME: RGBToHex ( R ; G ; B ) 17 | PURPOSE: Converts RGB values to Hex. 18 | EXAMPLES: 19 | RGBToHex ( 255 ; 255 ; 255 ) = "FFFFFF" 20 | HISTORY: 21 | Created: Daniel Wood, Digital Fusion Ltd 22 | Modified: 2011-09-12 19:00 PST - Donovan Chandler ; formatting 23 | */ 24 | -------------------------------------------------------------------------------- /SQLDate.calc: -------------------------------------------------------------------------------- 1 | "CAST( " & 2 | mFMb_DoSQL_Quote( Year( fmDateString ) & "-" & Month( fmDateString ) & "-" & Day( fmDateString) ) & 3 | " AS DATE )" 4 | 5 | /* —————————————————————————————— // 6 | NAME: 7 | SQLDate( fmDateStringString ) 8 | 9 | PURPOSE: 10 | Returns SQL expression that converts a FileMaker date to SQL format. 11 | 12 | EXAMPLES: 13 | SQLDate( "1/5/2010" ) = "CAST( '2010-1-5' AS DATE )" 14 | 15 | HISTORY: 16 | Created: 2010-Sep-09 19h58 PST — Donovan A. Chandler 17 | */ -------------------------------------------------------------------------------- /SQLDebug.calc: -------------------------------------------------------------------------------- 1 | If ( 2 | 3 | // The sql call results in an error, return empty so Data Viewer displays eror message 4 | sqlExecuted = "?" ; "" ; 5 | 6 | // The sql call is executed correctly, just return the result 7 | sqlExecuted 8 | ) 9 | 10 | /* __________________________________________________ 11 | 12 | NAME: SQLDebug ( sqlExecuted ) 13 | PURPOSE: Allows you to view error message from ExecuteSQL( ) when performed in Data Viewer. 14 | EXAMPLES: 15 | SQLDebug ( ExecuteSQL ( "SELECT unexistingfield from table" ; "" ; "" ) ) 16 | //= "The column named "unexistingfield" does not exist in any table in the column reference's scope." 17 | HISTORY: 18 | Created: Adapted from Andries Heylen (http://www.fmfunctions.com/mid/57) 19 | Modified: 2012-07-31 07:23 PST - Donovan Chandler 20 | */ -------------------------------------------------------------------------------- /SQLFieldSeparator.calc: -------------------------------------------------------------------------------- 1 | "|" 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: SQLFieldSeparator ( ) 6 | PURPOSE: Global storage of separator used between columns/fields returned from SQL queries. 7 | EXAMPLES: 8 | 9 | HISTORY: 10 | Created: 2012-03-13 11:20 PST - Donovan Chandler 11 | Modified: 12 | */ -------------------------------------------------------------------------------- /SQLFunctions.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DonovanChan/fmfunctions/7917c203b8c51c7ff00f94d6036ea36f117d5e2a/SQLFunctions.zip -------------------------------------------------------------------------------- /SQLResponse.calc: -------------------------------------------------------------------------------- 1 | ArrayCell ( 2 | array ; 3 | columnIndex ; 4 | SQLFieldSeparator ; 5 | rowIndex ; 6 | SQLRowSeparator 7 | ) 8 | 9 | /* __________________________________________________ 10 | 11 | NAME: SQLResponse ( array ; columnIndex ; rowIndex ) 12 | PURPOSE: Returns value from SQL response. 13 | Used when array of columns is returned. 14 | EXAMPLES: 15 | $_array = ExecuteSQL ( "SELECT city, state FROM table" ; "|" ; "¶" ) 16 | //= "Oakland|CA¶Portland|OR" 17 | 18 | SQLResponse ( $_array ; 2 ; 2 ) //= "OR" 19 | HISTORY: 20 | Created: 2012-05-25 10:49 PST - Donovan Chandler 21 | Modified: 22 | */ -------------------------------------------------------------------------------- /SQLRowSeparator.calc: -------------------------------------------------------------------------------- 1 | "¶" 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: SQLRowSeparator ( ) 6 | PURPOSE: Global storage of separator used between rows returned from SQL queries. 7 | EXAMPLES: 8 | 9 | HISTORY: 10 | Created: 2012-03-13 11:20 PST - Donovan Chandler 11 | Modified: 12 | */ -------------------------------------------------------------------------------- /SQLString.calc: -------------------------------------------------------------------------------- 1 | "'" & Substitute ( text ; "'" ; "''" ) & "'" 2 | 3 | /* __________________________________________________ 4 | 5 | WARNING: Function may be hardcoded into SqList ( ) 6 | 7 | NAME: SqString ( text ) 8 | PURPOSE: Quotes string for use in SQL 9 | EXAMPLES: 10 | SQLQuote ( "contact" ) = 'contact' 11 | NOTES: 12 | For escaping of reserved characters like "'" or "%", 13 | Use the optional arguments parameter in ExecuteSql( ) 14 | HISTORY: 15 | Created: 2012-03-28 11:11 PT - Donovan Chandler 16 | Modified: 17 | */ -------------------------------------------------------------------------------- /SQLTable.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | fieldName = GetFieldName ( field ) ; 3 | fieldName = If ( fieldName = "?" ; field ; fieldName ) ; 4 | table = Left ( fieldName ; Position ( fieldName ; "::" ; 1 ; 1 ) - 1 ) 5 | ]; 6 | "\"" & Lower ( table ) & "\"" 7 | ) 8 | 9 | /* __________________________________________________ 10 | 11 | NAME: SQLTable ( field ) 12 | PURPOSE: Returns name of field's basetable for use in SQL statements. 13 | EXAMPLES: 14 | SQLTable ( CONTACT::Name ) = "contact" 15 | SQLTable ( GetFieldName ( CONTACT::Name ) ) = "contact" 16 | HISTORY: 17 | Created: 2011-11-04 16:45 PT - Donovan Chandler 18 | Modified: 2012-11-20 17:43 PT - Donovan Chandler : Quotes in case of reserved word. 19 | */ -------------------------------------------------------------------------------- /ScriptMasterDependent/HTMLGetCellRight.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | pattern = 3 | ">" & cellValueToLeft & "<" // Label 4 | & ".+?" // Open cell to right 5 | & "(?:.*?>)?" // Skip inner tags 6 | & "(.*?)" // Capture 7 | & "<.*?" // Close cell to right 8 | ; value = FilterRegex( html ; pattern ; 1 ) 9 | ] ; 10 | Case ( 11 | value = "ERROR" ; "" ; 12 | LeftWords ( value ; 9999 ) 13 | ) 14 | ) 15 | 16 | /* —————————————————————————————— // 17 | NAME: 18 | HTMLGetCellRight ( html ; cellValueToLeft ) 19 | 20 | PURPOSE: 21 | Retrieves text of element to right of element containing specified value. 22 | 23 | EXAMPLES: 24 | 25 | 26 | HISTORY: 27 | Created: 2011-Aug-18 09h34 PST — Donovan A. Chandler 28 | */ -------------------------------------------------------------------------------- /ScriptMasterDependent/HTMLGetRow.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | row = FilterRegex ( text ; "()" ; occurrence ) 3 | ]; 4 | Case ( 5 | row = "ERROR" ; "" ; 6 | row 7 | ) 8 | ) 9 | 10 | /* —————————————————————————————— // 11 | NAME: 12 | HTMLGetRow ( text ; rowMatch ; occurrence ) 13 | 14 | PURPOSE: 15 | Returns nth row that matches rowMatch expression (regex). 16 | Leave occurrence parameter blank to receive all matching rows. 17 | 18 | EXAMPLES: 19 | HTMLGetRow ( 20 | " 21 | 22 | 23 |
DogRufus7yrs
CatSusie9yrs
" ; 24 | ">Rufus<" ; 25 | 1 26 | ) = "DogRufus7yrs" 27 | 28 | HISTORY: 29 | Created: 2011-Aug-26 13h54 PST — Donovan Chandler 30 | */ -------------------------------------------------------------------------------- /ScriptMasterDependent/HTMLGetRowCell.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | row = FilterRegex ( text ; "()" ; 1 ) ; 3 | cell = FilterRegex ( row ; "(?:(.*?)<" ; 1 ) 4 | ]; 5 | Case ( 6 | cell = "ERROR" ; "" ; 7 | LeftWords ( cell ; 9999 ) 8 | ) 9 | ) 10 | 11 | /* —————————————————————————————— // 12 | NAME: 13 | HTMLGetRowCell ( text ; rowMatch ; columnNum ) 14 | 15 | PURPOSE: 16 | Returns innermost text value of nth column in matched row. 17 | Also trims leading and trailing whitespace. 18 | 19 | EXAMPLES: 20 | HTMLGetRowCell ( 21 | "DogRufus7yrs" ; 22 | ">Rufus<" ; 23 | 1 24 | ) = "Dog" 25 | 26 | HTMLGetRowCell ( 27 | "DogRufus7yrs" ; 28 | "" ; 29 | 1 30 | ) = "Dog" 31 | 32 | HISTORY: 33 | Created: 2011-Aug-23 12h55 PST — Donovan A. Chandler 34 | */ -------------------------------------------------------------------------------- /ScriptTraceAdd.calc: -------------------------------------------------------------------------------- 1 | TraceAdd ( 2 | Get ( ScriptName ) ; 3 | "Script" ; 4 | action ; 5 | note 6 | ) 7 | 8 | /* __________________________________________________ 9 | 10 | NAME: ScriptTraceAdd ( action ; note ) 11 | PURPOSE: Appends new entry to trace stack. Used for monitoring script performance. 12 | EXAMPLES: 13 | ScriptTraceAdd ( "debug" ; "Finished sort operation" ) 14 | NOTES: 15 | Valid action values: {start, end, debug, error} 16 | HISTORY: 17 | Created: 2011-04-26 14:58 PT - Donovan Chandler 18 | */ -------------------------------------------------------------------------------- /ScriptTraceIsOn.calc: -------------------------------------------------------------------------------- 1 | GetAsBoolean ( $$_trace_enabled ) 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: ScriptTraceIsOn ( ) 6 | PURPOSE: Returns "1" (True) if scripts are permitted to build trace log. 7 | HISTORY: 8 | Created: 2012-04-11 11:27 PST - Donovan Chandler 9 | Modified: 10 | */ 11 | -------------------------------------------------------------------------------- /ScriptTraceOff.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | $$_trace_enabled = False 3 | ] ; 4 | $$_trace_enabled 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: ScriptTraceOff ( ) 10 | PURPOSE: Sets global flag to ensure scripts are NOT permitted to build trace log. 11 | HISTORY: 12 | Created: 2012-04-11 11:27 PST - Donovan Chandler 13 | Modified: 14 | */ -------------------------------------------------------------------------------- /ScriptTraceOn.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | $$_trace_enabled = True 3 | ] ; 4 | $$_trace_enabled 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: ScriptTraceOn ( ) 10 | PURPOSE: Sets global flag to ensure scripts are permitted to build trace log. 11 | HISTORY: 12 | Created: 2012-04-11 11:27 PST - Donovan Chandler 13 | Modified: 14 | */ -------------------------------------------------------------------------------- /SecondsAsString.calc: -------------------------------------------------------------------------------- 1 | Let([ 2 | secTotal = GetAsNumber( theSeconds ); 3 | sec = Mod( secTotal; 60 ); 4 | minTotal = Int( secTotal / 60 ); 5 | hour = Int( minTotal / 60 ); 6 | min = Mod( minTotal; hour ) 7 | ]; 8 | Case( 9 | //-- Errors 10 | IsEmpty( secTotal ); ""; 11 | 12 | //-- Custom formats 13 | 14 | //-- Default 15 | hour > 0; hour & " hr " & min & " min " & sec & " sec"; 16 | 17 | minTotal & " min " & sec & " sec" 18 | ) 19 | ) 20 | 21 | /* —————————————————————————————— // 22 | NAME: 23 | SecondsAsString ( theSeconds; format ) 24 | 25 | PURPOSE: 26 | Returns time value as readable string 27 | 28 | EXAMPLES: 29 | TimeAsString ( "10:25:44"; "" ) = 30 | 31 | HISTORY: 32 | Created: 2010-Sep-08 12h01 PST — Donovan A. Chandler 33 | */ -------------------------------------------------------------------------------- /SetIfEmpty.calc: -------------------------------------------------------------------------------- 1 | If ( IsEmpty ( existingValue ) ; newValue ; existingValue ) 2 | 3 | /* —————————————————————————————— // 4 | NAME: 5 | SetIfEmpty ( existingValue ; newValue ) 6 | 7 | PURPOSE: 8 | Analogous to "||=" assignment operator in Ruby. 9 | Replaces existingValue with newValue only if existingValue is empty. 10 | 11 | EXAMPLES: 12 | SetNotEmpty ( "" ; "fum" ) = "fum" 13 | SetNotEmpty ( "foo" ; "fum" ) = "foo" 14 | 15 | $_foo ||= "fum" // Ruby example 16 | 17 | HISTORY: 18 | Created: 2011-Aug-26 14h42 PST — Donovan A. Chandler 19 | */ -------------------------------------------------------------------------------- /SetNotEmpty.calc: -------------------------------------------------------------------------------- 1 | If ( IsEmpty ( newValue ) ; existingValue ; newValue ) 2 | 3 | /* —————————————————————————————— // 4 | NAME: 5 | SetNotEmpty ( existingValue ; newValue ) 6 | 7 | PURPOSE: 8 | Replaces existingValue with newValue only if newValue isn't empty. 9 | 10 | EXAMPLES: 11 | SetNotEmpty ( "" ; "fum" ) = "fum" 12 | SetNotEmpty ( "foo" ; "fum" ) = "fum" 13 | 14 | HISTORY: 15 | Created: 2011-Aug-26 14h42 PST — Donovan A. Chandler 16 | */ -------------------------------------------------------------------------------- /SqFieldListLoop.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | value = GetValue ( listOfFieldNames ; 1 ) ; 3 | valueNew = SqField ( value ) ; 4 | valueCnt = ValueCount ( listOfFieldNames ) 5 | ] ; 6 | Case ( 7 | valueCnt ≤ 1 ; valueNew ; 8 | List ( 9 | valueNew ; 10 | SqFieldListLoop ( RightValues ( listOfFieldNames ; valueCnt - 1 ) ) 11 | ) 12 | ) 13 | ) 14 | 15 | /* __________________________________________________ 16 | 17 | NAME: SqFieldListLoop ( listOfFieldNames ) 18 | PURPOSE: Converts list of field names into SQL-escaped field references. 19 | EXAMPLES: 20 | SqFieldListLoop ( List ( 21 | GetFieldName ( account::id_person ) ; 22 | GetFieldname ( ACCOUNT::PRIVILEGE_NAME_LT ) 23 | ) ) = "\"account\".\"id_person\"¶\"account\".\"privilege_name_lt\"" 24 | HISTORY: 25 | Created: 2013-02-18 12:18 PT - Donovan Chandler 26 | Modified: 27 | */ -------------------------------------------------------------------------------- /SqGetByID.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | query = 3 | "SELECT " & SqField ( targetField ) & 4 | "¶FROM " & SqTable ( targetField ) & 5 | "¶WHERE " & SqField ( idField ) & " = " & sqString ( idField ) 6 | ] ; 7 | SQL ( query ) 8 | ) 9 | 10 | /* __________________________________________________ 11 | 12 | NAME: SqGetByID ( targetField ; idField ) 13 | PURPOSE: Retrieves value from record matching supplied id value. 14 | EXAMPLES: 15 | 16 | HISTORY: 17 | Created: 2013-01-25 14:01 PT - Donovan Chandler 18 | Modified: 19 | */ -------------------------------------------------------------------------------- /SqGetColumn.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | query = 3 | "SELECT DISTINCT" & SqField ( targetField ) & 4 | "¶FROM " & SqTable ( targetField ) 5 | ] ; 6 | SQL ( query ) 7 | ) 8 | 9 | /* __________________________________________________ 10 | 11 | NAME: SqGetColumn ( targetField ) 12 | PURPOSE: Retrieves all unique values from a column. 13 | EXAMPLES: 14 | 15 | HISTORY: 16 | Created: 2013-01-25 14:01 PT - Donovan Chandler 17 | Modified: 18 | */ -------------------------------------------------------------------------------- /SqGetFields.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | fields = Substitute ( targetSQLFields ; ¶ ; ", " ) ; 3 | query = 4 | "SELECT " & fields & 5 | "¶FROM " & SqTable ( matchField ) & 6 | "¶WHERE lower(" & SqField ( matchField ) & ") = " & Lower ( SqStringSmart ( matchValue ) ) 7 | ] ; 8 | SQL ( query ) 9 | ) 10 | 11 | /* __________________________________________________ 12 | 13 | NAME: SqGetFields ( targetSQLFields ; matchField ; matchValue ) 14 | PURPOSE: Gets respective field values from record based on matching column value. 15 | EXAMPLES: 16 | SqGetFields ( 17 | List ( SqField ( PERSON::NAME ) ; SqField ( PERSON::EMAIL ) ) ; 18 | PERSON::ID ; 19 | "PERSON-0035" 20 | ) = "Donovan Chandler††donovan_c@beezwax.net" 21 | // Assuming SQL( ) uses "††" as the column separator 22 | HISTORY: 23 | Created: 2013-01-31 10:01 PT - Donovan Chandler 24 | Modified: 2013-02-14 11:50 PT - Donovan Chandler : supports number is matchValue. 25 | Modified: 2013-02-21 10:44 PT - Donovan Chandler : uses lower() to loosen search. 26 | */ -------------------------------------------------------------------------------- /SqGetLike: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | query = 3 | "SELECT " & SqField ( targetField ) & 4 | "¶FROM " & SqTable ( targetField ) & 5 | "¶WHERE " & SqField ( matchField ) & " LIKE " & matchSQLValue 6 | ] ; 7 | SQL ( query ) 8 | ) 9 | 10 | /* __________________________________________________ 11 | 12 | NAME: SqGetLike ( targetField ; matchField ; matchSQLValue ) 13 | PURPOSE: Gets value from record based on matching column value. Similar to SqGet( ) except it uses the "LIKE" operator. 14 | EXAMPLES: 15 | SqGetLike ( 16 | GetFieldName ( CONTACT::NAME ) ; 17 | GetFieldName ( CONTACT::NAME ) ; 18 | SqString ( "Do%" ) 19 | ) = "Dorothy‡‡Donald" // where SqRowSeparator() = "‡‡" 20 | HISTORY: 21 | Created: 2013-02-28 15:06 PT - Donovan Chandler 22 | Modified: 23 | */ -------------------------------------------------------------------------------- /SqGetLiteral: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | matchIsNumber = ( Left ( matchSQLValue ; 1 ) ≠ "'" ) ; 3 | query = 4 | "SELECT " & SqField ( targetField ) & 5 | "¶FROM " & SqTable ( targetField ) & 6 | If ( 7 | matchIsNumber ; 8 | "¶WHERE " & SqField ( matchField ) & " = " & matchSQLValue ; 9 | "¶WHERE " & SqField ( matchField ) & " = " & matchSQLValue 10 | ) 11 | ] ; 12 | SQL ( query ) 13 | ) 14 | 15 | /* __________________________________________________ 16 | 17 | NAME: SqGetLiteral ( targetField ; matchField ; matchSQLValue ) 18 | PURPOSE: Gets value from record based on matching column value. Similar to SqGet( ) except it searches for an exact match against the matchSQLValue parameter without using lower() or any escaping. 19 | EXAMPLES: 20 | SqGetLiteral ( 21 | GetFieldName ( CONTACT::NAME ) ; 22 | GetFieldName ( CONTACT::PHONE ) ; 23 | SqString ( "888.835.4483" ) 24 | ) = "Beezwax" // where CONTACT::PHONE is a text field 25 | HISTORY: 26 | Created: 2013-02-28 10:27 PT - Donovan Chandler 27 | Modified: 28 | */ -------------------------------------------------------------------------------- /SqListLoop: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | raw = GetValue ( listToDelimit ; 1 ) ; 3 | quoted = SqString ( raw ) ; 4 | count = ValueCount ( listToDelimit ) 5 | ] ; 6 | Case ( 7 | count > 1 ; 8 | quoted & "," & 9 | SqListLoop ( RightValues ( listToDelimit ; count - 1 ) ) ; 10 | quoted 11 | ) 12 | ) 13 | 14 | /* __________________________________________________ 15 | 16 | NAME: SqListLoop ( listToDelimit ) 17 | PURPOSE: Performs recursion for SqList. 18 | EXAMPLES: 19 | SqListLoop ( "dog¶cat\¶mouse" ) = "'dog','cat¶mouse'" 20 | HISTORY: 21 | Created: 2011-10-26 16:23 PT - Donovan A. Chandler 22 | */ -------------------------------------------------------------------------------- /SqResponseAsDate.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | lst = Substitute ( listOfSQLDates ; [ "-" ; ¶ ] ; [ " " ; ¶ ] ; [ ":" ; ¶ ] ) ; 3 | yr = GetAsNumber ( GetValue ( lst ; 1 ) ) ; 4 | mnth = GetAsNumber ( GetValue ( lst ; 2 ) ) ; 5 | dy = GetAsNumber ( GetValue ( lst ; 3 ) ) ; 6 | valueCnt = ValueCount ( listOfSQLDates ) ; 7 | value = 8 | Case ( 9 | IsEmpty ( lst ) ; "" ; 10 | Date ( mnth ; dy ; yr ) 11 | ) 12 | ] ; 13 | value 14 | & If ( valueCnt > 1 ; 15 | ¶ & SqResponseAsDate ( RightValues ( listOfSQLDates ; valueCnt - 1 ) ) 16 | ) 17 | ) 18 | 19 | /* __________________________________________________ 20 | 21 | NAME: SqResponseAsDate ( listOfSQLDates ) 22 | PURPOSE: Converts one or more return-delimted SQL dates to FileMaker equivalent 23 | EXAMPLES / TESTS: List ( 24 | SqResponseAsDate ( "2012-08-18" ) = "8/18/2012" 25 | ; SqResponseAsDate ( "2014-01-18¶2014-02-19" ) = "1/18/2014¶2/19/2014" 26 | ) 27 | HISTORY: 28 | Created: 2012-08-18 11:18 PST - Hanzel Morato 29 | Modified: 2012-09-27 16:08 PST — Will M. Baker. Updated for TimeStamp. 30 | Modified: 2014-02-11 13:16 PT - Donovan Chandler. Recursive; changed name from SqDateConvertSqlToFileMaker(). 31 | */ -------------------------------------------------------------------------------- /SqStringSmart.calc: -------------------------------------------------------------------------------- 1 | Case ( 2 | not IsEmpty ( textOrNumber ) and GetAsNumber ( textOrNumber ) = textOrNumber ; textOrNumber ; 3 | SqString ( textOrNumber ) 4 | ) 5 | 6 | /* __________________________________________________ 7 | 8 | NAME: SqStringSmart ( textOrNumber ) 9 | PURPOSE: Quotes string for use in SQL if it is a string. 10 | EXAMPLES: 11 | SqStringSmart ( "contact" ) = "'contact'" 12 | SqStringSmart ( "2.5" ) = "2.5" 13 | SqStringSmart ( "" ) = "''" 14 | NOTES: 15 | Use the optional arguments parameter in ExecuteSql( ) 16 | if you want to be sure of proper handling of strings. 17 | HISTORY: 18 | Created: 2013-02-14 11:48 PT - Donovan Chandler 19 | Modified: 2013-10-11 14:19 PT - Donovan Chandler : accounts for empty values. 20 | */ -------------------------------------------------------------------------------- /StringRepeat.calc: -------------------------------------------------------------------------------- 1 | Case ( 2 | repetitions ≤ 0 ; "" ; 3 | repetitions = 1 ; string ; 4 | string & StringRepeat ( string ; repetitions - 1 ) 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: StringRepeat ( string ; repetitions ) 10 | PURPOSE: Repeats string n times 11 | EXAMPLES: 12 | StringRepeat ( "-" ; 4 ) = "----" 13 | HISTORY: 14 | Created: 2011-02-02 16:23 PST - Donovan A. Chandler 15 | */ -------------------------------------------------------------------------------- /StringRepeatLoop.calc: -------------------------------------------------------------------------------- 1 | Case ( 2 | repMax ≤ 0 ; "" ; 3 | rep ≥ repMax ; string ; 4 | string & StringRepeatLoop ( string ; rep + 1 ; repMax ) 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: StringRepeatLoop ( string ; rep ; repMax ) 10 | PURPOSE: Performs recursion for StringRepeat () 11 | EXAMPLES: 12 | 13 | HISTORY: 14 | Created: 2011-02-02 16:26 PST - Donovan A. Chandler 15 | */ -------------------------------------------------------------------------------- /StringToList.calc: -------------------------------------------------------------------------------- 1 | ListTrimValues ( 2 | Substitute ( string ; delimiter ; ¶ ) 3 | ) 4 | 5 | /* —————————————————————————————— // 6 | NAME: 7 | StringToList ( string ; delimiter ) 8 | 9 | PURPOSE: 10 | Converts string to list, breaking lines on delimiter. 11 | Removes spaces 12 | 13 | EXAMPLES: 14 | StringToList ( "dog ,cat, mouse" ; "," ) = "dog¶cat¶mouse" 15 | 16 | HISTORY: 17 | Created: 2011-Feb-02 11h53 PST — Donovan A. Chandler 18 | */ -------------------------------------------------------------------------------- /SuperContainerViewRawTypes.calc: -------------------------------------------------------------------------------- 1 | List ( 2 | "pdf" ; 3 | "" 4 | ) 5 | 6 | /* —————————————————————————————— // 7 | NAME: 8 | SuperContainerViewRawTypes 9 | 10 | PURPOSE: 11 | Provides central list of all types of files to view in raw view. 12 | 13 | EXAMPLES: 14 | 15 | 16 | HISTORY: 17 | Created: 2011-May-13 13h32 PST — Donovan A. Chandler 18 | */ -------------------------------------------------------------------------------- /TextAsBoolean.calc: -------------------------------------------------------------------------------- 1 | Let([ 2 | stringTrim = Trim( string ); 3 | yes = "yes¶y¶1¶true"; 4 | no = "no¶n¶0¶false" 5 | ]; 6 | Case( 7 | //-- Null, convert if requested 8 | IsEmpty( stringTrim ) and nullAsFalse; 9 | 0; 10 | 11 | //-- True 12 | ValueCount( FilterValues( yes; stringTrim ) ); 13 | 1; 14 | 15 | //-- False 16 | ValueCount( FilterValues( no; stringTrim ) ); 17 | 0; 18 | 19 | //-- Unrecognized 20 | preserveUnrecognizedValues; 21 | string 22 | ) 23 | ) 24 | 25 | /* —————————————————————————————— // 26 | NAME: 27 | TextAsBoolean( string ; nullAsFalse ; preserveUnrecognizedValues ) 28 | 29 | PURPOSE: 30 | Converts recognized strings into boolean values. 31 | 32 | EXAMPLES: 33 | TextAsBoolean( "yes"; 1; 1 ) = 1 34 | TextAsBoolean( "maybe"; 1; 1 ) = "maybe" 35 | TextAsBoolean( "maybe"; 1; 0 ) = "" 36 | TextAsBoolean( ""; 1; 1 ) = 0 37 | TextAsBoolean( ""; 0; 1 ) = "" 38 | 39 | HISTORY: 40 | Created: 2010-Sep-21 14h26 PST — Donovan A. Chandler 41 | */ -------------------------------------------------------------------------------- /TextBeginsWith.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | len = Length ( matchString ) 3 | ] ; 4 | Left ( text ; len ) = matchString 5 | ) 6 | 7 | /* —————————————————————————————— // 8 | NAME: 9 | TextBeginsWith ( text ; matchString ) 10 | 11 | PURPOSE: 12 | Returns True if test begins with matchString 13 | 14 | EXAMPLES: 15 | TextBeginsWith ( "doggie" ; "Dog" ) // = True 16 | TextBeginsWith ( "doggie" ; "dot" ) // = False 17 | 18 | HISTORY: 19 | Created: 2012-Feb-02 10h36 PST — Donovan A. Chandler 20 | */ -------------------------------------------------------------------------------- /TextCapitalizeFirstLetters.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | ~line = GetValue ( text ; startLineNumber ) ; 3 | ~firstWord = LeftWords ( ~line ; 1 ) ; 4 | ~firstWordStart = Position ( ~line ; ~firstWord ; 1 ; 1 ) ; 5 | ~firstWordNew = Upper ( Left ( ~firstWord ; 1 ) ) & Middle ( ~firstWord ; 2 ; 99 ) ; 6 | ~remainingText = Middle ( ~line ; ~firstWordStart + Length ( ~firstWord ) ; Length ( ~line ) ) 7 | ] ; 8 | 9 | List ( 10 | Left ( ~line ; ~firstWordStart - 1 ) & ~firstWordNew & ~remainingText ; 11 | If ( ValueCount ( text ) > startLineNumber ; FormatWorkItemCapitalization ( text ; startLineNumber + 1 ) ) 12 | ) 13 | 14 | ) 15 | 16 | /* __________________________________________________ 17 | 18 | NAME: TextCapitalizeFirstLetters ( text ; startLineNumber ) 19 | PURPOSE: Capitalizes first letter of each line of text. 20 | Leaves leading symbols in tact. 21 | Leaves acronyms in tact. 22 | EXAMPLES: 23 | TextCapitalizeFirstLetters ( "the¶- red¶FOX" ; 1 ) 24 | // Returns "The¶- Red¶FOX" 25 | HISTORY: 26 | Created: 2013-09-27 10:30 PT - Donovan Chandler 27 | Modified: 28 | */ -------------------------------------------------------------------------------- /TextCleanQuotes.calc: -------------------------------------------------------------------------------- 1 | Substitute ( text ; [ Char ( 147 ) ; "\"" ] ; // left curly quote [ Char ( 148 ) ; "\"" ] ; // right curly quote [ Char ( 8220 ) ; "\"" ] ; // left curly quote [ Char ( 8221 ) ; "\"" ] // right curly quote ) /* __________________________________________________ NAME: TextCleanQuotes ( text ) PURPOSE: Replaces curly double and single quotes with regular double quotes. EXAMPLES: HISTORY: Created: 2011-07-22 14:14 PT - Donovan Chandler NOTES: Code ( " " ) = 32 Code ( "¶" ) = 13 */ -------------------------------------------------------------------------------- /TextEncodeForAppleScript.calc: -------------------------------------------------------------------------------- 1 | "\"" & Substitute ( text ; 2 | [ "\\" ; "\\\\" ] ; 3 | [ " " ; "\t" ] ; 4 | [ "\"" ; "\\\"" ] 5 | ) & "\"" 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: TextEncodeForAppleScript ( text ) 10 | PURPOSE: Escapes string literals for AppleScript 11 | EXAMPLES: 12 | TextEncodeForAppleScript ( "Quotation: \"hello\", Tab: , Backslash:\\" ) 13 | = "\"Quotation: \\\"hello\\\", Tab:\t, Backslash:\\\\\"" 14 | which reads in the data viewer as: "Quotation: \"hello\", Tab:\t, Backslash:\\" 15 | HISTORY: 16 | 2011-03-15 17:50 PDT - Donovan Chandler 17 | 2014-07-21 10:40 PDT - Donovan Chandler : Wrap result in quotation marks 18 | */ 19 | -------------------------------------------------------------------------------- /TextEncodeForFilePath.calc: -------------------------------------------------------------------------------- 1 | Substitute ( 2 | text ; 3 | [ ¶ ; " " ] ; 4 | [ "|" ; " " ] ; 5 | [ "<" ; " " ] ; 6 | [ ">" ; " " ] ; 7 | [ "..." ; "." ] ; 8 | [ "\"" ; "" ] ; 9 | [ "," ; "" ] 10 | ) 11 | 12 | /* __________________________________________________ 13 | 14 | NAME: TextEncodeForFilePath ( text ) 15 | PURPOSE: Ensures all characters in text are valid for a file path 16 | EXAMPLES: 17 | 18 | HISTORY: 19 | Created: 2011-03-03 17:47 PST - Donovan A. Chandler 20 | */ -------------------------------------------------------------------------------- /TextEscapeForCSV.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | ~text = Substitute ( text ; "\"" ; "\"\"" ) 3 | ] ; 4 | If ( 5 | Position ( ~text ; "," ; 1 ; 1 ) 6 | or Position ( ~text ; "¶" ; 1 ; 1 ) ; 7 | "\"" & ~text & "\"" ; 8 | ~text 9 | ) 10 | ) 11 | 12 | /* __________________________________________________ 13 | 14 | NAME: TextEscapeForCSV ( text ) 15 | PURPOSE: Ensures text is valid csv value 16 | TESTS: 17 | List ( 18 | TextEscapeForCSV ( "foo" ) = "foo" ; 19 | TextEscapeForCSV ( "foo," ) = "\"foo,\"" ; 20 | TextEscapeForCSV ( "foo\"" ) = "foo\"\"" 21 | ) 22 | 23 | HISTORY: 24 | Created: 2013-12-03 15:40 PT - Donovan Chandler 25 | Modified: 26 | */ -------------------------------------------------------------------------------- /TextEscapeSearchChars.calc: -------------------------------------------------------------------------------- 1 | Substitute ( searchString ; 2 | [ "\@" ; "@" ] ; 3 | [ "@" ; "\@" ] ; 4 | 5 | [ "\#" ; "#" ] ; 6 | [ "#" ; "\#" ] ; 7 | 8 | [ "\*" ; "*" ] ; 9 | [ "*" ; "\*" ] ; 10 | 11 | [ "\!" ; "!" ] ; 12 | [ "!" ; "\!" ] ; 13 | 14 | [ "\?" ; "?" ] ; 15 | [ "?" ; "\?" ] ; 16 | 17 | // Disabled because it was destroying the "today" operator (//) 18 | // [ "\/" ; "/" ] ; 19 | // [ "/" ; "\/" ] ; 20 | 21 | [ "\<" ; "<" ] ; 22 | [ "<" ; "\<" ] ; 23 | 24 | [ "\>" ; ">" ] ; 25 | [ ">" ; "\>" ] ; 26 | 27 | [ "\≤" ; "≤" ] ; 28 | [ "≤" ; "\<" ] ; 29 | 30 | [ "\≥" ; "≥" ] ; 31 | [ "≥" ; "\≥" ] ; 32 | 33 | [ "\=" ; "=" ] ; 34 | [ "=" ; "\=" ] 35 | ) 36 | 37 | /* __________________________________________________ 38 | 39 | NAME: TextEscapeSearchChars ( searchString ) 40 | PURPOSE: Escapes reserved characters in search strings. 41 | EXAMPLES: 42 | TextEscapeSearchChars ( "<20" ) = "\<20" 43 | HISTORY: 44 | Created: 2011-03-01 15:12 PT - Donovan Chandler 45 | */ -------------------------------------------------------------------------------- /TextFilterToText.calc: -------------------------------------------------------------------------------- 1 | //Filter( string; " !#$%&'()*+,-./:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`{|}~" ) 2 | 3 | Substitute( string; 4 | [ "0"; "" ]; 5 | [ "1"; "" ]; 6 | [ "2"; "" ]; 7 | [ "3"; "" ]; 8 | [ "4"; "" ]; 9 | [ "5"; "" ]; 10 | [ "6"; "" ]; 11 | [ "7"; "" ]; 12 | [ "8"; "" ]; 13 | [ "9"; "" ] 14 | ) 15 | 16 | /* —————————————————————————————— // 17 | NAME: 18 | TextFilterToAlpha( string ) 19 | 20 | PURPOSE: 21 | Returns string with numbers removed 22 | 23 | EXAMPLES: 24 | TextFilterToText( "number10!" ) = "number!" 25 | 26 | HISTORY: 27 | Created: 2010-Sep-14 17h51 PST — Donovan A. Chandler 28 | */ -------------------------------------------------------------------------------- /TextInjected?.calc: -------------------------------------------------------------------------------- 1 | Case ( 2 | PatternCount ( text ; "SELECT" ) ; 3 | "Possible injection: SELECT" ; 4 | PatternCount ( text ; "UPDATE" ) ; 5 | "Possible injection: UPDATE" ; 6 | PatternCount ( text ; "INSERT INTO" ) ; 7 | "Possible injection: INSERT INTO" ; 8 | PatternCount ( text ; "DELETE FROM" ) ; 9 | "Possible injection: DELETE FROM" ; 10 | PatternCount ( text ; "CREATE TABLE" ) ; 11 | "Possible injection: CREATE TABLE" ; 12 | PatternCount ( text ; "ALTER TABLE" ) ; 13 | "Possible injection: ALTER TABLE" ; 14 | PatternCount ( text ; "CREATE INDEX" ) ; 15 | "Possible injection: CREATE INDEX" ; 16 | PatternCount ( text ; "DROP INDEX" ) ; 17 | "Possible injection: DROP INDEX" 18 | ) 19 | 20 | 21 | /* __________________________________________________ 22 | 23 | NAME: TextInjected? ( text ) 24 | PURPOSE: Returns warning if possibly harmful SQL may be present into string (possible injection attack). 25 | Used to prevent SQL from being injected into evaluated strings. 26 | EXAMPLES: 27 | 28 | HISTORY: 29 | 2014-08-29 11:55 PDT - Donovan Chandler 30 | */ -------------------------------------------------------------------------------- /TextInsertAtCursor.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | text = Get ( ActiveFieldContents ) ; 3 | strNew = insertString ; 4 | curStart = Get ( ActiveSelectionStart ) ; 5 | curLen = Get ( ActiveSelectionSize ) ; 6 | strLeft = Left ( text ; curStart -1 ) ; 7 | strRight = Middle ( text ; curStart + curLen ; Length ( text ) ) 8 | ] ; 9 | strLeft & strNew & strRight 10 | ) 11 | 12 | /* —————————————————————————————— // 13 | NAME: 14 | TextInsertAtCursor ( insertString ) 15 | 16 | PURPOSE: 17 | Returns contents of active field with insertString pasted at cursor. 18 | Replaces selection. 19 | 20 | EXAMPLES: 21 | 22 | 23 | HISTORY: 24 | Created: 2011-Mar-03 17h19 PST — Donovan A. Chandler 25 | */ -------------------------------------------------------------------------------- /TextIsDate.calc: -------------------------------------------------------------------------------- 1 | not IsEmpty( string ) and 2 | GetAsText ( GetAsDate( string ) ) = GetAsText ( string ) 3 | 4 | /* —————————————————————————————— // 5 | NAME: 6 | TextIsDate( string ) 7 | 8 | PURPOSE: 9 | Returns True if string is a date 10 | 11 | EXAMPLES: 12 | 13 | 14 | HISTORY: 15 | Created: 2010-Aug-26 11h20 PST — Donovan A. Chandler 16 | */ -------------------------------------------------------------------------------- /TextMergeTags.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | tagCount = ValueCount ( mergeTagNames ) ; 3 | label = GetValue ( mergeTagNames ; 1 ) ; 4 | value = Evaluate ( GetValue ( mergeValues ; 1 ) ) ; 5 | result = Substitute ( text ; mergeTagOpen & label & mergeTagClose ; Quote ( value ) ) 6 | ] ; 7 | Case ( 8 | tagCount > 1 ; 9 | TextMergeTags ( 10 | result ; 11 | RightValues ( mergeTagNames ; tagCount - 1 ) ; 12 | RightValues ( mergeValues ; tagCount - 1 ) ; 13 | mergeTagOpen ; 14 | mergeTagClose 15 | ) ; 16 | result 17 | ) 18 | ) 19 | 20 | /* —————————————————————————————— // 21 | NAME: 22 | TextMergeTags ( text ; mergeTagNames ; mergeValues ; mergeTagOpen ; mergeTagClose ) 23 | 24 | PURPOSE: 25 | Replaces mergeLabels in text with corresponding mergeValues 26 | 27 | EXAMPLES: 28 | TextMergeTags ( "Middle ( {text} ; {start} ; 1 )" 29 | ; "text¶start" 30 | ; "\"dog\"¶\"5\"" 31 | ; "{" 32 | ; "}" 33 | ) = "Middle ( \"dog\" ; 5 ; 1 )" 34 | 35 | NOTES: 36 | mergeValues - each value must be quoted (to escape multi-line values) 37 | 38 | HISTORY: 39 | Created: 2011-Dec-22 21h31 PST — Donovan A. Chandler 40 | */ -------------------------------------------------------------------------------- /TextNthNodePosition.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | sNext = Position ( text ; openChars ; startPosition ; 1 ) ; 3 | eNext = TextClosePosition ( text ; openChars ; closeChars ; sNext ) 4 | ]; 5 | Case ( 6 | sNext = 0 ; "" ; 7 | nodeIndex = 1 ; sNext ; 8 | TextNthNodePosition ( text ; openChars ; closeChars ; eNext ; nodeIndex - 1 ) 9 | ) 10 | ) 11 | 12 | /* __________________________________________________ 13 | 14 | NAME: TextNthNodePosition( text ; openChars ; closeChars ; startPosition ; nodeIndex ) 15 | PURPOSE: 16 | Returns start position of Nth "node". 17 | Each node is demarcated by openChars and closeChars. 18 | EXAMPLES: 19 | Where $_text = "[ [1,2], [3] ],[ 4 ]" 20 | TextNthNodePosition ( $_text ; "[" ; "]" ; 1 ; 2 ) = 16 21 | HISTORY: 22 | Created: 2009-12-03 12:00 PT - Donovan Chandler 23 | Modified: 24 | */ -------------------------------------------------------------------------------- /TextOmitChars.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | string = Substitute ( text ; Left ( charactersToOmit ; 1 ) ; "" ) ; 3 | charRemaining = Right ( charactersToOmit ; Length ( charactersToOmit ) - 1 ) 4 | ]; 5 | Case ( 6 | IsEmpty ( charRemaining ) ; string ; 7 | TextOmitChars ( string ; charRemaining ) 8 | ) 9 | ) 10 | 11 | /* —————————————————————————————— // 12 | NAME: 13 | TextOmitChars ( text ; charactersToOmitToOmit ) 14 | 15 | PURPOSE: 16 | Removes each character from text. Functional inverse of Filter() 17 | 18 | EXAMPLES: 19 | TextOmitChars ( "23 Main Ave" ; "0123456789" ) = " Main Ave" 20 | 21 | HISTORY: 22 | Created: 2010-Dec-17 14h25 PST — Donovan A. Chandler 23 | */ -------------------------------------------------------------------------------- /TextPadColumn.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | length = Length ( col1Value ) ; 3 | tabNum = Ceiling ( (tabMax*tabSize-length) / tabSize ) ; 4 | tabNum = If ( tabNum < tabMin ; tabMin ; tabNum ) ; 5 | placeholder = Substitute ( 10^(tabNum-1) ; "0" ; 1 ) ; 6 | tabs = Substitute ( placeholder ; 1 ; " " ) 7 | ]; 8 | If ( not hideCol1 ; col1Value ) & tabs & col2Value 9 | ) 10 | 11 | /* —————————————————————————————— // 12 | NAME: 13 | TextPadColumn ( col1Value ; col2Value ; tabMax ; tabMin ; tabSize ; hideCol1 ) 14 | 15 | PURPOSE: 16 | Pads col2 (second column) with tab characters so that it is left-aligned regardless of col1 width. 17 | Requires monospaced font for effect to work. 18 | 19 | EXAMPLES: 20 | List ( 21 | TextPadColumn ( "bold" ; "Darker text" ; 3 ; 1 ; 5 ) ; 22 | TextPadColumn ( "lightest" ; "Not so dark" ; 3 ; 1 ; 5) 23 | ) 24 | 25 | HISTORY: 26 | Created: 2011-Mar-18 18h33 PST — Donovan A. Chandler 27 | */ -------------------------------------------------------------------------------- /TextPrependWithTimestamp.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | clrA = RGB ( 189 ; 76 ; 0 ) ; //Orange/// 3 | clrB = RGB ( 85 ; 85 ; 85 ) //Gray// 4 | ]; 5 | Case ( 6 | not IsEmpty ( newText ) ; 7 | GetAsDate ( timestmp ) & " " & 8 | TextColor ( GetAsTime ( timestmp ) & " by " ; clrB ) & 9 | TextColor ( name ; clrA ) & 10 | TextColor ( 11 | ":¶" & 12 | "-------------------------------------------------¶" ; clrB 13 | ) & 14 | newText & 15 | Case ( 16 | not IsEmpty ( oldText ) ; 17 | "¶¶" & oldText 18 | ) 19 | ) 20 | ) 21 | 22 | 23 | 24 | /* —————————————————————————————— // 25 | NAME: 26 | TextPrependWithTimestamp ( oldText ; newText ; name ; timestmp ) 27 | 28 | PURPOSE: 29 | Prepends block of text with header containing provided name and timestamp 30 | 31 | EXAMPLES: 32 | 33 | 34 | HISTORY: 35 | Created: 2010-Dec-21 12h25 PST — Donovan A. Chandler 36 | */ -------------------------------------------------------------------------------- /TextRepeatWithIncrement.calc: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------- 2 | NAME: 3 | text.repeatWithIncrement( text; matchString; startValue; endValue ) 4 | 5 | PURPOSE: 6 | Repeats text, incrementing matchString from startNumber to endNumber. 7 | 8 | HISTORY: 9 | Created 2010-Mar-20 16h02 donovan_c@beezwax.net 10 | 11 | INPUT: 12 | 13 | 14 | OUTPUT: 15 | 16 | ---------------------------------------------------------------------------------------*/ 17 | 18 | Let([ 19 | _text = text; 20 | _matchString = matchString; 21 | _numStart = startValue; 22 | _numEnd = endValue; 23 | 24 | _sMatch = Position( _text; _matchString; 1; 1 ); 25 | _textNew = Replace( _text; _sMatch; Length( _matchString ); _numStart ) 26 | ]; 27 | Case( 28 | //-- Invalid matchString 29 | _sMatch = 0; 30 | _text; 31 | 32 | //-- More values to add 33 | _numStart < _numEnd; 34 | _textNew & text.repeatWithIncrement( _text; _matchString; _numStart + 1; _numEnd ); 35 | 36 | //-- Default 37 | _textNew 38 | ) 39 | ) -------------------------------------------------------------------------------- /TextSplit.calc: -------------------------------------------------------------------------------- 1 | ListTrimValues ( 2 | Substitute ( text ; splitChar ; ¶ ) 3 | ) 4 | 5 | /* —————————————————————————————— // 6 | NAME: 7 | TextSplit ( text ; splitChar ) 8 | 9 | PURPOSE: 10 | Breaks text string on splitChar into return-delimited list. 11 | Also strips whitespace from ends of each line. 12 | 13 | EXAMPLES: 14 | TextSplit ( "dog, cat ,mouse" ; "," ) = "dog¶cat¶mouse" 15 | 16 | HISTORY: 17 | Created: 2011-Mar-08 09h33 PST — Donovan A. Chandler 18 | */ -------------------------------------------------------------------------------- /TextStripLeft.calc: -------------------------------------------------------------------------------- 1 | Case ( 2 | Left ( text ; 1 ) = charToStrip ; 3 | TextStripLeft ( Right ( text ; Length ( text ) - 1 ) ; charToStrip ) ; 4 | text 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: TextStripLeft ( text ; charToStrip ) 10 | PURPOSE: Strips all occurrences of character from beginning of text 11 | EXAMPLES: 12 | 13 | HISTORY: 14 | Created: 2011-07-09 21:26 PT - Donovan Chandler 15 | Modified: 16 | */ -------------------------------------------------------------------------------- /TextStripRight.calc: -------------------------------------------------------------------------------- 1 | Case ( 2 | Right ( text ; 1 ) = charToStrip ; 3 | TextStripRight ( Left ( text ; Length ( text ) - 1 ) ; charToStrip ) ; 4 | text 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: TextStripRight ( text ; charToStrip ) 10 | PURPOSE: Strips all occurrences of character from end of text 11 | EXAMPLES: 12 | TextStripRight ( "test:" ; ":" ) //= "test" 13 | TextStripRight ( "test: " ; ":" ) //= "test: " 14 | TextStripRight ( "test: " ; ": " ) //= "test: " 15 | HISTORY: 16 | Created: 2011-07-09 21:26 PT - Donovan Chandler 17 | Modified: 18 | */ -------------------------------------------------------------------------------- /TimeDurationAsText.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | then = GetAsTimestamp ( startTimestamp ) ; 3 | now = GetAsTimestamp ( endTimestamp ) ; 4 | dur = now - then ; 5 | hours = Hour ( dur ) ; 6 | days = Int ( Div ( hours ; 24 ) ) ; 7 | hours = Mod ( hours ; 24 ) ; 8 | mins = Minute ( dur ) 9 | ] ; 10 | Case ( 11 | IsEmpty ( startTimestamp ) or IsEmpty ( endTimestamp ) ; "" ; 12 | days > 0 ; days & " day" & If ( days > 1 ; "s" ) ; 13 | hours > 0 ; hours & " hour" & If ( hours > 1 ; "s" ) ; 14 | mins > 0 ; mins & " min" & If ( mins > 1 ; "s" ) 15 | ) 16 | ) 17 | 18 | /* __________________________________________________ 19 | 20 | NAME: TimeDurationAsText ( startTimestamp ; endTimestamp ) 21 | PURPOSE: Returns text description of duration, using largets denominator only. 22 | EXAMPLES: 23 | TimeDurationAsText ( "1/1/2012" ; "1/14/2012" ) = "13 days" 24 | TimeDurationAsText ( "1/1/2012 12:00 PM" ; "1/1/2012 1:00 PM" ) = "1 hour" 25 | TimeDurationAsText ( "1/1/2012 12:00 PM" ; "1/1/2012 12:38 PM" ) = "38 mins" 26 | HISTORY: 27 | Created: 2012-10-15 15:37 PT - Donovan Chandler 28 | Modified: 29 | */ -------------------------------------------------------------------------------- /TimeStampAsZulu.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | timeZ = 3 | Time ( 4 | Hour ( tme ) + ( hourOffsetFromZulu * -1 ) ; 5 | Minute ( tme ) ; 6 | Seconds ( tme ) 7 | ) ; 8 | m = Timestamp ( dte ; timeZ ); 9 | d = Date ( Month ( m ) ; Day ( m ) ; Year ( m ) ); 10 | t = Time ( Hour ( m ) ; Minute ( m ) ; Seconds ( m ) ) 11 | ] ; 12 | Year ( d ) & 13 | "-" & 14 | Right ( "00" & Month ( d ) ; 2 ) & 15 | "-" & 16 | Right ( "00" & Day ( d ) ; 2 ) & 17 | "T" & 18 | Right ( "00" & Hour ( t ) ; 2 ) & 19 | ":" & 20 | Right ( "00" & Minute ( t ) ; 2 ) & 21 | ":" & 22 | Right ( "00" & Seconds ( t ) ; 2 ) & ".000Z" 23 | ) 24 | 25 | /* —————————————————————————————— // 26 | NAME: 27 | TimestampAsZulu ( dte ; tme ; hourOffsetFromZulu ) 28 | 29 | PURPOSE: 30 | Takes timestamp and returns equivalent time in Zulu (GMT) forma 31 | 32 | EXAMPLES: 33 | TimestampAsZulu ( "12/1/10" ; "1:05 PM" ; -8 ) 34 | = "2010-12-01T21:00:05.000Z" 35 | 36 | HISTORY: 37 | Created: 2010-Dec-01 12h09 PST — Donovan A. Chandler based on function by Vincenzo Menanno 38 | */ 39 | -------------------------------------------------------------------------------- /TimeStampMicroUTC.calc: -------------------------------------------------------------------------------- 1 | GetAsTimestamp ( Get ( UTCmSecs ) / 1000 ) 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: TimestampMicroUTC ( ) 6 | PURPOSE: Returns UTC timestamp including microseconds. 7 | EXAMPLES: 8 | TimestampMicroUTC() = "11/9/2012 1:16:13.056 PM" 9 | HISTORY: 10 | Created: 2012-11-09 13:13 PT - Donovan Chandler using David Thorpe's calc. 11 | Modified: 12 | */ -------------------------------------------------------------------------------- /TimeZone.calc: -------------------------------------------------------------------------------- 1 | ( Get ( CurrentTimeStamp ) - Int ( Get ( UTCmSecs ) / 1000 ) ) / 3600 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: TimeZone ( ) 6 | PURPOSE: Returns hour offset of timezone 7 | EXAMPLES: 8 | TimeZone // returns "-8" when in PST 9 | HISTORY: 10 | Created: 2012-11-09 13:07 PT - Donovan Chandler using David Thorpe's calc. 11 | Modified: 12 | */ -------------------------------------------------------------------------------- /TimestampFromText.calc: -------------------------------------------------------------------------------- 1 | Let ([ 2 | day = LeftWords ( text ; 1 ) ; 3 | month = DateMonthNumber ( MiddleWords ( text ; 2 ; 1 ) ) ; 4 | year = MiddleWords ( text ; 3 ; 1 ) ; 5 | time = Middle ( text ; Position ( text ; " " ; 1 ; 1 ) ; 999 ) 6 | ]; 7 | If ( 8 | not IsEmpty ( text ) ; 9 | Timestamp ( Date ( month ; day ; year ) ; GetAsTime ( time ) ) 10 | ) 11 | ) 12 | 13 | /* —————————————————————————————— // 14 | NAME: 15 | TimestampFromText ( text ) 16 | 17 | PURPOSE: 18 | Converts text from text timestamp into a date 19 | 20 | EXAMPLES: 21 | TimestampFromText ( "23-JUL-2010 16:02" ) = "7/23/2010 4:02 PM" 22 | 23 | HISTORY: 24 | Created: 2011-Jun-14 11h51 PST — Donovan A. Chandler 25 | */ -------------------------------------------------------------------------------- /TimestampFromUnix.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | unixDiff = 62135596800 // GetAsNumber ( GetaSTimestamp ( "1/1/1970" ) ) 3 | ; timezoneDiff = 60 * 60 * currentTimezone 4 | ] ; 5 | GetAsTimestamp ( unixTimestampNumber + unixDiff + timezoneDiff ) 6 | ) 7 | 8 | /* —————————————————————————————— // 9 | NAME: 10 | TimestampFromUnix ( unixTimestampNumber ; currentTimezone ) 11 | 12 | PURPOSE: 13 | Converts unix timestamp ("epoch time") to FileMaker timestamp. 14 | Epoch time is stored as the number of seconds since midnight 1/1/1970 UTC/GMT. 15 | 16 | EXAMPLES: 17 | TimestampFromUnix ( 1329931434 ; -8 ) = "2/22/2012 9:23:53 AM" 18 | 19 | HISTORY: 20 | Created: 2012-Feb-22 14h29 PST — Donovan A. Chandler 21 | */ -------------------------------------------------------------------------------- /TimestampMicro.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | timezoneSec = Get ( CurrentTimeStamp ) - Int ( Get ( UTCmSecs ) / 1000 ) 3 | ] ; 4 | GetAsTimestamp ( ( Get ( UTCmSecs ) / 1000 ) + timezoneSec ) 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: TimestampMicro() 10 | PURPOSE: Returns local timestamp including microseconds. 11 | Use TimeStampMicroUTC() for faster results. 12 | EXAMPLES: 13 | TimestampMicro() = "11/9/2012 1:16:13.056 PM" 14 | HISTORY: 15 | Created: 2010-08-06 18:16 PT - Donovan Chandler 16 | Modified: 2012-11-09 13:06 PT - Donovan Chandler : Implemented David Thorpe's native version. 17 | */ -------------------------------------------------------------------------------- /TraceAdd.calc: -------------------------------------------------------------------------------- 1 | If ( 2 | not TraceIsOn ; "Trace log disabled" ; 3 | 4 | Let ( [ 5 | delim = " " ; 6 | row = Get ( UTCmSecs ) / 1000 & delim & objectName & delim & objectType & delim & action & delim & note ; 7 | $$_trace_log = List ( $$_trace_log ; row ) 8 | ] ; 9 | row 10 | ) 11 | ) 12 | 13 | /* __________________________________________________ 14 | 15 | NAME: LogTimeAdd ( objectName ; objectType ; action ; note ) 16 | PURPOSE: Appends entry to trace log in global variable. 17 | EXAMPLE: 18 | LogTimeAdd ( "record . delete" ; "Script" ; "Start" ; "note…" ) & TraceLog 19 | = "163491021512.292 record . delete Script Start note…" 20 | PARAMETERS: 21 | The parameters are all optional and for your discretion. 22 | I use them for parsing the log in a fashion inspired by FMBench. 23 | 24 | objectName Name of script, etc. 25 | objectType {script, calc} 26 | action {start, end, debug, error} 27 | Use "start" and "end" to determine the length of a script. 28 | NOTES: 29 | Optimized more for speed and ease of use. 30 | Use FMBench if you're looking for something robust. 31 | HISTORY: 32 | Created: 2012-04-11 10:34 PT - Donovan Chandler 33 | Modified: 34 | */ -------------------------------------------------------------------------------- /TraceAddSQL.calc: -------------------------------------------------------------------------------- 1 | If ( 2 | not TraceIsOn ; "Trace log disabled" ; 3 | 4 | Let ( [ 5 | fdTimestamp = GetFieldName ( performance_log::timestamp_value ) ; 6 | fdScript = GetFieldName ( performance_log::script_name ) ; 7 | fdMessage = GetFieldName ( performance_log::note ) ; 8 | ts = sqlPrepTimestampForInsert ( GetAsTimestamp ( TimestampMicro ) ) ; 9 | query = "INSERT INTO " & SQLTable ( fdScript ) & " ( " & 10 | SQLField ( fdTimestamp ) & ", " & SQLField ( fdScript ) & ", " & SQLField ( fdMessage ) & 11 | " ) VALUES ( " & 12 | ts & ", " & SQLString ( objectName ) & ", " & SQLString ( note ) & 13 | " )" 14 | ] ; 15 | sql ( query ) 16 | ) 17 | ) 18 | 19 | /* __________________________________________________ 20 | 21 | NAME: TraceAddSQL ( objectName ; objectType ; action ; note ) 22 | PURPOSE: Creates trace log entry directly into log table using SQL plug-in. 23 | NOTES: 24 | Requires SQL plug-in supporting INSERT statements. 25 | Optimized more for speed and ease of use. 26 | Use FMBench if you're looking for something robust. 27 | HISTORY: 28 | Created: 2012-09-17 11:59 PT - Donovan Chandler 29 | Modified: 30 | */ -------------------------------------------------------------------------------- /TraceClear.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | $$_trace_log = "" 3 | ] ; 4 | $$_trace_log 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: TraceClear ( ) 10 | PURPOSE: Clears values from trace log. Large logs can impact performance. 11 | EXAMPLES: 12 | 13 | HISTORY: 14 | Created: 2012-09-07 17:25 PT - Donovan Chandler 15 | Modified: 16 | */ -------------------------------------------------------------------------------- /TraceIsOn.calc: -------------------------------------------------------------------------------- 1 | $$_trace_enabled 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: TraceIsOn ( ) 6 | PURPOSE: Returns True if trace log is enabled. 7 | EXAMPLES: 8 | 9 | HISTORY: 10 | Created: 2012-09-07 16:20 PST - Donovan Chandler 11 | Modified: 12 | */ -------------------------------------------------------------------------------- /TraceLog.calc: -------------------------------------------------------------------------------- 1 | $$_trace_log 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: TraceLog ( ) 6 | PURPOSE: Displays trace log being managed by Trace function suite. 7 | EXAMPLES: 8 | 9 | HISTORY: 10 | Created: 2012-09-07 17:25 PT - Donovan Chandler 11 | Modified: 12 | */ -------------------------------------------------------------------------------- /TraceOff.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | $$_trace_enabled = False // Keeps variable so we can toggle it in the web viewer 3 | ] ; 4 | $$_trace_enabled 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: TraceOff ( ) 10 | PURPOSE: Disables trace log. Ensures scripts don't get bogged down unnecessarily. 11 | EXAMPLES: 12 | 13 | HISTORY: 14 | Created: 2012-09-07 16:21 PT - Donovan Chandler 15 | Modified: 16 | */ -------------------------------------------------------------------------------- /TraceOn.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | $$_trace_enabled = True 3 | ] ; 4 | $$_trace_enabled 5 | ) 6 | 7 | /* __________________________________________________ 8 | 9 | NAME: TraceOn ( ) 10 | PURPOSE: Enables trace log. 11 | EXAMPLES: 12 | 13 | HISTORY: 14 | Created: 2012-09-07 16:21 PT - Donovan Chandler 15 | Modified: 16 | */ -------------------------------------------------------------------------------- /TrimCRLF.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | delimiter = "::‡::" ; 3 | result1 = 4 | Substitute ( 5 | Trim ( 6 | Substitute ( text ; 7 | [ " " ; delimiter ] ; 8 | [ ¶ ; " " ] 9 | ) 10 | ) ; 11 | [ " " ; ¶ ] ; 12 | [ delimiter ; " " ] 13 | ) ; 14 | result2 = 15 | Substitute ( 16 | Trim ( 17 | Substitute ( result1 ; 18 | [ " " ; delimiter ] ; 19 | [ Char ( 10 ) ; " " ] 20 | ) 21 | ) ; 22 | [ " " ; Char ( 10 ) ] ; 23 | [ delimiter ; " " ] 24 | ) 25 | ] ; 26 | result2 27 | ) 28 | 29 | /* —————————————————————————————— // 30 | NAME: 31 | TrimCRLF ( text ) 32 | 33 | PURPOSE: 34 | Trims leading and trailing carriage returns and line feeds from text 35 | 36 | HISTORY: 37 | Created: 2009-Jan-13 — Charlie (http://www.fmfunctions.com/mid/132) 38 | Adapted: 2010-Aug-09 10h17 PST — Donovan A. Chandler 39 | Adapted: 2011-Sep-28 14h38 PST — Donovan Chandler ; added LF removal 40 | */ -------------------------------------------------------------------------------- /TrimCRLeft.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | char = Left ( text ; 1 ) 3 | ] ; 4 | Case ( 5 | char = "¶" ; 6 | TrimCRLeft ( Right ( text ; Length ( text ) - 1 ) ) ; 7 | text 8 | ) 9 | ) 10 | 11 | /* —————————————————————————————— // 12 | NAME: 13 | TrimCRLeft ( text ) 14 | 15 | PURPOSE: 16 | Trims leading carriage returns from text. 17 | 18 | EXAMPLES: 19 | TrimCRLeft ( "¶¶foo¶¶" ) = "foo¶¶" 20 | 21 | HISTORY: 22 | Created: 2011-Oct-31 14h41 PST — Donovan A. Chandler 23 | */ -------------------------------------------------------------------------------- /TrimCRRight.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | char = Right ( text ; 1 ) 3 | ] ; 4 | Case ( 5 | char = "¶" ; 6 | TrimCRRight ( Left ( text ; Length ( text ) - 1 ) ) ; 7 | text 8 | ) 9 | ) 10 | 11 | /* __________________________________________________ 12 | 13 | NAME: TrimCRRight ( text ) 14 | PURPOSE: Trims trailing carriage returns from text. 15 | EXAMPLES: 16 | TrimCRRight ( "¶¶foo¶¶" ) = "¶¶foo" 17 | HISTORY: 18 | Created: 2011-10-31 14:41 PST - Donovan A. Chandler 19 | */ 20 | -------------------------------------------------------------------------------- /TrimChar.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | delimiter = "::‡::" ; 3 | char = GetValue ( charsToTrimList ; 1 ) ; 4 | char = 5 | Case ( 6 | not IsEmpty ( char ) ; char ; 7 | not IsEmpty ( charsToTrimList ) ; charsToTrimList ; // accounts for LF 8 | "" 9 | ) ; 10 | result = 11 | Substitute ( 12 | Trim ( 13 | Substitute ( text ; 14 | [ " " ; delimiter ] ; 15 | [ char ; " " ] 16 | ) 17 | ) ; 18 | [ " " ; char ] ; 19 | [ delimiter ; " " ] 20 | ) 21 | ] ; 22 | Case ( 23 | ValueCount ( charsToTrimList ) > 1 ; 24 | TrimChars ( result ; LeftWords ( MiddleValues ( charsToTrimList ; 2 ; 999 ) ; 999 ) ) ; 25 | result 26 | ) 27 | ) 28 | 29 | /* —————————————————————————————— // 30 | NAME: 31 | TrimChars ( text ; charsToTrimList ) 32 | 33 | PURPOSE: 34 | Trims leading and trailing occurrences of character from text 35 | 36 | NOTES: 37 | Does NOT work with consecutive line terminators like CR and LF 38 | 39 | HISTORY: 40 | Created: 2011-Jul-09 21h26 PST — Donovan Chandler 41 | Modified: 2011-Sep-28 14h22 PST — Donovan Chandler ; now accepts list of chars to trim 42 | */ -------------------------------------------------------------------------------- /TrimWhitespaceLeft.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | ~char = Left ( text ; 1 ) ; 3 | ~charToTrim = 4 | "¶" 5 | & " " 6 | & Char ( 9 ) /* TAB */ 7 | & Char ( 10 ) /* LF */ 8 | ] ; 9 | Case ( 10 | not IsEmpty ( Filter ( ~char ; ~charToTrim ) ) ; 11 | TrimWhitespaceLeft ( Right ( text ; Length ( text ) - 1 ) ) ; 12 | text 13 | ) 14 | ) 15 | 16 | /* __________________________________________________ 17 | 18 | NAME: TrimWhitespaceLeft ( text ) 19 | PURPOSE: Removes leading whitespace from text. 20 | EXAMPLES: 21 | TrimWhitespaceLeft ( "¶ ¶text¶" ) = "text¶" 22 | HISTORY: 23 | 2013-09-27 12:13 PT - Donovan Chandler 24 | */ -------------------------------------------------------------------------------- /URLHash.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | pos = Position ( url ; "#" ; 1 ; 1 ) 3 | ] ; 4 | If ( 5 | pos > 0 ; Middle ( url ; pos ; Length ( url ) ) 6 | ) 7 | ) 8 | 9 | /* __________________________________________________ 10 | 11 | NAME: URLHash ( url ) 12 | PURPOSE: Returns hash portion of URL. Used for extracting info from web viewer. 13 | Web viewer must be referencing an external file for you to alter the url. 14 | Use GetLayoutObjectAttribute ( "wv_object" ; "sournce" ) to get the url. 15 | EXAMPLES: 16 | URLHash ( "file://tmp/page.html#paramForScript" ) = "paramForScript" 17 | HISTORY: 18 | Created: 2012-04-27 10:12 PST - Donovan Chandler 19 | Modified: 20 | */ -------------------------------------------------------------------------------- /URLParam.calc: -------------------------------------------------------------------------------- 1 | TextBetween ( url & "&" ; name & "=" ; "&" ; 1 ) 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: URLParam ( url ; name ) 6 | PURPOSE: Retrieves parameter value from url. 7 | Doesn't parse or decode full url because OnTimer script usually handles that. 8 | EXAMPLES: 9 | URLParam ( "http://domain.com#animal=dog&food=donuts%20" ; "food" ) = "donuts%20" 10 | HISTORY: 11 | Created: 2012-06-21 16:00 PST - Donovan Chandler 12 | Modified: 13 | */ -------------------------------------------------------------------------------- /URLSelf.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | ~isHosted = PatternCount ( Get ( HostApplicationVersion ) ; "Server" ) 3 | ] ; 4 | "fmp://" & 5 | If ( ~isHosted ; PathStripPrefix ( Get ( FilePath ) ) ; "$/" & Get ( FileName ) ) & 6 | If ( Length ( script ) ; "?script=" & script & If ( Length ( parameter ) ; "¶m=" & parameter ) ) 7 | ) 8 | 9 | /* __________________________________________________ 10 | 11 | NAME: URLSelf ( script ; parameter ) 12 | PURPOSE: Returns fmp:// url for calling script in current FileMaker file. 13 | EXAMPLES: 14 | 15 | HISTORY: 16 | Created: 2012-04-27 11:56 PST - Donovan Chandler 17 | Modified: 2014-04-03 14:05 PDT - Donovan Chandler : Incorporate Will M. Baker's mods for FMP 13.0v3 support for local references. 18 | */ -------------------------------------------------------------------------------- /UserIsFullAccess.calc: -------------------------------------------------------------------------------- 1 | Get ( AccountPrivilegeSetName ) = "[Full Access]" 2 | 3 | /* __________________________________________________ 4 | 5 | NAME: UserIsFullAccess ( ) 6 | PURPOSE: Returns True if user has full access privileges 7 | HISTORY: 8 | Created: 2012-09-12 PST -27 16h16 PST — Donovan A. Chandler 9 | */ -------------------------------------------------------------------------------- /VarAssign.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | names = VarAssignLoop ( encodedString ; listOfParams ) ; 3 | error = If ( IsEmpty ( names ) ; 0 ; 10 ) 4 | ] ; 5 | If ( 6 | error ≠ 0 ; 7 | Let ( [ 8 | count = ValueCount ( names ) ; 9 | str = Substitute ( names ; ¶ ; ", " ) ; 10 | msg = "Missing/invalid parameter" & If ( count > 1 ; "s" ) 11 | & ": " & str ; 12 | v = VarSet ( "_invalid_params" ; names ; "t" ; False ) ; 13 | v = VarSet ( "_error_message" ; msg ; "t" ; False ) 14 | ] ; 15 | "" 16 | ) 17 | ) 18 | & error 19 | ) 20 | 21 | /* __________________________________________________ 22 | 23 | NAME: VarAssign ( encodedString ; listOfParams ) 24 | PURPOSE: Instantiates variables from dictionary, with optional type casting and validation. 25 | EXAMPLES: See VarAssignMan() for documentation. 26 | HISTORY: 27 | Created: 2012-03-16 09:15 PST - Donovan Chandler 28 | Modified: 29 | */ -------------------------------------------------------------------------------- /VarAssign.fmfn: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | _S = If ( GetAsBoolean ( isGlobal ) ; "$$" ; "$" ) ; 3 | exError = "IsEmpty ( " & _S & name & ")" 4 | ] ; 5 | Evaluate ( 6 | "Let([" & _S & name & "=" & Quote ( value ) & "];" & exError & ")" 7 | ) 8 | ) 9 | 10 | /*--------------------------------------------------------------------------------------- 11 | NAME: 12 | VarSet ( name ; value ; isGlobal ) 13 | 14 | PURPOSE: 15 | Instantiates local or global variable 16 | 17 | HISTORY: 18 | Created 2008-Sep-24 — Donovan Chandler 19 | 20 | OUTPUT: 21 | Assigns local or global variable, returning "1" if variable is empty (else 0) 22 | 23 | EXAMPLE: 24 | VarSet ( "_tab_list" ; "tab_1" ; 1 ) = 0, sets $$_tab_list to "tab_1" 25 | VarSet ( "_tab_list" ; "" ; 1 ) = 1, = 1, sets $$_tab_list to null 26 | ---------------------------------------------------------------------------------------*/ -------------------------------------------------------------------------------- /VarAssignWithLog.fmfn: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------- 2 | •••• INCOMPLETE •••• 3 | 4 | NAME: 5 | var.assignWithLog( name; value; global; nameOfVariableLog ) 6 | Version 1.2 7 | 8 | PURPOSE: 9 | Instantiates local or global variable according to parameters 10 | 11 | HISTORY: 12 | Created 2010.06.04 by DChandler 13 | 14 | INPUT: 15 | name: Name of variable (text string) 16 | value: Value of variable (text string) 17 | global: (Boolean) - True creates variable as global 18 | 19 | OUTPUT: 20 | Assigns local or global variable, returning "1" if variable is empty (else 0) 21 | ---------------------------------------------------------------------------------------*/ 22 | 23 | Let([ 24 | _log = nameOfVariableLog 25 | ; _S = Case( global; "$$"; "$" ) 26 | ; _var = _S & name 27 | ; exError = "IsEmpty( " & _var & ") or " & _var & "=\"?\"" 28 | ]; 29 | Evaluate( "Let([" & 30 | _var & "=" & Quote(value) & ";" & 31 | "$$" & _log & "= $$" & _log & " & " & Quote( _var ) & " & " & "\¶" & 32 | "]; " & exError & " )" 33 | ) 34 | ) -------------------------------------------------------------------------------- /VarInvalid.calc: -------------------------------------------------------------------------------- 1 | VarInvalidLoop ( 2 | listOfVariables ; 3 | 1 ; 4 | PatternCount ( listOfVariables ; ¶ ) + 1 ; 5 | "" 6 | ) 7 | 8 | /* —————————————————————————————— // 9 | NAME: 10 | VarInvalid( listOfVariables ) 11 | 12 | PURPOSE: 13 | Returns list of names of variables containing invalid data 14 | 15 | EXAMPLES: 16 | (Where $_table = "CONTACT" and $_field = "") 17 | 18 | VarInvalid ( "$_table¶$_field" ) = "$_field" 19 | VarInvalid ( $_table & ¶ & $_field ) = "$_field" 20 | VarInvalid ( $_table & $_field ) = "" 21 | VarInvalid ( List ( $_table ; $_field ) ) = "" // CAUTION!!! 22 | 23 | HISTORY: 24 | Created: 2010-Aug-20 16h07 PST — Donovan A. Chandler 25 | 26 | NOTES: 27 | Be careful using the List() function with this; it will remove lines that contain no value. So this will not catch an error: 28 | VarValidate( List ( $_table ; $_field )) = 0 29 | */ -------------------------------------------------------------------------------- /VarInvalidLoop.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | var = GetValue ( listOfVariables ; rep ) ; 3 | value = 4 | Case ( 5 | Left ( var ; 1 ) = "$" ; Evaluate ( var ) ; 6 | var 7 | ) ; 8 | invalid = ( value = "?" or IsEmpty ( value ) ) ; 9 | newResults = If ( invalid ; List ( previousResults ; var ) ) 10 | ] ; 11 | 12 | Case ( 13 | rep < repMax ; 14 | VarInvalidLoop ( listOfVariables ; rep + 1 ; repMax ; newResults ) ; 15 | newResults 16 | ) 17 | ) 18 | 19 | /* —————————————————————————————— // 20 | NAME: 21 | VarInvalidLoop ( listOfVariables ; rep ; repMax ; previousResults ) 22 | 23 | PURPOSE: 24 | Performs recursion for VarInvalid () 25 | 26 | EXAMPLES: 27 | 28 | 29 | HISTORY: 30 | Created: 2010-Aug-20 16h07 PST — Donovan A. Chandler 31 | */ -------------------------------------------------------------------------------- /VarValidate.calc: -------------------------------------------------------------------------------- 1 | VarValidateLoop ( 2 | listOfVariables ; 3 | 1 ; 4 | PatternCount ( listOfVariables ; ¶ ) + 1 5 | ) 6 | 7 | /* —————————————————————————————— // 8 | NAME: 9 | VarValidate( listOfVariables ) 10 | 11 | PURPOSE: 12 | Returns count of variables with invalid data 13 | 14 | EXAMPLES: 15 | (where all variables contain values other than "?") 16 | 17 | VarValidate( "$_table¶$_field" ) = 0 18 | VarValidate( $_table & ¶ & $_field ) = 0 19 | VarValidate( "¶¶" ) = 1 20 | VarValidate( List ( $_empty_var ; $_good_var )) = 0 // CAUTION!!! 21 | 22 | HISTORY: 23 | Created: 2010-Aug-20 16h07 PST — Donovan A. Chandler 24 | 25 | NOTES: 26 | Be careful using the List() function with this; it will remove lines that contain no value. So this will not catch an error: 27 | VarValidate( List ( $_empty_var ; $_good_var )) = 0 28 | */ -------------------------------------------------------------------------------- /VarValidate2.calc: -------------------------------------------------------------------------------- 1 | Let([ 2 | //-- Increment counter 3 | $$_fn_varvalidate_rep = $$_fn_varvalidate_rep + 1; 4 | _rep = $$_fn_varvalidate_rep; 5 | 6 | _var = GetValue( listOfVariables; _rep ); 7 | _value = 8 | Case( 9 | Left( _var; 1 ) = "$"; Evaluate( _var ); 10 | _var 11 | ); 12 | _var_count = PatternCount( listOfVariables; ¶ ) + 1 13 | ]; 14 | //-- Add 1 if current value is invalid 15 | Case( 16 | _value = "?" or IsEmpty( _value ); 17 | 1; 18 | 0 19 | ) + 20 | //-- Iterate thru other values 21 | Case( 22 | _rep < _var_count; 23 | var.validate( listOfVariables ); 24 | Let($$_fn_varvalidate_rep = ""; 0 ) 25 | ) 26 | ) 27 | 28 | /* —————————————————————————————— // 29 | NAME: 30 | var.validate( listOfVariables ) 31 | 32 | PURPOSE: 33 | Returns count of variables with invalid data 34 | 35 | EXAMPLES: 36 | (where all variables contain values other than "?") 37 | 38 | var.validate( "$_table¶$_field" ) = 0 39 | var.validate( $_table & ¶ & $_field ) = 0 40 | 41 | HISTORY: 42 | Created: 2010-Aug-20 16h07 PST — Donovan A. Chandler 43 | */ -------------------------------------------------------------------------------- /VarValidateLoop.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | var = GetValue ( listOfVariables ; rep ) ; 3 | value = 4 | Case ( 5 | Left ( var ; 1 ) = "$" ; Evaluate ( var ) ; 6 | var 7 | ) ; 8 | invalid = ( value = "?" or IsEmpty ( value ) ) 9 | ] ; 10 | 11 | //-- Add 1 if current value is invalid 12 | Case( 13 | value = "?" or IsEmpty( value ); 14 | 1; 15 | 0 16 | ) + 17 | 18 | //-- Iterate thru other values 19 | Case ( 20 | rep < repMax ; 21 | VarValidateLoop ( listOfVariables ; rep + 1 ; repMax ) 22 | ) 23 | ) 24 | 25 | /* —————————————————————————————— // 26 | NAME: 27 | VarValidateLoop ( listOfVariables ; rep ; repMax ) 28 | 29 | PURPOSE: 30 | Performs recursion for VarValidate () 31 | 32 | EXAMPLES: 33 | 34 | 35 | HISTORY: 36 | Created: 2010-Aug-20 16h07 PST — Donovan A. Chandler 37 | */ -------------------------------------------------------------------------------- /WebNavHeader.calc: -------------------------------------------------------------------------------- 1 | If ( 2 | not IsHosted ; 3 | "path to exported file" ; 4 | 5 | "Data:text/html," & 6 | WebNavHeaderSub ( 7 | CodeMerge ( "‡‡CODE[1]‡‡" ) ; 8 | FOCUS::HEADER_LABELS ; 9 | ". nav . header" ; 10 | FOCUS::HEADER_INSTRUCTIONS 11 | ) 12 | ) 13 | 14 | /* __________________________________________________ 15 | 16 | NAME: WebNavHeader 17 | PURPOSE: Generates HTML for navigation header in web viewer. 18 | NOTES: 19 | HISTORY: 20 | Created: 2012-04-14 14:15 PST - Donovan Chandler 21 | Modified: 22 | */ -------------------------------------------------------------------------------- /WebViewerFieldDisplay.calc: -------------------------------------------------------------------------------- 1 | "data:text/html, ¶ " & GetAsCSS ( text ) & "" /* __________________________________________________ NAME: WebTextDisplay ( text ; fontSize ; customCSSForAllElements ) PURPOSE: Displays text in web viewer. EXAMPLES: WebTextDisplay ( TextColor ( TABLE::FIELD ; RGB ( 255 ; 0 ; 0 ) ) ; 10 ; "font-family:Verdana;¶" ) => Displays field contents in red, 10pt Verdana HISTORY: Created: 2011-09-14 13:58 PST - Donovan A. Chandler */ -------------------------------------------------------------------------------- /Weekdays.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | startDay = DayOfWeek ( startDate ) ; // startDate's day of the week 3 | rawRange = endDate - startDate + 1 ; // how many days there are between and inclusive of the two dates 4 | rawWeekendDays = Floor ( rawRange / 7 ) * 2 ; // weekend days included in full weeks 5 | modRange = Mod ( rawRange ; 7 ) ; // days left over, not part of full weeks 6 | modWeekendDays = Case ( 7 | startDay = 1 and modRange > 0 ; 1 ; 8 | modRange > ( 8 - startDay ) ; 2 ; 9 | modRange = ( 8 - startDay ) ; 1 ; 10 | 0 11 | ) ; // weekend days included in the leftover days 12 | weekendDays = rawWeekendDays + modWeekendDays // total weekend days 13 | ] ; 14 | 15 | rawRange - weekendDays 16 | 17 | ) 18 | 19 | /* —————————————————————————————— // 20 | NAME: 21 | Weekdays ( startDate ; endDate ) 22 | 23 | PURPOSE: 24 | Return the number of weekdays in and inclusive of the range, excluding Saturdays and Sundays. 25 | 26 | EXAMPLES: 27 | Weekdays ( 10/11/2010 ; 10/20/2010 ) = 8 28 | Weekdays ( 10/16/2010 ; 10/25/2010 ) = 6 29 | 30 | HISTORY: 31 | Created: 2010-Oct-12 13h51 PST — Will M. Baker 32 | */ -------------------------------------------------------------------------------- /WindowGetMeasurements.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | clear = GetAsBoolean ( clearMeasurements ) ; 3 | $$_window_orig_height = If ( clear ; "" ; Get ( WindowHeight ) ) ; 4 | $$_window_orig_width = If ( clear ; "" ; Get ( WIndowWidth ) ) ; 5 | $$_window_orig_top = If ( clear ; "" ; Get ( WIndowTop ) ) ; 6 | $$_window_orig_left = If ( clear ; "" ; Get ( WindowLeft ) ) 7 | ] ; 8 | "" 9 | ) 10 | 11 | /* —————————————————————————————— // 12 | NAME: 13 | WindowGetMeasurements ( clearMeasurements ) 14 | 15 | PURPOSE 16 | Measures location and dimensions of current window for use by WindowSetMeasurements() 17 | 18 | HISTORY: 19 | Created 2009.08.13 by Donovan Chandler 20 | 21 | INPUT: 22 | clearMeasurements: "False" or Null will set measurements. "True" will clear all variables instantiated by this function. 23 | 24 | OUTPUT: 25 | Global Variables 26 | */ -------------------------------------------------------------------------------- /calc.hideInvalid.calc: -------------------------------------------------------------------------------- 1 | If ( IsValid ( calculation ) ; calculation ) 2 | 3 | /* —————————————————————————————— // 4 | NAME: 5 | calc.hideInvalid ( calculation ) 6 | 7 | PURPOSE: 8 | Returns null if calculation result is invalid. Useful for hiding empty chart headers. 9 | 10 | EXAMPLES: 11 | 12 | 13 | HISTORY: 14 | Created: 2010-Jun-11 20h31 PST — Donovan A. Chandler 15 | */ -------------------------------------------------------------------------------- /calc_PythonSendMail.calc: -------------------------------------------------------------------------------- 1 | /* __________________________________________________ 2 | 3 | NAME: PythonSendMailScript ( ) 4 | PURPOSE: Stores python script for use in bBox plug-in. 5 | See http://bbox.beezwax.net/ for plug-in details. 6 | HISTORY: 7 | Created: 2013-10-25 12:36 PT - Donovan Chandler 8 | Modified: 2013-11-19 17:06 PT - Donovan Chandler : optinal text body and debug level. 9 | */ 10 | 11 | 12 | -------------------------------------------------------------------------------- /calc_StripDisk.calc: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | ~path = "" ; 3 | ~drive = Get ( SystemDrive ) ; 4 | ~driveStart = Position ( ~path ; ~drive ; 1 ; 1 ) 5 | ] ; 6 | If ( 7 | ~driveStart = 0 ; ~path ; 8 | "/" & Middle ( ~path ; ~driveStart + Length ( ~drive ) ; Length ( ~path ) ) 9 | ) 10 | ) -------------------------------------------------------------------------------- /calc_getApplicationVersion.calc: -------------------------------------------------------------------------------- 1 | /*-- Application is Pro, Runtime, or Go --*/ 2 | 3 | Let ( [ 4 | ~app = Get ( ApplicationVersion ) 5 | ] ; 6 | Position ( ~app ; "Pro" ; 1 ; 1 ) 7 | //a or Position ( ~app ; "ProAdvanced" ; 1 ; 1 ) 8 | or Position ( ~app ; "Runtime" ; 1 ; 1 ) 9 | or Position ( ~app ; "Go" ; 1 ; 1 ) 10 | ) 11 | 12 | /* 13 | Application versions (minus version number): 14 | - Pro // FileMaker Pro 15 | - ProAdvanced // FileMaker Pro Advanced 16 | - Runtime // FileMaker Runtime 17 | - FileMaker Web Publishing // FileMaker Web Client 18 | - Web Publishing Engine // FileMaker Server Web Client 19 | - xDBC // xDBC Client 20 | - Server // FileMaker Server 21 | - Go // FileMaker Go on the iPhone or iPod touch 22 | - Go_iPad // FileMaker Go on the iPad 23 | */ -------------------------------------------------------------------------------- /dev.getScriptName.txt: -------------------------------------------------------------------------------- 1 | Let([ 2 | _script_prefix = scriptPrefix; 3 | 4 | _script_list = ScriptNames( Get( FileName ) ); 5 | _found_list = list.filterCustom ( _script_list; "BeginsWith"; _script_prefix; False ) 6 | 7 | ]; 8 | GetValue ( _found_list; 1 ) 9 | ) 10 | 11 | 12 | /* —————————————————————————————— // 13 | NAME: 14 | dev.getScriptName ( scriptPrefix ) 15 | 16 | PURPOSE: 17 | Returns name of script based on prefix 18 | 19 | EXAMPLES: 20 | dev.getScriptName ( "001" ) = "001 Script Template" (if such a script exists) 21 | 22 | DEPENDENCIES: 23 | List.filterCustom() 24 | 25 | HISTORY: 26 | Created: 2010-May-25 16h33 PST — Donovan A. Chandler 27 | */ -------------------------------------------------------------------------------- /dev.layoutNamesPrefixed.calc: -------------------------------------------------------------------------------- 1 | Let([ 2 | _layouts = LayoutNames( Get( FileName ) ) 3 | ]; 4 | ListFilterCustom( _layouts; "BeginsWith"; layoutPrefix; 0 ) 5 | ) 6 | 7 | /* —————————————————————————————— // 8 | NAME: 9 | LayoutNamesPrefixed ( layoutPrefix ) 10 | 11 | PURPOSE: 12 | Returns list of layouts beginning with specified prefix. 13 | 14 | EXAMPLES: 15 | 16 | 17 | HISTORY: 18 | Created: 2010-Aug-11 00h13 PST — Donovan A. Chandler 19 | 20 | DEPENDENCIES: 21 | Custom Functions: list.custom 22 | */ -------------------------------------------------------------------------------- /nav.measureWindow.fmfn: -------------------------------------------------------------------------------- 1 | Let ( [ 2 | clear = GetAsBoolean ( clearMeasurements ) ; 3 | $$_window_orig_height = If ( clear ; "" ; Get ( WindowHeight ) ) ; 4 | $$_window_orig_width = If ( clear ; "" ; Get ( WIndowWidth ) ) ; 5 | $$_window_orig_top = If ( clear ; "" ; Get ( WIndowTop ) ) ; 6 | $$_window_orig_left = If ( clear ; "" ; Get ( WindowLeft ) ) 7 | ] ; 8 | "" 9 | ) 10 | 11 | /* __________________________________________________ 12 | 13 | NAME: NavMeasureWindow() 14 | PURPOSE: Measures location and dimensions of current window for use by NavSetWindowSettings() 15 | EXAMPLES: 16 | NavMeasureWindow( ) // sets window measurements to global vars 17 | NavMeasureWindow( False ) // clears global vars 18 | HISTORY: 19 | Created: 2009-08-13 16:02 PT - Donovan Chandler 20 | Modified: 2013-03-06 16:02 PT - Donovan Chandler : reformatted; changed var names; no longer uses Evaluate on boolean input. 21 | */ -------------------------------------------------------------------------------- /plugin.dialogResults.calc: -------------------------------------------------------------------------------- 1 | SDialog_Get ( data_selector ; optional_data ) 2 | 3 | /* —————————————————————————————— // 4 | NAME: 5 | DialogResult ( data_selector ; optional_data ) 6 | 7 | PURPOSE: 8 | Performs all calls to Simple Dialog function, SDialog_Get(). 9 | Contains plug-in references for future changes. 10 | 11 | EXAMPLES: 12 | 13 | 14 | HISTORY: 15 | Created: 2010-May-26 14h53 PST — Donovan A. Chandler 16 | */ -------------------------------------------------------------------------------- /sqlList.calc: -------------------------------------------------------------------------------- 1 | Case ( 2 | IsEmpty ( listToDelimit ) ; "" ; 3 | "(" & SqListLoop ( listToDelimit ) & ")" 4 | ) 5 | 6 | /* __________________________________________________ 7 | 8 | NAME: SqList ( listToDelimit ) 9 | PURPOSE: Converts return-delimited list into comma-delimited list of quoted strings. 10 | Useful for IN clauses in SQL statements. 11 | EXAMPLES: 12 | SqList ( "dog¶cat\¶mouse" ) = "('dog','cat¶mouse')" 13 | HISTORY: 14 | Created: 2011-10-26 16:23 PT - Donovan A. Chandler 15 | */ -------------------------------------------------------------------------------- /test.compareFields.calc: -------------------------------------------------------------------------------- 1 | Let([ 2 | _field_cur = GetFieldName ( Self ); 3 | _field_comp = "UNIT_OF_INCIDENT_SELECTED::MANUF_YEAR" 4 | ]; 5 | Self ≠ Evaluate ( _field_comp ) 6 | ) 7 | 8 | /* —————————————————————————————— // 9 | NAME: 10 | 11 | 12 | PURPOSE: 13 | 14 | 15 | EXAMPLES: 16 | 17 | 18 | HISTORY: 19 | Created: 2010-Jun-25 13h02 PST — Donovan A. Chandler 20 | */ -------------------------------------------------------------------------------- /test.sortDisplay.calc: -------------------------------------------------------------------------------- 1 | Let([ 2 | _field = fieldName; 3 | _rep = displayFieldRepetition; 4 | _isDescending = If ( _rep = 2; 1; 0 ); 5 | _sortedFieldName = UIN_FOCUS::GT_SORT_FIELD_NAME; 6 | _sortedDescending = UIN_FOCUS::GN_SORT_DESCENDING_FLAG; 7 | 8 | _table = ExtractTableName ( _field ); 9 | _index = TableIndex( _table ); 10 | _sort_field = GetRepetition( _sortedFieldName; _index ); 11 | _sort_desc = GetRepetition( _sortedDescending; _index ) 12 | ]; 13 | Case( 14 | _field = _sort_field and 15 | _sort_desc = GetAsBoolean( _isDescending ); 16 | 1 17 | ) 18 | ) 19 | 20 | /* —————————————————————————————— // 21 | NAME: 22 | test.sortDisplay( fieldName; displayFieldRepetition ) 23 | 24 | PURPOSE: 25 | Returns True if specified field is being sorted 26 | 27 | EXAMPLES: 28 | test.sortDisplay( 29 | GetFieldName( ERD_COMPANY::NAME ); 30 | 1 31 | ) returns True if sort is by Name ascending 32 | 33 | HISTORY: 34 | Created: 2010-Aug-20 12h49 PST — Donovan A. Chandler 35 | */ -------------------------------------------------------------------------------- /web.dataStore.calc: -------------------------------------------------------------------------------- 1 | "Data:text/html," & ¶ & 2 | "" & ¶ & 3 | "¶" 6 | 7 | /* —————————————————————————————— // 8 | NAME: 9 | WebDataStore ( dataString; backgroundColor ) 10 | 11 | PURPOSE: 12 | Stores text in hidden webviewer for retrieval. 13 | 14 | EXAMPLES: 15 | WebDataStore( 16 | #( "TABLE" ; "CONTACT" ) & #( "FILTER_TABLE"; "POPUP" ) 17 | "RGB( 249,249,249 )" 18 | ) 19 | Creates webviewer with a gray background. 20 | 21 | To Use: 22 | #Value( 23 | GetLayoutObjectAttribute( "webviewer_name" ); 24 | "TABLE" 25 | ) = "CONTACT" 26 | 27 | HISTORY: 28 | Created: 2010-Sep-06 10h00 PST — Donovan A. Chandler 29 | 30 | NOTES: 31 | Best practice is to place the webviewer in the bottom-right, or bottom-left corner and on a white background so that it is inconspicuous while loading. 32 | Retrieve dataString using GetLayoutObjectAttribute( "webviewer_name"; "content" ). 33 | Webviewer is hidden using background color. 34 | backgroundColor param can be passed any CSS-valid value, so words like "white" are also supported. 35 | */ -------------------------------------------------------------------------------- /xml.transform.fmfn: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------------- 2 | NAME: 3 | xml.transform( xmlSource; addCharacters ) 4 | 5 | PURPOSE: 6 | Adds or removes replacement characters that aid in XML parsing 7 | 8 | HISTORY: 9 | Created 2008.12.16 by DChandler 10 | 11 | INPUT: 12 | xmlSource: Text string in XML format 13 | addCharacters: Boolean - True adds transformation, False removes it 14 | 15 | OUTPUT: 16 | xmlSource with ">" characters replaced with "‡>". This allows tags to be parsed easily with or without the presence of attributes 17 | ---------------------------------------------------------------------------------------*/ 18 | 19 | Case( 20 | Evaluate( addCharacters ); 21 | 22 | // Add search characters 23 | Substitute( xmlSource; [" "; "‡"]; ["‡>"; ">"]; [">"; "‡>"]; [""; ">"]; ["‡"; " "]; ["≤/"; " True 19 | xml.verify( ""; False ) -> False 20 | xml.verify( "Error 101: Invalid Path"; False ) -> False 21 | xml.verity( "value"; False ) -> True 22 | ---------------------------------------------------------------------------------------*/ 23 | 24 | Let( 25 | [ 26 | //xmlResult = xmlResult 27 | //; useNullValues = useNullValues; 28 | 29 | bnError = ( Left( xmlResult; 5 ) = "Error" ) 30 | ; bnNull = IsEmpty( xmlResult ) 31 | ; bnInvalid = bnError or Case( Evaluate( useNullValues ); bnNull; 0 ) 32 | ]; 33 | not bnInvalid 34 | ) --------------------------------------------------------------------------------