Trigger script referencing and changing a field in a linked entry in another library

1,207 views
Skip to first unread message

Keith P

unread,
Mar 24, 2021, 1:07:51 AM3/24/21
to memento...@googlegroups.com
Hello all,  
   I've searched through the forum and wiki, bit haven't found what I'm looking for.

I have an Inventory library, an Acquisitions library, and an Expenditures library.  I'm trying to set up a trigger script in the Acquisitions and Expenditures libraries that will increase or decrease the Total Count field in the linked entry of the Inventory library.

I can see how to call a library with the libByName(), but I haven't seen a way to reference a field in another library. Also, how would I set the value of that field in the other library. 

Thank you
Keith

Gilles Mons

unread,
Mar 24, 2021, 3:28:24 AM3/24/21
to Keith P, mementodatabase
Hello Keith,

Here are several solutions:

To modify one or more field (s) without modifying the others:
X1 (script modifying one or more fields in X2)

X2
---‐-----------------------------------------

Make stock movements:

Stock v2.2 English (Android only) 

Components for Stock v2.2



--
You received this message because you are subscribed to the Google Groups "mementodatabase" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mementodataba...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/mementodatabase/CACDFz-stTMP7q-JDA3aS7dVqiGW0eRJs5Getu82xv-nNdGrZFg%40mail.gmail.com.

Er Mo

unread,
Mar 24, 2021, 2:02:53 PM3/24/21
to mementodatabase
Hallo Keith
Sie sind schon auf den Richtigen Weg . Sie Rufen die bibliothek auf -> Holen sich alle Einträge ->Suchen nach den gewünschten Eintrag -> Überschreiben den Eintrag .

Hi keith
You are already on the right track. You call up the library -> Get all entries -> Search for the desired entry -> Overwrite the entry.

Gilles Mons

unread,
Mar 24, 2021, 3:11:59 PM3/24/21
to Er Mo, mementodatabase
Hello Er Mo,

No it is not necessary to overwrite the recording .....

With the following script I discovered how to modify a field found in another database, without recovering the initial data, erasing them, then saving them again....

For me this script is the great saint of MDB....

I'll share it with you all, the trick is in the for loop....


Hallo Er Mo, Nein, die Aufnahme muss nicht überschrieben werden....

Mit dem folgenden Skript habe ich herausgefunden, wie ein in einer anderen Datenbank gefundenes Feld geändert werden kann, ohne die ursprünglichen Daten wiederherzustellen, zu löschen und dann erneut zu speichern.

Für mich ist dieses Skript der große Heilige von MDB....

Ich werde es mit euch allen teilen, der Trick ist in der for-Schleife..

var e = entry();
//X2 eng Table
var LBNx2 = libByName("X2 eng");
var entriesx2 = LBNx2.entries();
var l2 = entriesx2.length;
//X1 eng Table
var name1 = e.field("Name 1");

//
for ( var i=0;((i<l2)&&(name1 != name2));i++)
{

var name2 = entriesx2[i].field("Name 2");

var id2 = entriesx2[i].id;

var record2ID = LBNx2.findById(id2);

var nomixe = entriesx2[i].field("nbr of modifications in X2 eng");

var newDate = new Date();

if ( name1 === name2 )
{
  record2ID.set("Result X1 in X2 eng",e.field("Result in  X1 eng"));

  record2ID.set("nbr of modifications in X2 eng",nomixe +1);

  record2ID.set("Last Update",newDate)
}

};


👍👍👍 😛 👍👍👍

Er Mo

unread,
Mar 24, 2021, 3:26:44 PM3/24/21
to mementodatabase
Hallo Gilles
Das ist wohl ein Übersetzungsfehler . Überschreiben = den vorhandenen Eintrag ersetzen oder Teile davon . Es wird NICHT der Eintrag gelöscht und mit den Neuen Daten ein Neuer Eintrag erstellt .

Bonjour Gilles
C'est probablement une erreur de traduction. Ecraser = remplacer l'entrée existante ou des parties de celle-ci. L'entrée n'est PAS supprimée et une nouvelle entrée est créée avec les nouvelles données.

Keith P

unread,
Mar 24, 2021, 3:31:22 PM3/24/21
to Gilles Mons, mementodatabase
Ok I got the Android beta so I can see the Stock v2.2 and components libraries.   It's gonna take me a while to look through that and understand what's going on.    

I still am unable to open the X1 and X2 libraries.  The android app says "You don't have permission to access this library", and the PC app says "The URL could not be found in Memento Cloud". 

Gilles Mons

unread,
Mar 24, 2021, 3:35:40 PM3/24/21
to Er Mo, mementodatabase
Er mo

Avec le script seul le ou les champs sont modifier, l'enregistrement reste le même (l'id ne change pas...)

Ont ne crée pas de nouvelles entrées, cela permet de :

Gérer un stock
Relevé les prix les moins chers...

Tester la base x1 et x2  et vous comprendrez...

Je crois que vous êtes sur PC, je suis pas sur que cela fonctionne mais sur Android sa fonctionne...


Er mo With the script only the field (s) are modified, the record remains the same (the id does not change ...)

