Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Question regarding updating sheets and repeating sections

1605560170
Yui V.
Pro
Sheet Author
Hello, I'm working on an update for a character sheet, and my issue regards repeating sections. Does adding new attributes inside of a repeating section (like adding a roll button and a number input) cause any problem with information retention between versions? Would it change the row's attributes name or something like this? What about changing an input type from text to number? (it would get rid of any letter, but would it still retain the numbers in it?) My hypothesis is that nothing would 'break' a repeating fieldset except modifying attribute names inside it (and its own attribute name). Is that true? Another question is: How could I create a new row to implement inputs that are currently outside the fieldset: The sheet I'm working on has four repeating sections, and just above each one, there are rows with the same inputs as the fieldsets' row (just with slightly different attribute names), so it's a permanent row, outside the repeating section. I would like to copy the values of these permanent rows, create a sectionRow in the repeating section to paste the values into, and delete the permanent rows. I have no experience with sheet versioning and little sheetworker smartness. (also, would it be possible to have an action button outside the fieldssets that essentially dispay:none's the new inputs, to allow choice between old style and new style, since the latter is just adding stuff in the repeating section?) Thank you!
1605565352
GiGs
Pro
Sheet Author
API Scripter
A few questions here! :) My hypothesis is that nothing would 'break' a repeating fieldset except modifying attribute names inside it (and its own attribute name). Is that true? You are correct. The repeating section you define in the sheet is essentially a template of instructions, that roll20 uses to build the sheet when a user views it. The attribute values &nbsp;are not stored in the sheet, but in&nbsp; abackend database. So you can delete and remove attributes from the section, and any already created attributes will still exist in the backend database - there's just no where to display them on the sheet. If you later recreated inputs with the same attribute name, those values would reappear. So yes, as long as you dont change the data type (like your example of text to number), the stored data is safe and you can add new contents to a repeating section safely. (also, would it be possible to have an action button outside the fieldssets that essentially dispay:none's the new inputs, to allow choice between old style and new style, since the latter is just adding stuff in the repeating section?) Yes, this kind of thing is done through CSS - there are examples on the roll20 wiki, in the CSS Wizardry page.&nbsp; How could I create a new row to implement inputs that are currently outside the fieldset: The sheet I'm working on has four repeating&nbsp;sections, and just above each one, there are rows with the same inputs as the fieldsets' row (just with slightly different attribute names), so it's a permanent row, outside the repeating&nbsp;section. I would like to copy the values of these permanent rows, create a sectionRow in the repeating&nbsp;section to paste the values into, and delete the permanent rows. This is where things get tricky. If you are modifying a sheet that is already in use (making changes to a sheet on roll20's github), you'll need to look into sheet versioning. The basic principle is simple: just add a hidden input containing a sheet version attribute, with a default value of 0. Then pick a version number you want to update the sheet to, say 1. Now, in your sheet's script block, add a sheet worker that runs on the&nbsp; sheet:opened &nbsp;event, checks the sheet's version number and if it is below the 1 (which all sheets will be, initially), run a version function to update the sheet. And at the end of the function, set the sheet's version attribute to a value of 1. With that set up, the first time anyone opens their sheet, the version updating function will run and make whatever changes you want. The second time, and all subsequent times, the sheet is opened, that version checker will run, see the sheet is now at version 1, and so will skip the updating function. With this method, you guarantee that a version update runs only once, and updates any sheets that have been in use prior to the changes. To the other part of your question: yes, you can get attribute values off a sheet and add a new row to the repeating section to add them. Theres a function to create new row ids:&nbsp; <a href="https://wiki.roll20.net/Sheet_Worker_Scripts#generateRowID.28.29" rel="nofollow">https://wiki.roll20.net/Sheet_Worker_Scripts#generateRowID.28.29</a> You'd have a worker that generates a row id, then uses that to create attribute names in the repeating section for your old stats, and stores the values with them using the setAttrs function. Hope this helps!
1605635442
Yui V.
Pro
Sheet Author
Thank you for your answer! So changing the input type would not 'retain' the value, ok. Is it possible to get the value of one text input and paste it after the value of an other text input, to combien both into one input, without 'losing' data? A setattr that would add text without replacing the older value...
1605635840
GiGs
Pro
Sheet Author
API Scripter
Yui V. said: Thank you for your answer! So changing the input type would not 'retain' the value, ok. Is it possible to get the value of one text input and paste it after the value of an other text input, to combien both into one input, without 'losing' data? A setattr that would add text without replacing the older value... Changing the input type would only delete the value, if the old value was incompatible with the new type. If you have type="text" and the value is "12", and you change the type to number, then the value of 12 would be retained, because 12 is a valid number. If you have type = text, and the value is "1d6+1", and you change to type=number, that value would not be visible on the sheet. I'm not sure the data would be lost though - it might still exist until the value is manually changed. That's not something I've ever tested (but sounds easy to test). "Is it possible to get the value of one text input and paste it after the value of an other text input, to combine both into one input, without 'losing' data?" yes, this is very possible.
1605659509
Yui V.
Pro
Sheet Author
Hello back! I'm experimenting with adding a new row to transfer the fixed inputs inside a repeating section, but it doesn't work... Here's my code on(`sheet:opened`, function() { &nbsp; &nbsp; &nbsp; &nbsp; getAttrs(["competence_1","competence_2"], function() { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let c1 = values.competence_1; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let c2 =&nbsp; parseInt(values.competence_2)||0; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var newrowid = generateRowID(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var newrowattrs = {}; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newrowattrs["repeating_competences_" + newrowid + "competence_3"] = c1; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newrowattrs["repeating_competences_" + newrowid + "competence_4"] = c2; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setAttrs(newrowattrs); &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; }); So here, as you can see, I have attr_competence_1 and attr_competence_2 outside the repeating_competence section, and I want to transfer them to the attr_competence_3 and attr_competence_4 attributes inside the repeating section. But I get nothing. (comp_1 and comp_3 are text inputs while comp_2 and comp_4 are number inputs, hence the parseInt(...), although it may be unnecessary?) I'll later change the on(" sheet:opened "&nbsp;to some versioning stuff, but for now I figured it would be easier for testing. What am I doing wrong here? also, I'm not sure how to add another generaterowID function on this event (I have 4 repeating sections to update just like this, and since it will be versioning, I need to execute the four changes on one single event...)
1605723442

Edited 1605723555
GiGs
Pro
Sheet Author
API Scripter
It's hard to say without seeing your repeating section code. The code looks like it should work, but does the repeating section have attributes named competence_3 and competence_4? One thing: you dont need to parseInt on the competence_2. You arent doing anything mathematical with it, so you can just grab the value, the same way you did with c1. With 4 sections to update, I'd create a loop or similar function. Something like this: const &nbsp; transferOldAttributesToSections &nbsp;&nbsp;=&nbsp;( values ,&nbsp; version )&nbsp; =&gt; &nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp; const &nbsp; sections &nbsp;=&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; section_1 : &nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oldstat1 : &nbsp; 'newstat1' , &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oldstat2 : &nbsp; 'newstat2' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; section_2 : &nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stat : &nbsp; 'stat' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; section_3 : &nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stat : &nbsp; 'stat' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; section_4 : &nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stat : &nbsp; 'stat' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp; const &nbsp; fieldnames &nbsp;=&nbsp;[]; &nbsp;&nbsp;&nbsp;&nbsp; Object . keys ( sections ). forEach ( section &nbsp; =&gt; &nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object . keys ( sections [ section ]). forEach ( key &nbsp; =&gt; &nbsp; fieldnames . push ( key )); &nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp; getAttrs ([ fieldnames ],&nbsp; values &nbsp; =&gt; &nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const &nbsp; output &nbsp;=&nbsp;{}; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object . keys ( sections ). forEach ( section &nbsp; =&gt; &nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const &nbsp; id &nbsp;=&nbsp; generateRowID (); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object . entries ( sections [ section ]). forEach (([ oldstat ,&nbsp; newstat ])&nbsp; =&gt; &nbsp; output [ `repeating_ ${ section } _ ${ id } _ ${ newstat } ` ]&nbsp;=&nbsp; values [ oldstat ]); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; output . version &nbsp;=&nbsp; version ; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setAttrs ( output ); &nbsp;&nbsp;&nbsp;&nbsp;});&nbsp;&nbsp; }; In this function, you have a variable at the start called sections. It has 4 blocks, one for each section. Change the name of each block to the name of the repeating section 9without the repeating_ part). You can see I;ve done that on the first block. Change section_2, section_3, and section_4 to match your sheet's repeating section names. Then inside each block there are pars of stat names: each pair is separated by a comma, and is in the form: &nbsp; &nbsp; oldstat (the one outside the repeating section): newstat (the name isnide the repeating section you want it transferred to). So just go in and create the matching pairs of attribute names under each block. Remember if there's more than one, put a comma after each (as in the first block). This is the only section of the function you need to edit . It's very important to format it correctly. Explaining the rest: The first Object.keys loop goes through the sections variable, and builds an array of all the old stat attribute names. The it uses that array withgetAttrs, to get the matching values from the sheet. Then the second Object.keys function loops through the old stat names, and for each one, grabs the old value, and assigns it to its matching stat in the repeating section. Finally it updates the version attribute on the sheet. You call the function like this: on ( `sheet:opened` ,&nbsp; function ()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp; getAttrs ([ 'code_version' ],&nbsp; values &nbsp; =&gt; &nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const &nbsp; version &nbsp;=&nbsp; parseInt ( values . code_version )&nbsp;||&nbsp; 0 ; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( version &nbsp;&lt;&nbsp; 0 )&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transferOldAttributesToSections ( values ,&nbsp; 1 );&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}); }); This requires you have an attribute on the sheet named code_version. I usually create this at the very start of the sheet like so &lt;input type="hidden" name="attr_code_version" value="0" step="0.01"&gt; While i'm testing the version update, I make it visible &lt;input type="number" name="attr_code_version" value="0" step="0.01"&gt; Then I can open a sheet, which will run the code. If it hasnt worked as expected, I can manually change the version number back to 0, close the sheet, edit the code, update it, and then reopen the sheet to run it again. Once I'm happy everything is working, I change that input to type="hidden"
1605740111
Yui V.
Pro
Sheet Author
Thank you,&nbsp; yes, the repeating section has attributes named competence_3 and competence_4 (which may be a bit confusing). I worked a bit with my code, the first obvious mistake was that there were no underscores on front of the attribute names in the newrowattrs string: newrowid + "&gt;&gt;&gt;here&lt;&lt;&lt;competence_3"] Secondly, I tweaked things a bit, and taking random(cause I have no idea what I'm doing honestly) inspiration from your code just above and replaced the first&nbsp; function() { &nbsp;by&nbsp; values =&gt; { &nbsp;after the getAttrs. Now this version of the code does work!! &nbsp; &nbsp; on(`sheet:opened`, function() { &nbsp; &nbsp; &nbsp; &nbsp; getAttrs(["competence_1","competence_2"], values =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let c1 = values.competence_1; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let c2 =&nbsp; values.competence_2; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var newrowid = generateRowID(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var newrowattrs = {}; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newrowattrs["repeating_competences_" + newrowid + "_competence_3"] = c1; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newrowattrs["repeating_competences_" + newrowid + "_competence_4"] = c2; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setAttrs(newrowattrs); &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; }); Regarding your code however, I can't get it to work. I've pasted it along with the code_version attribute, replaced section_1 to _4 by repeating section names, and oldstats and newstats by the corresponding attributes. But nothing works. When I open the sheet, the code_version attribute isn't set to 1, it stays at 0, so the transferoldattributestosection constant does not trigger it seems. I tried changing&nbsp; if(version &lt; 0) &nbsp;to&nbsp; if(version &lt; 1) &nbsp;but it doesn't change anything. Here's my whole &lt;script&gt;, I put the code_version input just above it in the code. Maybe my Tabs script inteferes with the rest? &lt;input type="hidden" name="attr_code_version" value="0" step="0.01"&gt; &lt;script type="text/worker"&gt; &nbsp; &nbsp; const buttonlist = ["sombre","clair"]; &nbsp; &nbsp; buttonlist.forEach(button =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; on(`clicked:${button}`, function() { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setAttrs({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sheetTab: button &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; }); &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; const transferOldAttributesToSections&nbsp; = (values, version) =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; const sections = { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; competences: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; competence_1: 'competence_3', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; competence_2: 'competence_4' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dons: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; don_1: 'dons_3', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; don_2: 'dons_4' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; equipements1: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; equipement_1: 'equipement_5', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; equipement_2: 'equipement_6' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; equipements2: { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; equipement_3: 'equipement_7', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; equipement_4: 'equipement_8' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; &nbsp; const fieldnames = []; &nbsp; &nbsp; &nbsp; &nbsp; Object.keys(sections).forEach(section =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Object.keys(sections[section]).forEach(key =&gt; fieldnames.push(key)); &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; getAttrs([fieldnames], values =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const output = {}; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Object.keys(sections).forEach(section =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const id = generateRowID(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Object.entries(sections[section]).forEach(([oldstat, newstat]) =&gt; output[`repeating_${section}_${id}_${newstat}`] = values[oldstat]); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output.version = version; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setAttrs(output); &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp;&nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; on(`sheet:opened`, function() { &nbsp; &nbsp; &nbsp; &nbsp; getAttrs(['code_version'], values =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const version = parseInt(values.code_version) || 0; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(version &lt; 1) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; transferOldAttributesToSections(values, 1);&nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; }); &lt;/script&gt;
1605743801
Yui V.
Pro
Sheet Author
Couldn't figure out why your version didn't work, but I made this version that do work, based on the code from my previous post. It needs to get fed all the outsider attribute names, but it does the job and the versioning works too... on(`sheet:opened`, function() { &nbsp; &nbsp; &nbsp; &nbsp; getAttrs(["code_version","competence_1","competence_2","don_1","don_2","equipement_1","equipement_2","equipement_3","equipement_4"], values =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let version = parseInt(values.code_version)||0; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(version &lt; 1) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var newrowid = generateRowID(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var newrowattrs = {}; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newrowattrs["repeating_competences_" + newrowid + "_competence_3"] = values.competence_1; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newrowattrs["repeating_competences_" + newrowid + "_competence_4"] = values.competence_2; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newrowattrs["repeating_dons_" + newrowid + "_dons_3"] = values.don_1; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newrowattrs["repeating_dons_" + newrowid + "_dons_4"] = values.don_2; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newrowattrs["repeating_equipements1_" + newrowid + "_equipement_5"] = values.equipement_1; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newrowattrs["repeating_equipements1_" + newrowid + "_equipement_6"] = values.equipement_2; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newrowattrs["repeating_equipements2_" + newrowid + "_equipement_7"] = values.equipement_3; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newrowattrs["repeating_equipements2_" + newrowid + "_equipement_8"] = values.equipement_4; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setAttrs(newrowattrs); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setAttrs({code_version: 1}); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; });
1605746733
GiGs
Pro
Sheet Author
API Scripter
It's possible I have a mistake in my code, I dont have the html of a sheet to test it with. It's best to use code you can write, so your code is better than mine in that respect :) I'd suggest making two changes. First (or last!): &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setAttrs(newrowattrs); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setAttrs({code_version: 1}); For efficiency purposes its best to combine setAttrs statements, so you only have one setAttrs per sheet worker. You can do that by changing the above to &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newrowattrs['code_version'] = 1; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setAttrs(newrowattrs); Just add the code_version name and value to the same newrowattrs variable you are already using. Secondly, create a new row id each time you change the repeating section. Like: on(`sheet:opened`,&nbsp;function()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;getAttrs(["code_version","competence_1","competence_2","don_1","don_2","equipement_1","equipement_2","equipement_3","equipement_4"],&nbsp;values&nbsp;=&gt;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;version&nbsp;=&nbsp;parseInt(values.code_version)||0; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(version&nbsp;&lt;&nbsp;1)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;newrowid&nbsp;=&nbsp;generateRowID(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;newrowattrs&nbsp;=&nbsp;{}; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newrowattrs["repeating_competences_"&nbsp;+&nbsp;newrowid&nbsp;+&nbsp;"_competence_3"]&nbsp;=&nbsp;values.competence_1; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newrowattrs["repeating_competences_"&nbsp;+&nbsp;newrowid&nbsp;+&nbsp;"_competence_4"]&nbsp;=&nbsp;values.competence_2; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newrowid&nbsp;=&nbsp;generateRowID(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newrowattrs["repeating_dons_"&nbsp;+&nbsp;newrowid&nbsp;+&nbsp;"_dons_3"]&nbsp;=&nbsp;values.don_1; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newrowattrs["repeating_dons_"&nbsp;+&nbsp;newrowid&nbsp;+&nbsp;"_dons_4"]&nbsp;=&nbsp;values.don_2; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newrowid&nbsp;=&nbsp;generateRowID(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newrowattrs["repeating_equipements1_"&nbsp;+&nbsp;newrowid&nbsp;+&nbsp;"_equipement_5"]&nbsp;=&nbsp;values.equipement_1; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newrowattrs["repeating_equipements1_"&nbsp;+&nbsp;newrowid&nbsp;+&nbsp;"_equipement_6"]&nbsp;=&nbsp;values.equipement_2; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newrowid&nbsp;=&nbsp;generateRowID(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newrowattrs["repeating_equipements2_"&nbsp;+&nbsp;newrowid&nbsp;+&nbsp;"_equipement_7"]&nbsp;=&nbsp;values.equipement_3; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newrowattrs["repeating_equipements2_"&nbsp;+&nbsp;newrowid&nbsp;+&nbsp;"_equipement_8"]&nbsp;=&nbsp;values.equipement_4; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newrowattrs["code_version"]&nbsp;=&nbsp;1; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setAttrs(newrowattrs); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}); }); I added some line breaks to make it clear where the changes are - they aren't essential. Here the newrowid variable is being reused, to hold a new row id for each repeating section. Technically speaking, it's not essential to do this. It's just better for row ids to be unique, and this makes sure they are.