How to remove in export code name and tags appearing in text

I need to modify notes when exported to csv, keeping their complete versions in Tinderbox. More specifically, I would like to remove all occurrences of the name and tags of each note in their respective texts.

I have achieved how to hide the occurrences of the name of each note in its text, and to export only the second paragraph of each note if it has more than one:

"^value($Name)^","^if(Text.paragraphCount>1)^^value($Text.paragraph(1).replace($Name,"XXX"))^^else^^value($Text.replace($Name,"XXX"))^^endIf^"

I have also created a working action to hide tags in text:

$MyList=;$Tags.each(TagItem){$MyString=$MyList+TagItem;$Text=$Text.replace($MyString,"XXX");$MyString=;}

But I don’t want to modify the note itself, but the text exported to csv.

I am unable to traduce the latter to export code and, moreover, combine it with the previous one. Any help?

Not time to test just now (late here), but look at ^action()^.

I did read about ^action^ but, if I understood it well, it will modify the notes themselves, not just what gets exported to csv, as I want.

Thanks and no hurry :grinning:

No, ^action()^ does not necessarily alter the note any more than working internally. What it does do is allow you to run action code within the context of a template. Thus you might use action at the top of the template to load a processed string into an attribute, use the value of the string, then reset the attribute at the end. Net result no change. In pseudocode terms, in the template:

^action($MyString= processed list output)^
...normal template code...
^value($MyString)^
...rest of template code...
^action($MyString=;)^

At the beginning and end of the note using the template $MyString is the default empty value, no other attribute or notes are affected.

Make a small test file to experiment before trying on your actual data.

Won’t an ^action^ load only one of the values from the iteration of .each() into ^value^?

At least that is what seems to happen they way I have implemented it:

"^value($Name)^","^action($MyString=;$MyList=;$Tags.each(TagItem){$MyString=$MyList+TagItem})^^value($Text.replace($MyString,"XXX"))^^action($MyString=;$MyList=;)^"

If the above is correct, is there another way to modify the text exported without modifying its note of origin?

Thanks again for your help.

Let’s unpack that:

^action(
$MyList=;
$Tags.each(TagItem){
    $MyString=$MyList+TagItem
}
)^

Which would indeed do as you describe. I think you mean to do this (indented, etc., only for clarity here):

^action(
$MyList=;
$Tags.each(TagItem){
    $MyList=$MyList+TagItem
};
$MyString=$MyList;
)^

now, $MyList will add items each loop of the .each(). After all items in $Tags are processed only then do you pass to $MyString. Ay that latter point you can also change the format. Default will be “ant;bee;cow” but you might do:

$MyString=$MyList.format(", ");

…and get a $MyString of “ant, bee, cow”.

Does that help?

I wonder if I have conveyed well the outcome I expect -and can get as an action, but not in export code. I am not looking for a list of tags in any format.

Let’s say I have a note containing the following text by Chesterton -to make the example more interesting, though it’s not the case:

People wonder why the novel is the most popular form of literature; people wonder why it is read more than books of science or books of metaphysics

That note has novel, science and metaphysics among its tags. I would like the text exported to be (without modifying the text of the note stored in Tinderbox):

People wonder why the XXX is the most popular form of literature; people wonder why it is read more than books of XXX or books of XXX

It will be much easier to test against a common example. Could you please post a small TBX doc with notes showing the start, the intended outcome and an example of where you are (i.e. code you’ve used)? Put any other explanatory info in other notes, then it’s all in one place.

Well if not in $Tags, then where? I only referred to that attribute because you used it in your previous code example. Or are you saying that note might have more tags, but you only want the ones in text (bit harder, or rather slower to process but probably do-able)?

There seem to be some hidden assumptions here, which is why i suggest to move to testing a common model. Please don’t read that as a negative, it is just sometimes easier to see the problem rather than read a description of it. :grinning:

I don’t need the tags of the note exported to csv. What I want exported is the text of the note, with each of its words that match any tags of the note substituted with XXX. And this only in the exported csv, whilst the original note remains intact.

I will certainly prepare a TBX sample later in the day. Thanks for your patience.

1 Like

Aha. I look forward to the TBX, but it sounds like your`^action()^ should be this:

^action(
$MyString=$Text;
$Tags.each(TagItem){
    $MyString=$MyString.replace(TagItem,"XXX");
};
)^

You then use the eventual value of $MyString, before clearing the attribute at the end of the template. $Text is unaffected. Note that .replace() is case-sensitive.

N.B. not tested, it may be using a a loop var in a .replace() operation may not work (untested levels/degree of nested evaluation).

1 Like

That’s it, and it’s working!

Thank you so much for your last input, as well as for the previous ones. They are also valuable for me to go through their outcomes and attempt to understand how they are constructed.

As for a case insensitive version of .replace(), I see it was discussed in the forum as a possible feature request. Here I have adapted a previous solution that works -presumably except when the first character is a capital accented character, as reported in this topic.

I attach a sample file.

Export with text replacement.tbx (106.9 KB)

The rabbit hole here is there isn’t an easy way to do a case-insensitive replace where the match string is is the loop variable.

I’m buried thesis writing, but perhaps a lurker could step in an help with trying a query back-reference, where instead of using just replace you do something like (untested!):

$MyString=$Text;
$Tags.each(TagItem){
    if($MyString.icontains(TagItem){
        $MyString=$MyString.replace("$1","XXX");
    };
};

I’m not sure (thus, test!) if a loop variable can be used in .contains() and I don’t recall if it is quoted or not as a parameter (I’d assume not, lest it the var name be considered a string leteral leading to an erroneous (non-)match).

I can see all sorts of edge cases here, e.g. where the case-insensitive match string is a substring of a word. In that case you might want a the replace match to be "\b$1\b" where \b is a word boundary.