Have not created new entries, this allows to: Manage a stock Recorded the cheapest prices ...
Test the base x1 and x2 and you will understand ...

I believe you are on PC, I'm not sure it works but on Android it works ...

Er mo Mit dem Skript werden nur die Felder geändert, der Datensatz bleibt gleich (die ID ändert sich nicht ...)

Haben Sie keine neuen Einträge erstellt, so können Sie: Verwalten Sie eine Aktie Die günstigsten Preise verzeichnet ...

Testen Sie die Basis x1 und x2 und Sie werden verstehen ...

Ich glaube, Sie sind auf dem PC, ich bin nicht sicher, ob es funktioniert, aber auf Android funktioniert es ...

Gilles Mons

unread,
Mar 24, 2021, 3:39:03 PM3/24/21
to Keith P, mementodatabase
Pardon Keith, c'est une erreur de ma part, je viens de les mettre en public, c'est bon...

Sorry Keith, it's a mistake on my part, I just put them in public, it's good ...

Gilles Mons

unread,
Mar 24, 2021, 3:50:32 PM3/24/21
to mementodatabase
Explication de la base X1 et X2

On crée un enregistrement dans X1, il est créé dans X2 jusque-là rien de compliqué...

Après on modifie l'enregistrement que l'on vient de créer dans X1, les champs correspondant dans x 2 sont mises à jour, sans que l'enregistrement soit recréer où qu'un nouvelle enregistrement soit créer, pour le prouver j'ai mis le champ id,que vous pouvez noté avant de faire la modification.....

Explanation of the base X1 and X2

We create a record in X1, it is created in X2 so far nothing complicated ... 

After we modify the record we just created in X1, the corresponding fields in x 2 are updated, without the record having to be recreated or a new record created, to prove it I put the id field, which you can write down before making the modification.....

Erklärung der Basis X1 und X2

Wir erstellen einen Datensatz in X1, er wird in X2 erstellt, bisher nichts Kompliziertes..

Nachdem wir den Datensatz geändert haben, den wir gerade in X1 erstellt haben, werden die entsprechenden Felder in x 2 aktualisiert, ohne dass der Datensatz neu erstellt oder ein neuer Datensatz erstellt werden muss, um zu beweisen, dass ich das ID-Feld eingefügt habe, das Sie notieren können vor der Änderung .....

Gilles Mons

unread,
Mar 24, 2021, 4:18:28 PM3/24/21
to mementodatabase
Pou ceux que sa intéresse voici les explications de la boucle for

for (i=0;.....
Sa c'est facile i=0 😁

.....((i<l)&&(name1 != name2));....
ont peux simplifier par

"tant que i est inférieur à la longueur du tableau et que name1 n'est pas égal à name2.."

....i++)
Ont incrément i (i+1)...

Voilà....

Franchement je suis trop comptent de moi, car on nous disez (jusqu'à aujourd'hui...😛) que ce n'était pas possible....

For those who are interested here are the explanations of the for loop
for (i = 0; ..... Its easy i = 0 😁

..... ((i <l) && (name1! = name2));...
can simplify by
"as long as i is less than the length of the array and name1 is not equal to name2 .." 

... i ++) 
Have increment i (i + 1) ...

Here....

Frankly I count too much of me, because we are told (until today ... 😛) that it was not possible ....

Für diejenigen, die hier interessiert sind, sind die Erklärungen der for-Schleife

für (i = 0; ..... Es ist einfach i = 0 😁

..... ((i <l) && (name1! = name2));....
kann vereinfachen durch
"Solange i kleiner als die Länge des Arrays ist und name1 nicht gleich name2 ist."
.... i ++) Inkrementiere i (i + 1) ...

Hier....

Ehrlich gesagt zähle ich zu viel von mir, weil uns (bis heute ... 😛) gesagt wird, dass es nicht möglich war ....

Gilles Mons

unread,
Mar 25, 2021, 12:46:32 AM3/25/21
to mementodatabase
Maintenant le prochain challenge pour moi depuis que l'on peut partager les scripts va être de créer une fonction pour simplifier tout ça et pouvoir modifier un ou plusieurs champs dans une ou plusieurs bases...

Bon codage à tous...

Gilles Mons

unread,
Mar 25, 2021, 10:00:42 AM3/25/21
to mementodatabase
Bonjour à tous....

Entre 2 dépannage, j'ai écrit une Fonction pour simplifier le script graal 😊

Voici 6 bases (3 en français, 3 en anglais) pour tester cette fonction...

Si vous avez besoin d'explications, n'hésitez pas....


Good morning all....

Between 2 troubleshooting, I wrote a Function to simplify the grail script 😊

Here are 6 bases (3 in French, 3 in English) to test this function..

If you need an explanation, do not hesitate ....

Français 
Test fonction

Résultat 1 de fonction

Résultat 2 de fonction

English
Fonction test

Fonction result 1

Fonction result 2


Keith P

unread,
Mar 27, 2021, 4:41:47 PM3/27/21
to Gilles Mons, mementodatabase
That seems like an interesting way to create new entries in another library or libraries.  What I'm trying to do is keep a sort of running total of widgets in one library based on a library of purchases and a separate library of expenditures. I am not seeing how I can use your script in my application. 
This is kind of what I'm working with.

