Tinderbox Forum

Tinderbox Training Video 31 - Integrating Export Code & Action Code in Your Text

Tinderbox Training Video - Integrating Export Code & Action Code in Your Text

Level Advanced
Published Date 2/12/21
Tags Tinderbox, aTbRef, 4Cs of Knowledge Exchange, Export Code, Action Code
Video Length 07:59
Video URL https://youtu.be/5ynL1LgpLzA
Example File TBX - L Integration Export Code & Action Code in Your Text.tbx (153.6 KB)
Revision 1
TBX Version 8.9
Instructor Michael Becker

In this lesson, I explain how you can use export code and action code together, in a note’s $Text, to pull attribute values from other notes into the note you’re working on. There are all kinds of applications for this, such as building a table to contents, pulling in key points from other notes, etc. I recently used it to pull in a list of milestones from a project into a project summary report. This is a super great way of pulling all your hard-earned insight into one place so that you can contribute them to the world.

TBX - L Integrating Export Code & Action Code in Your Text

Reference Material


I found this very helpful — I’d never really seen a use (for me) for action codes so I’d practically ignored them, but the video has given me some ideas for a project I’m working on, which I wouldn’t otherwise have considered.

Many thanks!

1 Like

Oh! This not makes me soooo happy. :). Thanks for taking the time to provide feedback. Would you mind sharing any details on your project? I’d love to learn more.

Don’t hesitate to shoot over any questions if you have them. I have so many more tips and tricks up my sleeve, just not enough time to create more videos. I get inspired by the communities comments and questions.

It’s just a day book: a single ‘header note’ per note, with individual logs as child notes, all in markdown format. At the end of the day, the day and children are exported to single markdown file with appropriate headers, and the file in indexed in Devonthink. That all works fine, but the code you’ve described looks like it will be useful for, say, a TOC, or to add all the links in the child notes in markdown format.

At the moment the header note starts off in DT3, because I have an AppleScript which populates it with weather conditions, a quote and national and local headlines. I haven’t worked out how to do that in Tinderbox — the weather shouldn’t be too difficult (Jack Baty has a script to do) but I’m not sure about the quotation and headlines. I haven’t looked at it seriously yet, though.

Thanks again.

Depending on your sources you might be able to use the autofetech() action script or a watch folder. Please do share, I love this idea. I was thinking it would be cool to pull in the word of the day, but have not gotten around to do it.

1 Like

Just wanted to pop in here and say a big thanks to @satikusala for this video.

I figured out how to create a stamp that (1) traverses all the descendants of a given note, (2) makes a list of the tags those descendants, and (3) assign all those tags to the (in this case) grandparent note’s $Tags.

In my case, I’m using TB for QDA and the grandparent notes are participants, the parents are data items, and the children are data extracts. The extracts have tags and I want those to bubble up so I can see all the different tags for a given participant. This is something I’ve been stumped by, not even sure where to start, but the explanations of the code in this video allowed me to apply it to a different problem and make headway.

Thanks, Michael!


Question about creating bulleted lists of note attributes… is there a way to have the bullets $MyList creates contain more than one attribute? For example:

<ol>...<li>$Name ($Tags)</li>...</ol>

