Can Drafts get a bunch of entries in a Workspace and create a CSV or Plaint text file tab separated?

So I have a workspace setup to create flash cards in the format as follows:

The first line is the question or statement and this corresponds to Column A in the CSV and the bottom part is the answer or statement and this corresponds to Column B.

That’s how I draft them. So the question I have is if I could select separate drafts note from the same workspace and spit out a CSV formatted to two columns as I described above from all the entries selected that look like so


Yep. Seems do-able to me.

Is your first line always a single line? Is there always a line of space between your question (first line) and answer? Is the answer always a single line/paragraph?

I’m not in Drafts javascript headspace, but it should be reasonably easy to create an action that gets the content of a draft and converts the line space to a comma draft.content.replace(“\n\n”,”,”). If you include some script to append the output to the clipboard (or append to a specific draft instead) you could run this on a range of selected drafts and compile as many rows of CSV as you need…

It’s definitely possible. It requires scripting, but once you are scripting you can pretty much do anything to manipulate text. CSV files are just plain text formatted in the proper way, so can be written by Drafts FileManager object.

Do you have any scripting experience?

1 Like

Ah— your post says CSV, your title says TSV. Should be able to do either, just make sure you set your separator appropriately.

@crownandbridge, this is definitely something that could be scripted. Here’s a very crude version of said script that you can adapt to your specific use case if you’ve got scripting knowledge.

let workspace = Workspace.find("Flash Cards");
let drafts = workspace.query("all");
let csvText = "";
for (let d of drafts) {
    let content = d.content.split("\n");
    let question = content[0];
    let answer = content[2];
    csvText += "\"" + question + "\"," + answer + "\"" + "\n";

let fmLocal = FileManager.createLocal(); // Local file in app container
let success = fmLocal.writeString("/flash.csv", csvText);

Hope this helps

Is your first line always a single line? Is there always a line of space between your question (first line) and answer?

Always 1 space from the question to answer it could be 2 space as well

Is the answer always a single line/paragraph?

the questions can be multiline as well and so can the answer.

Excellent news ! No, no experience with Scripting but I"m willing to pay anyone for such a script a reasonable amount though.

CSV thanks so much !!

Here’s another example

So the goal is to create the cards as described above and then select whatever number of drafts created probably anywhere from 1-100 drafts notes at a time and then have a CSV exported to whatever folder it wants eg. download or whichever desktop, any folder will work.

And as I mentioned above and I more than willing to pay for a functioning script. Now there’s an idea for @agiletortoise a sort of Drafts marketplace if there is such a demand for that. Regardless, if anyone can reach out, we can come to agreement and I can remit payment via PayPal to anyone who provides me such a script.

Thanks guys/gals

Later tonight I’ll share a modified version of the action I posted for you to test. The version I posted above basically does everything you need but isn’t well tested and could have bugs.


Thank you, yes I did test it but it gave me an error. I basically highlighted two notes and ran the action and it came back with an error code. I’ll update this post in an 1hr with the screenshot. Thank you

It did work !! it produced a flash.csv as your wrote for the entire workspace which I created based on your code called Flash cards and it workspace.query (“all”)

I’ll setup a clean workspace now to see how it literally handle it with 3 notes. It would be great if it scanned for a tag ie. csv and matched to the workspace so then one can just untag the already CSV’d items. thanks

I’ve actually bundled this code within a shareable action here. It’s still not great code, but there’s a short description and I can tweak based on feedback. I can definitely change the code to work based on scanning for a tag if you’d like, but the initial request was based on a workspace. It’s a trivial change. Personally I like the Workspace model a bit better. The workspace can be set to search for everything with that tag!

Additionally, I changed to code to only look in the Inbox. After it finishes executing, it gives you the option to archive all those drafts.

1 Like

@motopascyyy thanks, let me try this one now.

It worked like a charm !! @motopascyyy just like you coded. Now, if I can filter the Workspace for the tag called csv it would be grand, that way it looks at the said workspace scans for the tag csv and outputs the csv file as you coded.

Amazing work, if you have patron account or something similar I love to buy you a few cups of coffee as they or beer.


I’ve updated the action. It now allows you to define the workspace and the output filename in the action itself and if for whatever reason you haven’t defined the 2 values, it will let you know.

Regarding patreon etc, I don’t have one setup. I’m just happy to help. Feel free to pay it forward, buy a random person a cup of coffee as a random act of kindness or donate a few bucks to your preferred charity.

1 Like

@motopascyyy thank you !! I will test it this evening and will certainly pay it back.

So I tried and followed your instructions and here are the results.

I first setup the following as instructed.

and here’s the other template tag

Here’s the workspace

and I get this


So I’m not sure what it asking in the error message.

The first action step defines the variable workspace.

let workspace = draft.getTemplateTag("flashcard_workspace");

The third action step then attempts to redefine it.

let workspace = Workspace.find(workspaceName);

That’s not allowed, and that’s let doing its job of not allowing it within the same scope - they are both defined at the top level of the script and so apply across the whole script.

Those two variables, and their subsequent use, need to use unique variable names.

I thought I had fixed that before publishing. I will fix later today. Thanks @sylumer for catching