"Widgets" this is the Inventory.
Important Field:
"Count"  the thing I'm trying to keep updated

"Widget Acquisitions" is the list of purchases.
Important Field: "Widgets Acquired"

"Widget Expenditures" is the list of widgets burned, skipped on the river, or put in a machine.
Important Fields: "Acquisition (attribute: Number Used)" or "Number Expended"

Sorry if anyone tries to take a look at these that are not in the Android Beta.  I don't know what to change to make it work with the stable version again. I already left the beta.

Keith


Gilles Mons

unread,
Mar 27, 2021, 10:43:04 PM3/27/21
to Keith P, mementodatabase
Bonjour Keith,

Maintenant que nous avons vos bases, que souhaitez vous faire exactement...

Peut-être avec un exemple 
A , B , C....


Hello Keith,

Now that we have your basics, what exactly do you want to do..

Maybe with an example A, B, C...

Gilles Mons

unread,
Mar 28, 2021, 2:14:25 AM3/28/21
to Keith P, mementodatabase
Keith,

Si j'ai bien compris ce que vous souhaitez faire est géré le stock de widgets...?

Les entrées et les sorties...?

Gilles Mons

unread,
Mar 28, 2021, 2:35:09 AM3/28/21
to Keith P, mementodatabase
KEITH,

Avez-vous besoin de compter les widgets entre B et C....?

Voir photo jointe....

KEITH,

Do you need to count widgets between B and C....?

See attached photo....
20210328_083323.jpg

Gilles Mons

unread,
Mar 28, 2021, 3:52:16 AM3/28/21
to Keith P, mementodatabase
Keith,

Ou souhaitez vous récupérer le calcul ? 

Or do you want to recover the calculation?

Gilles Mons

unread,
Mar 28, 2021, 4:12:09 AM3/28/21
to Keith P, mementodatabase
Comme je vois que vous travaillez sur vos bases mais que vous ne répondez pas à mes questions....

 je n'ai qu'une chose à vous dire:

vous allez avoir du mal à faire ce que vous souhaitez car vous n'avez pas de  champ(s) commun:

Dans la table widget:
Il n'y a pas de champ que l'on retrouve dans les deux autres tables....

Quand vous souhaiterais qu'on vous aide n'hésitez pas à répondre aux questions



As I see that you are working on your bases but that you do not answer my questions .... 
I only have one thing to tell you: you will have a hard time doing what you want because you don't have any common field (s):
In the widget table: There is no field found in the other two tables ....

When you would like us to help you, do not hesitate to answer the questions

Gilles Mons

unread,
Mar 28, 2021, 6:32:49 AM3/28/21
to Keith P, mementodatabase
Dans la table "Widget Acquisitions" vous créez un champ entier "test" et voici le code:

var e = entry();

// in Widgets
var A = libByName("Widgets");
var ent = A.entries();
var l = ent.length;

// in Widget Acquisitions
var bcB = e.field("Barcode");

for (var b in bcB )
var bcB2 = bcB[b].field("Barcode");

var wa = (e.field("Widgets / Box") * e.field("Boxes Acquired"))
;

for (var i=0;((i<l)&&(bcB2!=bcA));i++)

var bcA = ent[i].field("Barcode");

var countA = ent[i].field("Count");
{
if ( bcA === bcB2)
e.set("test",wa)

};

Gilles Mons

unread,
Mar 29, 2021, 12:15:12 AM3/29/21
to Keith P, mementodatabase
Voici le code pour copier la valeur de la base " Widgets Acqui " vers la base " Widgets ",
Dans un trigger script, en modification d'enregistrement 


Here is the code to copy the value of the "Acqui Widgets" database to the "Widgets" database, In a trigger script, modifying a record

var e = entry();

// in Widgets
var A = libByName("Widgets");
var ent = A.entries();
var l = ent.length;

// in Widget Acquisitions
var bcB = e.field("Barcode");

for (var b in bcB )
var bcB2 = bcB[b].field("Barcode");

var wa = (e.field("Widgets / Box") * e.field("Boxes Acquired"))
;

for (var i=0;((i<l)&&(bcB2!=bcA));i++)
{
var bcA = ent[i].field("Barcode");

var idA = ent[i].id;

var recordA= A.findById(idA)

if ( bcA === bcB2)

recordA.set("Count",wa)

};



--

Gilles Mons

unread,
Mar 29, 2021, 4:44:43 AM3/29/21
to Keith P, mementodatabase
For a trigger script, at creation, which will add the qtt to each widget stock entry you must do:

for (var i=0;((i<l)&&(bcB2!=bcA));i++)
{
var bcA = ent[i].field("Barcode");

var idA = ent[i].id;

var recordA = A.findById(idA)

var countA = recordA.field("Count")

if ( bcA === bcB2)

recordA.set("Count",countA+wa)
message (countA)
};

And the same creation script in the "expend widget" database but with "countA - wa" ...


Le mer. 24 mars 2021 à 06:07, Keith P <epee...@gmail.com> a écrit :
--

Keith P

unread,
Apr 1, 2021, 11:53:51 PM4/1/21
to mementodatabase

