Script: Copy as CSV

This script copies the selected rows in Bike into a CSV format on the pasteboard.


To test in Script Editor.app,

  • set the language selector at top left to JavaScript (rather than AppleScript)
  • copy and past the whole of the script behind the expansion triangle below,
  • select some lines in Bike
  • and click Run.
Expand disclosure triangle to view JS Source
var bikeApp = Application("Bike")

bikeApp.includeStandardAdditions = true

var document = bikeApp.documents.at(0)
var zip = (a, b) => a.map((k, i) => [k, b[i]])

var ancestors = []
var results = []
var selectedRows = document.rows.where({selected: true})()

for (each of selectedRows) {
	const eachLevel = each.level()
	
	while (ancestors.length > 0 && ancestors[ancestors.length - 1].level() >= eachLevel) {
		ancestors.pop()
	}
	
	ancestors.push(each)
	
	if (!each.containsRows()) {
		let line = []
		for (eachAncestor of ancestors) {
			let eachName = eachAncestor.name()
			let eachEscapedName = eachName.replace(/"/g, '""')
			line.push('"' + eachEscapedName + '"')
		}
		results.push(line.join())
	}
}

bikeApp.setTheClipboardTo(results.join('\n'))

results

Using Scripts - Bike

2 Likes

and a minor variant for a slightly different context – CSV for the full path to each selected row that is:

  1. not empty, and
  2. either childless or collapsed
Expand disclosure triangle to view JS source
(() => {
    "use strict";

    // Ver 0.03

    // CSV of full path to each leaf or collapsed row
    // that is selected.
    // Returned and copied to clipboard.
    const main = () => {
        const doc = Application("Bike").documents.at(0);

        return doc.exists() ? (() => {
            const
                csvLeafPaths = selectedUILeaves(doc)
                .map(csvOfFullRowPath)
                .join("\n");

            return (
                Object.assign(
                    Application.currentApplication(),
                    {includeStandardAdditions: true}
                )
                .setTheClipboardTo(csvLeafPaths),
                csvLeafPaths
            );
        })() : "No documents open in Bike.";
    };

    // --------------------- BIKE ---------------------

    // csvOfFullRowPath :: Row -> CSV String
    const csvOfFullRowPath = row =>
        pathToRow(row)
        .slice(1)
        .map(x => `"${x.name().replace(/"/ug, "\"\"")}"`)
        .join(",");


    // pathToRow :: Bike Row -> [Bike Row]
    const pathToRow = row => {
        // Ancestral path from root row to given row.
        const
            go = x => null !== x
                ? [...go(x.containerRow()), x]
                : [];

        return go(row);
    };


    // selectedUILeaves :: Bike Document -> IO [Row]
    const selectedUILeaves = doc =>
    // Rows in the selection which not empty
    // and are either leaves or collapsed parents.
        doc.rows.where({
            selected: true,
            _not: [{name: ""}],
            _or: [
                {containsRows: false},
                {collapsed: true}
            ]
        })();

    // MAIN ---
    return main();
})();

( testing and use as above )

2 Likes