5 Replies Latest reply on Oct 29, 2016 6:50 AM by K.Daube

    How to find a variable just after a marker?

    K.Daube Level 1

      Dear experts,

      My project steps further - but as soon as I have to deal with FM-objects I still struggle. The script should do this:

      • In the document (http://www.daube.ch/zz_tests/Markers-and-variables.fm) there are markers of type #calc (which are all found and stored into an array.
      • Some of them are immediately followed by a variable (called temporary variable, because the names are built by date/time).
      • Before I insert the new variable, the old one should be found and removed.
      • The problem is that I do not find the old variable and hence can not remove it, before the new one is inserted. The inserting is OK, but it occurs independently of existing variables.
      • Line 49 always evaluates to false, even if there is a variable present.

      How can I find (at first hand) any variable (Later I will need to check whether it is really a temprary variable) ?

      #target framemaker
      // Required doc: Markers-and-variables.fm:
        aVariables = ["#DOCname", "#TEST", "2016-09-27T10:28:46.060Z"];
        goCurrentDoc =  app.ActiveDoc;
        giNCalcMarkers = CollectMarkers  (gaoCalcMarkers, "#calc");
      
      for (j = 0; j < giNCalcMarkers; j++) {
        goCurrentMarker = gaoCalcMarkers[j];            // find a marker
        oFound = FindVariable (goCurrentDoc, goCurrentMarker);
        if (oFound[0]) {                                // true, variable found
          oFound[1].Delete();                           // remove temp. variable from document
        }
        oTextLoc = goCurrentMarker.TextLoc;
        oTextLoc.offset = oTextLoc.offset + 1;          // insert temp variable behind marker
        InsertVariable (goCurrentDoc, oTextLoc, "#TEST", "\+1.275×10<super>\+9" );
      }
      // ================= Routines to be tested ========================================================
      function CollectMarkers (aMarkers, sMarkerName) { //=== Collect marker-objects, store in array ====
      // In        aMarkers:    global array of markers to be filled
      //           sMarkerName: type of marker to be collected
      // Out       Return number of markers collected
      var  oMarker, MarkerTI, nMarkers;
        tsSave = goCurrentDoc.TextSelection;            // save current cursor location
        oMarker = goCurrentDoc.FirstMarkerInDoc;
        while (oMarker.ObjectValid()) {
          MarkerTI = oMarker.MarkerTypeId;
          if (MarkerTI.Name == sMarkerName) {
            aMarkers.push(oMarker);                     // store the marker objects 
          }
          oMarker = oMarker.NextMarkerInDoc;
        }
        goCurrentDoc.TextSelection = tsSave;            // Restore cursor location 
        nMarkers = aMarkers.length;
        return nMarkers;                                // number of markers in array
      } //--- end CollectMarkers  
      
      function FindVariable (oDoc, oMarker) { //=== Find variable behind marker ========================
      // In        oMarker: current marker
      // Out       Function returns [true, found variable] or [false, loc behind the marker]
      var tLoc1 = oMarker.TextLoc,
          tLoc2 = oMarker.TextLoc,                      // should be just behind the marker
          j, myTextRange, findParams, fRange, oTextItem, aVarsRange, nVars, thisVar;  
        tLoc1.offset = tLoc1.offset + 1;
        tLoc2.offset = tLoc2.offset + 2;
        myTextRange  = new TextRange(tLoc1,tLoc2);
        oDoc.TextSelection = myTextRange;               // Does this hold a variable ?
        findParams= GetFindParamsVariable ("");         // search for any variable
        fRange = goCurrentDoc.Find  (tLoc1, findParams);// is a textrange
        if (fRange.beg.obj.ObjectValid()) {
          aVarsRange = goCurrentDoc.GetTextForRange (fRange, Constants.FTI_VarBegin);
          nVars = aVarsRange.length;
          for (j = 0; j < nVars; j++) {                   // loop should not be necessary
            oTextItem = aVarsRange[j];                    // superfluous ?
            thisVar = oTextItem.obj;                      // should contain only one variable
            return [true, thisVar];
          }
        } else {
          return [false, tLoc1];
        }
      } //--- end FindVariable  
      
      function GetFindParamsVariable (sVarName) { //=== Set up parameters to Find variable ==============
      // In        sVarName: variable type to be found
      // Out       Returns parameters for the find function: no wrapping around ?
      var findParams;
        findParams = AllocatePropVals (2);  
        findParams[0].propIdent.num = Constants.FS_FindWrap ;  
        findParams[0].propVal.valType = Constants.FT_Integer;  
        findParams[0].propVal.ival = 0 ; // don't start at the beginning => seems to be 'nowrap'
        findParams[1].propIdent.num = Constants.FS_FindNamedVariable;  
        findParams[1].propVal.valType = Constants.FT_String;  
        findParams[1].propVal.sval = sVarName;  
        return findParams;  
      } //--- end GetFindParams
      
      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; 
      }
      
        • 1. Re: How to find a variable just after a marker?
          Klaus Göbel Level 3

          Hi Klaus,

          you can't use "find" with Constants.FS_FindNamedVariable and name = "" for any variable.

          You have to use Constants.FS_FindObject and Constants.FV_FindAnyVariable.

           

          cu in Stuttgart (tekom) ?

          • 2. Re: How to find a variable just after a marker?
            K.Daube Level 1

            Thanks, Klaus, for the tip.

            It is, however, not easy to find all necessary ingredients of the PropVals setup:

            Is It (a):

              findParams[1].propIdent.num = Constants.FS_FindObject;  
              findParams[1].propVal.valType = Constants.FV_FindAnyVariable;  
              findParams[1].propVal.ival = 0;     // ???
            

            or (b):

              findParams[1].propIdent.num = Constants.FS_FindObject;  
              findParams[1].propVal.valType = Constants.FV_FindAnyVariable;  
              findParams[1].propVal.sval = "";    // ???
            

            With a) the variable far away is found (after the next marker)

            With b) nothing is found (as I had it before your answr).

            Whether the third item (ival/sval) is needed and what the necessary values are: I have not found any information about that in the FDK - not speak of ES-docu.

            Information such as "Parmeter name = findParams, Data Type = PropVals, Option = No, Desctiption = A property list that specifies what to search for" is the end of the story. No indication at all, what to specify for PropVals!

            I have also tinkered around a lot with the tLoc1.offset value to start the find operation: even if stepping back 5 from the marker location the variable behind the next (not the current) marker is found.

             

            Stuttgart (tekom) ? - I will not attend: to many items on stack.

            Klaus

            • 3. Re: How to find a variable just after a marker?
              Klaus Göbel Level 3
                  propVal = new PropVal() ;  
                  propVal.propIdent.num = Constants.FS_FindObject;  
                  propVal.propVal.valType = Constants.FT_Integer;  
                  propVal.propVal.ival = Constants.FV_FindAnyMarker ;  
                  FindParams.push(propVal);  
              
              

               

              We discussed it some months ago.

              Re: Find next marker

               

              BTW: gaoCalcMarkers is undefined.

              • 4. Re: How to find a variable just after a marker?
                K.Daube Level 1

                Thanks, now it works!

                gaoCalcMarkers - undefined only in this snippet

                I had used Find next marker as the base - but still was not clever enough.

                • 5. Re: How to find a variable just after a marker?
                  K.Daube Level 1

                  To sum up, here the complete working example - needs a proper document.

                  #target framemaker
                  // Required doc: Markers-and-variables.fm:
                    oDoc =  app.ActiveDoc;
                    oMarker = oDoc.FirstMarkerInDoc;
                    while (oMarker.ObjectValid()) {                 // get markers in order of creation
                      MarkerTI = oMarker.MarkerTypeId;
                      if (MarkerTI.Name == "#calc") {
                        bFound = FindVariable (oDoc, oMarker);      // remove already existing variable
                        if (bFound) {
                          oTextLoc = oMarker.TextLoc;
                          oTextLoc.offset = oTextLoc.offset + 1;    // insert temp variable behind marker
                          InsertVariable (oDoc, oTextLoc, "#TEST", "\+1.275×10<super>\+9" );
                        }
                      }
                      oMarker = oMarker.NextMarkerInDoc;
                    }
                  
                  function FindVariable (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;
                    myTextRange  = new TextRange(tLoc1,tLoc2);
                    oDoc.TextSelection = myTextRange;
                    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 variableb
                  } //--- end FindVariable  
                  
                  function GetFindParamsVariable () { //=== Set up parameters to Find a variable ====================
                  // Out       Returns parameters for the find method
                  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 ;  
                    findParams.push(propVal);  
                    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; 
                  }