This is basically working.  Thanks!  I'd like to understand it better, because I might make some modifications. I've made some notes on the code of what I think it is doing.  Please let me know what I'm misunderstanding, and help me with the loops.

var e = entry();                                      // Calling this entry

// in Widgets
var A = libByName("Widgets");             
// The Widgets Library
var ent = A.entries();                             // A list of the entries in the Widgets Library
var l = ent.length;                                  // The number of entries in the Widgets Library?

// in Widget Acquisitions
var bcB = e.field("Barcode");                 // The Barcode field in the current entry

for (var b in bcB )                                  // Loop  of some kind?
var bcB2 = bcB[b].field("Barcode");      //  ???

var wa = (e.field("Widgets / Box") * e.field("Boxes Acquired"))   // Multiplying the Widgets per Box by the Boxes Acquired.
;

for (var i=0;((i<l)&&(bcB2!=bcA));i++)     // Loop checking the barcode field in the current entry against entries in the Widgets Library


{
var bcA = ent[i].field("Barcode");

var idA = ent[i].id;                                    // The entry id of the entry with a Barcode field matching the current entry

var recordA= A.findById(idA)                  // Finding the entry with the above id

if ( bcA === bcB2)                                   //  If the Barcode field of the entry in the Widgets library EXACTLY matches the Barcode field in the current entry then...
recordA.set("Count",wa)                        // In the Count field of the entry in the Widgets Library enter the (wa) Widgets Acquired value.

};


Thanks!


Gilles Mons

unread,
Apr 2, 2021, 12:29:49 AM4/2/21
to Keith P, mementodatabase
Vous pouvez essayer 

//for (var b in bcB) // Boucle d'une sorte?
var bcB2 = bcB /*[b] */.field ("Code-barres"); // ???

Cela fonctionne....

Je ne sais plus pourquoi j'ai écrit ça comme cela la fatigue sûrement....🤔

Explication de la boucle :

for (var i = 0; ((i <l) && (bcB2! = bcA)); i ++)

var i=0 // déclaration de la variable globale + initialisation de la variable à zéro

((i<l)&&(bcB2 !=bcBA)) // tant que i est inférieur à la taille du tableau et que bcB2 n'est pas égal bcBA ont continue

i++ // i+1 puis ont verifi la condition précédente...

J'espère avoir apporté quelques réponses...


You can try

// for (var b in bcB) // Loop of some sort? var bcB2 = bcB / * [b] * /. field ("Barcode"); // ???
It works....

I no longer know why I wrote it like that is surely tiring...

Explanation of the loop:
for (var i = 0; ((i <l) && (bcB2! = bcA)); i ++) var i = 0 // declaration of the global variable + initialization of the variable to zero

((i <l) && (bcB2! = bcBA)) // as long as i is less than the size of the array and bcB2 does not equal bcBA have continue

i ++ // i + 1 then have checked the previous condition ...

I hope I have provided some answers ...


--
You received this message because you are subscribed to the Google Groups "mementodatabase" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mementodataba...@googlegroups.com.

Gilles Mons

unread,
Apr 2, 2021, 12:37:55 AM4/2/21
to Keith P, mementodatabase
Je n'ai pas trop le temps maintenant mais ce weekend je vous expliquerai tout le code en essayant d'être le plus clair possible


I don't have much time now but this weekend I will explain all the code to you, trying to be as clear as possible

--
You received this message because you are subscribed to the Google Groups "mementodatabase" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mementodataba...@googlegroups.com.

Gilles Mons

unread,
Apr 2, 2021, 10:32:18 AM4/2/21
to Keith P, mementodatabase

J'ai un peux de temps alors voilà...

J'expliquerai ici que ce que je pense que vous n'avez pas compris ou compris partiellement....

var l = ent.length;                   
/* l = à la taille du tableau des entrées de la bibliothèque Widgets */

var wa = (e.field("Widgets / Box") * e.field("Boxes Acquired"))   /* on fait le calcul que vous faites dans votre champ "Widgets Acquired" mais on ne peut pas le récupérer car votre champ est un champ javascript, donc ont refait le calcul */

var idA = ent[i].id;

//ont peux comprendre: dans les entrées de la base Widgets[index de l'enregistrement, dans la boucle].identifiant mementodatabase

La chose importante à comprendre est que la condition dans la boucle "for" (bcB2 != bcA)doit être l'inverse de la condition du "if" ( bcA === bcB2)

Même si la variable bcA est déclarer après, ce n'est pas important, car nous la déclarons avec "var", si on l'avais déclarer avec "let" on aurais du la déclaré avant la boucle...

I have a little time so here ...

I will explain here that what I think you did not understand or partially understood .... var l = ent.length; / * l = the size of the Widgets library entry array * / 

var wa = (e.field ("Widgets / Box") * e.field ("Boxes Acquired")) / * we do the calculation you do in your "Widgets Acquired" field but we cannot retrieve it because your field is a javascript field, so have redone the calculation * / 

var idA = ent [i] .id;

// can understand: in the Widgets database entries [record index, in the loop]. mementodatabase identifier

The important thing to understand is that the condition in the "for" loop (bcB2! = BcA) must be the inverse of the condition in the "if" (bcA === bcB2)