<li> ^value($Name) ... $value($Tags() </li>

This may be the task’s way of suggesting to you that you really want a table, not a list:

<td> ^value($Name) </td>
<td> ^value($Tags) </td>

A table would be great for other purposes, though I really do want a list this time.

Mark, what would I query to get two variables in $MyList?

Simply add two ^value() clauses instead of one, separated by a space so the values don’t run together.

Hmmm… I get how to pull multiple values, but how to get them in a $MyList?

Here’s some code that queries my file and gets me an ordered list (per Michael’s example):
^action($MyList=collect_if(descendants(this),$Prototype=="Data Extract",$Name);$MyList=$MyList.format("<ol>","<li>","</li>","</ol>");)^

And then I get that list by:

What do I add to the query to grab $Name and $Tags for any given “Data Extract?”

Beck, there might be a more efficient way to accomplish what you want to do? Are you looking to create a bulleted list that looks like this:

  • Becker, Privacy
  • Mark, Developer
  • Peter, Engineer

And then, do you want it in the body of a specific not surrounded by some text, i.e. embedded as include, or represented in some other way? In other words, can you create a quick example (hand-drawn picture is fine) as to what you want you output to look like and where your data is coming from?

How about

$MyList=collect_if(descendants(this),$Prototype==“Data Extract”,$Name+","+$OtherAttribute)


Got it! I tried that at first and it did not work. I must have had a typo. Beck, this works in the example:

^action($MyList=collect_if(descendants("Key points"),$Prototype!="pNotes",$Name+", "+$Point);$MyList=$MyList.format("<ol>","<li>","</li>","</ol>");)^

Output is this:
List attributes for Key points.

  1. Point 1, Interesting idea 1
  2. Point 2, Interesting idea 2
  3. Point 3, Interesting idea 3
  4. Point 4, Interesting idea 4
  5. Point 5, Interesting idea 5
  6. Sub-point of 5,

This works! In my code example:

^action($MyList=collect_if(descendants(this),$Prototype=="Data Extract",$Name+", "+$Tags);$MyList=$MyList.format("<ol>","<li>","</li>","</ol>");)^ ^value($MyList)^

Now, to get those items with multiple tags formatted well… stay tuned!


BTW, I think it is important to remember that all this export code need not be done in the note itself, it can also be integrated into export templates, its natural home. Just another amazing point about Tinderbox’s flexibility.

1 Like

Yes! This was a realization I made yesterday!


Twisting the ideas in this thread a little further, I’m trying to turn the concepts into a Table of Contents to be exported in Markdown format, incorporating links to the actual header.

E.g. I export a note with children to a markdown file, and at the top of the file there’s a TOC with clickable links to the child sections (which have to be in the format [Heading name](#heading-name))

Using the code in this thread so far, I have:

^value((collect(descendants(this),"[" +$Name+"](#"+$Name.lowercase.replace(" ","-")+")")).unique.format("","- ","\n",""))^

This produces:

- "[Daily Notes](#daily-notes)"

- "[Markdown image links redux](#markdown-image-links-redux)"

- "[Another note](#another-note)"

As you can see, the problem is that it surrounds each line with unwanted quotation marks, and I can’t see where they’re coming from.

If I replace the string concatenation with $Name on its own, there are no quotation marks and it turns out as expected:

^value((collect(descendants(this),$Name)).unique.format("","- ","\n",""))^


- Daily Notes
- Markdown image links redux
- Another note

If I take the concatenation out of the action code and preset it into a calculated attribute ($TOCtitle), so the collect is calling an simple attribute rather than constructing the string on the fly, I still get the unnecessary quotation marks — so why is this different from calling another string $Name?

I must be missing something obvious, but I can’t see what it is…

Thanks for any help (and thanks very much for all the great ideas in the thread so far. It’s expanded my knowledge and ambitions hugely…)

OK, the cause is the parentheses () in the literal string sections of the collect(). It has nothing to do with attribute called AFAICT. This is easily proven if you change the from () to {}. Now the content exports OK, without the quotes but with the wrong type of brackets.

I made a wrong call here, fixed/explained further below. I’ll leave my error in strike-through so the thread doesn’t get confusing. But, my sincere apologies to @eastgate

I tried escaping the parentheses in the original code, i.e. \( and \) but that still resulted in quoted output. I then used the curly bracket substitution and a pair of replace calls to the overall formatted list. IOW after the .format() call. I tried with and without escaping of the parentheses, here with escape code:


No joy. It seems in both context—within collect() and within .replace()—you can’t seemingly use literal parentheses without getting an incorrect result. FWIW, I did a lot more testing but I won’t bore all with detail of things that didn’t work around the issue.

I would note, in fairness, that IIRC until recently collect() was only used for pulling a single attribute value from each note in the designated group rather than creating strings.

@eastgate, is this result to be expected. I had assumed that \( would cause Tinderbox to treat a parenthesis symbol as a literal and not a closure around an input or subordinate clause.

My error with .replace() was to forget that it is the first input term was is a regex. Unfortunately, the made me overlook the fact that the curly brackets needed escaping, like so:


Sorry, everyone. An updated demo file with additional code resolving this issue is further below.

1 Like

Hi, Mark,

Thanks for the explanation! I’d been doing some more digging and had just found this in atbref, (I had it ready to post when I saw your reply…) so I was beginning to suspect it was the parentheses.


If the collected attribute type is multi-value, i.e. Set or a List type, collect() adds its elements to the result. If the collected attribute is not a Set or List type attribute, but contains a semicolon, quotation mark, or parentheses, the value will be added to the result as a quoted string. The change should correct a variety of confusing edge cases.

There are always going to be odd cases where regular expressions don’t work, and this is a fairly niche case, perhaps.

I suppose the next question is, is there a way to build the list of bullet points without using collect or replace?

Something like (conceptually):

while there are still children
$TOCtext = $TOCtext + "- [" + child($Name) +  "](" + child($AmendedName) + ")\n"

only using syntax that actually exists… I’ve never used repeat loops in Tinderbox, so I’m off to look at atbref again, but I suspect it will fail because there’ll have to be a set, list or replace() in there somewhere…