Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Contents
Contents ........................................................................................................................................... i
1 Welcome to the Advanced WebReports Workshop ........................................................... 1
1.1 Workshop Audience and Objectives ................................................................................... 1
1.2 Prerequisites ....................................................................................................................... 1
1.3 Class Information ................................................................................................................ 1
2 Accessing Content Server Data Structures ........................................................................ 3
2.1 Overview and Objectives .................................................................................................... 3
2.2 Accessing Content Server Data Structures......................................................................... 3
2.2.1 The Problem and Solution....................................................................................... 3
2.2.2 Other Content Server Data Structures .................................................................... 4
2.2.3 Coping with Nested Data Structures ....................................................................... 5
2.3 Exercises ............................................................................................................................. 7
2.3.1 Task List Report ...................................................................................................... 7
2.3.2 WebReport with Constants Report.......................................................................... 7
3 Action Sub-tags...................................................................................................................... 9
3.1 Overview and Objectives .................................................................................................... 9
3.2 Action Sub-tag List .............................................................................................................. 9
3.3 Action Sub-tag Properties ................................................................................................. 11
3.4 Display Considerations ..................................................................................................... 11
4 Variables and Variable Action Sub-tags ............................................................................ 12
4.1 Overview and Objectives .................................................................................................. 12
4.2 The Variable Tag ............................................................................................................... 12
4.3 Variable Sub-tag Types ..................................................................................................... 13
4.4 Using Variable Sub-tag Actions ......................................................................................... 14
4.4.1 Using CONCATVAR and ADDVAR ....................................................................... 14
4.4.2 Using CURRENTVAL to Display Intermediate Variable Values ............................ 15
4.4.3 Using Variable Data with Other Action Tags.......................................................... 16
4.5 Variables and Conditional Tags ......................................................................................... 17
4.6 Exercises ........................................................................................................................... 18
4.6.1 Building an email distribution list ........................................................................... 18
5 NODEACTION & USERACTION Sub-tags .......................................................................... 19
5.1 Overview and Objectives .................................................................................................. 19
5.2 Using NODEACTION ........................................................................................................ 19
5.3 Using USERACTION ........................................................................................................ 21
5.4 Exercises ........................................................................................................................... 22
5.4.1 Copying Content Server content ........................................................................... 22
6 Pre-defined Sort Parameters .............................................................................................. 23
6.1 Overview and Objectives .................................................................................................. 23
6.2 SORT Review.................................................................................................................... 23
6.3 New SORT Directives ....................................................................................................... 24
6.4 Exercises ........................................................................................................................... 26
6.4.1 Specifying Complex sort keys ............................................................................... 26
7 Initiating Workflows ............................................................................................................. 27
7.1 Overview and Objectives .................................................................................................. 27
7.2 Concepts ........................................................................................................................... 27
7.3 Populating Workflow Attributes ......................................................................................... 29
The intended participants are report developers who want to create more sophisticated
WebReports or even build applications within Content Server using WebReports and other
objects such as Content Server Forms.
1.2 Prerequisites
Delegates attending this workshop are expected to be familiar with creating WebReports and
LiveReports including writing SQL. The following are considered prerequisites:
Username:
wr (1,2,3,etc.)
Password:
livelink
URL:
http://training.v.resonatekt.com/T97/livelink.exe
Index into Content Server data structures like Assoc and RecArray to extract the data
you want.
Sometimes useful data that you need in a report or application is stored in the database in a
special proprietary format that is difficult to unravel with a SQL query. For example Content
Servers task list object stores data in a structure known as an Assoc. Lets look at an
example:
Tasks store their data in the DTree table and many of the fields are separate columns but not
all. Some are stored in a string representation of an Assoc in the ExtendedData column.
For the task above the ExtendedData column looks like this:
This string represents a data structure with the following key-value pairs:
Key Value
If you wanted to create a report displaying comments and instructions from a task you would
need a way to index into the Assoc to get the values you wanted. WebReports provides a
simple way to do this using a sub-tag:
[LL_REPTAG=extendedData ASSOC:Instructions /]
The Assoc sub-tag takes a parameter that identifies the key for the value you want returned.
The overall result of the tag above would be the insertion of the following text:
Content Server has a number of proprietary data structures posing the same issues as the
Assoc for report developers. The following table describes them and shows examples of sub-
tags to access their data. See also the tag syntax reference in the online help or user
documentation for reference documentation.
RecArray An array of records. E.g. this RecArray has RECARRAY:2:name returns the
two records (each with fields name and role): name field of the 2nd record i.e.
V{<'name','role'><'Steve', Lee
'Finance'><'Lee','Marketing'>} RECARRAY:1:2 returns the
second field of the first record
i.e. Finance
Sometimes useful Content Server data can be buried inside highly nested data structures
which combine a number of different data types in a hierarchy. We can access these by
combining the sub-tags and using them one after the other to work our way into the data
structure.
Category and attribute metadata is stored in Content Server in two tables LLAttraData and
LLAttrBlobData. Both contain the same data but in a different structure. The second of these
is really intended for internal use only. However it has the advantage of storing the
information in a flattened form with a nodes ID and version number as keys to a row in the
table that holds all the attribute data for that node. (LLAttraData has the same data but data
for each node is split over many rows requiring lots of SQL self joins to bring it together).
The columns for LLAttraBlobData are ID, VerNum, SegmentID, SegmentBlob. The attribute
data appears in SegmentBlob. Here is an example:
A<1,?,{274176,3}=A<1,?,'CustomID'=0,'ID'=1,'Values'={A<1,?,2=A<1,?,'I
D'=2,'Values'={'home & home office','small
business'}>,3=A<1,?,'ID'=3,'Values'={1}>,4=A<1,?,'ID'=4,'Values'={'On
the
Road'}>,5=A<1,?,'ID'=5,'Values'={?}>,6=A<1,?,'ID'=6,'Values'={'Good'}
>,7=A<1,?,'ID'=7,'Values'={'Good'}>,8=A<1,?,'ID'=8,'Values'={'Better'
}>,9=A<1,?,'ID'=9,'Values'={'N/A'}>,10=A<1,?,'ID'=10,'Values'={'Best'
}>,11=A<1,?,'ID'=11,'Values'={1}>>}>>
Look closely and you can see that there are Assocs nested within Assocs. The first key of the
first Assoc {274176,3} is a List that identifies a category (274176 is the nodeID of the
category and 3 is the version of the category in use). The value that goes with this key
represents the attribute data. This attribute data for the node looks like this:
As an example lets imagine we want to get access to the usage attribute (which has
attribute ID 4). Its nested inside several Assocs, but by combining several sub-tags we can
get to it (the relevant bits are highlighted in the data structure above):
On the Road
While this is syntactically correct, creating a key such as {274176,3} can be difficult in practice
as you would need to find a category ID as well as the latest version of that category. For this
particular table, this Assoc has only one member so a simpler syntax to use would be:
This variation is mentioned in section 2.2.2 and basically allows each ASSOC item to be
referenced using a numeric index instead of the specific name key.
2.3 Exercises
2.3.1 Task List Report
1. Create a task list with a couple of tasks in it that include example data in the name,
status, comments and instruction fields.
2. (Optional -) Write a LiveReport called List Tasks that lists all the DTree columns for the
tasks in your list. Here is the SQL you will need (note the minus sign):
Find the node ID of your task list by hovering the mouse over the task list link and
observing the URL in your browser status bar.
3. Create a WebReport to display the tasks from your created task list. This can either be
done by using the task list as a data source or by using the List Tasks LiveReport as a
data source. For a reportview you could use the basic reportview as a starting point. Edit
the reportview to provide a tabular report with the following columns:
Task Name
Status (hint: to convert to the phrase, try using the STATUS:TASK sub-tag)
Instructions
Comments
4. Add a column on the far left that contains a link or icon or button to open the task for
editing.
Want to cheat? Here is the code to provide an icon that does this:
WebReports objects themselves make use of the ExtendedData column in the DTree table.
Each WebReport object holds information about things like Parameters, Constants and Export
(Destination) settings inside Content Server data structures in the ExtendedData column.
1. Create a LiveReport called List WebReports to list all the DTree fields for all
WebReports in the system. Here is the SQL you will need:
2. Create a new WebReport using List WebReports as your data source. Edit the
reportview to display the following information in separate columns:
WebReport Name
Name and Value of the first constant if it is defined (display as <name> = <value> in a
single column)
Name and Value of the second constant if it is defined
3. Now filter the results so only WebReports that have constants defined are included in the
report. Use the INCLUDEIF tag to achieve this.
3 Action Sub-tags
SETVAR Takes the data specified by the associated tag and sets a
named variable with it
ADDVAR Takes the data specified by the associated tag and adds it
numerically to a named variable
SETFORM Used with the Form export destination to specify which field in
the form will be set with data from the corresponding tag
An action sub-tag can have any number of normal sub-tags to the left of it in the tag
syntax. Any changes these normal subtags make will be used to perform the
specified action.
Most sub-tags used to the right of an action sub-tag will be ignored. The SHOW sub-
tag (described below) and the CURRENTVAL sub-tag (described in chapter 5) are
notable exceptions to this rule.
Use the CURRENTVAL sub-tag to show the new value of variables following
operations by variable sub-tags
[LL_REPTAG_%test /]
This example shows the syntax if we wanted to display a variable called test in the report
output. This tag can be used anywhere in the reportview but will always display the final
value of the variable. That is, after any variable sub-tags elsewhere in the reportview have
modified the variable. Normal formatting type sub-tags can be used with this tag, e.g.:
[LL_REPTAG_%test UPPER /]
If you want to see the current value of a variable at a specific point in the reportview
(reflecting only the sub-tag actions that have occurred up to that point) you must use the
CURRENTVAL sub-tag as shown here:
[LL_REPTAG_%test CURRENTVAL /]
Action sub-tags can not be used with variable tags unless this CURRENTVAL sub-tag has
been included.
In the upcoming sections we will explore various ways the CURRENTVAL sub-tag can be
used to allow variables to interact with other action sub-tags.
The sub-tags ADDVAR and CONCATVAR are most useful when used in the row section to
combine multiple cells of data into a single value. Note that for adding multiple numeric
values from report data columns, the [LL_REPTAG_@SUM /] tag can also be used. We will
examine some examples of using CONCATVAR and ADDVAR here using this sample data
source and the following syntax explanation table.
ID Name Quota
1 Bob 100
2 Ted 250
3 Carol 150
4 Alice 50
5 Bob 50
The CURRENTVAL sub-tag is used to allow variable sub-tags to display the current value of a
variable according to its position within the reportview. Variable sub-tags are processed
starting at the top of the file and working towards the bottom (rows are also processed in
order from 1 to n). A variable tag of the form, [LL_REPTAG_%test /], returns the final value of
a variable regardless of where it was positioned in the reportview; however, if the
CURRENTVAL sub-tag is included in a variable tag, the tag will display its value according to
its position in the reportview. This example illustrates the difference.
Reportview
[LL_WEBREPORT_STARTROW /]
[LL_WEBREPORT_ENDROW /]
Output
The same output could also be produced with this alternative syntax:
[LL_WEBREPORT_STARTROW /]
[LL_WEBREPORT_ENDROW /]
This variation uses a simple report tag, [LL_REPTAG=quota /], to display the quota value then
when adding the quota to totals, the CURRENTVAL sub-tag is used to display the new value
of totals after ADDVAR executes.
Normal variable tags can not be used to supply data for action sub-tags unless the
CURRENTVAL sub-tag is used.
It is also possible to use formatting or display type sub-tags to modify the data that is output
by CURRENTVAL.
More than one CURRENTVAL sub-tag can be used in a tag provided all syntax requirements
are met.
The last example works as follows: the current value of names is output by the first
(leftmost) CURRENTVAL. This output is then processed by TRUNC:5 (which truncates the
output string to 5 characters) and then concatenated with the variable namestr. Finally the
last CURRENTVAL sub-tag causes the new value of namestr to be displayed in the
reportview
A CURRENTVAL sub-tag must be the first sub-tag used in a variable tag list or must
have a variable action tag (e.g. ADDVAR, CONCATVAR, SETVAR) immediately to its
left in the sub-tag list.
Syntax Validity
Where a CURRENTVAL sub-tag has other action sub-tags to its right, the output of
the CURRENTVAL sub-tag can be used by the next action sub-tag to its right in the
sub-tag list.
Syntax Validity
Where there are non-action (e.g. formatting) sub-tags between CURRENTVAL and
the next action sub-tag to its right, the formatting sub-tags will effect the output of
CURRENTVAL to modify the data that will be used by the next action sub-tag
In this example the output of temp is converted to uppercase, truncated and then
added to anyvar.
The next example illustrates the cause and effect of using variables in conditional expressions
as well as placing variable action sub-tags within a conditional expression.
This example sets a variable called somestr to the string Name List:. In the row section,
multiple names are potentially concatenated to the variable called names. Following the row
section we have a check to see if the names variable is empty or not. If the names variable
is not empty, we concatenate the names variable to the somestr variable to create an
output that would be something like: Name List: Bob, Ted, etc. If the names variable is
empty then we simply set somestr to the literal string: No Names. The somestr variable is
output at the end of the report output.
4.6 Exercises
4.6.1 Building an email distribution list
1. Create a basic WebReport with the _listUsers data source provided and note the
response when you run this report to the browser
2. In the row section for this WebReport, add a report tag to return the mail-addresses from
the data source (E.g. [LL_REPTAG=MAILADDRESS /]). Add the CONCATVAR sub-tag to
this tag so that all of the mail addresses will concatenated (using a comma as the
delimiter) and stored in a variable called emails.
3. Add a variable somewhere near the top of the reportview to show the final value of the
variable emails. Run the WebReport manually and observe the variable result
4. Find a way to force the CONCATVAR sub-tag to use the delimiter for separating email
addresses as defined for the Content Server system. Re-run the WebReport to examine
the final variable result again
5. Add to the row section of the reportview a variation on the variable tag that will show for
each row, the current value of the emails variable
6. Change the destination of the reportview so that the output will be sent via email. Use a
WebReports variable tag to allow the emails variable to be inserted as the E-mail Address:
field
Superficially NODEACTION and USERACTION are similar to other sub-tags but on closer
inspection they differ considerably from both regular sub-tags and action sub-tags. Whilst
regular sub-tags effect formatting and action sub-tags effect data in the WebReport
destination (for example meta data in a workflow) these two sub-tags directly effect the items
that they are executed against, which can be any number of items anywhere in Content
Server.
Understand how to use NODEACTION to create, update, move and delete content in
Content Server
Understand how to use USERACTION to create, update and delete users and groups
in Content Server
[LL_REPTAG=DATAID NODEACTION:DELETE /]
Would delete every object returned by the data source. If the data source was a LiveReport
returning 1,000 rows, you can quickly see what can be achieved!
Copy Allows any node in Content Server (providing the user running the
WebReport has permission) to be copied to a specified
destination. Its possible to specify a name for the new node and
also whether it contains all the versions in the source node or just
the latest version
5.4 Exercises
5.4.1 Copying Content Server content
3. Add TOTALROWS and ACTUALROWS to the report to verify you are filtering on
documents. Run the report and check they return different values.
a. Look in the Tag Guide to get the NODEACTION syntax for COPY
b. Use the USERID tag in combination with the USERINFO sub-tag to get the objectid of
your PWS
5. Execute the report and check the items were added to your PWS.
7. Modify the WebReport so that instead of using the USERID tag you use a user type
parameter for the ID of the user. On the parameters tab, give the parameter a default
value of your own user.
8. Run the WebReport again you should observe the same behavior
Note: By making the userid a parameter we can call this WebReport as a Sub WebReport any
number of times we want passing a new userid each time.
Another possibility is to change the destination of the WebReport so that it does the action
copy, move, delete, etc. then sends an email to the owner of the content informing them of the
action taken
Predefining complex SORT keys so they dont have to be passed as URL parameters
Defining URL parameters that will be used to pass SORT information (removes the
need for WebReports parameter tags to be used as SORT keys
This feature allows complex sort keys to be associated with simple references that can be
passed in the URL. This feature is particularly useful when setting up reports that are sorting
using WebReports tags and sub-tags. When the user selects a column for sorting, it can be
difficult to pass the necessary tag syntax in the URL in order for the SORT tag to execute. To
solve this problem, this feature provides the ability to specify:
The name of one or more parameters that should be checked in the URL
A series of reference words and their associated tag syntax
When this is setup correctly, each specified parameter is checked to see if one of the
predefined reference words has been found. If a specified reference word is found in the URL
parameter then the corresponding syntax for this word is inserted into the SORT tag.
In order to demonstrate the new functionality and to understand some of the benefits it brings,
we will review some of the basics of the original functionality and how the new functionality
addresses some limitations of the original SORT tag functionality.
The basic sort syntax allows one or more sort keys to be specified as well as a sort direction.
E.g.:
In this example the keys are specified directly by using the name of a column such as Name
or DataID. While this is useful, the more common case is that we need to run a WebReport
and specify (using a URL parameter) which column should be sorted. Currently we handle
this situation by using WebReports Parameter tags.
E.g.:
This technique is useful to make a SORT tag flexible enough that a WebReport can be re-run
multiple times using a different SORT order each time.
Another common scenario is that we need to be able to sort according to the fully processed
output of a WebReports tag/sub-tag combination. In many WebReports there will be one or
more display columns that use WebReports to provide data that is not in the data source. For
example, if a data source only provides a list of data IDs. The WebReports sub-tag
NODEINFO could be used to return other pieces of information such as the item Name. E.g.
[LL_REPTAG=DataId NODEINFO:NAME /]
When used in a row section, this allows a WebReports developer to display data that does not
necessarily correspond with any column in the data source. This means that if we want to be
able to sort on this particular column, we need to be able to specify a SORT key in a similar
way. This is done like this:
[LL_WEBREPORT_SORT "[LL_REPTAG=dataid nodeinfo:name /]" /]
This example shows how we would setup a SORT tag to sort based on the output of:
[LL_REPTAG=dataid nodeinfo:name /]
Now if we extend the requirement to pass a sort key as a parameter, we need to be able to
pass syntax such as: [LL_REPTAG=dataid nodeinfo:name /] in a URL parameter. The SORT
tag syntax might look the same as our previous example but the problem is that we have to
pass a relatively complex set of characters in the URL. For example, our URL might look like
this:
&sortkey=[LL_REPTAG=dataid nodeinfo:name /]
There are ways of reducing the amount of tag that needs to be passed as a URL parameter;
however, in general this syntax is fairly verbose and in some cases, the need to include
special characters such as quotes in this syntax can actually cause a rendered WebReport to
fail with JavaScript errors.
This particular requirement is being addressed with the new SORT syntax.
In order to provide the new functionality, two "directives" are provided that can be included
within the SORT tag. These directives are: @PARMNAMES AND @PREDEFKEY. These
directives are explained in depth in the next table.
Directive Description
@PARMNAMES One or more of these directives can optionally be
SORTCOL:<sortcolname> specified. If none of these directives are specified (and a
SORTDIR:<directioncolname> predefined key - as below - is specified) then it is
assumed that the parameters &sort and &direction will be
used to pass any sort or directional references. For each
@PARMNAMES directive that is supplied, an alternative
URL parameter name can be specified for either the sort
column or the sort direction. The ability to specify more
than one @PARMNAMES directive allows multiple sort
columns to be specified. These parameters are used in
the order of the @PARMNAMES directives specified in
the SORT tag. For example, given the following set of
directives:
If the URL
contained:&sortcol3=parentid&sortcol1=Name&sortcol2=
dataid
@PREDEFKEY REF:col3
PARM:"[LL_REPTAG=DATAID
CAT:somecat:attr1:DISPLAY /]"
6.4 Exercises
6.4.1 Specifying Complex sort keys
1. Create a WebReport using the basic reportview and the simple List Docs with Category
data source
2. Change the last two columns so that they display two of the attribute values shown in the
graphic below (use the CAT: sub-tag)
3. For each column that displays an attribute, create a hyper link in the column name.
E.g. <A HREF="[LL_REPTAG_URLPREFIX /][LL_REPTAG_MYID LLURL:REPORT /]&mysort=col1">ColName1</A>
4. Create an empty SORT tag and then add an @PARMNAMES directive to ensure that the
URL parameter (mysort in the example) is recognized by the SORT tag. Specify a
direction parm name as well (although the hyperlink does not actually include any
direction parameters in the URL)
5. In this SORT tag, add two @PREDEFKEY directives so that when each column hyperlink
is activated, the correct tag/sub-tag syntax is executed. Hints:
Each hyperlink should specify a sort parameter and a unique (simple) value for that
sort parameter
The (two) PREDEFKEY directives should be used to map the unique value to
whatever tag/sub-tag syntax is required for the SORT to occur properly
Category Sample:
6. (Advanced) Add the JavaScript listed below and change the hyperlinks as per the
example so that selecting a column multiple times will reverse the direction of the SORT
<script>
var direction="[LL_REPTAG_&dirkey /]";
function doSort(colref) {
url = "[LL_REPTAG_URLPREFIX /][LL_REPTAG_MYID LLURL:REPORT /]";
url += "&sortkey=" + colref;
if (direction == "DESC") {
url += "&dirkey=ASC";
} else {
url += "&dirkey=DESC";
}
document.location = url;
// document.location.replace(url); // if different sort pages are not wanted in history
}
</script>
<A href="javascript:doSort(colname1);">col name1</A>
7 Initiating Workflows
7.2 Concepts
In order for a workflow to be triggered the developer must first set the destination tab of the
WebReport to point to the workflow requiring initiation. Below is a typical configuration
Remember from
WR Design I the blue
callouts provide inline help
for individual fields, the red
flags indicate support for
tag replacement and the
yellow exclamations
indicate mandatory fields.
In the above example the workflow specific field values can be described as follows
Field Description
2. Initiate Map This is a browse field and must be set to the workflow that is to be
initiated. In the example above the standard browse has been
used to define the map. It is also possible to do this via a tag, for
example, a parameter of the form [LL_REPTAG_&MAPID /] could
be used and then passed at run time. The implication of this is that
you can use logic in the reportview to determine which map you
wish to initiate.
3. Workflow Title This is the title you wish to give to the initiated instance of the map.
As this field supports tags, the developer might, as in the example,
pass a parameter to dynamically provide all or part of the name.
4. Workflow Description The description of the instance of the triggered map. In the
example above you will note that the date is also being used as
part of the description.
5. Workflow Due This field determines when the workflow is due. In the example
above the workflow is due in two days. We could have specified
hours here by entering a fraction of a day. So, for example, 0.25
would mean the workflow is due in 6 hours. We could also enter a
fixed due date buy using the due on option.
6. Attach Output to Workflow This field determines whether the results of the report that
triggered the workflow are attached to the instance as a document.
This can be useful when person working on a workflow task wants
to see the reason or set of conditions that caused the workflow to
be triggered.
9. Attachment Categories As above but for categories associated with the attachment
10. Attachment MIME Type As above but for the MIME type
Tip: if you wish to populate a field based on more complicated calculations (as an example a
column total) it is possible to use WebReports variables to build the data then use a variable
tag in the appropriate field on the destination tab.
When this WebReport runs a single workflow will be initiated and the various pieces of meta-
data above will be auto populated at that time. This is illustrated below.
LiveReport
Main Workflow
WebReport Instance
Results attached
Basic meta-data populated
Triggering a Workflow
To set workflow attribute values we must define them in the reportview via the SETWFATTR
(SET WorkFlow ATTRibute) sub-tag. Example:
[LL_REPTAG_DATETIME SETWFATTR:INITDATE /]
The current date and time is returned from the main tag. SETWFATTR then takes this value
and maps it into the workflow attribute called InitDate.
Workflow attributes also support multi values which can be populated using the WebReports
MV operator and the optional ++ operand.
As an example, the File Owner attribute in the diagram above can be populated as follows
This would insert whatever is in the USERID column for the current row into the first element
of the multi value workflow attribute File Owner. To populate the second and any subsequent
elements the ++ operand must be used. As an example,
Remember to use
quotes around field names
[LL_REPTAG_USERID SETWFATTR:MV++:"File Owner" /]
that contain spaces.
would insert the userid of the person running the report into the next element of the attribute
File Owner. By using ++ in this way it is possible to populate multi value attributes of any
length.
The following series of image and tag examples relate to a workflow form called Allocations.
Unless otherwise stated, the image shows the field and the tag shows the syntax to populate
it.
[LL_REPTAG_"TRUE" SETWFFORM:Allocations:"Approved" /]
In this example the SETWFFORM sub-tag is being used to set the Approved field for the
form called Allocations to the literal value TRUE which results in the field being checked.
1.5556
1.6667
1.8889
In order to set the above multi-value Cost Allocation field we need to use the MV operator:
The above statement will insert the literal 1.5556 into the first element of the multi-value field
Cost Allocation. To access any subsequent elements we must use the ++ operand. So,
would insert the literal 1.6667 into the second element of the multi value field and then
Microsoft On Hold
Oracle
Test
In this example we need to use the MVSET operator to index into the Competitors multi-
value set.
[LL_REPTAG_"Microsoft"
SETWFFORM:Allocations:MVSET:Competitors:Developer /]
The two statements above would insert the words Microsoft and On Hold into the two fields
in the first element of the multi-value set.
SETWFFORM
does not output the results
directly to the report by
default. If you also want to
view the value that is being
set, use the optional
SHOW sub-tag.
In order to populate subsequent elements in the multi value set the ++ operand must be used.
As an example,
[LL_REPTAG_"Oracle"
SETWFFORM:Allocations:MVSET++:Competitors:Developer /]
would populate the second value in the multi value set if the statement was used after an
MVSET to populate at least one field in the first element (here the first one inserts the word
Microsoft). As the statement above has had the effect of incrementing the position in the set
to the second element we can use MVSET without the ++ operand to access the field, Temp,
at the current element index, or we can use MVSET++ and move on to the third element of
the multi value set without populating the Temp field.
[LL_REPTAG_"Test" SETWFFORM:Allocations:MVSET++:Competitors:Temp /]
In this example, because we have incremented the MVSET again, we are populating the third
element of the multi value set with the value Test.
March 15 2007
April 1 2009
No Test Info
The following statement has the effect of setting the current date into the first element of the
multi-value attribute Target within the multi-value set Inputs. In this case 15th March 2007.
[LL_REPTAG_DATETIME SETWFFORM:Allocations:MVSET:Inputs:MV:Target /]
This next statement increments the multi-value with the same element of the multi-value set
and inserts the date from the URL parameter called &date1. In this case the value in the URL
is set to 1st April 2007.
[LL_REPTAG_&DATE1 SETWFFORM:Allocations:MVSET:Inputs:MV++:Target /]
Finally this statement show the multi-value set being incremented and a value being inserted
into the Reasons field.
Sub Unlimited # of
Main
LiveReport
WebReport Workflow Instances
WebReport
Results attached
Workflow Dest.
Basic meta-data populated
Form data populated
Attribute data populated
By breaking the problem down into a WebReport and sub-WebReport we are able to report
on all the data were interested in then pass a key as a parameter to a sub-WebReport. The
sub-WebReport has its output destination set to export to a workflow.
In the diagram above we might have the main report returning a list of Content Server dataids
that we want to perform some action on (e.g. theyre all to have an attribute assigned to them
that is in a particular condition). In this case we would want to pass the dataid to the sub-
WebReport and have the sub-WebReport trigger a workflow for that object. The main
WebReport (assuming all filtering etc. is done at the data source level) would simply consist
of:
[LL_WEBREPORT_STARTROW /]
[LL_WEBREPORT_SUBWEBREPORT NODEID:[LL_REPTAG_$SWR /]
PARM:INPUTLABEL1:[LL_REPTAG=DATAID /] /]
[LL_WEBREPORT_ENDROW /]
Here the call to the sub-WebReport is in the row section (between STARTROW and
ENDROW) which means it is called once for each row of data returned by the data source.
The sub-WebReport is defined as a constant called SWR and the column called DATAID is
passed to the sub-WebReport as the parameter inputLabel1.
The sub-WebReport can optionally have a data source that takes parameters and looks up
further information about the nodeid we have passed. The results of this can be used to
populate meta-data.
7.6 Exercises
Use export to workflow to trigger a workflow when a user has exceeded 500 bytes of space in
their personal workspace.
At this stage we have initiated a workflow for the selected user and we have used parameter
tags to populate basic metadata in the workflow (the title).
Now were initiating a workflow and populating basic Metadata as well as attribute data using
a combination of parameters, tags and WebReports variables (where we need to calculate
values).
<IFRAME SRC="?func=ll&objId=xyz&objAction=RunReport"></IFRAME>
Where xyz is the object id of the WebReport you want to run in the IFRAME.
This method has some limitations but is simple and can be used to good effect. There are
two main limitations with this method
IFRAMES always return a string. This is difficult to parse when compared to Ajax
which can return an XML document.
Positioning and sizing within the page is not always easy and often results in
unsightly scrollbars appearing in document. Fixed result sizes are better to deal with
because you can determine the dimensions of the IFRAME in advance.
Note that for any submissions to Content Server that require a document upload (using the
TYPE=FILE form field) it is not possible to use AJAX to post this type of field. For these
scenarios an IFRAME would need to be used.
Use EXCLUDEHTML
to stop headers and footers
appearing in the IFRAME. This
is unsightly and also breaks
some of the Livelink menus
Customview
1. Request WebReport
<DIV ID=customView>
2. Returned Data
</DIV>
<SCRIPT>
updatePage( 1234, 'customView' );
</SCRIPT>
This example is designed to update an HTML DIV that is always added by Content Server as
part of any customview. This DIV has not been included in this example but is assumed to
exist in any customview. Any content in a customview is inserted into this DIV. In our
example we use Ajax to update the contents of this DIV dynamically. While this example is
using an existing DIV, you could just as easily create your own DIV with a unique name and
adapt this example accordingly.
It is not mandatory to
use a DIV, any HTML element
where the attribute innerHTML
is writable can be used.
This first line is a JavaScript include file reference that contains the code to make and return
the Ajax request. This JavaScript library is packaged with WebReports.
The tag
[LL_REPTAG_LIBPATH /]
returns the path to a folder on
the Livelink server which
contains the library file ajax.js.
However, because we are
referencing the include file from
a customview (not a
WebReport) we need to use a
qualified path. In a WebReport
we would only need the tag and
filename
The next reference is a call to the library function, updatePage(). This function takes two
parameters. The first is the object id of the WebReport we are using to retrieve the additional
data (If we had been making the call from another WebReport instead of a customview, we
could have used a WebReports constant which would resolve to an object id). It is also
possible to use a Content Server nickname instead of a literal object ID. The second
parameter is the id of the HTML element we wish to update - in this case we're updating a
customview and we know all customviews are wrappered by a DIV with id, "customView"; this
is the DIV that will be updated with any data returned by the WebReport that is being called
via AJAX.
An example of this could involve displaying each folders category information in its own
customview. To do this we need to pass an extra parameter to the WebReport so that we can
retrieve the category information relevant to the current folder. Here's an example of what the
updated call to updatePage() might look like:
<SCRIPT>
updatePage('nickname', 'customView', '&folderid=' + getURLParm('objid'));
</SCRIPT>
The difference between this and the previous example is a third optional parameter, folderid,
which can be used by the Ajax report to retrieve information specific to the folder we're in. The
function getURLParm() accepts a parameter name and returns the value that is associated
with that parameter in the current URL. In the example above we would end up with
something looking like updatePage('nickname', 'customView', '&folderid=5678' ).
Customview 1. Request
+ folderid
WebReport
<DIV ID=customView>
If folderid == x
process1
else
2. Returned Data process2
end
</DIV>
If you run the Ajax WebReport on its own, everything you see in the browser will be returned
to the main report. For this reason, remember to use [LL_WEBREPORT_EXCLUDEHTML /]
to turn off the standard Content Server headers, footers and include files.
Although we have called this an Ajax example, it is not true Ajax as there is no XML
component were returning plain text instead.
Heres how it might look as the user is typing (observe the number at the bottom of each).
First, create a simple LiveReport (LiveReport Extensions must be installed) which counts the
number of matches for a given string. Something like:
Define the parameter, %1, as type insertString. The LiveReport should prompt for user input
and count all items that start with the letters provided.
Next add a new WebReport that uses the above LiveReport as its data source. Edit this
WebReport and create a simple XML schema so that you have something that looks like:
Set the WebReports Destination page set the mime type to text/xml so that we can make
use of the XML response when we call this WebReport. Now run the report in the browser
and verify that it runs with no errors.
If the destination
mimetype is left as plain text or
html the
http_request.responseXML
object will not be properly
populated when the report runs.
This is in spite of the fact it
looks fine in the browser.
At this point we have finished the WebReport that will return the count information, now we
need to call this from where the user will run his query.
Create a second LiveReport that returns a list of DTree items based on the first part of their
name (Like the LiveReport in 7.5.1, this requires an insertString parameter type). As an
example:
You will note that this is very similar to the previous query; the only difference being that we're
bringing back the data set rather than a count.
Finally, create a second WebReport and use the new LiveReport as the data source. Edit the
reportview so that you have something like:
<SCRIPT>
function updateHits( myFilter ) {
function displayHits( ) {
if (http_request.readyState == 4) {
document.getElementById("hitsText").innerHTML = "Matches: " +
http_request.responseXML.childNodes[1].text;
}
}
</SCRIPT>
[LL_REPTAG_MYID NODEINFO:NAME /]
[LL_REPTAG_MYID LLURL:FUNCTIONMENU /]
[LL_REPTAG_MYID LLURL:UPALEVEL /]
<BR>
<TABLE>
<TR>
<TD>[LL_REPTAG_COLNAME1 /]</TD>
<TD>[LL_REPTAG_COLNAME++ /]</TD>
<TD>[LL_REPTAG_COLNAME++ /]</TD>
<TD>[LL_REPTAG_COLNAME++ /]</TD>
<TD>[LL_REPTAG_COLNAME++ /]</TD>
</TR>
[LL_WEBREPORT_STARTROW /]
<TR>
<TD>[LL_REPTAG_1 /]</TD>
<TD>[LL_REPTAG_2 /]</TD>
<TD>[LL_REPTAG_3 /]</TD>
<TD>[LL_REPTAG_4 /]</TD>
<TD>[LL_REPTAG_5 /]</TD>
</TR>
[LL_WEBREPORT_ENDROW /]
</TABLE>
2. Returned Data
</DIV>
Each time a user presses a key in the filter box a request is issued from the main report
(created in 7.5.2) asking for a new count from the Ajax report (created in 7.5.1). These
requests are very quick as there is no Content Server header, footer or other weighty data to
bring back across the network.
The main report uses a constant, AJAXWR, which needs to be defined on the constants tab
by setting the object type to Content Server and browsing for the Ajax report. Each time the
user clicks, it is the report defined on the constants tab that executes.
The main report also expects a parameter which, unless the report developer states
otherwise will cause a prompt when the report runs. The developer could, on the parameters
tab, enter the parameter name, inputLabel1 in this case, along with an empty default value
and the prompt field set to no. This will have the effect of causing all the results to be returned
initially. Obviously other values could be used although the developer needs to be careful how
many results will be returned when the user first runs the report.
All the code in this chapter has been cut down to a minimum to demonstrate principles and
techniques. It takes no account of error paths, browsers other than IE or Content Server
permissions. These things can all be easily added by the developer.
Starting with WebReports version 5.0.0 there is a feature that allows WebReports sub-tag
processing to be invoked as a service. This feature is invoked using a unique URL as follows:
&func=webreports.runservice
&servicetype= Description/Parameters
gettagdata This service allows the execution of static tags and or sub-tags from the
WebReports engine to be invoked directly. This capability provides a way to
leverage the vast number of useful functions that are available through thie engine,
particularly with the ability to access the 60+ sub-tags and several static tags. Many
of the sub-tags provide the ability to access some useful Content Server functions
such as looking up categories and attributes, testing group membership and even
performing Content Server actions (subject to normal permissions controls).
This table illustrates the supplementary parameters that are used by this service.
Parameter
Mand- Description
Name
atory
TAGDATA YES (if no This parameter can be used to specify data to be operated on by
STATIC any specified sub-tags. If a statictag has also been specified, the
tag is tagdata will be ignored unless the static tag returns a blank
specified string. This allows the tagdata to be used as a default value for
or STATIC situations where the static tag doesn't return a useful value.
tag returns
an empty
string)
STATICTAG Yes (if This parameter can be used to specify one of a selection of
TAGDATA WebReports static tags that can be invoked. If the specified tag
is not returns a blank string, then the value of tagdata (if any) will be
specified) used instead, otherwise, the output from the statictag is used by
any sub-tags that have been specified. The static tag parameter
does not require the full WebReports syntax; only the static tag
name is used. For example, the [LL_REPTAG_USERID /] tag
would be invoked using:
&statictag=USERID
Note that WebReports services only supports a small subset of
the available static tags. In general, any static tags that are used
to return information about an executing WebReport will not be
valid as there is no WebReports object associated with a service
call. To find out which static tags are available, you can use the
liststatictags service type (described below).
&subtags=NODEINFO:NAME UPPER
This service returns all appropriate static values from the WebReports engine in a
getstatictags
data structure according to the responsetype parameter; however, only the json
responsetype is currently supported. Static tags are all of the tags in the
WebReports tag guide that come under the heading of "data tags" and which have
fixed names such as: [LL_REPTAG_DATETIME /].
This service provides a simple list of all the static tags that are available for usage in
liststatictags
the gettagdata and getstatictags services. It is primarily used for the convenience
of developers.
The ajax.js file packaged with WebReports includes a function designed to aid in the use of
WebReport services in conjunction with AJAX technology. The ajax.js file is accessed using a
SCRIPT include like this:
If this file is being included into a WebReport or ActiveView the LIBPATH tag can be used like
this:
servicetype Mandatory This parameter expects a string with one of the supported
servicetypes for running a WR service (as specified in the table
above).
responseTarget Mandatory This parameter expects either a JavaScript function that has
been created by the developer, or a string representing the ID
of an HTML object where the returned data should be inserted.
If a JavaScript function is created (and passed to this
parameter) it should be written to accept the http_request as a
parameter. For example:
function myHandlerFunction(httpRequest) {
alert('the response was: '+
httpRequest.responseText);
}
getPost Optional This parameter can be used to specify whether the AJAX
request should be GET or POST. If omitted, the POST method
is used.
8.7 Exercises
8.7.1 Creating a Dynamic PWS page
1. Create a basic WebReport that uses the LiveReport getMyLastLogin as a data source
2. Note that the data source returns two rows. Find a way to only display the last row (the
second most recent login) in the WebReport.
3. Change the formatting of the AuditDate column to be more user friendly. Use the DATE
sub-tag to achieve this.
4. Edit the reportview so that you have a WebReport that returns My Last Login Was:
<date>
5. Create a Customview in your personal workspace and call the WebReport using the ajax
library.
6. Open your personal workspace - notice you have two sets of Content Server headers and
footers. Edit the WebReport to exclude all the Content Server wrapper HTML
Consider how you might put a copy of the Customview into the personal workspace of every
user in a Content Server system.
This exercise can be completed using information from the WebReports online help,
Advanced Information->WR Services, example 1.
1. Create an HTML Text input field that allows a static tag name to be specified. E.g.:
2. Create an HTML Text input field that allows a list of sub-tags to be specified. E.g.:
3. Create an HTML DIV field that can be updated with returned information from a
service call. Give this DIV a unique ID.
6. Test the service using something like this: statictag USERID, subtags
USERINFO:FULLNAME
9.1 Overview
WebReport data sources (LiveReports, Search Queries, Forms, etc.) can be manipulated
using special parameters called data source parameters. These parameters are passed in the
URL when a WebReport is executed and control things like the maximum number of results
on each page:
?func=ll&objId=1234&objAction=RunReport&sourceid=12345&DSstartrow=11&DSendr
ow=100&DSmaxrows=50
In this example, the data source identified by nodeid 12345 will be used to supply data for the
WebReport. The data used will end at row 50 (despite the DSendrow parameter being set to
100) because the DSmaxrows parameter is set to 50.
9.3 Example
1. Create a new WebReport and name it Display request data with no data source and
the basic_report reportview
2. Create a new WebReport and name it Application with no data source and the
blank_report reportview
3. Add a LivelinkObject type Constant to the Application WR and select the Display
request data WebReport for constant value
4. Edit the Application ReportView; add delimited text in a textarea box; with two input
fields for Row Separator and Column Separator. Add a submit button that will call a
javascript function in the report header. The javascript will retrieve the form data and
send a request to Display request data WR, using the DSRequestData, DSRowSep
and DSColumnSep parameters
9.4 Exercises
1. Create a new WebReport and name it Target Listing Report with no data source and
the basic_report reportview
2. Create a new WebReport and name it Selection Report with no data source and the
blank_report reportview
3. On the Constants tab of the Selection Report, add three LivelinkObject type
constants. The first constant will reference the Content Server User List document
in your Data Sources folder. The second constant will reference the Content Server
Doc List document in your Data Sources folder. The third constant will reference the
Target Listing Report WebReport
Edit the Selection Report reportview and create two hyperlinks. Using the constants above,
each hyperlink should call the Target Listing Report WebReport with objAction=RunReport
and pass in the sourceId parameter to reference each of the document constants.
Example:
<a href="?func=ll&objId=[LL_REPTAG_$targetWR
/]&ObjAction=RunReport&sourceid=[LL_REPTAG_$DocList /]" target="_blank">Open
the Document Listing Report</a>
4. Modify the URL to use URLPREFIX and LLURL WR tags for WebReport call:
10 WR Trigger
10.1 Overview
The WR Trigger feature allows WebReports to be initiated by specific events in Content
Server. For node types that have been enabled with the feature, which is off by default and
can be enabled per node type in the administration pages under WR Trigger Administration,
the WebReport developer can choose to initiate a WebReport for the following Content Server
events:
Add Version
Category Update
Create
Delete
Move
Update
When an item is "Deleted" using the function menu one of two things can happen. The item
might be truly deleted and so completely removed from the database, or the item might be
moved to the Recycle Bin or Undelete Volume. The behavior will depend on how specific
subtypes (Documents vs. Folders etc.) are configured with these modules. The Delete trigger
only fires on a true database delete - i.e. when items are destroyed. If it is required to trigger a
WebReport based on a "function menu delete" that results in the item being moved to the
Recycle Bin or Undelete Volume, the Move trigger event must be used. Logic can then be
used in the WebReport (simply use NODEINFO:PARENTID /OWNERID) to determine
whether the item was moved to one of these locations or elsewhere in Content Server.
When a root node (a container with other items in it) is copied, moved or deleted, the trigger
occurs on the root node only. No WebReport will be initiated for individual sub items. If a
WebReport needs to be initiated for each specific item, it can be achieved using a query that
takes the node that initiated the trigger to find all the children, then use a subWebReport to
implement the specific behavior - e.g. trigger a workflow.
All triggers are initiated after the event has occurred with the exception of Delete. For
example, if using [LL_REPTAG_TRIGGERID NODEINFO:PARENTID /] in a WebReport that
has been initiated by a Move trigger event, the objectid of the new parent will be returned (see
[LL_REPTAG_TRIGGERORIGPARENTID /] for accessing the original). With the delete
trigger, the event is fired just before the delete so that we have the maximum meta data
available. Once a node is truly deleted, it no longer exists and so has no valid meta data.
When a document is added to Content Server, both the Create trigger and the Add Version
trigger are fired. This is because Content Server sees this as two actions. First a node
creation occurs and once the node is created a new version (in this case version 1) is added
to that node. If a folder were added, only the Create trigger would fire.
10.4 Exercises
Initiate a workflow and attach a document to it when a new item is created in a folder with a
WR Trigger applied.
1. Create a new WebReport and name it Item Created WR, with No Data Source and
Basic ReportView. Set the Destination of the WR to your workspaces
DestinationsWorkflow to be initiated by a trigger.
2. Edit the WebReport ReportView and add the following line in either the Header or Footer
section:
[LL_REPTAG_TRIGGERID SETWFATTACH:COPY:INHERITATTRS:MERGED /]
NOTE: TRIGGERID is the id of the object that initiated the event and
SETWFATTACH:COPY:INHERITATTRS:MERGED copies this node to the attachments folder
merging the categories of the node with those of the attachments folder.
4. Select the WR Trigger tab (Properties WR Trigger) on the new folder. Select the
Create Event; choose this node and all children as Inheritance option; and select the
WebReport above.
Note: Rather than initiating a workflow, the WebReports destination tab could be set to send
an email. To attach the item that fired the event to the email destination use
[LL_REPTAG_TRIGGERID /]. It's worth noting that SETWFATTACH and SETEMAILATTACH
can be used multiple times to attach several items to the destination.
Challenge Questions
1. Why did you use the Header or Footer section of the ReportView and not the Row
Section?
2. Go back to the WR Trigger tab on the folder and check the Show WebReport checkbox
for your trigger event. What do you think will happen when you run the report again?
11 WR Power View
Understand the benefits of using a WR Power View over a standard form view
From the form template function menu select "Export as HTML" then save the file to
your desktop.
Go to Properties - Views tab of the from template and select "Add View" followed by
"WR Power View".
You are now presented with the regular add WebReport interface. When selecting
the reportview browse for the file saved to your desktop in the first step.
Open the WebReports tag guide and start making immediate use of the 100+ tags
inside your form view.
WebForms module
must be installed for WR Power
View to be selectable.
Native support for existing form tags like [LL_FormTag_1_1_2_1 /] and [LL_FUNC /]
meaning that WR Power Views are backwards compatible with HTML views.
Full support for WebReports static tags, constants and parameters which can be used
together with form tags.
Ability to apply a WR Data Source enabling you to include dynamic data to your form
display.
Select a WR Power View for a workflow form and use WebReports parameter tags,
[LL_REPTAG_& /], to access information about the executing workflow (e.g. workid,
subworkid, taskid, mapid) then use these to lookup further information specific to the
current step, user or workflow instance.
Below is an example of what you might use WR Power View to achieve. Its an example of a
forms step in a workflow that is being used to re-skin a whole section of workflow functionality.
Allow the forms module to process forms tags and the WebReports engine to process
the WebReports specific tags. This is default behavior and no action is required to
enable it.
Allow the WebReports engine to process both forms and WebReport tags. To enable
this functionality the [LL_WEBREPORT_FORMPARSEOFF /] tag must be included in
the reportview.
If allowing forms to
process a reportview with more
than one form various
behaviors up to as extreme as
SNDR (Server Did Not
Respond) may be observed
WebReports provides several sub-tags which are very useful in the context of workflow forms.
These are
Sub-tag Description
These sub-tags are useful because they all take a subworkid id as an input and use that to
access meta data in the executing workflow. The key to this is knowing that the subworkid is
a parameter in the URL when looking at a WR Power View step. With this knowledge much
of the data in the workflow is accessible. E.g.
[LL_REPTAG_&SUBWORRKID WFINFO:ATTACHMENTFOLDER /]
Tip: if you need to apply a WebReports sub-tag to a form tag, put the form tag inside a
WebReports literal tag to exploit the processing order. E.g.
[LL_REPTAG_[LL_FORMTAG_1_1. /] UPPER /]
11.5 Exercises
In your 11.5.1 Exercise folder, you will find four prepared items:
Power View (html document that will later be used as your Power View)
You will create a PowerView as a View on the Form Template and create a new Form that will
use that View to submit form data.
When editing the form, you will select a Contract Type which will invoke a call to the Folder
Content Display webreport and pass in a sourceid value of a folder that contains the documents
for the selected contract type. You will then select a particular document template and the id will
be stored in the form data.
1. Download the HTML document named Power View and save it to your desktop
3. From the Add View menu, select WR Power View. Name the View CS Initiation
Power View and Browse to select the Power View html file you saved to your desktop.
Without selecting a data source, select the Add button to create the View.
5. Extract the Constants from the content (blue down arrow icon on right)
7. Select the Update button to save the Constants; then return to the Exercise folder
8. From the function menu of the Form Template, select Make Form
9. Make a new Form named Contract Submission Form. For now, select Livelink
Versions for both the Revision and Submission Mechanisms and select Continue button
10. Select the CS Initiation Power View as the Custom View and Add
11. Run the Contract Submission Form and toggle between the two contract type radio
buttons
Challenge
2. Modify the Contract Submission Process workflow form step to use a form with
Power View
Tag Description
From WebReports 4.0.0 onwards all this information, and a lot more, can be collected by
issuing a WebReports specific sysreport using the following URL.
?func=webreports.sysreport
Verify the data source Try running the data source (e.g. Search Query, or
LiveReport) on its own. Do you get the expected
results?
Simplify the destination Does the report work when running the output to the
browser? Make sure this works before sending report s
to more exotic destinations like forms and workflows.
The two most common mistakes when reporting WebReports bugs are:
Upgrading to a new version of WebReports and leaving a patch in the patch folder
that relates to the old version of WebReports
https://knowledge.opentext.com/knowledge/llisapi.dll/open/3945818
13 Help!
There are several resources to be aware of that can be very useful when working with
WebReports:
http://www.resonatekt.com
http://www.resonatekt.com/support.htm
http://www.resonatekt.com/training.htm
WebReports Discussion:
https://knowledge.opentext.com/knowledge/llisapi.dll/open/WebReportsDiscussion
WebReports Documentation:
User Guide
Admin Guide
Release Notes
https://knowledge.opentext.com/knowledge/llisapi.dll/open/17655534 (v5.1.0)
Online Help:
Detailed Examples worked examples for Pagination, Cats & Atts, AJAX.
The template feature allows optional SQL clauses to be predefined in the LiveReport. Each
template is created so that only the pieces of data that need to be variable are passed as
parameters. Each template may be configured so that a predetermined condition must be
met in order for the template to be included.
Templates are useful when creating ad-hoc reporting tools where the ability to dynamically
add or remove filters or change the data set is important.
Additional templates
can be created using the
icon. Templates can be
removed by clearing any text in
the SQL source box and saving
the LiveReport.
Field Description
Auto-Where Checking this box will automatically add the correct filter word (either
WHERE or AND or OR) to the beginning of a template
SQL Source The statement which will optionally be added to the SQL
Auto Comma Ensures that any comma separated variables (e.g. %1, %2, %3) have the
correct number of commas in place after the variables have been
resolved
Include IF The conditions for template inclusion are selected using this option
Mandatory (no The template will always be inserted when this option is selected. This
condition) option is useful for breaking the SQL down into smaller pieces
URL Parameter This option specifies that this template will be inserted if a named
parameter is found in the URL
No Inputs set to The template is only included if none of the values in the user inputs
Not all inputs set Similar to the previous option the template will be included, unless all
to flag input values have been set to the specified flag
The SQL block order by Name will be inserted in place ~1 when the parameter nameorder is
present in the URL. If nameorder is not present in the URL or is set to false, the template will
not be inserted and ~1 will be replaced with an empty string.
Example URL
/livelink.exe?func=ll&objAction=RunReport&objId=32666&nameorder=true
From looking at these examples it can be observed that they need to be joined together with
OR, AND or WHERE logic depending on the particular use. If Auto-Where is ticked and the
main SQL source doesnt include a WHERE statement, the first template to be added to the
source needs to be preceded by WHERE, instead of AND or OR.
The Auto-Where feature deals with all of these AND/WHERE/OR scenarios as follows
Auto-Where Rules
Any template without Auto-Where selected will be ignored by the Auto-Where feature, even
if one of the reserved words WHERE, AND, OR has been included in the template source
If the first word is WHERE, AND or OR and this is the first template to be included, then the
word is converted to or left as WHERE
If neither WHERE, AND or OR are found and this is the first template to be included, then
the word WHERE is added to the front of the template
If the first word is AND or OR and this is NOT the first template to be included, then the
template is left as is
If the first word is WHERE and this is NOT the first template to be included, then WHERE is
replaced with AND
If none of these words are found and this is NOT the first template to be included, the word
AND is added to the front of the template
This feature provides a mapping capability that allows users to insert the same template
multiple times with different inputs on each occasion.
Repeatedly inserting the same template using a different user inputs requires constructing
multiple OR clauses. The use of the Auto-Where feature allows the template to automatically
add WHERE instead of OR when the first template is inserted, and then to use OR for each
subsequent template that is inserted. An example:
Defines a simple SQL statement that has a single template inserted at the end of it.
Template configuration
Here the template is defined. The template is controlled by a URL Parameter called
nameclause. The SQL Source for the template contains a parameter reference #1. It is
important to note this is different to &1. Where &1 would always insert the contents of the
parameter &inputLabel1, #1 allows any of the user input parameters to be mapped into the
template using &namecause=Ux where x is the number of the user input parameter.
Parameters
...&nameclause=U1&nameclause=U2&nameclause=U3&inputlabel1=cat&inp
utlabel2=dog&inputlabel3=frog...
In the URL the parameter nameclause (which controls the template insertion) appears three
times which means the template will be inserted three times. The value of nameclause is
different in each of the three occurrences. In the first case, nameclasue is equal to U1 which
has the effect of inserting the template and passing the first user input parameter
(&inputLabel1) to the template. The second time nameclause appears it has a value of U2
which has the effect of inserting the template with the value of the second user input
parameter.
Resulting SQL
The following example shows two different templates. One supports a direct match using
equals (=) and the other supports a partial match using LIKE. Either one can be selected
using the appropriate parameter (likecompare or equalscompare). The two parameters are
passed with a value containing a list of which User Inputs to insert in the template.
Here we can see a simply query with two templates being inserted.
Template configuration
Example URL
...&likecompare=u1,u2&equalscompare=u3,u4&inputLabel1=name&inputLabel
2=%new%&inputLabel3=dataid&inputLabel4=12345
Resulting SQL
Graphical Illustration
#1 #2 #1 #2
&likecompare=u1,u2 &equalscompare=u3,u4
select * from DTREE WHERE name LIKE '%new%' AND dataid = '12345'
Template ~1 is included because likecompare is in the URL and there are two User inputs
specified (#1 & #2) as required by the template. #1 is replaced with U1 (inputlabel1) which
equates to name. #2 is replaced with U2 (inputlabel2) which equates to %new%
Template ~2 is included because equalscompare is in the URL and there are two User inputs
specified (#1 & #2) as required by the template. #1 is replaced with U3 (inputlabel3) which
equates to dataid. #2 is replaced with U4 (inputlabel4) which equates to 12345
%1, %2, %3
When these User Input parameters are resolved, if one of them resolves to an empty string,
e.g. &inputlabel2, then the output could end up looking like: apple,,pear. If the Auto Comma
feature is enabled then the output would be corrected to: apple,pear.
15.1 Overview
Although WebReports provides a number of tags to control what is included and excluded in a
WebReport, there remain tasks that demand the power of a fully fledged scripting language at
the server (before the report reaches a client). In WebReports version 4.0 and onwards the
optional ability to embed a section of script within a reportview is provided.
This feature offers tremendous power and flexibility for reporting or web application
developers. As with many powerful features, it follows that this capability also has potential
risks if used improperly. To reduce these to a minimum WebReports scripting has been
carefully secured and constrained in a configurable way that allows each Content Server
instance to choose precisely which script features should be enabled and which not.
Presently the only script language supported is Oscript. Oscript has the advantage of running
natively on the Content Server platform and hence offers excellent performance. Although
technically it is not required for creating WebReports with Oscript, developers with access to
the Content Server SDK will benefit from the Content Server Builders debugging facilities. In
practice, for anything but relatively simple scripts access to the Content Server Builder
debugger will be essential to allow developers to step through their code and debug it.
This section explains how to implement a script within a WebReport, but does not cover how
to write Oscript or provide a reference for Oscript syntax. For more information about Oscript
consult the Content Server SDK documentation such as the Content Server Builder help, or
contact OpenText for details of Content Server SDK training.
15.2 Security
There are a number of layered security measures to ensure that WebReports scripting is as
safe as possible:
1. If not required, the entire feature can be turned off globally by the Content Server
Administrator. Users may wish to check with their Administrator that the feature is
active before attempting to use it.
2. Even if the feature is on globally, it must be enabled for each individual WebReport
that uses it, every time a new reportview version is added to the WebReport. Any
user who can create a WebReport can include the tags to define and call scripts but
the tags will remain disabled until a System Administrator reviews and enables
scripting for the report. Disabled reports will run but will ignore and not execute
scripts.
3. The functions available within Oscript are heavily restricted by default. For example
you may not access Global variables or many of the Builder built-in packages such as
CAPI, DAPI, File, etc. What is and is not available can be configured by the Content
Server Administrator.
Only users with the system administration rights privilege have the ability to enable scripting
for a particular WebReport. There are three different ways of doing this:
1. Add the new Reportview version. When a System Administrator adds a reportview
containing scripting it is automatically enabled.
2. Go to the Properties -> Specific tab for the WebReport and check the Oscript
Scripting Enabled checkbox which will appear if scripting is present in the reportview.
Clearly, users without the system administration rights privilege will find developing a
WebReport that contains scripting a tedious process since each new version of their
WebReport will need to be enabled by someone who does have that privilege. This is one
reason why it make sense to develop scripted WebReports on a non-production instance
where the developer may be granted the system administration rights privilege. See 9.3.
The only exception to this is that any user may create a WebReport from a default reportview
that contains oscript and it will be enabled automatically without the need for a System
Administrator to enable it. If the reportview for the WebReport is later edited or a new version
added, then its oscript will be disabled unless re-enabled by a System Administrator.
Because default reportviews are pre-enabled it is essential that any reportviews containing
oscript that are to be made default reportviews (by placing them in the default reportview
folder See the WebReports Installation and Administration Guide) must be tested and
approved.
WebReports uses a scheme of restrictions to make Oscript in the reportview more secure.
These are:
No ability to use parenthesis like this .() to evaluate the contents of a variable. For
example you cannot do this as .(s) is not permitted:
Assoc myAssoc
String s = 'item1'
myAssoc.item1 = 'first item'
echo ( myAssoc.(s) )
Some functions within certain restricted Builder Packages are permitted (see list
below)
The following Builder Packages are permitted by default. However the Content Server
Administrator can chose to add anything to or remove anything from the permitted list of
Packages or Package functions.
Permitted packages: 'Assoc', 'Bytes', 'Date', 'List', 'Math', 'Pattern', 'RecArray', 'Str', 'String',
'Boolean', 'Undefined', 'Void', 'Integer', 'Real', 'Record'
Once in place on the production instance, a System Administrator should use the WebReports
admin page Manage WebReports Scripting to review all the reports and enable them if they
are satisfied that the reports and in particular the scripting aspects are safe. The kinds of
pitfalls to check for are:
Possibility of infinite loops which could tie up threads on theContent Server server
Lack of checks for undefined data or passed parameters (i.e. the script must check
for and handle undefined parameters)
The first two of these represent the risks with the greatest potential to impact Content Server.
[LL_WEBREPORT_STARTSCRIPT NAME:myFunc /]
function String anyName(Dynamic c)
String s = 'Testing'
return s
end
[LL_WEBREPORT_ENDSCRIPT /]
When called this simple script returns the string Testing to the reportview. The string will be
inserted into the resulting report output where the call to the script was made. To call the
script use:
[LL_WEBREPORT_CALL NAME:myFunc /]
This tag will cause the script named myFunc to be executed and any result returned by it to
be inserted into the report output in place of the tag. Scripts can be called from anywhere in
the reportview.
Data as passed to the WebReport from the data source may be accessed from within the
script. The first parameter passed to the first Oscript function declared in the script will always
be an Assoc called the Context. If there is a data source for the WebReport, the Context
Assoc will contain a key called data holding a RecArray (a two-dimensional array) which will
represent all the data passed to the WebReport by the data source.
[LL_WEBREPORT_STARTSCRIPT NAME:myFunc /]
function String anyName(Dynamic context)
String cell = ""
if isDefined (context.data) // check there is a data source
cell = context.data[1][1] // return the first cell of data
end
return cell
end
[LL_WEBREPORT_ENDSCRIPT /]
Note the check to determine if context.data is defined. If there had been no data returned by
the data source (or no data source at all) context.data would be undefined and failing to check
for it would result in the entire WebReport failing to continue processing. The script is always
responsible for checking that the data it expects has in fact been passed.
When calling a script you may explicitly pass any number of parameters. For example the
following passes three parameters:
Parameters containing spaces can be delimited with double or single quotes. The parameters
are passed to the first function declared in the myFunc script. They appear as an Oscript List
of values in the second parameter (after the Context Assoc). For example:
[LL_WEBREPORT_STARTSCRIPT NAME:myFunc /]
function String anyName(Dynamic context, List args)
String s
s = args[1] + "-" + args[2] + "-" + args[3]
return s
end
[LL_WEBREPORT_ENDSCRIPT /]
Example
The following example reportview illustrates how to access the data in the Context Assoc and
also how to explicitly pass a parameter to a script. This report will display all the data from a
data source regardless of how many columns that data source might return.
[LL_WEBREPORT_STARTSCRIPT NAME:doRow /]
Function String doRow (Dynamic c, List args)
Integer row, col
String s =''
row = Str.StringToInteger(args[1])
if isDefined(row)
for col=1 to length(c.data[1])
s+= Str.Format( '<TD>%1</TD>', c.data[row][col])
end
end
return s
end
[LL_WEBREPORT_ENDSCRIPT /]
[LL_WEBREPORT_STARTSCRIPT NAME:doRowHeader /]
Function String doRowHeader (Dynamic c, List args)
String field
String s =''
List fields
if isDefined(c.data) // check there is data
fields = RecArray.FieldNames(c.data)
for field in fields
s+= Str.Format( '<TD>%1</TD>', field)
end
end
return s
end
[LL_WEBREPORT_ENDSCRIPT /]
<TABLE>
<TR>
[LL_WEBREPORT_CALL NAME:doRowHeader /]
</TR>
[LL_WEBREPORT_STARTROW /]
<TR CLASS="[LL_REPTAG_ROWNUM ODDEVEN:Browserow1:Browserow2 /]"
VALIGN="CENTER" NOWRAP ALIGN="LEFT">
[LL_WEBREPORT_CALL NAME:doRow PARM:[LL_REPTAG_ROWNUM /] /]
</TR>
[LL_WEBREPORT_ENDROW /]
</TABLE>
For example you may need to know the value of a WebReport constant or parameter.
Although you could arrange to pass these items as parameters at the time the script is called,
you can also access them directly using the built-in dot function ._repTag which has the
following syntax:
Parameters:
tag - A string value representing the tag plus optional sub-tags
Returns:
A String value containing the final value of the specified tag and sub-tags.
Here are two examples which return the value of a WebReport constant called report:
Note that you may specify either the full tag name or a shortened version which omits the
opening [LL_RETAG_ and closing /]. Here are some further examples:
Note that not all sub-tags are supported when used within ._repTag. Generally sub-tags that
cause some other action besides returning formatted data do not work. The following sub-
tags are not supported: ADDVAR, CONCATVAR, NEXT, PREV, SETFORM, SETVAR,
SETWFATTR, SETWFFORM.
Parameters:
data - A String value to be operated on by the sub-tags
subtags - A String containing the sub-tags to use on the data
Returns:
A String value containing the result of the data transformed by the sub-tags.
String s = ._subTag('3','DECODE:1:Beginning:2:Middle:3:End:Other
UPPER')
Note that not all sub-tags are supported when called by ._subTag. Generally sub-tags that
cause some other action besides returning formatted data do not work. The following sub-tags
are not supported: ADDVAR, CONCATVAR, NEXT, PREV, SETFORM, SETVAR,
SETWFATTR, SETWFFORM.
Parameters:
nodeid - A String or Integer value specifying the nodeid of the report to run
parms - An optional String containing the parameters to pass to the sub-
WebReport. The required format is
'PARM:myParm1:myVal1:myParm2:myVal2' etc.
option - An optional String value of either output, data or all selecting the
required form of the results (see below); defaults to output.
Returns:
In all cases an Assoc is returned with a key ok holding a Boolean value that
is TRUE if the call was successful. If unsuccessful there is a further key err
containing an error String. If successful, the additional keys are as follows:
There follows an example which takes a nodeID (DataID) from the data source and uses it as
a parameter when calling a sub-WebReport. The script checks the sub-WebReport call was
successful and either outputs the result or an error message:
[LL_WEBREPORT_STARTSCRIPT NAME:callSWR /]
Function string callSWR(Dynamic c)
Assoc result
String parm = Str.Format('PARM:inputlabel1:%1', c.data[1].DataID)
if result.ok
return result.output
else
return result.err
end
end
[LL_WEBREPORT_ENDSCRIPT /]
[LL_WEBREPORT_CALL NAME:callSWR /]
In this example ._repTag is used to return the value of a constant that points to the sub-
WebReport required.
Note that multiple oscript functions may also be declared within a single script block (i.e.
between [LL_WEBREPORT_STARTSCRIPT /] and [LL_WEBREPORT_ENDSCRIPT /]).
Functions within the same script block may call each other. However, only the first function
declared in any script block can be called from another script block (or from the reportview
using [LL_WEBREPORT_CALL /]). One can think of a script block as a discrete oscript
feature within the Content Server builder which behaves the same way in this respect.
Readers familiar with JavaScript should note that the rules described here are quite different
from those that apply to JavaScript.
To call another script in the reportview simply preface the name of the script block with a dot
.. This is illustrated in the following, somewhat contrived, example that performs an HTML
escape on every item of data in the Name column and concatenates them together
separated by semi colons:
[LL_WEBREPORT_STARTSCRIPT NAME:escape /]
function String escape(String input = '')
return Web.EscapeHTML(input)
end
[LL_WEBREPORT_ENDSCRIPT /]
[LL_WEBREPORT_STARTSCRIPT NAME:Main /]
function String anyName(Dynamic context)
String s
Integer i
if isDefined (context.data) // check there is a data source
for i = 1 to length (context.data)
s += .escape(context.data[i].Name) + '; '
end
end
return s
end
[LL_WEBREPORT_ENDSCRIPT /]
[LL_WEBREPORT_CALL NAME:Main /]
15.10 Exercises
15.10.1 Scripting Exercise
In this exercise you will create a report that outputs a comma separated values report for any
number of columns. As you are working on your reportview, cick Add Version & Continue
from time to time to save your work. This also has the benefit of identifying errors as you go
which often makes it easier to identify what is wrong.
1. Create a WebReport using a List DTree LiveReport as a data source and using the
basic_scripted reportview. If that reportview does not appear in the list of default
reportviews, it can be added by an administrator or supplied by your instructor. (It exists
along with other useful reportviews in the module\webreports_4_x_x\examplereportviews
folder in the module).
2. Edit the reportview and click on the Header Section to expand that section where most
of the code is. This report contains all the code to handle a variable number of columns
and output a simple HTML tabulated reported. Your task is to modify it to output CSV.
3. Find the script block called doHeading. Note how the string s is used to build up the
report output. We dont want any HTML tags so remove the s += '<TR>' and s +=
'</TR>' lines of code. Change the code inside the for-loop to read
s += Str.String(columnNames[col]) + ','
This give us a basic header row in CSV format. The only problem is we will have an extra
comma at the end of the header row, so add this code after the for-loop to drop the extra
comma:
if length(columnNames) > 0
s = s[1:-2]
end
4. Find the script block called doAllRows. Again make changes so that the string s is
building up a CSV report and not an HTML table. Remove the following lines of code:
s += '<TR CLASS="' + ((row%2==1)?'browseRow1':'browseRow2') + '"
VALIGN="CENTER" ALIGN="LEFT">'
s += '</TR>'
5. Change the last line of doAllRows to read as follows in order to make sure each row
ends with a newline character:
return Str.Catenate(rowArray,Str.CRLF)
6. Get rid of any other HTML code or spare carriage returns or line feeds in the header, row-
section or footer. Take care not to delete the [LL_WEBREPORT_CALL /] tags at the
bottom of the header. This is what actually calls the script blocks.
7. Save your reportview. If there are any compile errors correct them and save again.
Change the destination of the WebReport to Desktop (go to the function menu for your
WebReport and select Properties -> Destination. Select Desktop). Set the MIME type to
text/csv and the filename to data.csv.
8. Now run your report. It should download and invite you to open or save. Click open and
the report should open in Excel. Youll notice that in some places the data seems to
occupy more columns than there are headings. This is because there are commas in the
data causing Excel to get confused. Data that has commas or new line characters needs
to be escaped by wrapping it in quotes. There is a handy sub-tag that does this called
ESCAPECSV. Review the chapter on calling sub-tags from a script block and use it to fix
the problem.
The information in this document is subject to change without notice. All rights reserved.