Even if the variable bcA is declared after, it is not important, because we declare it with "var", if we had declared it with "let" we should have declared it before the loop ...

Keith P

unread,
Apr 3, 2021, 4:19:53 PM4/3/21
to Gilles Mons, mementodatabase
Ok so the if statement tells where to stop running the for loop.  

I'm still a little unclear about the for...in loop:

var bcB = e.field("Barcode");

for (var b in bcB )

var bcB2 = bcB[b].field("Barcode");

I'm reading the MDN web docs page about for...in loops, so b is assigned to the properties of the Barcode field in the current entry, right? So is this loop duplicating the Barcode field in the current entry with all it's properties (I don't know what those would be) and not just the value that is displayed in the library?  Why would you need to do that? I thought matching the value would be enough. 


Gilles Mons

unread,
Apr 3, 2021, 10:21:34 PM4/3/21
to Keith P, mementodatabase
hello Beith,

I wrote in a post: 
You can try 
" // for (var b in bcB) 
 var bcB2 = bcB / * [b] * /. field ("Barcode"); 
It works ....
I no longer know why I wrote it like that is surely tiring ... "

in other words you can write instead of the 2 lines
var bcB2 = bcB.field ("Barcode");

here is a script I wrote for example tables x1 and x2:

var e = entry();
//Base X2 fr
var LBNx2 = libByName("X2 fr");
var entréesx2 = LBNx2.entries();
var l2 = entréesx2.length;
//Base X1 fr
var nom1 = e.field("Nom 1");

//
for ( var i=0;((i<l2)&&(nom1 != nom2));i++)
{

var nom2 = entréesx2[i].field("Nom 2");

var id2 = entréesx2[i].id;

var enregistrement_x2= LBNx2.findById(id2);

var ndm = entréesx2[i].field("nbr de modifications");

var nouvDate = new Date();

if ( nom1 === nom2 )
{
enregistrement_x2.set("Résultat 2",e.field("Résultat 1"));

enregistrement_x2.set("nbr de modifications",ndm+1);

enregistrement_x2.set("Dernière Mise à Jour",nouvDate);
}

};

Bill Crews

unread,
Apr 4, 2021, 1:09:07 AM4/4/21
to Gilles Mons, Keith P, mementodatabase
Keith, keep in mind that the comment delimiters ... /*, */, and // ... are inseparable units. As I said before, / * something * / (note the spaces) gets a syntax error, because you're using a / divide operator, a * multiply operator, something, and then * and / operators again, making no sense.
Instead of those operators you want  /* (no space between) and */ delimiters (no space).

If you break them apart, it completely changes what they are. The same with relational operators, like <=, ==, ===, >=, and so on. Don't break them apart.

Spacing between them is a good thing, though, so good instinct there.

--
You received this message because you are subscribed to the Google Groups "mementodatabase" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mementodataba...@googlegroups.com.

Keith P

unread,
Apr 4, 2021, 3:37:38 PM4/4/21
to Gilles Mons, mementodatabase
Giles, When I replace the 2 lines with the new one I get an error.   Cannot execute script.....TypeError: Cannot find function field in object [].  I also tried skipping bcB2 and replaced it with bcB in the for loop.  That runs successfully.  What was the purpose of bcB2?

Gilles Mons

unread,
Apr 4, 2021, 9:52:39 PM4/4/21
to Keith P, mementodatabase
Désolé c'est une erreur de ma part vous devez écrire

Sorry it's an error on my part you should write

var bcB2 = e.field ("Barcode");

Keith P

unread,
Apr 23, 2021, 4:19:56 PM4/23/21
to Gilles Mons, mementodatabase
Thanks Bill, for recommending Grasshopper.  I'm working through that and it is helping.  
Question for anyone:
Is there a way for me to limit the choices of link to entries I see based on another link to choice? Specifically in the Expenditures library (link below),  When I choose the Inventory entry to link (ex. Tan cone widgets) , I want the choices in the Acquisitions link field to be limited to only those that share that same Inventory link (only Acquisitions of Tan cone widgets). 

I had a problem, but I think I solved it, you can read on if you're super interested....

Ok I think I'm getting close with the scripts in this group of Libraries.  I added a few things, but ran into a problem.  While trying to put a quantity check in a script in the Expenditure Library, I got an error message.
The libraries are still available at these links if it's easier:
A) Widgets (Inventory)   http://libs.mobi/s/zWmfOYz38 
B) Widget Acquisitions   http://libs.mobi/s/QakexQyrB
C) Widget Expenditures   http://libs.mobi/s/maE9XkVeN

 Changes:
• Added 'Widgets Remaining' field to the Acquisitions dB to keep track of when stock is gone but retain the quantity originally purchased
• Expenditures now deducts from the (Inventory) 'Count' AND the (Acquisitions) 'Widgets Remaining' fields
• Added 'Previous Value' field to the Acquisitions and Expenditures dBs which is used in case the entries are updated due to mistake or testing
• Added 'NEWcount' variable to the scripts in order to make conditional statements and messages to the user easier
• Added trigger scripts to Acquisions and Expenditures dBs for 'Creating before save' and 'Updating at open' phases
• I also added javascript 'Color' fields in the Inventory and Acquisitions dBs to help spot low stock items
• Started Annotating scripts

