Concatenating Rich Attributes with OLE objects

Hi all.

I found a similar thread to this one, but it does not answer the same question.

I have a script which runs through a set of objects and builds up a string consisting of all the child objects' Object Text. It then sets the parent Object Text to that of its children, and deletes the children.

I have had success with children all consisting of text, or one child including an OLE object (RichTextWithOLE function used), but when I have many children each with OLE objects I generally end up with either nothing or only the last one.

I have a feeling this has something to do with RTF headers, but don't know. Does anyone know how to help?

Thanks!
 

s = ""    // s is used to build up the requirement body and then store it in the parent
                for co in o do
                {
                        // reset the child counter
                        ic = 0
                        // find the parent object type
                        sIEOT = co."IE Object Type"
                        // if the parent is a requirement then...
                        if( sIEOT == "Requirement" )
                        {
                                // get the object text of the child
                                st = richTextWithOle(co."Object Text")
                                // for the first child
                                if( ic == 0 )                   
                                {
                                        // set the combined string to the first child object
                                        s = richTextFragment(st)                                        
                                } else {
                                        // set the combined string to what it was plus a new line, then the new chold text
                                        s = s "\n" richTextFragment(st)
                                }
                                // increment child counter
                                ic = ic+1
                        }
                }
                // store the combined text back into the parent object text
                o."Object Text" = s
                // for each child object
                for co in o do
                {
                        // mark it as deleted
                        softDelete co
                }
        }

Elliot-A - Wed Oct 14 05:12:46 EDT 2009

Re: Concatenating Rich Attributes with OLE objects
Peter_Albert - Wed Oct 14 06:42:54 EDT 2009

First, assigning a richTextstring to "Object Text" requires the 'richText' perm, hence replace

o."Object Text" = s

by

o."Object Text" = richText s

.

Secondly, you have to remove the 'richTextFragment' part, at this effectively removes OLE objects from the string. Well, they are not removed, but something breaks, and they are no longer displayed.

Thirdly, on a side note, I would recommend to use Buffers instead of strings to avoid memory leaks, and finally, just my 2 cents, I would start with more meaningful variable names right from the start. It will help you on the long run. Not to mention autodeclaration, which seems to be turned off in your case.

Regards,

Peter

Re: Concatenating Rich Attributes with OLE objects
Elliot-A - Wed Oct 14 07:27:31 EDT 2009

Peter_Albert - Wed Oct 14 06:42:54 EDT 2009

First, assigning a richTextstring to "Object Text" requires the 'richText' perm, hence replace

o."Object Text" = s

by

o."Object Text" = richText s

.

Secondly, you have to remove the 'richTextFragment' part, at this effectively removes OLE objects from the string. Well, they are not removed, but something breaks, and they are no longer displayed.

Thirdly, on a side note, I would recommend to use Buffers instead of strings to avoid memory leaks, and finally, just my 2 cents, I would start with more meaningful variable names right from the start. It will help you on the long run. Not to mention autodeclaration, which seems to be turned off in your case.

Regards,

Peter

In fact, I have already removed 'richTextFragment' and included 'richText s'. Now, the parent object's Object Text is set to the value of only the last child - all the previous ones are ignored somehow. This was the reason that I included richTextFragment in the first place; but it did exactly as you predicted - stripped the OLE objects.

Your other comments are useful for the long run, but I don't think will directly impact the aim of this script, so I've noted them for general use thanks. You mentioned auto declaration - this is not something I've seen before in DXL; how is it turned on? If it's the same as VBA's Implicit option, I'd rather leave it off (I set my VBA to Option Explicit to save any headaches later, e.g. misspelled variables being defined and used without my knowledge).

Re: Concatenating Rich Attributes with OLE objects
SystemAdmin - Wed Oct 14 07:49:08 EDT 2009

Elliot-A - Wed Oct 14 07:27:31 EDT 2009
In fact, I have already removed 'richTextFragment' and included 'richText s'. Now, the parent object's Object Text is set to the value of only the last child - all the previous ones are ignored somehow. This was the reason that I included richTextFragment in the first place; but it did exactly as you predicted - stripped the OLE objects.

Your other comments are useful for the long run, but I don't think will directly impact the aim of this script, so I've noted them for general use thanks. You mentioned auto declaration - this is not something I've seen before in DXL; how is it turned on? If it's the same as VBA's Implicit option, I'd rather leave it off (I set my VBA to Option Explicit to save any headaches later, e.g. misspelled variables being defined and used without my knowledge).

To set autodeclare off you have to modify DOORS client's startup.dxl file. From DXL Help:

Auto-declare
In DXL there is a mechanism called auto-declare, which means that a user need not specify a type for a variable. For example, in the script:

i=5
print i
the interpreter declares a new variable and deduces from the assignment that its type is int.

Because DXL is case-sensitive, there is a potential hazard when relying on this mechanism to type variables. If you make a mistake when typing a variable name, the interpreter assumes that a new variable is being used, which creates errors that are hard to find.

