Plug-In: Append Copied Spreadsheet Apple Vision Pro

If you wish to include formatted spreadsheet data in the note of a project or task, here’s a plug-in that will append the copied spreadsheet data to the note of the selected item using the user-indicated tab formatting.

REQUIREMENTS:

TIPS:

Spreadsheet data in note spreadsheet-parameters-illustration

Return to: OmniFocus Plug-In Collection

Append Copied Spreadsheet
   

/*{ "type": "action", "targets": ["omnifocus"], "author": "Otto Automator", "identifier": "com.omni-automation-of.append-copied-spreadsheet", "version": "1.0", "description": "Creates a table using the copied spreadsheet data and appends it to the note of the selected project or task. NOTE: Both row and column headers are required to be included within the copied data.", "label": "Append Copied Spreadsheet", "shortLabel": "Append Spreadsheet", "paletteLabel": "Append Spreadsheet", "image": "tablecells" }*/ (() => { var preferences = new Preferences() // NO ID = PLUG-IN ID var shouldLog = true function checkLengths(rowData){ x = rowData[0].length for (i = 1; i < rowData.length; i++) { if(rowData[i].length !== x){return false} } return true } const action = new PlugIn.Action(async function(selection, sender){ try { selectedItem = selection.databaseObjects[0] // RETRIEVE CLIPBOARD TEXT tabbedText = Pasteboard.general.string // DIVIDE INTO ARRAYS OF ROW DATA copiedData = tabbedText.split('\n').map(line => line.split('\t')) if(shouldLog){console.log("copiedData", copiedData)} // CHECK LENGTH OF EVERY ROW checkResult = checkLengths(copiedData) if(!checkResult){ throw { name: "Data Integrity Issue", message: "Not all rows have the same number of columns." } } // PREFERENCES tabStopIndex = preferences.readNumber("tabStopIndex") if(!tabStopIndex){ preferences.write("tabStopIndex", 5) tabStopIndex = 5 } headerTabTypeIndex = preferences.readNumber("headerTabTypeIndex") if(!headerTabTypeIndex){ preferences.write("headerTabTypeIndex", 1) headerTabTypeIndex = 1 } dataTabTypeIndex = preferences.readNumber("dataTabTypeIndex") if(!dataTabTypeIndex){ preferences.write("dataTabTypeIndex", 2) dataTabTypeIndex = 2 } tabStopWidthIndex = preferences.readNumber("tabStopWidthIndex") if(!tabStopWidthIndex){ preferences.write("tabStopWidthIndex", 5) tabStopWidthIndex = 5 } firstTabStopIndex = preferences.readNumber("firstTabStopIndex") if(!firstTabStopIndex){ preferences.write("firstTabStopIndex", 5) firstTabStopIndex = 5 } // CREATE AND PRESENT FORM numTabStopOptions = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12] numTabStopNames = ["3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] numTabStopsMenu = new Form.Field.Option( "tabStopCount", "Number of Data Columns", numTabStopOptions, numTabStopNames, tabStopIndex ) tabTypesOptions = [0, 1, 2, 3] tabTypesNames = ["Left-Aligned", "Center-Aligned", "Right-Aligned", "Decimal-Aligned"] tabTypesIndicators = ["L", "C", "R", "D"] headerTabTypesMenu = new Form.Field.Option( "headerTabType", "Column Headers Tab Type", tabTypesOptions, tabTypesNames, headerTabTypeIndex ) dataTabTypesMenu = new Form.Field.Option( "dataTabType", "Data Columns Tab Type", tabTypesOptions, tabTypesNames, dataTabTypeIndex ) tabStopWidthsOptions = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] tabStopWidthsNames = ["28", "36", "48", "56", "64", "72", "84", "96", "112", "128", "140", "168", "196", "212", "224"] tabStopWidthsMenu = new Form.Field.Option( "tabStopWidth", "Distance Between Tabs (points)", tabStopWidthsOptions, tabStopWidthsNames, tabStopWidthIndex ) firstTabStopOffsetOptions = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] firstTabStopOffsetNames = ["0", "16", "32", "48", "64", "72", "96", "112", "128", "144", "160", "176", "192", "208", "224", "240"] firstTabStopOffsetMenu = new Form.Field.Option( "firstTabOffset", "Width of Row Headers Column (points)", firstTabStopOffsetOptions, firstTabStopOffsetNames, firstTabStopIndex ) inputForm = new Form() inputForm.addField(headerTabTypesMenu) inputForm.addField(dataTabTypesMenu) inputForm.addField(numTabStopsMenu) inputForm.addField(tabStopWidthsMenu) inputForm.addField(firstTabStopOffsetMenu) formPrompt = "Formatting for copied spreadsheet:" buttonTitle = "Continue" formObject = await inputForm.show(formPrompt,buttonTitle) // RETRIEVE USER-PROVIDED SETTINGS columnCount = formObject.values["tabStopCount"] if(shouldLog){console.log("columnCount", columnCount)} headerTabTypeIndex = formObject.values["headerTabType"] headerTabTypeIndicator = tabTypesIndicators[headerTabTypeIndex] if(shouldLog){console.log("headerTabTypeIndicator", headerTabTypeIndicator)} dataTabTypeIndex = formObject.values["dataTabType"] dataTabTypeIndicator = tabTypesIndicators[dataTabTypeIndex] if(shouldLog){console.log("dataTabTypeIndicator", dataTabTypeIndicator)} tabStopWidthIndex = formObject.values["tabStopWidth"] tabStopWidth = tabStopWidthsNames[tabStopWidthIndex] if(shouldLog){console.log("tabStopWidth", tabStopWidth)} firstTabStopIndex = formObject.values["firstTabOffset"] firstTabOffset = firstTabStopOffsetNames[firstTabStopIndex] if(shouldLog){console.log("firstTabOffset", firstTabOffset)} // WRITE VALUES TO PREFERENCES preferences.write("tabStopIndex", columnCount) preferences.write("headerTabTypeIndex", headerTabTypeIndex) preferences.write("dataTabTypeIndex", dataTabTypeIndex) preferences.write("tabStopWidthIndex", tabStopWidthIndex) preferences.write("firstTabStopIndex", firstTabStopIndex) // CONVERT TO NUMERIC VALUES tabStopWidthValue = parseInt(tabStopWidth) firstTabOffsetValue = parseInt(firstTabOffset) // EXTRACT AND REMOVE THE FIRST DATA ROW columnHeaders = copiedData.shift() // TAB STOPS FOR COLUMN HEADERS ROW columnHeaderTabStops = String(firstTabOffsetValue) + headerTabTypeIndicator for (i = 1; i < columnCount; i++) { columnHeaderTabStops += "," + String(firstTabOffsetValue + (i * tabStopWidthValue)) + headerTabTypeIndicator } console.log(columnHeaderTabStops) // TAB STOPS FOR CONTENT ROWS contentTabStops = String(firstTabOffsetValue) + dataTabTypeIndicator for (i = 1; i < columnCount; i++) { contentTabStops += "," + String(firstTabOffsetValue + (i * tabStopWidthValue)) + dataTabTypeIndicator } console.log(contentTabStops) console.log(JSON.stringify(columnHeaders)) console.log(JSON.stringify(copiedData)) // CREATE PARENT TEXT OBJECT tableTextObj = new Text("", baseStyle) // CREATE TEXT OBJECT FOR COLUMN HEADERS ROW columnHeadersStr = columnHeaders.join('\t') txtObj = new Text(columnHeadersStr, baseStyle) txtObj.style.set(Style.Attribute.ParagraphTabStops, columnHeaderTabStops) txtObj.style.set(Style.Attribute.ParagraphDefaultTabInterval, tabStopWidthValue) // ADD COLUMN HEADERS ROW TO PARENT TEXT OBJECT tableTextObj.append(txtObj, baseStyle) // CREATE A NEW LINE TEXT OBJECT newLineObject = new Text("\n", baseStyle) // APPEND DATA ROWS TO PARENT TEXT OBJECT for (indx in copiedData){ aRow = copiedData[indx] aRowStr = aRow.join('\t') txtObj = new Text(aRowStr, baseStyle) txtObj.style.set(Style.Attribute.ParagraphTabStops, contentTabStops) txtObj.style.set(Style.Attribute.ParagraphDefaultTabInterval, tabStopWidthValue) tableTextObj.append(newLineObject, baseStyle) tableTextObj.append(txtObj, baseStyle) } // APPEND PARENT OBJECT TO ITEM NOTE noteObj = selectedItem.noteText noteObj.append(tableTextObj, baseStyle) } catch(err){ if(!err.causedByUserCancelling){ console.error(err.name, err.message) new Alert(err.name, err.message).show() } } }); action.validate = function(selection, sender){ singleItemIsSelected = ( selection.databaseObjects.length === 1 && selection.projects.length === 1 || selection.tasks.length === 1 ) return (Pasteboard.general.hasStrings && singleItemIsSelected) }; return action; })();