Problem:
I wanted a way to prevent making Expenditure entries that cause the 'Remaining' field in Acquisitions OR the 'Count' field in Inventory to drop below zero.   If I focus on the 'Remaining' field, that should also prevent the 'Count' from going negative.  So in the Update script I added this condition: 

if ( NEWcount < 0// Test if the new 'Widget Remaining' count will be negative...

message ("Number Expended exceeds Widgets Remaining. Canceling changes."); //Notify user
e.set("Number Expended", pv); // Reset Expended to previous value
e.set("Previous Value", ''); // Reset Previous to blank
exit(); // Stop running the trigger script. Entry will save with previous value and not change Inventory or Remaining fields in linked libraries.
}

This worked fine in the 'Update before save' script.  It modified the correct linked fields. I didn't get messages as if the script was trying to modify every Acquisitions and Inventory entry.

When I tried to move it over to the 'Creating before save' script the script was not working.  Before I stared mucking around the creating script was working.  Not sure what I did.  As I was writing this message, and continuing to troubleshoot so I could provide as much info here, I found I was missing the block brackets after an if test. 



Bill Crews

unread,
Apr 23, 2021, 5:10:38 PM4/23/21
to Keith P, Gilles Mons, mementodatabase
After a quick partial read of your message, I can suggest one thing. If you start with the original version of your Updating script and after copying it to become a Creating script, change your reference(s) to entry() to defaultEntry(), that might be all you have to do to get it to work.

--
You received this message because you are subscribed to the Google Groups "mementodatabase" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mementodataba...@googlegroups.com.

Keith P

unread,
Apr 23, 2021, 7:15:57 PM4/23/21
to Bill Crews, mementodatabase
I tried var e = defaultEntry() in my 'Creating before save' scripts, and in both places I have one, and the Run script tester says defaultEntry is undefined.

Also, I did a quick check of the Wiki and it seems a little contradictory.  Probably just an editing mistake.  

"if you needed for the Creating Script to be executed Before saving, you'll need to change defaultEntry() to use entry() instead"

later it says: 

"Creating scripts are different ....

Use the method defaultEntry(), rather than entry(), to get the DefaultEntry object (the unstored template, if you will, for the eventual Entry object)."

Bill Crews

unread,
Apr 23, 2021, 7:26:26 PM4/23/21
to Keith P, mementodatabase
Yes, the first one was backwards. I'll fix that right away. Thanks for taking me!

As for the undefined, please send a copy of your script.

Er Mo

unread,
Apr 24, 2021, 6:21:45 AM4/24/21
to mementodatabase
Hallo
Ich glaube es ist euch ein Fehler unterlaufen . Es müsste entryDefault() heisen und nicht defaultEntry()

Hello
I think you made a mistake. It should be entryDefault () and not defaultEntry ()

Bill Crews

unread,
Apr 24, 2021, 8:31:49 AM4/24/21
to Er Mo, mementodatabase
Yes, Ernst. Thanks for correcting me again. Yet another silly mistake on my part! I think it's about time to consider if I should continue trying to help people. I'm getting old for this.

Keith P

unread,
Apr 24, 2021, 9:55:38 PM4/24/21
to Bill Crews, mementodatabase
So I tried entryDefault() instead of defaultEntry().  It doesn't give any errors, but the script doesn't update the linked inventory entry and the Widgets Acquired value does not get copied to Widgets Remaining. It does work when I leave it as entry().

var e = entryDefault();


// in Widgets
var A = libByName("Widgets");

var ent = A.entries();
var l = ent.length;
// in Widget Acquisitions


var bcB = e.field("Barcode");
for (var b in bcB )
var bcB2 = bcB[b].field("Barcode");

var wa = e.field("Widgets Acquired");
e.set("Widgets Remaining",wa);
var wr = e.field("Widgets Remaining");

for (var i=0;((i<l)&&(bcB2!==bcA));i++)


{
var bcA = ent[i].field("Barcode");
var idA = ent[i].id;

var recordA = A.findById(idA);

var countA = recordA.field("Count");
var NEWcount = countA + wr;

if ( bcA === bcB2)

recordA.set("Count",NEWcount),
message ("Updated inventory count to " + NEWcount)
};


Er Mo

unread,
Apr 25, 2021, 2:47:06 AM4/25/21
to mementodatabase
Hallo
Das entryDefault() ist für Einträge die noch NICHT Existieren  . Man muss dabei darauf achten WANN das Skript ausgefürt wird . Bei " Vor den Speichern " und " Nach den Speichern " ist der Eintrag schon existent .

Hello
The entryDefault () is for entries that do not yet exist. You have to pay attention WHEN the script is executed. The entry already exists for "Before saving" and "After saving".

Keith P

unread,
Apr 25, 2021, 9:14:53 AM4/25/21
to Er Mo, mementodatabase
Really? Ok.  I thought for a Creating entry trigger it wouldn't exist until the save.  But then my script was working with entry().  Do you know when memento creates the entry? Is it as soon as a new one is opened? 

--
You received this message because you are subscribed to the Google Groups "mementodatabase" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mementodataba...@googlegroups.com.