This feature can be disabled by adding the line:

XFLAGS_ &=~AutoDeclare_
to the bottom of the file $DOORSHOME/lib/dxl/startup.dxl.

Re: Concatenating Rich Attributes with OLE objects
Peter_Albert - Wed Oct 14 08:17:13 EDT 2009

Elliot-A - Wed Oct 14 07:27:31 EDT 2009
In fact, I have already removed 'richTextFragment' and included 'richText s'. Now, the parent object's Object Text is set to the value of only the last child - all the previous ones are ignored somehow. This was the reason that I included richTextFragment in the first place; but it did exactly as you predicted - stripped the OLE objects.

Your other comments are useful for the long run, but I don't think will directly impact the aim of this script, so I've noted them for general use thanks. You mentioned auto declaration - this is not something I've seen before in DXL; how is it turned on? If it's the same as VBA's Implicit option, I'd rather leave it off (I set my VBA to Option Explicit to save any headaches later, e.g. misspelled variables being defined and used without my knowledge).

> Now, the parent object's Object Text is set to the value of only the last child

It would be best if you posted the current code, that's easier than guessing mistakes.

Peter

Re: Concatenating Rich Attributes with OLE objects
Elliot-A - Wed Oct 14 08:21:18 EDT 2009

Peter_Albert - Wed Oct 14 08:17:13 EDT 2009
> Now, the parent object's Object Text is set to the value of only the last child

It would be best if you posted the current code, that's easier than guessing mistakes.

Peter

So I need to point out that child requirements are merged into the parent, and other objects are copied out after the object, in order.
 

// Parent = Requirement with IEPUID  ""
// Child = Requirement with IE PUID = ""
 
 
/**
*    DECLARE VARIABLES
*/
Object o                                        // current object reference
Object co                                       // current child object reference
Object no                                       // current new object
Object op                                       // current post object
Module m = current Module       // current module reference
string s = ""                         // 
string st  =""                                // temporary string
string sIEOT                            // IE Object Type String
int i = 0                                       // general counter
int ic = 0                                      // child counter
 
bool debug = false                      // debug output
 
if( debug ) print "Declared variables\n"
 
 
 
/**
*       SET FILTER FOR ALL PARENT REQUIREMENT OBJECTS
*/
// print some messages
if( debug ) print "Applying Filter..."
// switch on filtering
filtering on
// Create a filter to find all requirements
Filter f1 = attribute "IE Object Type" == "Requirement"
// Create a filter to find all objects with IE PUID set
Filter f2 = notNull(attribute "IE PUID")
// Create a filter to exclude leaf nodes
Filter f3 = excludeLeaves 
// Create a filter that is the logical AND of all previous filters
Filter f = f1 && f2 && f3
// Apply the filter
set f
// refresh the screen
refresh current
 
if( debug ) print "OK\n"
 
 
 
/**
*       SET FILTER FOR ALL PARENT REQUIREMENT OBJECTS
*/
for o in all(m) do
{
        // print out some messages
        if( debug ) print "Object " i "\n"
        if( debug ) print "## object:"
        if( debug ) print identifier o
        if( debug ) print "\n"
        
        if( true ) // i < 10 - for limited test set
        {
                //reset some variables
                s = ""        // s is used to build up the requirement body and then store it in the parent
                op = o  // op is a reference to the main object, or any objects created after it (in the loop)
                                // to ensure that comments and tables stay in the right order.
                for co in o do
                {
                        // reset the child counter
                        ic = 0
                        // find the parent object type
                        sIEOT = co."IE Object Type"
                        // if the parent is a requirement then...
                        if( sIEOT == "Requirement" )
                        {
                                // get the object text of the child
                                st = richTextWithOle(co."Object Text")
                                // for the first child
                                if( ic == 0 )                   
                                {
                                        // set the combined string to the first child object
                                        s = st //richTextFragment(st)                                   
                                } else {
                                        // set the combined string to what it was plus a new line, then the new chold text
                                        s = s "\\par" st //richTextFragment(st)
                                }
                                // increment child counter
                                ic = ic+1
                                // print out some messages
                                if( debug ) print "#### child-req:" identifier co
                                if( debug ) print "\n"
                        // Otherwise we have found a comment
                        } else {
                                // create a new object after the last one (either parent or previous comment)
                                no = create after op
                                // get the object text
                                st = co."Object Text"
                                // set the new object text to that collected
                                no."Object Text" = st
                                // print some messages 
                                if( debug ) print "#### child-com:" identifier co
                                if( debug ) print "\n"
                                // set the reference to the new object (so that further comments are created after this one)
                                op = no
                        }
                }
                // store the combined text back into the parent object text
                o."Object Text" = richText(s)
                if( ic > 0 ){ print "Multiple Merge: " identifier(o) "\n"}
                // print some messages
                if( debug ) print "Deleting: "
                // for each child object
                for co in o do
                {
                        // mark it as deleted
                        softDelete co
                        // and print some messages
                        if( debug ) print "," identifier co
                }
                //print some more messages
                if( debug ) print "\n"
        }
        // increment the counter
        i = i + 1
} 
 
