Andreas J. said: Victor B. said: The bad news is that you'll have to copy your characters over into this and it's doubtful the field names are the same between this new version and any other sheet you may be using. I'd suggest creating a new game and having both old and new up at the same time so you can quickly copy data into this new sheet. There could be created sheetworkers to to migrate stats from the old attributes to new ones if you changed the names. Any particular reason why you changed name of stats? Trying to search the forums I didn't immediately find an example on how to migrate attributes, sure be great if any such examples would exist as there are many great sheets like this that would benefit from that, shrinking the work of people to migrate from one sheet to another. Well....here's how I do it for the Savage Worlds Tabbed sheet. I'm sure GiGs could make this more efficient/cleaner... :) function convertRS (originSection, destinationSection, ofieldArray, dfieldArray, daddlfieldArray, defaultValues) { /*------ example of call ------ || originSection = section (without repeating_) fields will be migrated FROM || destinationSection = section (without repeating_) fields will be migrated TO || ofieldArray = Array of Fields that need to be migrated || dfieldArray = Array of Fields the ofieldArray will be mapped to || NOTE: The number of fields in the ofieldArray and dfieldArray should be the same || daddlfieldArray = Additional fields in the destination section that may not be in the original section || defaultValues = Default values for list of fields in daddlfieldArray || NOTE: The number of fields in the daddlfieldArray and defaultValues should be the same || || Example: || var hindranceFields = ["hindrance","hindrancedescription"]; || convertRS("mhindrances","hindrances",hindranceFields,hindranceFields); --------*/ console.log("originSection: " + originSection); console.log("destinationSection: " + destinationSection); console.log("ofieldArray: " + ofieldArray); console.log("dfieldarray: " + dfieldArray); console.log("Number of Entries in ofieldArray: " + ofieldArray.length); console.log("Number of Entries in dfieldArray: " + dfieldArray.length); let originRS = "repeating_"+originSection; getSectionIDs(originRS, function(idArray) { if (idArray.length > 0) { console.log("originSection IDs: " + idArray); let oldAttrs = []; for (let a=0; a < idArray.length; a++) { for (let b=0; b < ofieldArray.length; b++) { oldAttrs[oldAttrs.length] = originRS + "_" + idArray[a] + "_" + ofieldArray[b]; } } getAttrs(oldAttrs, function(v) { let sattrs = {}; for(let i=0; i < idArray.length; i++) { let newrowid = generateRowID(); console.log("~~~~ ConvertRS Iteration " + i + ":: for Section: "+ originSection + ":: id generated: " + newrowid +" ~~~~"); let originRF = "repeating_" + originSection + "_" + idArray[i] + "_"; let destinationRF = "repeating_" + destinationSection + "_" + newrowid + "_"; //migrate original fields to new fields for(var r=0; r < ofieldArray.length; r++) { let getORF = '', putdestinationRF = ''; console.log("********************"); console.log("** originRF: "+originRF+ofieldArray[r]); console.log("** destinationRF: "+destinationRF+dfieldArray[r]); console.log("********************"); getORF = originRF+ofieldArray[r]; console.log(i+"-"+r+") Current value of getORF: "+getORF+": "+v[getORF]); putdestinationRF = destinationRF+dfieldArray[r]; if (ofieldArray[r] === "DmgType" || ofieldArray[r] === "RDmgType") { if (typeof v[getORF] === 'undefined') { sattrs[putdestinationRF]="d4!" } else { sattrs[putdestinationRF]="d"+v[getORF]; } } else { if (typeof v[getORF] === 'undefined') { sattrs[putdestinationRF]=''; } else { sattrs[putdestinationRF]=v[getORF]; } } } //Check to see if we need to set any default values console.log("*** Checking for Additional Fields to set Defaults ***"); if(typeof daddlfieldArray === 'undefined') { console.log("*** No Additional Fields to set...undefined ***"); } else { if (daddlfieldArray.length > 0 && daddlfieldArray.length === defaultValues.length) { console.log("!! Need to set some additional fields !!"); //Set default value for other fields for(let r=0; r < daddlfieldArray.length; r++) { let getORF = '', putdestinationRF = ''; console.log("********************"); console.log("** destinationRF: "+destinationRF+daddlfieldArray[r]); console.log("********************"); putdestinationRF = destinationRF+daddlfieldArray[r]; sattrs[putdestinationRF] = defaultValues[r]; } } else { console.log("!! No additional fields to set OR the number of fields doesn't match the number of values !!"); } } console.log("##### sattrs: " + JSON.stringify(sattrs) + " #####"); setAttrs(sattrs); sattrs = {}; } }); } else { console.log("<===== "+originSection+" had no rows =====>"); } }); } const upgradeSheet = function(version) { if (version < 3.0) { //migrate old fields to new const oldAtts = ["agMod","smMod","spMod","stMod","viMod","UnskilledEncumbrance","FightingMod","Academicsskill","AcademicsskillMod","Athletics","AthleticsMod","Battle","BattleMod","BoatingMod","Climbing","ClimbingMod","Commonknowledge","CommonknowledgeMod","Driving","DrivingMod","Electronics","ElectronicsMod","Faith","FaithMod","Focus","FocusMod","Gambling","GamblingMod","Guts","GutsMod","Hacking","HackingMod","Healing","HealingMod","Intimidation","IntimidationMod","Investigation","InvestigationMod","Language","LanguageMod","Lockpicking","LockpickingMod","Notice","NoticeMod","Occult","OccultMod","Performance","PerformanceMod","Persuasion","PersuasionMod","Piloting","PilotingMod","Psionics","PsionicsMod","Repair","RepairMod","Research","ResearchMod","Riding","RidingMod","Ritual","RitualMod","Science","ScienceMod","Shooting","ShootingMod","Spellcasting","SpellcastingMod","Stealth","StealthMod","Streetwise","StreetwiseMod","Survival","SurvivalMod","Swimming","SwimmingMod","Taunt","TauntMod","Thievery","ThieveryMod","Throwing","ThrowingMod","Tracking","TrackingMod","WeirdScience","WeirdScienceMod","LinkedPsionicsAtt","LinkedRitualAttScore","LinkedSpellcastingAttScore","LinkedWeirdScienceAttScore","PAstrength","PAstMod","PAstrollMod"]; const newAtts = ["agilitymod","smartsmod","spiritmod","strengthmod","vigormod","unskilledencumbrance","fightingmod","academicsskill","academicsskillmod","athletics","athleticsmod","battle","battlemod","boatingmod","climbing","climbingmod","commonknowledge","commonknowledgemod","driving","drivingmod","electronics","electronicsmod","faith","faithmod","focus","focusmod","gambling","gamblingmod","guts","gutsmod","hacking","hackingmod","healing","healingmod","intimidation","intimidationmod","investigation","investigationmod","language","languagemod","lockpicking","lockpickingmod","notice","noticemod","occult","occultmod","performance","performancemod","persuasion","persuasionmod","piloting","pilotingmod","psionics","psionicsmod","repair","repairmod","research","researchmod","riding","ridingmod","ritual","ritualmod","science","sciencemod","shooting","shootingmod","spellcasting","spellcastingmod","stealth","stealthmod","streetwise","streetwisemod","survival","survivalmod","swimming","swimmingmod","taunt","tauntmod","thievery","thieverymod","throwing","throwingmod","tracking","trackingmod","weirdscience","weirdsciencemod","linkedpsionicsatt","linkedritualattscore","linkedspellcastingattscore","linkedweirdscienceattscore","pastrength","pastmod","pastrollmod","rastrength","rastmod","rastrollmod"]; let sAttrs = {}; getAttrs(oldAtts, function(v) { //Convert from Old Trait Mod Format (e.g. agMod) to the new format (e.g. agilitymod) for (let i=0; i<oldAtts.length; i++) { console.log(newAtts[i] + " = " + v[oldAtts[i]]); sAttrs[newAtts[i]] = v[oldAtts[i]]; } setAttrs(sAttrs); //Need to create rank and display values for existing sheets const otraits = ['agility','smarts','spirit','strength','vigor','fighting','academicsskill','athletics','battle','boating','climbing','commonknowledge','driving','electronics','faith','focus','gambling','guts','hacking','healing','intimidation','investigation','language','lockpicking','notice','occult','performance','persuasion','piloting','psionics','repair','research','riding','ritual','science','shooting','spellcasting','stealth','streetwise','survival','swimming','taunt','throwing','thievery','tracking','weirdscience','repeating_skills:skillnamerank','pastrength','rastrength']; otraits.forEach(otraits => { rankNdisplay(otraits); }); }); //migrate old repeating skills fields to new getSectionIDs("skills", function(idArray) { if (idArray.length > 0) { console.log("originSection IDs: " + idArray); let oldAttrs = []; let newAttrs = []; for (let a=0; a < idArray.length; a++) { oldAttrs[oldAttrs.length] = "repeating_skills_" + idArray[a] + "_" + "skillnamemod"; newAttrs[newAttrs.length] = "repeating_skills_" + idArray[a] + "_" + "skillnamerankmod"; } getAttrs(oldAttrs, function(v) { const sattrs = {}; for(let i=0; i < idArray.length; i++) { console.log(newAttrs[i]+" == "+oldAttrs[i]); console.log(newAttrs[i]+" == "+ v[oldAttrs[i]]); if (typeof v[oldAttrs[i]] !== 'undefined') { sattrs[newAttrs[i]]=v[oldAttrs[i]]; } else { sattrs[newAttrs[i]] = 0; } } console.log("##### sattrs: " + JSON.stringify(sattrs) + " #####"); setAttrs(sattrs); }); setAttrs({staticKnowledgeOther: "on"}); } else { console.log("<===== had no rows =====>"); } }); //Migrate Melee Weapons to Weapons let meleeFields = ["WeaponType","MeleeDieNum","DmgType","MDmgMod","WeaponWeight","meleeWNotes"]; let weaponFields = ["weapon","dmgnumdice","dmgdietype","dmgbonusnum","weaponweight","weaponnotes"]; let moreweaponFields = ["weaponcarried"]; let weaponDefaultValues = ["on"]; convertRS("meleeweapons","weapons",meleeFields,weaponFields,moreweaponFields,weaponDefaultValues); //Migrate Ranged Weapons to Weapons let rangedFields = ["RWeaponType","WeaponRange","WeaponRoF","NoDmgDice","RDmgType","RDmgMod","RWeaponWeight","rangeWNotes"]; let weaponFieldsII =["weapon","range","rof","dmgnumdice","dmgdietype","dmgbonusnum","weaponweight","weaponnotes"]; let morerangedweaponFields = ["damageatt","weaponcarried"]; let rangedweaponDefaultValues = ["na","on"]; convertRS ("rangeweapons", "weapons", rangedFields, weaponFieldsII,morerangedweaponFields,rangedweaponDefaultValues); //Migrate Power Armor Ranged Weapons to Power Armor Weapons let parangedFields = ["PAWeaponType","PAWeaponRange","PAWeaponRoF","PANoDmgDice","PARDmgType","PARDmgMod","PAWeaponNotes"]; let paweaponFieldsII =["paweapon","parange","parof","padmgnumdice","padmgdietype","padmgbonusnum","paweaponnotes"]; let pamorerangedweaponFields = ["padamageatt"]; let parangedweaponDefaultValues = ["na"]; convertRS ("PAweapons", "paweapons", parangedFields, paweaponFieldsII, pamorerangedweaponFields, parangedweaponDefaultValues); //Migrate Power Armor Melee Weapons to Power Armor Weapons let pameleeFields = ["PAMWeaponType","PAMMeleeDieNum","PAMDmgType","PAMMDmgMod","PAMmeleeWNotes"]; let paweaponFields = ["paweapon","padmgnumdice","padmgdietype","padmgbonusnum","paweaponnotes"]; let pamoreweaponFields = ["padamageatt"]; let paweaponDefaultValues = ["strength"]; convertRS("PAmeleeweapons","paweapons", pameleeFields, paweaponFields, pamoreweaponFields, paweaponDefaultValues); //Migrate Robot Armor Ranged Weapons to Robot Armor Weapons let rarangedFields = ["RAWeaponType","RAWeaponRange","RAWeaponRoF","RANoDmgDice","RARDmgType","RARDmgMod","RAWeaponNotes"]; let raweaponFieldsII =["raweapon","rarange","rarof","radmgnumdice","radmgdietype","radmgbonusnum","raweaponnotes"]; let ramorerangedweaponFields = ["radamageatt"]; let rarangedweaponDefaultValues = ["na"]; convertRS ("RAweapons", "raweapons", rarangedFields, raweaponFieldsII, ramorerangedweaponFields, rarangedweaponDefaultValues); //Migrate Robot Armor Melee Weapons to Robot Armor Weapons let rameleeFields = ["RAMWeaponType","RAMMeleeDieNum","RAMDmgType","RAMMDmgMod","RAMmeleeWNotes"]; let raweaponFields = ["raweapon","radmgnumdice","radmgdietype","radmgbonusnum","raweaponnotes"]; let ramoreweaponFields = ["radamageatt"]; let raweaponDefaultValues = ["strength"]; convertRS("RAmeleeweapons","raweapons", rameleeFields, raweaponFields, ramoreweaponFields, raweaponDefaultValues); //Migrate Damaging Spells to powers let dmgSpells = ["Spell","SpellCost","SpellRange","SpellDuration","NoSpllDmgDice","SDmgType","SDmgMod","DmgSpellNotes"]; let powerFields =["power","pp","powerrange","powerduration","spelldmgnumdice","spelldmgdietype","spelldmgbonusnum","spellnotes"]; let moredmgspellFields = ["spelldamageatt"]; let moredmgspellDefaultValues = ["na"]; convertRS ("dmgspells", "spells", dmgSpells, powerFields, moredmgspellFields, moredmgspellDefaultValues); //Migrate Non-Damaging Spells to Powers let nondmgSpells = ["NDSpell","NDSpellCost","NDSpellRange","NDSpellDuration","ndSpellNotes"]; let powerFieldsII = ["power","pp","powerrange","powerduration","spellnotes"]; let morespellFields = ["spelldamageatt","spellbutton","spelldmgnumdice"]; let morespellDefaultValues = ["na","2","0"]; convertRS ("ndspells", "spells", nondmgSpells, powerFieldsII, morespellFields, morespellDefaultValues); //Migrate Ground Vehicles Crew let crewfields = ["GVCrewName","GVCrewType","GVCrewPos","GVCrewSalary","GVCrewShares","GVCrewNotes"]; convertRS ("FShipCrew", "GShipCrew", crewfields, crewfields); //Migrate Walker Vehicles Crew let wcrewfields = ["WalkerCrewName","WalkerCrewType","WalkerCrewPos","WalkerCrewSalary","WalkerCrewShares","WalkerCrewNotes"]; convertRS ("FShipCrew", "WShipCrew", wcrewfields, wcrewfields); } if (version < 3.1) { console.log(`!@!@! UPGRADING TO VERSION 3.1 !@!@!`) //Set up Multi Attack option stepwiseFaux("weapons","rof"); //Migrate Nerves of Steel getAttrs(["NoS"], function(v) { if(v.NoS === "-1") { console.log("!!! Nerves of Steel !!!"); let nerves = getTranslationByKey('nerves-of-steel'); setAttrs({ reducewoundsby: "-1", reducereason: nerves }); } else if(v.NoS === "-2") { console.log("!!! Nerves of Steel !!!"); let nerves = getTranslationByKey('improved-nerves-of-steel'); setAttrs({ reducewoundsby: "-2", reducereason: nerves }); } else { console.log("No Nerves of Steel to care for"); } }); } else { console.log("!!! Sheet Already Upgraded !!!"); } //Update Sheet Version Number console.log("**** Updating Sheet Version ****"); setAttrs({ character_sheet: sheetVersionPrefix + sheetVersion }); console.log("<===== End Sheet Upgrade Conversion Process =====>"); };