Skip to main content
sam95317750
Known Participant
May 21, 2020
Answered

I want to add marker to all H1 headings in a FrameMaker document

  • May 21, 2020
  • 3 replies
  • 2666 views

I want to grab the heading text and add it as a marker to all the respective H1 headings in my FrameMaker document. I am using the following script but it gives me an error and FM crashes after adding the marker.

 

Also, this is adding only a fixed text as a marker:

 

var doc = app.ActiveDoc;

var flow = doc.MainFlowInDoc;

var tframe = flow.FirstTextFrameInFlow;

var pgf = tframe.FirstPgf;

var target1 = doc.GetNamedObject(Constants.FO_PgfFmt, "h1");

while (pgf.ObjectValid())   {

if (pgf.Name == target1.Name)   {

    createMarker (doc, pgf, 0, "newlink h1", "");
	 
}

pgf = pgf.NextPgfInDoc;

}

function createMarker(doc, pgf, offset, type, text) {

    var tLoc = new TextLoc(pgf, offset);

    var marker = doc.NewAnchoredObject(Constants.FO_Marker, tLoc);

    var markerType = doc.GetNamedObject(Constants.FO_MarkerType, type);

    marker.MarkerTypeId = markerType;

    marker.MarkerText = text;

    return 1;

    }

   Please help.

    This topic has been closed for replies.
    Correct answer Klaus Göbel

    You disregarded my advice NOT to use NextPgfInDoc !!

    So it couldn't work.

     

    Try this version. As writen above, it only works, if you have only one Flow (MainFlowInDoc) in your bodypages.

    Otherwise you'll have to follw my advices above.

     

    #target framemaker 
    #strict on
        
        var doc = app.ActiveDoc;
        var flow = doc.MainFlowInDoc;
        var tframe = flow.FirstTextFrameInFlow;
        var goPgf = tframe.FirstPgf;
        
        var markerTypeName = "Hypertext";
        
        var target1 = "h1 head 1";
        var target2 = "h1t head 1.top";
        
        var markerType = doc.GetNamedObject(Constants.FO_MarkerType, markerTypeName);
           
        if (!markerType.ObjectValid())
            {
             markerType = doc.NewNamedMarkerType (markerTypeName);    
            }
            
        setMarker(doc,goPgf);
        
    function setMarker(foDoc,foPgf)
    {
        var sText;
        
        while (foPgf.ObjectValid())
            {
            if (foPgf.Name == target1) 
                {
                sText = GetTextFromPgf(foPgf);
                createMarker(foDoc, foPgf,markerType,"newlink Filename:" + sText);
                }
            
            if (foPgf.Name == target2) 
                {
                sText = GetTextFromPgf(foPgf);
                createMarker(foDoc, foPgf,markerType,sText);
                }
            
            foPgf = foPgf.NextPgfInFlow;
            }
    }
    
    function GetTextFromPgf(foPgf)
    {
        var oTextItems = foPgf.GetText (Constants.FTI_String);
        
        var sText = "";
        
        for (var i = 0; i <= oTextItems.length -1; i++)
            {
            sText = sText + oTextItems[i].sdata;
            }
    
        sText = sText.replace(" ","_");     // you've asked for in PM
        return sText;
    }
    
    
    function createMarker(foDoc, foPgf,foMarkerType,fsText) 
    {
        var tLoc, oMarker;
        tLoc = new TextLoc(foPgf, 0);
        
        oMarker = foDoc.NewAnchoredObject(Constants.FO_Marker, tLoc);
        oMarker.MarkerTypeId = foMarkerType;
        oMarker.MarkerText = fsText;
    }

     

    3 replies

    Klaus Göbel
    Legend
    June 5, 2020

    You just have to add a query:

     

    function setMarker(foDoc,foPgf)
    {
        var sText;
        var bMarkerExists = false;
        
        
        while (foPgf.ObjectValid())
            {
            bMarkerExists = false;
            
            var oMarkers = foPgf.GetText(Constants.FTI_MarkerAnchor);
            
             for (var i = 0; i < oMarkers.length; i++)
                {
                 if (oMarkers[i].obj.MarkerTypeId.Name == gMarkerTypeName)   
                    {
                     bMarkerExists = true;   
                     break;
                    }
                }   
            
             if (!bMarkerExists)
                {
                if (foPgf.Name == target1) 
                    {
                    sText = GetTextFromPgf(foPgf);
                    createMarker(foDoc, foPgf,markerType,"newlink Filename:" + sText);
                    }
                
                if (foPgf.Name == target2) 
                    {
                    sText = GetTextFromPgf(foPgf);
                    createMarker(foDoc, foPgf,markerType,sText);
                    }
                }
            
            foPgf = foPgf.NextPgfInFlow;
            }
    }

     

    sam95317750
    Known Participant
    June 5, 2020

    Thank you Klaus

     

    This is working perfectly fine.

    Klaus Göbel
    Klaus GöbelCorrect answer
    Legend
    May 28, 2020

    You disregarded my advice NOT to use NextPgfInDoc !!

    So it couldn't work.

     

    Try this version. As writen above, it only works, if you have only one Flow (MainFlowInDoc) in your bodypages.

    Otherwise you'll have to follw my advices above.

     

    #target framemaker 
    #strict on
        
        var doc = app.ActiveDoc;
        var flow = doc.MainFlowInDoc;
        var tframe = flow.FirstTextFrameInFlow;
        var goPgf = tframe.FirstPgf;
        
        var markerTypeName = "Hypertext";
        
        var target1 = "h1 head 1";
        var target2 = "h1t head 1.top";
        
        var markerType = doc.GetNamedObject(Constants.FO_MarkerType, markerTypeName);
           
        if (!markerType.ObjectValid())
            {
             markerType = doc.NewNamedMarkerType (markerTypeName);    
            }
            
        setMarker(doc,goPgf);
        
    function setMarker(foDoc,foPgf)
    {
        var sText;
        
        while (foPgf.ObjectValid())
            {
            if (foPgf.Name == target1) 
                {
                sText = GetTextFromPgf(foPgf);
                createMarker(foDoc, foPgf,markerType,"newlink Filename:" + sText);
                }
            
            if (foPgf.Name == target2) 
                {
                sText = GetTextFromPgf(foPgf);
                createMarker(foDoc, foPgf,markerType,sText);
                }
            
            foPgf = foPgf.NextPgfInFlow;
            }
    }
    
    function GetTextFromPgf(foPgf)
    {
        var oTextItems = foPgf.GetText (Constants.FTI_String);
        
        var sText = "";
        
        for (var i = 0; i <= oTextItems.length -1; i++)
            {
            sText = sText + oTextItems[i].sdata;
            }
    
        sText = sText.replace(" ","_");     // you've asked for in PM
        return sText;
    }
    
    
    function createMarker(foDoc, foPgf,foMarkerType,fsText) 
    {
        var tLoc, oMarker;
        tLoc = new TextLoc(foPgf, 0);
        
        oMarker = foDoc.NewAnchoredObject(Constants.FO_Marker, tLoc);
        oMarker.MarkerTypeId = foMarkerType;
        oMarker.MarkerText = fsText;
    }

     

    sam95317750
    Known Participant
    May 28, 2020

    Thank you Klaus_Göbel

     

    This is working fine now. I have used your advice also and my script is also adding markers to all headings. 

    Klaus Göbel
    Legend
    May 21, 2020

    Hi sanjivb,

    there are some problems in your code:

     

    1. You are starting with MainFlowInDoc, but continue with NextPgfInDoc instead of NextPgfInFlow.

    So you can't be sure, that the next pgf is in main flow.

     

    2. You don't check, if the MarkerType exists (ObjectValid()). So this is probably the reason for the crash.

     

    3. If you use more flows in your bodypages than only the MainFlow you won't get all paragraphs.

     

    How to go through all flows you can find here:

    https://community.adobe.com/t5/framemaker/script-no-longer-working/td-p/11071057?page=1

     

    #target framemaker 
    #strict on
        
        var goDoc = app.ActiveDoc;
        var goFlow = goDoc.MainFlowInDoc;
        var goTextFrame = goFlow.FirstTextFrameInFlow;
        var pgf = goTextFrame.FirstPgf;
        
        
        var MarkerTypeName = "newlink h1";
        var gsTargetName = "h1";
        
        var goMarkerType = goDoc.GetNamedObject(Constants.FO_MarkerType, MarkerTypeName);
           
        if (goMarkerType.ObjectValid())
            {
            while (pgf.ObjectValid())
                {
                if (pgf.Name == gsTargetName) 
                    {
                    createMarker(goDoc, pgf,goMarkerType,"TestText");
                    }
                pgf = pgf.NextPgfInFlow;
                }
            }
            else
                {
                alert("MarkerType not found") ;
               
        }
    
    function createMarker(foDoc, foPgf,foMarkerType,fsText) 
    {
        var tLoc, oMarker;
        tLoc = new TextLoc(foPgf, 0);
        
        oMarker = foDoc.NewAnchoredObject(Constants.FO_Marker, tLoc);
        oMarker.MarkerTypeId = foMarkerType;
        oMarker.MarkerText = fsText;
    }
    frameexpert
    Community Expert
    Community Expert
    May 21, 2020

    Here is a convenience function for getting a marker type. If a marker type doesn't exist in the document, it will get created.

    function getMarkerType (markerName, doc) {  
         
        // Get a marker type from the document; if it doesn't exist, create it.
        
        var markerType = doc.GetNamedMarkerType (markerName);  
        if (markerType.ObjectValid () === 0) {  
            markerType = doc.NewNamedMarkerType (markerName);  
        }  
        return markerType;  
    } 

     

    www.frameexpert.com
    sam95317750
    Known Participant
    May 26, 2020

    Thank you @Klaus_Gobel and @frameexpert for your responses.

    I am not good at FM Scripting but managed to add markers (with your help) like "marker_text" + 1 to the h1 headings.

     

    Now, what I want the script to do is to read the heading text and add that text as a hypertext marker to that heading.

    I used @frameexpert's solution on this link and some part of the code from the link mentioned by @Klaus_Gobel.

    But, I am facing following issues:

    1. Script is adding markers to only some headings (skipping some headings)
    2. This is adding space also as a marker. For e.g. Heading 1 is the heading text, the marker is added as marker = Heading 1

          I want to remove space from the marker text.

     

    Please suggest a correction.

     

     

     

     

    var doc = app.ActiveDoc;
    
    var flow = doc.MainFlowInDoc;
    
    var tframe = flow.FirstTextFrameInFlow;
    
    var pgf = tframe.FirstPgf;
    
    var target1 = doc.GetNamedObject(Constants.FO_PgfFmt, "h1 head 1");
    
    var target2 = doc.GetNamedObject(Constants.FO_PgfFmt, "h1t head 1.top");
    
    function getText (textObj, doc) {
    // Gets the text from the text object.
    var text = "", textItems, i;
    // Get a list of the strings in the text object or text range.
    if (textObj.constructor.name !== "TextRange") {
    textItems = textObj.GetText(Constants.FTI_String);
    } else {
    textItems = doc.GetTextForRange(textObj, Constants.FTI_String);
    }
    // Concatenate the strings.
    for (i = 0; i < textItems.len; i += 1) {
    text += (textItems[i].sdata);
    }
    return text; // Return the text
    }
    while (pgf.ObjectValid())   {
    if (pgf.Name == target1.Name)   {
        createMarker (doc, pgf, 0, "Hypertext", "newlink Filename:" + getText(pgf));
    }
    else if (pgf.Name == target2.Name)  {
    
        createMarker (doc, pgf, 0, "Hypertext", getText(pgf));
    
    }
    
    pgf = pgf.NextPgfInDoc;
    
    }
    
    function createMarker(doc, pgf, offset, type, text) {
    
        var tLoc = new TextLoc(pgf, offset);
    
        var marker = doc.NewAnchoredObject(Constants.FO_Marker, tLoc);
    
        var markerType = doc.GetNamedObject(Constants.FO_MarkerType, type);
    
        marker.MarkerTypeId = markerType;
    
        marker.MarkerText = text;
    
        return 1;
    
        }