Er Mo

unread,
Apr 25, 2021, 11:43:49 AM4/25/21
to mementodatabase
Hallo
Nein ich Weiss auch nicht mehr . Sind auch nur Vermutungen . Das könnte auch von Betribssystem abhängen und so die Unterschiede zwischen PC und Mobil erklären .

Hello
No, I don't know anymore either. Are only guesses. That could also depend on the operating system and thus explain the differences between PC and mobile.

Bill Crews

unread,
Apr 25, 2021, 2:00:06 PM4/25/21
to Er Mo, mementodatabase
Yes, based on what I'm hearing, it's not only the JDK & Memento user interface pages that change between mobile & desktop, but also substantive stuff like how & when Entry & DefaultEntry objects are instantiated. The more commonality the better, but I guess that stuff had to work differently in the desktop edition.

Gilles Mons

unread,
Apr 25, 2021, 2:57:58 PM4/25/21
to Keith P, mementodatabase
Keith,

Vous dite :

"When I tried to move it over to the 'Creating before save' script the script was not working."

Mais le champ pv est null à la création d'après mes essais !!


Keith,
You say :

"When I tried to move it over to the 'Creating before save' script the script was not working."

But the pv field is null at creation according to my tests !!

Bill Crews

unread,
Apr 25, 2021, 3:06:44 PM4/25/21
to Gilles Mons, Keith P, mementodatabase
Unless I'm blind, there is no pv field referenced in his script. In fact, none of the fields are abbreviations. What am I missing? A shared library with test field?

--
You received this message because you are subscribed to the Google Groups "mementodatabase" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mementodataba...@googlegroups.com.

Bill Crews

unread,
Apr 25, 2021, 3:21:13 PM4/25/21
to Er Mo, mementodatabase
Between now and Tuesday morning US (eastern daylight time), I'll be updating the wiki with a table of all trigger events, phases, execution modes, and the objects & functions to call in each case. Credit goes to Vasiliy & his people. I started the table from one already available in Memento Help. If I should compensate them for that, I'm sure I'll be hearing from them on that.

I'm also working on completion of a couple of pages in the triggers wiki that have existed as mere stubs for 4 years now!

EVERYONE! PLEASE => Update us by email whenever you run across errors of any size & kind in the wiki as well as any suggestions you might have for its improvement! Bill....@gmail.com & Beth.Ea...@gmail.comWhen we fix or enhance the wiki, everyone reading the wiki or forum will benefit!
The wiki has always been a user wiki, as I & now Beth are users. I'm very pleased Beth Dixon has joined me now administering the wiki, so please include both of us in your email.

Though I had always imagined the wiki to have many or at least several authors over time, I never reached out for that to happen. I guess I thought people would volunteer. We had one recent prospective author offering to join us, but Beth & I need some time to get my solo wiki playpen and Beth's materials into enough order to handle additional authors. BUT, we're working on it, so please stay tuned!


Gilles Mons

unread,
Apr 25, 2021, 4:05:37 PM4/25/21
to Bill Crews, Keith P, mementodatabase
Bill,

Dans le script de Keith du 23 avr. 2021 à 22:19 il y a un pv....

Keith,

Voici m'a proposition:
Les //☆ sont les modifications que je propose...

Bill,
In Keith's script from Apr 23, 2021 at 10:19 PM there is "... pv) ...."

Keith, Here is my proposition:
The // ☆ are the modifications that I propose ...

var e = entry();


// in Widgets
var A = libByName("Widgets");

var entA = A.entries();
var lA = entA.length;
// in Widget Acquisitions
var B = libByName("Widget Acquisitions");
var entB = B.entries();
var lB = entB.length;
// in Widget Expenditures
var bcC = e.field("Barcode");
for (var b in bcC)
var bcC2 = bcC[b].field("Barcode");
var acC = e.field("AcID");
for (var a in acC)
var acC2 = acC[a].field("AcID");
var we = e.field("Number Expended");

for (var r=0;((r<lB)&&(acC2!==acB));r++)
{
var acB = entB[r].field("AcID");
var idB = entB[r].id;
var recordB = B.findById(idB);

var countB = recordB.field("Widgets Remaining");

if ( acB === acC2 )
{
var NEWcount = countB - we;

if ( NEWcount < 0 )  // Test if the new 'Widget Remaining' count will be negative...

message ("Number Expended exceeds Widgets Remaining. Canceling changes."); //Notify user

e.set("Number Expended","");//☆ // Reset Expended to previous value
//☆e.set("Previous Value", ''); // Reset Previous to blank
exit(); // Stop running the trigger script. Entry will save with previous value and not change Inventory or Remaining fields in linked libraries.*/
}//☆
else//☆
{//☆
recordB.set(e2.field("Widgets Remaining"),NEWcount),
message ("Decreasing " + acB + " remaining count to " + NEWcount)

for (var i=0;((i<lA)&&(bcC2!==bcA));i++)
{
var bcA = entA[i].field("Barcode");
var idA = entA[i].id;
var recordA = A.findById(idA);

var countA = recordA.field("Count");
var NEWcount = countA - we;

if ( bcA === bcC2)
{
recordA.set("Count",NEWcount),
message ("Decreasing " + bcA + " inventory count to " + NEWcount)
}
}
}//☆
};//☆
};