// refresh the screen
refresh current
 
// and print a final message
if( debug ) print "Done\n"

Re: Concatenating Rich Attributes with OLE objects
Elliot-A - Wed Oct 14 08:23:50 EDT 2009

Elliot-A - Wed Oct 14 08:21:18 EDT 2009

So I need to point out that child requirements are merged into the parent, and other objects are copied out after the object, in order.
 

// Parent = Requirement with IEPUID  ""
// Child = Requirement with IE PUID = ""
 
 
/**
*    DECLARE VARIABLES
*/
Object o                                        // current object reference
Object co                                       // current child object reference
Object no                                       // current new object
Object op                                       // current post object
Module m = current Module       // current module reference
string s = ""                         // 
string st  =""                                // temporary string
string sIEOT                            // IE Object Type String
int i = 0                                       // general counter
int ic = 0                                      // child counter
 
bool debug = false                      // debug output
 
if( debug ) print "Declared variables\n"
 
 
 
/**
*       SET FILTER FOR ALL PARENT REQUIREMENT OBJECTS
*/
// print some messages
if( debug ) print "Applying Filter..."
// switch on filtering
filtering on
// Create a filter to find all requirements
Filter f1 = attribute "IE Object Type" == "Requirement"
// Create a filter to find all objects with IE PUID set
Filter f2 = notNull(attribute "IE PUID")
// Create a filter to exclude leaf nodes
Filter f3 = excludeLeaves 
// Create a filter that is the logical AND of all previous filters
Filter f = f1 && f2 && f3
// Apply the filter
set f
// refresh the screen
refresh current
 
if( debug ) print "OK\n"
 
 
 
/**
*       SET FILTER FOR ALL PARENT REQUIREMENT OBJECTS
*/
for o in all(m) do
{
        // print out some messages
        if( debug ) print "Object " i "\n"
        if( debug ) print "## object:"
        if( debug ) print identifier o
        if( debug ) print "\n"
        
        if( true ) // i < 10 - for limited test set
        {
                //reset some variables
                s = ""        // s is used to build up the requirement body and then store it in the parent
                op = o  // op is a reference to the main object, or any objects created after it (in the loop)
                                // to ensure that comments and tables stay in the right order.
                for co in o do
                {
                        // reset the child counter
                        ic = 0
                        // find the parent object type
                        sIEOT = co."IE Object Type"
                        // if the parent is a requirement then...
                        if( sIEOT == "Requirement" )
                        {
                                // get the object text of the child
                                st = richTextWithOle(co."Object Text")
                                // for the first child
                                if( ic == 0 )                   
                                {
                                        // set the combined string to the first child object
                                        s = st //richTextFragment(st)                                   
                                } else {
                                        // set the combined string to what it was plus a new line, then the new chold text
                                        s = s "\\par" st //richTextFragment(st)
                                }
                                // increment child counter
                                ic = ic+1
                                // print out some messages
                                if( debug ) print "#### child-req:" identifier co
                                if( debug ) print "\n"
                        // Otherwise we have found a comment
                        } else {
                                // create a new object after the last one (either parent or previous comment)
                                no = create after op
                                // get the object text
                                st = co."Object Text"
                                // set the new object text to that collected
                                no."Object Text" = st
                                // print some messages 
                                if( debug ) print "#### child-com:" identifier co
                                if( debug ) print "\n"
                                // set the reference to the new object (so that further comments are created after this one)
                                op = no
                        }
                }
                // store the combined text back into the parent object text
                o."Object Text" = richText(s)
                if( ic > 0 ){ print "Multiple Merge: " identifier(o) "\n"}
                // print some messages
                if( debug ) print "Deleting: "
                // for each child object
                for co in o do
                {
                        // mark it as deleted
                        softDelete co
                        // and print some messages
                        if( debug ) print "," identifier co
                }
                //print some more messages
                if( debug ) print "\n"
        }
        // increment the counter
        i = i + 1
} 
 
// refresh the screen
refresh current
 
// and print a final message
if( debug ) print "Done\n"

small ammendment due to html filter:

// Parent = Requirement with IEPUID != ""
// Child = Requirement with IE PUID = ""

Re: Concatenating Rich Attributes with OLE objects
Elliot-A - Wed Oct 14 08:32:56 EDT 2009

Peter_Albert - Wed Oct 14 08:17:13 EDT 2009
> Now, the parent object's Object Text is set to the value of only the last child

It would be best if you posted the current code, that's easier than guessing mistakes.

Peter

Well, having posted the code I gave it one final read, thinking the problem could well be irritatingly obvious.

And it was... In the code above I am reseting the child count for every child object. I moved that outside the child loop, and the code works perfectly otherwise.

Thank you Peter Albert for your help!