Coming soon: Your brand new Help Center & Community! Get a sneak-peek here

CRMScript: DocTmplHeadingLink Query

Hi there,

using CRMScript how could I work out if a particular Template is visible under a particular Heading?

I have tried using the SearchEngine but it reports "Unknown Table: doctmplheadinglink"

I tried using the NSArchiveAgent too but there doesn't appear to be a suitable Archive Provider

Many thanks in advance


Hi James,

Looking at table SDK you should use table name DocTmplHeadingLink in SearchEngine.

Von: Michel Krohn-Dale 16. Sep 2019

Take a look at the list agent - it has methods to tell you about headings and list items.



Von: Christian Mogensen 16. Sep 2019

Hi again,

thanks for the assitance so far, using the ListAgent though

  NSListAgent listAgent;
  NSSelectableMDOListItem[] oHeadings = listAgent.GetHeadingsForListItemFromListName("DocTmpl", iTemplateId, false);
  NSSelectableMDOListItem[] oItems = listAgent.GetListItemsForHeadingFromListName("DocTmpl", iMembInvHeadingId);

oHeadings seems to be a list of all of the headings not just the the headings that the Template is visible under


oItems seems to be a list of all of the templates not just the ones visible under that heading

Cheers James

Von: James Carter 16. Sep 2019

SearchEngine is case sensitive, so important to use correct casing.

Von: Stian Andre Olsen 18. Sep 2019

oHeadings is a list of selectable items - the items that are marked with selected = true are the headings that are active for that item.

Von: Christian Mogensen 18. Sep 2019

HI James,

OK, to address your OP  "how to determine if a particular Template is visible under a particular Heading?"

I created a method that will loop over all the headings and determine if the templateId has that heading selected.

Bool IsSelectedUnderHeading(String listName, String heading, Integer templateId) {
  NSListAgent listAgent;
  NSSelectableMDOListItem[] headings = listAgent.GetHeadingsForListItemFromListName(listName, templateId, false);
  //printLine("Headings count: " + headings.length().toString());
  for(Integer i = 0; i < headings.length(); i++)
    //printLine("Headings name: " + headings[i].GetName());
    if((headings[i].GetName() == heading) && headings[i].GetSelected())
      return true;
  return false;

Then you could use is like this:

printLine("IsSelected = " + IsSelectedUnderHeading("DocTmpl", "System", 155).toString());


Alternatively, maybe you want to get a list of all Headings, and see what templates are associated with each. In that case, here is a simple struct to contain the Heading name and all child templates (as NSMDOListItem[]). 

An afterthought...Maybe a Map would have been better suited... But having a Struct gives it abillity to grow...

struct Heading
  String Name;
  NSMDOListItem[] ChildItems;

// constructor
Heading Heading(String name, NSMDOListItem[] children) 
  Heading heading;
  heading.Name = name;
  heading.ChildItems = children;
  return heading;

Then create a method to get all document templates and transform them into a heading array:

Heading[] GetAllHeadingsAndChildren()
  Heading[] headings;
  NSMDOAgent mdo;
  NSMDOListItem[] documentTemplates = mdo.GetList("doctmpl", false, "", false);
  for(Integer i = 0; i < documentTemplates.length(); i++)
    NSMDOListItem[] childItems = documentTemplates[i].GetChildItems();
    if(childItems.length() > 0)
      Heading h = Heading(documentTemplates[i].GetName(), childItems);
  return headings;

Then all you have to do is call it and print out all the Heading's to see them formatted accordingly.

Heading[] heads = GetAllHeadingsAndChildren();

for(Integer i = 0; i < heads.length(); i++)
  printLine("Head name: " + heads[i].Name);
  //NSMDOListItem[] childItems = heads[i].ChildItems;
  for(Integer j = 0; j < heads[i].ChildItems.length(); j++)
    printLine("Template name: " + heads[i].ChildItems[j].GetName());


Should get something like this:

Hope this helps!



Von: Tony Yates 18. Sep 2019


I ended up with this:

       Integer iTemplateId = ev.getInputValue("CurrentEntity.DocumentTemplate.DocumentTemplateId").toInteger();
      SearchEngine se;
      se.addCriteria("DocTmplHeadingLink.heading_id", "OperatorEquals", iHeadingId.toString());
      se.addCriteria("DocTmplHeadingLink.doctmpl_id", "OperatorEquals", iTemplateId.toString());
      Integer iRowCount = se.countRows();

So if iRowCount > 0 then the template is visible under the iHeadingId Heading

As pointed out the SearchEngine is case sensitive.


Many thanks for all of the replies

Von: James Carter 19. Sep 2019