Bill Crews

unread,
Apr 25, 2021, 5:31:50 PM4/25/21
to Gilles Mons, Keith P, mementodatabase
His more recent script, posted yesterday looks like this:

var e = entryDefault();

// in Widgets
var A = libByName("Widgets");
var ent = A.entries();
var l = ent.length;
// in Widget Acquisitions

var bcB = e.field("Barcode");
for (var b in bcB )
var bcB2 = bcB[b].field("Barcode");
var wa = e.field("Widgets Acquired");
e.set("Widgets Remaining",wa);
var wr = e.field("Widgets Remaining");

for (var i=0;((i<l)&&(bcB2!==bcA));i++)


{
var bcA = ent[i].field("Barcode");
var idA = ent[i].id;
var recordA = A.findById(idA);

var countA = recordA.field("Count");

var NEWcount = countA + wr;

if ( bcA === bcB2)

recordA.set("Count",NEWcount),
message ("Updated inventory count to " + NEWcount)
};

Keith P

unread,
Apr 26, 2021, 12:48:22 PM4/26/21
to Gilles Mons, mementodatabase
Sorry that post was long, easy to miss details for either one of us. It was longer before I found my mistake! I had three scripts and even more explanations.
  
The variable pv in the Expenditures library ('Acquisitions' library too) refers to a 'Previous Value' field that is used to check for changes when saving an update to an entry.  I have a separate script for opening an entry to edit.  It's a short script that copies the 'Number Expended' to the 'Previous Value'.  Then the Update at save script that you are talking about takes that 'Previous Value' (pv) and compares it to 'Expended' (we). If there is no change, nothing is done.  If there is a change, the 'Previous Value' is added back to 'Widgets Remaining' and the new 'Expended' is subtracted (NEWcount = countB ('Widgets Remaining' in Acquisitions)  + pv - we).  The update at save script then clears the 'Prevoious Value' field to prevent user confusion. 
This way if the user opens an entry changes nothing and taps the check mark to go back to the list they are not changing the 'Widgets Remaining' count accidentally. 


Keith P

unread,
Apr 27, 2021, 12:24:04 AM4/27/21
to Gilles Mons, mementodatabase
Oh I see.  Sorry for my misunderstanding. 

When I tried your modifications, the script cleared the Number Expended and didn't deduct from Widgets Remaining. It did, however subtract from the Count in the Widgets library. 
The abridged novel I wrote a few days ago, had some details cut out in an effort to be respectful of the reader's time.  I assumed if anyone was really interested to see the whole story they would look at the shared libraries in the cloud.
When I "copied" that little bit of script from the Updating trigger to the Creating trigger of course I changed the relevant equation so it actually looks like this:

var e = entry();


// in Widgets
var A = libByName("Widgets");

var entA = A.entries();
var lA = entA.length;

// in Widget Acquisitions


var B = libByName("Widget Acquisitions");
var entB = B.entries();
var lB = entB.length;
// in Widget Expenditures
var bcC = e.field("Barcode");
for (var b in bcC)
var bcC2 = bcC[b].field("Barcode");
var acC = e.field("AcID");
for (var a in acC)
var acC2 = acC[a].field("AcID");
var we = e.field("Number Expended");

for (var r=0;((r<lB)&&(acC2!==acB));r++)
{
var acB = entB[r].field("AcID");
var idB = entB[r].id;
var recordB = B.findById(idB);

var countB = recordB.field("Widgets Remaining");

if ( acB === acC2 )
{
var NEWcount = countB - we;

if ( NEWcount < 0// Test if the new 'Widget Remaining' count will be negative...
{
message ("Number Expended exceeds Widgets Remaining."); // notify user
cancel (); // Cancel the save operation


exit(); // Stop running the trigger script.

};

recordB.set("Widgets Remaining",NEWcount),


message ("Decreasing " + acB + " remaining count to " + NEWcount)
}};

for (var i=0;((i<lA)&&(bcC2!==bcA));i++)
{
var bcA = entA[i].field("Barcode");
var idA = entA[i].id;
var recordA = A.findById(idA);

var countA = recordA.field("Count");
var NEWcount = countA - we;

if ( bcA === bcC2)
{
recordA.set("Count",NEWcount), message ("Decreasing " + bcA + " inventory count to " + NEWcount)

}}


If I run it as above, it will notify the user and keep the entry creation window open, but if the check mark is tapped again it will save the entry and subtract from the Inventory Count (but not 'Widgets Remaining').  If I remove the cancel() function and include your line that clears 'Number Expended', it will save the entry with an empty 'Expended' field. I think I prefer keeping the entry open, so it could be fixed.



Gilles Mons

unread,
Apr 27, 2021, 2:56:52 AM4/27/21
to Keith P, mementodatabase
Keith,
You need to define your needs precisely: What do you want to happen if you want to ship more than the quantity in stock ....?
1 - the new entry is not written and they warn the user... Or 2 - they write the entry anyway and warn the user that the quantity they want to ship is too big... Or Ect.... Thanks for clarifying....
Reply all
Reply to author
Forward
0 new messages