5 Replies Latest reply on Nov 11, 2016 4:20 AM by Klaus Göbel

    Find name of variable

    K.Daube Level 1

      Dear friends and experts, I'm again at the end of my knowledge:

      • A variable just behind a marker is found and the variable can be deleted in the text


      • This variable should also be removed from the catalogue. I'ts name is not known, because the name is generated at the time of insertion (the current name is 2016-11-10T09:46:52.136Z).
      • Experiments with the text selection after finding the variable (line 31) did not reveal anything useful to get the name of the variable.
      • Do You have an idea?
      #target framemaker
      // Required doc: #calc Marker with text containing "C7 at the beginning
      //               behind this marker the variable of unknown name is found
      sMarkerText = '"C7';
        oDoc =  app.ActiveDoc;
        oMarker = oDoc.FirstMarkerInDoc;
        while (oMarker.ObjectValid()) {
          if (oMarker.MarkerTypeId.Name == "#calc") {
            if (oMarker.MarkerText == sMarkerText) {
              bFound = FindAndDeleteVariable (goCurrentDoc, goCurrentMarker); // remove already existing variable
      // How to get the name of the variable to be able to remove it from the catalogue also?        
              oTextLoc = goCurrentMarker.TextLoc;
              oTextLoc.offset = oTextLoc.offset + 1;        // insert temp variable behind marker
              InsertVariable (goCurrentDoc, oTextLoc, "#TEST", "\+1.275×10<super>\+9" );
      function FindAndDeleteVariable (oDoc, oMarker) { //=== Find variable behind marker and remove it ==
      // In        oMarker: current marker
      // Out       Function returns true for found+removed variable
      var tLoc1 = oMarker.TextLoc,
          tLoc2 = oMarker.TextLoc,                      // should be just behind the marker
          iUnique1= oMarker.TextLoc.obj.Unique,         // ¶ of the marker
          myTextRange, findParams, fRange;  
        tLoc2.offset = tLoc2.offset + 1;                // a - c are required!
        myTextRange  = new TextRange(tLoc1,tLoc2);      // b
        oDoc.TextSelection = myTextRange;               // c
        findParams= GetFindParamsVariable ();           // search for any variable
        fRange = oDoc.Find  (tLoc1, findParams);        // finds variable
        if (fRange.beg.obj.ObjectValid()) {             // variable found ?
          if (fRange.beg.obj.Unique == iUnique1) {      // same ¶ as the marker ?
            if (fRange.beg.offset == tLoc1.offset+1) {  // TR =? variable behind marker
              oDoc.DeleteText(fRange);                  // Delete the selected Variable
              return true;
        return false;                                   // there was'nt a variable
      } //--- end FindAndDeleteVariable  
      function GetFindParamsVariable () { //=== Set up parameters to Find a variable ====================
      // Out       Returns parameters for the find function: no wrapping around ?
      // Reference Klaus Göbel, https://forums.adobe.com/thread/2227993
      //           FDK Function Reference, F_ApiFind()
      var findParams = new PropVals() ;  
        propVal = new PropVal() ; 
        propVal.propIdent.num = Constants.FS_FindObject;  
        propVal.propVal.valType = Constants.FT_Integer;  
        propVal.propVal.ival = Constants.FV_FindAnyVariable ;  
        return findParams;  
      } //--- end GetFindParamsVariable
      function InsertVariable (oDoc, oTextLoc, sVarName, sContent) { //=== Insert variable at location ==
      // In        oTextLoc: where to insert the variable 
      //           sVarName: name of the variable
      //           sContent: content of the variable
      var oVar;  
        oVar = oDoc.NewAnchoredFormattedVar (sVarName, oTextLoc);  
        oVar.Fmt = sContent; 


      BTW the marker contains this text: "C7 ¶ after T2 TB" = @PI / 180.0; which is successfully evaluated and placed in the temporary variable - there is progress in my project¨.

      Thank You very much for Your help!


        • 1. Re: Find name of variable
          K.Daube Level 1

          Well, I already thought of this method:

          • All of these variables have a name with a distinct pattern (Regex /\d+\-\d+\-\d+T\d+:\d+:\d+\.\d+Z/ ).
          • Run through all variables in cataloge and look for those with this pattern
          • If found: is is really used? => have not found the appropriate property
          • If not used, delete from catalogue

          You see, just another problem here.

          • 2. Re: Find name of variable
            frameexpert Level 4

            Hi Klaus,


            I am not clear on what you are trying to do, but here is the general algorithm for deleting unused formats:


            1) Make an array to hold the used variable names.

            2) Loop through all of the variables in the document, and if the name is not currently in the list, add it to the list. When the loop is done, you will have an array of all of the names of the variables in use.

            3) Loop through all of the variable formats in the document. For each one, see if its name is in the used variables array; if not, delete the format. You should test each variable to make sure it is a user variable because system variables can't be deleted.


            There is no property on a variable format itself to say that it is in use.



            • 3. Re: Find name of variable
              K.Daube Level 1

              Tank You, Rick, this gave me the kick!

              The following works as expected:

              function DeleteUnusedVariables (oDoc) { //=== Delete temporary variables in catalogue =============
              // In        oDoc: Current document
              // Out      Function returns false only in case of problems; else true
              // Comment  Only #calc temporary variables are deleted, if they are not used in the document
              //          What kind of problem could be encountered? => return false
              // Reference Ric Quatro, https://forums.adobe.com/thread/2234619
              var aUsedVariables = [],
                  oVar, oCatVarFmt, oNxtVarFmt,
                  re_TmpVarName = /\d+\-\d+\-\d+T\d+:\d+:\d+\.\d+Z/, // e.g. 2016-11-10T09:46:52.136Z
                  sVarName, sName, j;
                oVar = oDoc.FirstVarInDoc;
                while (oVar.ObjectValid()) {
                  sVarName = oVar.VarFmt.Name;
                  if (re_TmpVarName.test(sVarName)) {          // is it a temporary variable ?
                    if (IsInArray (aUsedVariables, sVarName)) { // already in the list
                  oVar = oVar.NextVarInDoc;
                oCatVarFmt = oDoc.FirstVarFmtInDoc;
                while (oCatVarFmt.ObjectValid()) {
                  if (oCatVarFmt.SystemVar > 0) {              // skip system variables
                    oCatVarFmt = oCatVarFmt.NextVarFmtInDoc;
                  sName = oCatVarFmt.Name;
                  if (re_TmpVarName.test(sName)) {              // is it a temporary variable ?
                    if (IsInArray (aUsedVariables, sName) != null) {
                      oCatVarFmt = oCatVarFmt.NextVarFmtInDoc;
                      continue;                                // it is used in the document
                    } else {
                      oNxtVarFmt = oCatVarFmt.NextVarFmtInDoc;
                      oCatVarFmt.Delete();                      // remove from catalogue
                      oCatVarFmt = oNxtVarFmt;
                  } else {
                    oCatVarFmt = oCatVarFmt.NextVarFmtInDoc;
                return true;
              } //--- end DeleteUnusedVariables
              function IsInArray (array, item) { //=== Get index of item in array ===============================
              // In       array: where to find the item
              //          item:  to be found in the array
              // Out      Returns index of found element or null. 
              // Comment  array.indexOf() is not supported in ExtendScript, only  string.indexOf () is defined.
              var j, arLen = array.length;
                for (j = 0; j < arLen; j++) {
                  if (array [j] == item ) { return j;}
                return null;                                    // not found in array
              } //--- end IsInArray
              • 4. Re: Find name of variable
                frameexpert Level 4

                Hi Klaus, Thank you for marking my answer as correct. I have to commend you on how much your scripting skill has increased, especially your use of functions. I do have one suggestion: I would consider separating the DeleteUnusedVariables function into two. One might be "getVariablesInUse". The advantage is that you could reuse this in another script where you just may want to report the variable formats in use, without actually deleting them. Also, in development, you would want to test your "get" code without actually deleting any of the variable formats. The third reason is that it keeps your functions shorter, which makes them easier to follow and understand when you visit them later. But this probably just quibbling; overall, I think you did an excellent job. -Rick

                • 5. Re: Find name of variable
                  Klaus Göbel Level 3

                  Hi Klaus,

                  there's a script on my website you could use. Feel free to load it there: Kostenlose Skripte


                  It's only in German at the moment, but that should'nt be a problem for you.