Type search words and press enter
A new GSTR-2B API is applicable from 14th Nov 2024, which affects auto-reconciliation of GSTR-2B for Oct-24. Stay tuned for our upcoming release, TallyPrime 5.1, which supports this and makes reconciliation even smoother.
https://help.tallysolutions.com/docs/td9rel54/tdlreference/release_1_8.htm

What’s New in Release 1.8

Invoking Actions on Event Occurrence - with System and Printing Events Introduced

In any language, event handling is one of the powerful features, as it allows the developer to perform some operation based on some implicit action. In order to detect the events and to perform some action based on the event, a proper Event Framework is required.

Prior to this release, the Events Form Accept and Focus had been introduced. In this release, there has been a major enhancement in Event Framework as a whole. We will see in detail the events supported in TDL. Let’s start with an overview of Event Framework and types of events.

Event Framework Overview

When the user does something, an event takes place. Events are actions which are detected by a program and can change the state of system or execution flow. Events can occur based on user actions, or can be system-generated. In TDL, the Key Framework is mainly used to handle user actions like keyboard and mouse events. This can be considered as a part of Event Framework.

We know that TDL is a definition language which does not have any explicit control on the flow of execution. The programmer has no control over what will happen when a particular event occurs. There are certain attributes like SET/PRINTSET, used to initiate some action on occurrence of event/change of state (like report construction,etc.). In this scenario, there is a need of a generic Event Framework, which allows the programmer to trap the events and initiate an action/set of actions in the state when the event has occurred.

The event framework allows the specification of an Event Handler, where it is possible to specify an event Keyword, a Condition to control event handling and the Action to be performed. The process of detecting an event and executing the specified action is called as Event handling.

Types of Events

When the user operates the application, different types of events are generated. The events are classified as System Events or Object-Specific Events, based on their origin.

System events are for which no object context is available, when they occur.

Example

Tally application launch.

Object Specific events are performed only if the specific object context is available.

Example

Form Accept is a Form-specific event.

System Events

In TDL, a new type ‘Events’ has been introduced in the System definition. All the system events are defined under this definition. As of now, TDL event framework supports the following four system events, viz. System Start, System End, Load Company and Close Company.

Syntax

[System : Events]

Label : <EventKeyword> : <ConditionExpr> : <ActionKeyword> : <Action Parameters>

Where,

< Label > is a name assigned to the event handler. It has to be unique for each event handler.

< EventKeyword > can be one of System Start, System End, Load Company or Close Company.

< ConditionExpr > should return a logical value.

< ActionKeyword > can be any one of the actions.

< Action Parameters > are parameters of the action specified.

The events System Start and System End are executed when the user launches or quits Tally application, respectively. The events Load Company and Close Company are executed when the user loads or closes a company, respectively.

Example

[System : Events]

AppStart1 : System Start : TRUE : CALL : MyAppStart

The function MyAppstart is called as soon as the Tally application is launched.

Object Specific Events

Objects specific events can be specified for the associated object only.

Example

Before Print event is specific to ‘Report’ object. The attribute ON is used to specify the object specific events as follows:

Syntax

ON : EventKeyword : <ConditionExpr> : <ActionKeyword> : <Action Parameters>

Where,

< EventKeyword > can be any one of ‘Focus’, ‘Form Accept’, ‘Before Print’ and ‘After Print’.

< ConditionExpr > should return a logical value.

< ActionKeyword > can be any one of the actions.

< Action Parameters > are parameters of the action specified.

ON is a list type attribute, so a list of actions can be executed when the specific event occurs.

Event – FORM ACCEPT

The event Form Accept is specific to ‘Form’ object; hence, can be specified only within Form definition. A list of actions can be executed when the form is accepted, which can also be based on some condition. After executing the action Form Accept, the current object context is retained. So all the actions that are executed further, will have the same object context.

The event ‘Form Accept’, when specified by the user, overrides the default action Form Accept. So, when ‘Form Accept’ event is triggered, the Form will not be accepted until the user explicitly calls the action ‘Form Accept’.

Example

[Form : TestForm]

On : FormAccept : Yes : HttpPost : @@SCURL : ASCII : SCPostNewIssue : SC NewIssueResp

Action Http Post is executed when the event ‘Form Accept’ is encountered. But, the form will not be accepted until the user explicitly calls the action Form Accept on event Form Accept as follows:

On : FormAccept : Yes : Form Accept

Now, after executing the action Http Post , Tally will execute the action Form Accept as well.

Event – FOCUS

The event Focus can be specified within the definitions Part, Line and Field. When Part, Line or Field receives focus, a list of actions get executed, which can also be conditionally controlled.

Example

[Part : TestPart2]

On : FOCUS : Yes : CALL : SCSetVariables : $$Line

Event – BEFORE PRINT

The event Before Print is specific to ‘Report’ object; so it can be specified only within ‘Report’ definition. The event ‘Before Print’ is triggered when the user executes the ‘Print’ action. The action associated with the event is executed first, and then the report is printed.

A list of actions can be executed before printing the report, based on some condition.

Example

[Report : Test Report]

On : BEFORE PRINT : Yes : CALL : BeforeRepPrint

The function BeforeRepPrint is executed first and then the report Test Report is printed.

Event – AFTER PRINT

The event After Print can be specified for Report, Form, Part and Line definitions. It first prints the current interface object and then executes the specified actions for this event. A list of actions can be executed after printing the report based on some condition. Print is an alias for After Print.

Example

[Line : LV AccTitle]

On : After Print : Yes : CALL : SetIndexLV : #LedgerName

The function SetIndexLV is called after printing the line LV AccTitle . So, if there are 10 lines to be printed, the function will be called ten times.

Collection Enhancements

Using External Plug-Ins as a Data Source for Collections

A Dynamic Link Library takes the idea of an ordinary library one step further. The idea with a static library is for a set of functions to be collected together, so that a number of different programs could use them. This means that the programmers only have to write code to do a particular task once, and then, they can use the same function in lots of other programs that do similar things.

A Dynamic Link Library is similar to a program, but instead of being run by the user to do one thing, it has a lot of functions “exported”, so that other programs can call them. There are several advantages of this. First, since there is only one copy of the DLL on any computer used by all the applications that need the library code, each application can be smaller, thus saving disk space. Also, if there is a bug in the DLL, a new DLL can be created and the bug will be fixed in all the programs that use the DLL just by replacing the old DLL file. DLLs can also be loaded dynamically by the program itself, allowing the program to install extra functions without being recompiled.

What is DLL?

A Dynamic Link Library (DLL) is a library that can be called from any other executable code, i.e., either from an application or from another DLL. It can be shared by several applications running under Windows. A DLL can contain any number of routines and variables.

Dynamic Link Library has the following advantages:

Saves memory and reduces swapping: Many processes can use a single DLL simultaneously, sharing a single copy of the DLL in memory. In contrast, Windows must load a copy of the library code into memory for each application that is built with a static link library.

Saves disk space: Many applications can share a single copy of the DLL on disk. In contrast, each application built with a static link library has the library code linked into its executable image as a separate copy.

Upgrades to the DLL are easier: When the functions in a DLL change, the applications that use them do not need to be recompiled or re-linked, as long as the function arguments and return values do not change. In contrast, statically linked object code requires that the application be relinked when the functions change.

A potential disadvantage of using DLLs is that the application is not self-contained; it depends on the existence of a separate DLL module.

Differences between Applications and DLLs

Even though DLLs and applications are both executable program modules, they differ in several ways. To the end user, the most obvious difference is that DLLs are not programs that can be directly executed. From the system's point of view, there are two fundamental differences between applications and DLLs:

An application can have multiple instances of itself running in the system simultaneously, whereas a DLL can have only one instance.

An application can own things such as a Stack, Global memory, File handles, and a message queue, but a DLL cannot.

Types of DLL

When a DLL is loaded in an application, there are two methods of linking, i.e., Load-time Dynamic Linking and Run-time Dynamic Linking. Static Linking happens during program development time, whereas dynamic linking happens at run time.

Load time Dynamic Linking /Static Linking

In Load-time Dynamic Linking, an application makes explicit calls to exported DLL functions like local functions. To use load-time dynamic linking, a header(.h) file and an import library (.lib) file are provided, while compiling and linking the application. Thus, the linker will provide the system with information required to load the DLL and resolve the exported DLL function locations at load time.

Run-time Dynamic Linking /Dynamic Linking

Dynamic linking implies the process that Windows uses to link a function call of one module to the actual function in DLL. In Run-time Dynamic Linking, an application calls either the function LoadLibrary or the function LoadLibraryEx to load the DLL at run time. After the DLL is successfully loaded, the function GetProcAddress can be used to obtain the address of the exported DLL function that has to be called. In case of run-time dynamic linking, an import library file is not required.

Please note that Tally does not support Static Linking; only Dynamic Linking is possible.

DLL Approach in T ally

As discussed before, Dynamic Link Library (DLL) is a file that can contain many functions. We can compare it with the library functions provided with many programming languages like C, C++. In Tally, there is provision to access the external functions by uploading the DLLs. In general, the DLLs can be generated using VC++, VB, .Net framework, etc., and can be invoked from TDL. Hence, using TDL, the functions of DLL can be invoked to perform the necessary operations.

Why it is required in Tally?

In Tally, all functions are not required for all the customers. Only generalized features are included to keep the functionality of Tally simple. But, for some customers, basic Tally may not cater the need. For that, we may need to extend the functionality of Tally by writing programs in TDL. TDL is designed to handle the functions in-built in Tally. For the functions that are not available in Tally, we use DLL, wherein we can include many functions and use it in Tally by calling those functions.

How to use DLL in Tally?

Loading the DLL’s

1. Copy the DLL file to Tally folder, say C:\Tally.ERP9.

DLL points to the external functions that are to be loaded during startup of Tally application. Tally loads DLLs from the source to the memory, and DLL functions are available with Tally for usage.

OR

2. Register the DLL file using setup program or Command prompt.

In TDL, DLL can be invoked by using C a llDLLFuncti o n and DLL Co l lection .

Note: The CallDLLFunction is a platform function which was already available earlier, and is NOT a part of Collection Enhancements. It has been discussed here just as an additional information. DLL Collection is an enhancement in this Release, which has been emphasized in the subsequent sections.

Function - $$CallDLLFunction

The internal Function $$CallDLLFunction can be used to call an external DLL containing multiple Functions

Example

If a DLL “TestDll” contains two functions FuncA and FuncB, where

FuncA takes one parameter of ‘String’ Data Type and returns a String

FuncB takes a parameter of ‘String’ Data Type and Executes the Function. It only returns the status of the function execution (boolean value)

The syntax of invoking the DLL from TDL will be as follows:

Syntax

[Field : <Field Name>]

Set A s : $$CallDllFunctio n : <DllName>:<Functi o nName> : <Param 1> : <Param 2> ….

Where,

< DLLName > is the name of the DLL.

< Function Name > is the name of the Function.

< Param1 > and < Param2 >…. are the Parameters for the function.

The value returned from the function will be available in the field.

To call FuncA

[Field : Field2]

Use : NameField

;; Assuming Field1 is of Type ‘String’

Set As : $$CallDllFunction:TestDll:FuncA:#Field1

To call FuncB

[Key : Key1]

Key : Ctrl+A

Action : Set : VarStatus : $$CallDllFunction:TestDll:FuncB:#Field1

This key can be associated to a Form or a Menu. The function FuncB in TestDll can be used to return the status of the execution, i.e., Success/Failure (1/0). This value can be obtained in a variable in TDL and used to display the appropriate message to the user.

$$CallDllFunction can be used to call any function which returns single values. If the function returns an array of values, then it is advisable to use $$DLLCollection.

Let us have an overview of the usage of DLL Collection.

DLL Collection, its Attributes and Usage

Tally now provides a TDL interface to obtain data sets in Collection from external Plug-Ins. These Plug-Ins are written as DLL’s which can be used to fetch external data (i.e., from Internet, external Database, etc.). These DLL's should return a valid XML which can be easily mapped into TDL Collection. In other words, TDL developer can provide a simple string value and/or XML to the

DLL function. The DLL gives XML data as an output. Collection takes this data and converts it into objects and object methods, which can be accessed in TDL like other objects.

DLL collection will be very useful in the following scenarios:

1. To display stock quotes from the internet

2. To get data from different formats like CSV, HTML

3. External device interfaces

4. RFID Barcode scanner

5. Petrol Pump device interface

6. Foot fall count

7. External application interfaces

8. GAS distributor application

9. To get attendance details in Pay Roll through swipe

In DLL collection, support is being provided for Plug-Ins and ActiveX-Plug-Ins.

Plug-Ins: DLLs created using C++ or VC++. These DLLs need not be registered separately.

ActiveX Plug-Ins: DLLs created by using VB6, VB.Net, C#.Net, etc. These DLLs have to be registered. Registration process has been explained in detail later.

At present, the ‘Collection’ definition allows working with a C++ DLL, VB DLL, .Net DLL, etc., which has a function defined by the name TDLCollection (The function has to be created by this name ONLY). This function delivers an XML which is available as objects in the Collection.

Attributes of DLL Collection

The attributes of DLL Collection can be categorized as follows:

For specifying the source

o Data Source

For sending inputs to DLL

o Input Parameter

o Input XML

For validating/formatting the data received from DLL

o Break On

o XSLT

For selective conversion of XML

o XML Object

o XML Object Path

Attribute - Data Source

The attribute Data Source is used to set the source of the collection. By using this attribute, the actual DLL is invoked to TDL for further process.

Syntax

[Collection : <Collection Name>]

Data Source : <Type> : <Identity> [:< Encoding>]

Where,

< Type > specifies the type of data source, i.e., File XML, HTTP XML, Report, Parent Report, Variable, PlugIn XML, AxPlugIn XML.

< Identity > can be file path / source of DLL.

< Encoding > can be ASCII or UNICODE. It’s applicable only for File XML and HTTP XML.

For Plug-in DLL

Syntax

Data Source : PlugIn XML : <Path to dll>

Where,

< Type > is ‘PlugIn XML’.

< Identity > identifies the source of DLL, i.e., the path of DLL.

Example

Data Source : PlugIn XML : m y dll.dll

For ActiveX DLL

Syntax

Data Source : AxPlugin XML : < Project Name>.<Class Name>

Where,

< Type > is “AxPlugin XML”.

< Identity > identifies the source of DLL, i.e., < Project Name>.<Class Name>

Example

Data Source : AxPlugin XML : DLLEg1.MyClass

For C#.Net, which has concept of namespaces, the source identifier is “Namespace.ClassName”

Syntax

Datasource : AxPlugin XML : <namespace>.<classname>

Example

Datasource : AxPlugin XML : testcsharpdll.Class1

Attribute - Input Parameter

The attribute Input Parameter is used to pass a single string value to the DLL function.

Syntax

Input Para m eter : <Expression>

Where,

< Expression > returns a string value, which is used to pass to the DLL function.

Example

Input Parameter : Test string

In this example, ‘Test String’ is the string value, which is used to pass to the specified DLL.

Attribute - Input XML

The attribute Input XML is used to pass the XML format data to the DLL function.

Syntax

Input XML : <Post Request Report Name>, <Pre-Request Report Name>

Where,

< Post Request Report Name > is the name of the TDL report. It is responsible for generating XML data, which is passed to the DLL function as input.

< Pre-Request Report Name > is optional. It is used to get any input from the end user.

Example

Input XML : DLLRequestReport

Attribute - Break On

The attribute Break On is used to validate the XML data received from the DLL function. If the XML data contains the string specified in this attribute which is referred as error string, then the validation fails and the collection will not be constructed.

Syntax

Break On : <String Expression1>, <String Expression 2> …..

Where,

< String Expression 1 >, < String Expression 2 >… gives the string values which act as error string to validate the XML data.

Example

Break On : My Error String

If XML data received from DLL function contains “My Error String”, then the collection will not be constructed, just as in XML collection.

Attribute - XSLT

The attribute XSLT is used to transform the XML document received from DLL function to another XML document. It will be applied before constructing the collection. This attribute is same like in XML collection.

Syntax

XSLT : <XS L T File name>

Where,

< XSLT File name > is the name of the XSLT file name.

Example

XSLT : "C:\\Myfile.xslt"

Attribute - XML Object

The attribute XML Object is used to represent the structure of DLL collection object to which the obtained data is mapped. It is an optional attribute, and is same like in XML collection.

Syntax

XML Object : <Object Name>

Attribute - XML Object Path

The attribute XML Object Path is used to set the starting XML node from where the object construction starts. If only a specific data fragment is required, it can be obtained using the collection attribute ‘XML Object Path’. This attribute is same like in XML collection.

Syntax

XML Object Path : <StartNode> : <StartNodePosition> : <Path to start node>

Where,

< StartNode > gives the name of the starting XML Node.

< StartNodePosition > gives the position of the starting XML Node.

< Path to Start Node > gives the path of the starting XML Node.

<P ath to start node > can be extended as follows:

<root node> : <child node> : <start position> : <child node> : <start position>:....

Example

XML Object Path : MyNode : 1 : Root

Note:

In DLL collection, all the attributes except Datasource are optional.

All error messages related to DLL collection are stored in dllcollection.log file.

Usage of DLL Collection attributes

The following examples demonstrate the usage of DLL collection attributes:

Example: Data Source - AxPlugIn Xml

XML data received from the ActiveXDLL “testdll.class1” is to be displayed in a Report. For this, a DLL XML collection is constructed and only a fragment of XML data is to be populated in the collection. Consider the following input XML fragment:

< EmpColl e ction>

<Emp>

<Name>Emp1 < /Name>

<EmpId>101 < /EmpId>

<Designati o n>Mana g er </Des ignati o n >

</Emp>

<Emp>

<Name>Emp2 < /Name>

<EmpId>102 < /EmpId>

<Designati o n >Sen i or Mana g er </D e signati o n>

</Emp>

< /EmpCol l ection>

Note: The same XML has been used to explain all further examples.

The TDL code snippet for generating the report is as follows:

[Part : DLL C oll Pa r t]

Lines : DLL Coll Li n e1, D L L Coll L ine2

Repeat : DLL Coll Line2 : My DLL Collection

Scroll : Ver t ical

[Line : DLL C oll Li n e1]

Fields : DLL Coll Field1

[Field : DLL Coll Fi e ld1]

Set As : “R e trive f r agment EMP List from X ML data”

[Line : DLL C oll Li n e2]

Fields : SL N o, Emp N ame, E m p ID, E m p Desig

[Field : SL N o]

Use : Na m e Field

Set A s : $$ L ine

[Field : Emp Name]

Use : Name Field

Set A s : $N a me

[Field : Emp ID]

Use : Name Field

Set A s : $E m pId

[Field : Emp Desig]

Use : Na m e Field

Set A s : $D e signati o n

[Collection : My DLL Collec t ion]

Datasource : AxPlugin XML : te s tdll.class1

XML Object P ath : Emp : 1 : EmpCo l lection

In this example, the attribute Datasource is used to set the source of DLL, i.e., the class name from the DLL “testdll.class1”. The attribute XMLObjectPath retrieves the XML fragment starting from the first <EMP> tag under the XML tag <EmpCollection> from the specified DLL. The XML data thus fetched from the DLL is then displayed in a Report. Here, Emp is the name of the starting XML Node, 1 is the position of the starting XML Node and EmpCollection is the path of the starting XML node

Note: In this case, DLL has to be registered. The registration process is explained in detail in the section “Implementation and Deployment of DLL”.

Example: Da t a Source - PlugIn XML

In the previous exampl e , Activ e X Plugin D LL was used. N o w , inste a d o f ActiveX Plugin’ DL L , the data source is simple PlugI n DLL. The source keyword PluginXML is used in the attribute Data sourc e . In this case, only the DLL name must b e s p ecified.

The collection definition is as foll o ws:

[Collection : My DLL Collec t ion]

Datasource : Pl u gin XM L : testd l l.dll

XML Object P ath : Emp : 1 : Em p Collec t ion

Note: The only difference from the previous example is that, here the DLL registration is not required. What’s just required is to Copy the DLL to Tally.ERP 9 folder and execute the program.

Example: Attribute - Input XML

There are scenarios where the DLL expects some input as in XML fragment before sending the required XML output. The DLL XML collection attribute InputXML allows sending the Input XML to the source DLL in XML format. As explained earlier, the attribute InputXML accepts two parameters, i.e., PostReqReport and PreReqReport .

The collection is defined as follows:

[Collection : Input X MLColle c tion]

Data Source : Ax P lugin X ML : Te s tDLL.C l ass1

XML Object Path : Emp : 1 : EmpCo l lection

Input XML : Po s tReqRe p , PreRe q Rep

In this example, the report ‘PreReqRep’ accepts the user input and the report ‘PostReqRep’ generates the input XML, which is sent to the DLL. The response received from the DLL is populated in the collection InputXMLCollection .

The reports ‘PostReqRep’ and ‘PreReqRep’ are defined as follows:

[Report : PostReqRe p ]

Form : PostReqRepo r t

Export : Yes

[Form : Post R eqRepo r t]

.

.

[Line : Pos t ReqRepo r t]

Fi elds : S hort Na m e Fiel d , PostR e qRepor t Name, N a me Fie l d, +

P ostReqR e pID, S i mple Fi e ld, Po s tReqRep D esig

Local : Fie l d : Short Name F ield : Set As : “Name:”

Local : Fie l d : Name Field : S et As : “Emp I D :”

Local : Fie l d : Simp l e Field : Set As : “Designation:”

[Field : Pos t ReqRepo r tName]

Set As : ## P reReqNa m eVar

X M LTag : N ame”

.

.

;; Pre Request Report accepting U ser Inpu t s

[Report : PreReqRep]

Form : Pre R eqReport

.

.

[Part : PreR e qRepor t ]

Lines : Pre R eqReport Name, PreReqR e portID, PreReq R eportD e sig

[Line : PreR e qReport Name]

Fields : Sh o rt Name Field, PreReqR e port N a me

Local : Fi e ld : Sh o rt Name Field : Info : “Enter Employ e e Name:”

[Field : Pre R eqReport Name]

Use : N a me Field

Set A s : E nter yo u r Name”

Width : 50

Modifies : D L LPreReq N ameVar

.

.

[System : Va r iable]

DLLPreReqNa m eVar :

Example: Attribute - InputParameter

In scenarios where only one value is to be sent as an input to the source DLL, the attribute Input Parameter can be used as follows:

[Collection : InpParameterColl]

Data Source : AxPlugin XML : TestDLL.Class1 XML Object Path : result

Input Parameter : ##InputParameterVar

The value of the variable InputParameterVar is sent as an input to the DLL “TestDLL.Class1”. The response received is available in the collection InpParameterColl .

Example: Attribute - BreakOn

The following code snippet validates the XML received from the DLL "tesdll.class1".

[Collection : DLL X M L Get CollObjPa t h]

Datasource : Ax P lugin X ML : tes t dll.cl a ss1

XML Object Path : Emp : 1 : EmpColl e ction

Breakon : Ma n ager

Break On attribute is used to check whether the error string “Manager” exists in the output xml. If the error string exists, the XML is considered as an invalid XML and an empty collection is created. Otherwise, the XML is considered as valid and the collection is populated from the received XML fragment.

Signature of function ‘TDL Collection’ in the DLL

The DLL created using any programming language, when called from Tally, must contain a main function named as TDL Collection. The signature of this function is specific to each programming language.

The detailed signature of the function TDL Collection in different languages is as follows:

For VC++ DLL

Consider the following example for VC++ DLL to generate an XML fragment for Employee details. This DLL accepts the input from the TDL, and returns an XML file as output from DLL. Using this XML fragment, it constructs a collection.

extern “C” H RESULT decls p ec(dlle x port)

TDLCollecti o n (con s t wchar _ t * pIn p utPara m ,

const wchar _ t * pIn p utXML,

wchar_t ** pX M LColle c tion,

long * pCo l lectio n Size)

{

*pCollectio n Size = 1 024;

if ( (*pXMLC o llection = (wc h ar_t *)

( CoTaskM e mAlloc ( *pColl e ctionSi z e * si z eof (w c har_t) ) ))== NU L L)

{

r eturn - 1 ;

}

wcscpy (*pX M LCollec t ion, L "<EmpCo l lectio n >\

<Emp>\

<Name>Em p 1</Name > \

<EmpId>1 0 1</EmpI d >\

<Designa t ion>Man a ger</ D esignat i on>\

</Emp>\

<Emp>\

<Name>Em p 2</Name > \

<EmpId>1 0 2</EmpI d >\

< Designa t ion >S e nior Ma n ager</Designa t ion>\

</Emp>\

</EmpCol l ection> " \

);

In this example, there are different inputs given as parameters to the function TDLCollection.

pInputParam : It is an input value to the DLL and is a string value of collection attribute “Input Parameter”. The TDL passes an input parameter to the DLL.

pInputXML : It is an input to DLL and XML data constructed using collection attribute "Input Xml"

Output values from TDLCollection function:

pXMLCollection : O/P buffer containing resultant data, based on which, collection is constructed.

pCollectionSize : Number of wide characters, including the terminating NULL character.

For VB 6 DLL

Consider the following example for displaying the values in XML format using VB6. Here also, two parameters are being passed to the TDL Collection.

Public Func t ion TD L Collect i on(pInp u tParam As Stri n g,pInp u tXML As String) As St r ing TDLCollection = “<Root>

<Name > Amazing < /Name>

<Name > Brillia n t</Nam e >

</Roo t >”

End Function

In this example, two attributes are being given as parameters to the function TDLCollection.

pInputParam : Simple string value to the function, as specified in ‘Collection’ definition, using the attribute “Input Parameter”.

pInputXM : Input value in Xml format, as specified in the ‘Collection’ definition, using the attribute “Input XML”.

The function must return an output String value in XML format.

For C#.Net DLL

Consider the following example for .Net DLL to convert the input string’s case to upper case. Here, TDLCollection is passed two parameters.

public stri n g TDLC o llection (string pInpu t Param, s tring p InputXm l )

{

string resu l txml; / / to c o ntain x m l to be sent b a ck to T ally

if ( !String . IsNullO r Empty( p InputXm l ))

{

resultxml = pInputX m l.ToUp p er();

}

else

{

resultxml = null;

}

return res u ltxml;

}

In this example, XML data is being passed to the function TDLCollection. All the data present in various tags are converted to upper case.

The Input XML will be as follows:

<Root>

<Name>

<fname>fn a me 1</f n ame>

<lname>ln a me 1</l n ame>

</Name>

<Name>

<fname>fn a me 2</f n ame>

<lname>ln a me 2</l n ame>

</Name>

</Root>

The output XML will be as follows:

<Root>

<Name>

<fname>FNA M E 1</fn a me>

<lname>LNA M E 1</ln a me>

</Name>

<Name>

<fname>FNA M E 2</fn a me>

<lname>LNA M E 2</ln a me>

</Name>

</Root>

Inputs to the TDLCollection function:

pInputParam: It is an input value to the DLL and is a string value of collection attribute “Input Parameter”. The TDL passes an input parameter to the DLL.

pInputXML: It is an input value to the DLL and the XML data constructed using collection attribute "Input Xml".

For VB.Net DLL

In VB.Net, the signature for the function TDL Collection is as follows:

Public Function TDLCollection (ByVal pInputParam As String, ByVal pInputXML As String) As String

Inputs to the TDLCollection function:

pInp u tP a r a m : I t is an input value to the DLL and is a stri n g value of c o llecti o n a t tribute “ In p ut Paramete r ”. The TDL passes an input par a meter to the DLL.

pInp u tXM : T h is is an input value to the DLL and the XML da t a construct e d using c o llection attribute “ Input Xm l ”.

Implementation and Deployment of DLL

Once the DLL is ready for deployment, the following should be ensured for implementation of the same:

The dependency for the particular DLL needs to be checked, based on the environment in which it is developed. The necessary environment needs to be installed for the same.

The DLL needs to be registered in the system where it is to be deployed. This can be done in two ways:

Registering the DLL manually.

Running the setup program which is created for deployment.

Dependencies with respect to DLLs created using various Environments

Created using .NET framework : For DLLs created using VB .NET, C# .NET, etc., we require Microsoft .Net Framework. For example, if the DLL is created using Visual Studio 2005, then Microsoft .Net Framework 2.0 or above should be installed on the system.

Created using Visual Basic 6.0 : For DLLs created using VB 6, we require service pack 6 to be installed on the system.

References

.Net Framework can be downloaded and installed from the following link: http://download.microsoft.com/download/6/0/f/60fc5854-3cb8-4892-b6db-bd4f42510f28/dotnet-fx35.exe

Service Pack 6 for Visual Basic 6.0 can be downloaded from the following links: http://www.microsoft.com/downloads/details.aspx?FamilyId=9EF9BF70-DFE1-42A1-A4C8- 39718C7E381D&displaylang=en

Multi part - http://www.microsoft.com/downloads/details.aspx?familyid=83BF08E6-012D-4DB2- 8109-20C8D7D5C1FC&displaylang=en

How to register DLLs?

After downloading the necessary environment, the DLL needs to be registered before it is used and called by the Tally program. As already discussed, there are two ways in which a DLL can be registered.

Let’s discuss the two ways of Registering a DLL (Manual & Set Up) one by one:

Manual Registration

For VB6 DLLs

Copy the DLL file to the specific folder say C:\Tally.ERP9

Open Command Prompt and change the current directory to the folder where DLL is copied, i.e., :\Tally.ERP9

Type the command RegSvr32 <DLL Name>

After the command is entered in command prompt, a message box is displayed as shown:

Figure_1._Registering_DLL_using_command_prompt_(1.8).jpg

Now you can use the DLL for calling from Tally.

For .NET DLLs

To register .Net DLL, the RegAsm command needs to be used, instead of RegSvr32 .

Note: Manual registration does not automatically take care of missing dependencies. So, it is always advisable to use Set Up Programs for Registration.

Registering DLLs by using Setup Program

To register using this method, double click on the setup program and proceed with the installation. This automatically registers the required DLL into the selected folder.

Creating a Set Up Program

The creation of Set Up program varies from one language to another. Please refer to any learning material for Set Up creation specific to your Development Environment. As an example and common usage, we will just discuss creating Set Up using VB 6. The steps for deployment of VB6 DLLs using Package and Deployment Wizard are as follows:

1. Open the VB project where you want to create a setup program.

2. Select Package and Deployment wizard from Add-In menu.

3. If the option isn’t there, choose Add-In Manager and double click Package and Deployment wizard.

4. Proceed with the Wizard options.

For more details, please refer to the following links:

http://www.configure-all.com/deployment.php

http://www.developerfusion.com/article/27/package-deployment-wizard/2/

Dynamic Table Support - using ‘Unique’ Attribute

The Unique attribute of Collection definition is used to control the display of unique values in the table for a specified method, based on values selected from the table previously in a field. The display of values is changed dynamically based on the field value.

Existing syntax

The existing syntax of the attribute Unique is:

Syntax

Unique : <Table Object Method> [,<Field Object Method>]

Where,

< Table Object Method > is a method whose value is uniquely displayed in the table.

< Field Object Method > is the storage/method, which is associated with the field which is used to control the display of Table values dynamically. If a particular table object method value from the Table is selected in the field, then that value is removed from the table based on the value of <Field Object Method>. This parameter is optional.

Example

[Part : StkB a t]

Repeat : Gr p LedLn : S tkItem C oll

[Line : Grp L edNm]

Field : St k It, Stk B atNm

[Field : St k It]

Use : Na m e Field

Storage : It e mName

[Field : St k BatNm]

Use : Name F i eld

Table : BatList

Storage : BtName

Show Table : Always

Dynamic : Yes

[Collection : BatLi s t]

Title : L ist of B atches”

Type : B a tch

Format : $BatchName,20

Child of : #StkIt

Unique : $BatchName, $BtName

[Collection : StkItemColl]

Type : StockItem

Fetch : Name

[System : UDF]

BtName : String : 2010

ItemName : String : 2010

The table “Bat List” is used to display batch names in a Table attached to the field “StkBatNm” . The storage associated with the field is “BtName” . Once the Batch name is selected in the field “StkBatNm” , in the next line, the table will be populated with batches which are not selected previously in the field.

Even if some stock items belong to more than one batch, the table won’t display the common batches, since it may have been already selected in the field for a different stock item. To provide this flexibility for controlling the uniqueness of data, the attribute ‘Unique’ has been enhanced.

New E n hanced S y ntax

The new enhanced syntax is:

Syntax

Unique : <Table Object Method> [,<Field Object Method>[,<Extended method>]]

Where,

< Table Object Method > is a method whose value is uniquely displayed in the table.

< Field Object Method > is the storage/method, which is associated with the field which is used to control the display of Table values dynamically. If a particular table object method value from the Table is selected in the field, then that value is removed from the table based on the value of <Field Object Method>. This parameter is mandatory if <Extended method> is specified, else it is optional.

< Extended Method > is a storage/method, whose value specifies whether the previous value of the field object method should be used to control unique values display in the table. If the current value of the value of <Extended Method> is same as that of previous values, then <Field Object Method> value is considered while populating unique values in the table. Otherwise, the <Field Object Method> value is ignored to set the unique values in the table. This parameter is optional.

The collection and definition is modified as follows, so that while populating unique values of Batch names in the table, StockItem name is also considered apart from the value of the field storage/method “BtName”, i.e., if the same stock item is selected in the field which has been selected previously, then the field storage/method value “BtName” is considered for controlling display of Batches, else it is ignored.

Example

[Collection : BatList]

Title    : “List of Batches”

Type     : Batch

Format   : $BatchName,20

Child of : #StkIt

Unique   : $BatchName, $BtName, $ItemName

Here, the method $ Itemname used in the ‘Unique’ attribute is the storage defined in the field ‘StkIt’.

Use Case:

Consider t he followi n g Scen a rio:

Stock Item

Batch Name

Item 1

Batch A

Batch B

Batch C

Item 2

Batch A

Batch C

Item 3

Batch A

Batch B

Batch C

There are two fields in the line, one of which displays stock item name and the other displays batches. The selected batch is stored in a UDF, say BtName.

Following table displays the values in each field and unique values in tables based on selection:

Line No

Value in Field 1

Values in Table

Selected Value in Field 2

1

Item 1

Batch A

Batch B

Batch C

Primary Batch

Batch A

2

Item 2

Batch A

Batch C

Primary Batch

Batch C

3

Item 3

Batch B

Batch C

Primary Batch

Batch B

Using Variable as a Data Source for Collections

Collection attribute Data Source has been enhanced to support 'Variable' as a data source. Now, variable element(s) can be gathered as objects in the collection and the respective simple member variables are available as methods. Member list variables will be treated as sub-collections.

Syntax

Data Source : <Type> : <Identity> [:<Encoding>]

Where,

< T ype> is the type of d a ta source, i.e., File XML, HTTP XML, Report, Parent Report, V ariable .

<Identity> can be f ile p ath/scope key w o rds/varia b le specificati o n, based on type of d a ta source.

<Encod i ng> can be ASCII or UNICODE. It s applicable for the types File XML & HTTP XML.

Note: Please refer to the topic “Using Variable as a Data Source for Collections” under Variable Framework for more clarity, with examples.

Evaluating expressions by Changing the Object Context with $$ReqOwner Introduced

In a programming language, an expression is a combination of values, variables, operators and functions that are evaluated according to the rules of their precedence and association. Similarly, expressions in TDL can be a combination of Method/Variable/Field/Constant Values, and Function/Formula evaluation results.

Example: For TDL Expression

$Name + ##VarTest + $$MachineDate + @@FormABC + 90 + #FieldXYZ

Where,

Name is a Method, VarTest is a Variable, MachineDate is a Function, FormABC is a System Formula, 90 is a constant value, and FieldXYZ is a Field.

Methods, Variables and Fields are Leaf components in an expression as other components like Formulae or Functions finally evaluate into either one of these, or result into constants.

A TDL Expression always gets evaluated in the context of an Interface (Requestor) and Data Object. Whenever a report is constructed, an Interface object hierarchy is created, i.e., Report contains a Form, Form contains a Part, and so on. Every Interface Object is associated with a Data Object. In the absence of explicit data object association, an implicit anonymous object gets associated. A method value is evaluated in context of the data object, while Variable and Field values are evaluated in context of Interface object. There may be cases where we would require evaluating these in a context different from the implicit context (Interface and Data). TDL provides many functions which provide the facility to change the Data or Interface Object Context. A change in Data Object context does not change the current Interface (Requestor) Object context and a change in Interface Object Context does not change the current Data Object Context.

We can categorize these functions into mainly two categories:

Data Object Context Switching Functions

Interface Object Context Switching Functions

Data Object Context Switching Functions

The Tally database is hierarchical in nature, in which the objects are stored in a tree-like structure. Each node in the tree can be a tree in itself. An object in Tally is composed of methods and collections. Method is used to retrieve data from the database. A collection is a group of objects. Each object in the collection can further have methods and collections. The Internal Object hierarchy is predefined in Tally and cannot be altered. These can only be persisted in Tally Database.

Every Interface Object exists in the context of a Data Object which is associated to it. As discussed above, an expression (specifically method value) gets evaluated in context of the Data Object associated with the Requestor (Interface Object). By using the functions as given ahead, we can change the Data Object Context for expression evaluation.

Note: Switching the Data Object Context does not imply a change in the current Requestor (Interface Object)

In all the subsequent examples, we will be using the ‘Voucher’ Data Object hierarchy to demonstrate the various scenarios for Context Change. Hierarchy of the ‘Voucher’ Object is as shown in the following figure.

Figure_2._Data_Object_Hierarchy_of_Voucher_(1.8).jpg

Function - $$Owner

The function $$Owner evaluates the given expression in the context of the parent data object in the Data Object hierarchy chain, i.e., it will change the Data Object context to the parent of the current Data Object in context. For example, if the current object context is Batch Allocations, then to access the value from Inventory Entries, which is its parent data object, the $$Owner function can be used.

Syntax

$$Owner : <Expression>

Example: 1

In this example, let us assume that the “ Bill Allocations Amount ” field (Requestor) exists in context of Bill Allocations Data Object. In order to evaluate the method “Amount” from Ledger Entries Object Context, we need to use the function $$Owner.

[Field : Bill Allocations Amount]

Set As : $$Owner:$Amount

In this field, method Amount from parent object LedgerEntries is set by using $$Owner function.

Example: 2

Similarly, let’s assume that the current data object context for the field “ Bill Allocations Remarks ” is Bill Allocations , and we need to evaluate the method Narration from Voucher Object.

[Field : Bill Allocations Remarks]

Set As : $$Owner:$$Owner:$Narration

In this field, Narration from object Voucher, which is 2 levels above in hierarchy, is set using $$Owner twice. In other words, we are requesting for method Narration from the owner of owner. Alternatively, in these examples, we can use the dotted method formula syntax .

[Field : Bill Allocations Amount]

Set As : $..Amount

[Field : Bill Allocations Remarks]

Set As : $...Narration

In these examples, .. denotes the parent and … denotes the Grand Parent.

Function - $$BaseOwner

Function $$BaseOwner evaluates the given expression in the context of the base/primary data object in the Data Object hierarchy chain available with the ‘Report’ Object (in memory).

Note: Since the entire Data Object hierarchy is cached with the Object associated at the Report, the function $$BaseOwner changes the Data Object context to the Object associated at the Report.

For example, if the current data object context is Batch Alloc a tion s , then to access the method value from V ouche r , $ $BaseOwn e r function can be used.

Syntax

$$BaseOwner : <Expression>

Example

As per the Voucher hierarchy, let’s assume that our current data object context for the field “ Bill Allocations Remarks ” is Bill Allocations. In order to access the value of Method Narration from Voucher Object, which is the base/primary object in the object hierarchy chain, we can use the function $$BaseOwner.

[Field : Bill Allocations Remarks]

Set As : $$BaseOwner:$Narration

In this field, the Method Narration from the base Object Voucher is set, using $$BaseOwner. Alternatively, in the above example, we can use the dotted method syntax.

[Field : Bill Allocations Remarks]

Set As : $().Narration

In this example, (). navigates to the Primary/Base Data Object

Function - $$PrevObj

Function $$ PrevObj evaluates the given expression in the context of the previous data object of the collection, which contains the current data object in context.

Syntax

$$PrevObj : <Expression>

Example:

Assume that a line is being repeated over a collection of Outstanding Bills, which is sorted based on PartyName . After every Party Info, a Total Line is needed to print subtotal for current Party.

[Line : Outstanding Bills]

Option : Partywise Totals : $$PrevObj:$PartyName!=$PartyName

[!Line : Partywise Totals]

Add : Lines : At Beginning : Party SubTotal Line

In this example, an optional line will be included only if the method PartyName of the previous object is not equal to that of the current object.

Function - $$NextObj

Function $$ NextObj evaluates the given expression in the context of the next data object of the collection, which contains the current data object in context.

Syntax

$$NextObj : <Expression>

Example:

Assume that a line is being repeated over a collection of Outstanding Bills, which is sorted based on PartyName. After every party Info, a Total Line is needed to print the subtotal for current Party.

[Line : Outstanding Bills]

Explode : Partywise Totals : $$NextObj:$PartyName!=$PartyName

In this example, a part is exploded, provided the method PartyName of the next object is different from that of the current object. This will enable explosion for each party only once, and thereby, we can easily achieve the subtotal line as desired.

Function - $$FirstObj

Function $$ FirstObj evaluates the given expression in the context of the first data object of the collection, which contains the current data object in context.

Syntax

$$FirstObj : <Expression>

Example

Assume that a line is being repeated over the ledger collection, where in a field, we require the first object's name to be set.

[Field : First Name]

Set As : $$FirstObj:$Name

In t his exampl e , a Field Fir s t Name i s set as the Nam e M e thod o f the first object in the Collection .

Function - $$LastObj

Function $$ LastObj evaluates the given expression in the context of the last data object of the collection, which contains the current data object in context.

Syntax

$$LastObj : <Expression>

Example

Assume that a line is being repeated over the ledger collection, where in a field, we require the last object's name to be set.

[Field : Last Name]

Set As : $$LastObj:$Name

In t h is exampl e , a Field L a st Name i s se t a s Name Method of the last object in the Collecti o n.

Function - $$TgtObject

As we already know, apart from Interface (Requestor) and current Data Object Context, there is one more context available with reference to User Defined Functions and Aggregate Collections, i.e, the Target Object Context. In case of functions, the object being manipulated is the Target Object. In case of aggregate Collection, the object being populated in the resultant collection is the Target Object.

There are scenarios where the expression needs to be evaluated in the context of the Target object. In such cases, the function $$ TgtObject can be used. Using $$TgtObject, values can be fetched from the target object without setting the target object as the current context object.

Syntax

$$TGTObject : <Expression>

Example: 1

Consider writing a Function to import a Voucher from Excel, wherein the Source Object is the Collection gathered out of Objects in an Excel Worksheet, the Target Object being the Voucher and its sub objects. While setting value to Inventory Entries sub-object, the Target Object is changed to Inventory Entries and the Source Object continues to be Excel Objects. In order to set values to the methods Quantity and Rate, Stock Item context is required since Unit Information is available for Item. Hence, $$TGTObject Function is prefixed to the Expression @ BillQty and @ BillRate , in order to evaluate these Methods in the context of the Target Object, which is the ‘Inventory Entries’ Object.

[Function : Import Voucher]

Local Formula : BillQty : $$AsQty:$ExcelBilledQty

Local Formula : BillRate : $$AsRate:$ExcelItemRate

90 : INSERT COLLECTION OBJECT : Inventory Entries

100 : SET VALUE : BilledQty : $$TgtObject:@BillQty

110 : SET VALUE : Rate : $$TgtObject:@BillRate

120 : SET TARGET ..

130 : SAVE TARGET

Example:2

Consider another example where, while populating a summary collection of Sales Vouchers, we need to track the maximum sales amount for each Item with the date on which the maximum sales was triggered.

[Collection : Src Voucher]

Type : Vouchers : VoucherType

ChildOf : $$VchTypeSales

[Collection : Summ Voucher]

Source Collection : Src Voucher

Walk : Inventory Entries

By : ItemName : $StockItemName

;; The following returns the Date and Amount for an Item, on which Maximum sales has happened

Aggr Compute : MaxDate : SUM : IF $$IsEmpty:$$TgtObject:$MaxItemAmt OR $$TgtObject:$MaxItemAmt <$Amount THEN $Date ELSE +

$$TgtObject:$MaxDate

;; MaxItemAmt is a method in the Target Object. Hence, the function $$TgtObject is used to evaluate the Method

;; MaxItemAmt in Target Object Context

Aggr Compute : MaxItemAmt : MAX : $Amount

In this example, while populating the Summary Collection, Method MaxItemAmt is being computed for Maximum Amount. Subsequently, Date is also computed by validating if the current object's Amount is greater than the previous computed Amount. Since Maximum Amount so far is computed and accumulated in the Target Object being populated, we need to access it using the function $$TGTObject. Hence, $$TgtObject:$MaxItemAmt evaluates the Method MaxItemAmt in the context of the computed Target Object MaxItemAmt.

Function - $$LoopCollObj

As we are aware, it is now possible to gather Data Collection in context of each object of another collection, which is referred to as a Loop Collection. To access the methods of Loop Collection Objects from within the Data Collection, $$LoopCollObj is used, with which the expression is evaluated in the context of the Loop Collection Objects.

Syntax

$$LoopCollObj : <Expression>

Example:

To see a consolidated list of vouchers across all the loaded companies.

[Collection : Company Collection]

Type : Company

Fetch : Name

[Collection : Vouchers of Multiple Companies]

Collection : MultiCmpDB VchCollection : Company Collection

Sort : Default : $Date, $LedgerName

[Collection : MultiCmpDB VchCollection]

Type     : Voucher

Fetch    : Date, Vouchernumber, VoucherTypeName, Amount, MasterID, LedgerName

Compute  : Owner Company : $$LoopCollObj:$Name

In this example, the function $$ LoopCollObj changes the context to Loop Collection Objects, which is the Company Collection and hence, returns the company name.

Function - $$ReportObject

The func t ion $ $ R e portObj e ct ev a luates the given expression in the con t ext of the Da t a O b ject associated with t h e Report Interface Object.

One of the important Use Cases of $$ ReportObject is its usage in purview of in-memory Collection gathering. Whenever a collection is gathered, it is retained in memory with the Data Object of the current Interface (Requestor) Object. If the same collection is being used in expressions again and again, then it is beneficial from the performance point of view to attach it to the ‘Report’ Object and evaluate it in the context of ‘Report’ Object n number of times. This eliminates the need to re- gather the collection every time in context of other Data Objects.

Syntax

$$ReportObject : <Expression>

Example: 1

From Bill Allocations Data Object context, Voucher No. of Report Object Voucher is required.

[Field : Bill No]

Set As : $$ReportObject:$VoucherNumber

Example: 2

In a Report, Sales of each Item against the corresponding Parties is required.

[Collection : CFBK Voucher]

Type : Voucher

Filter : IsSalesVT

[Collection : CFBK Summ Voucher]

Source Collection : CFBK Voucher

Walk : Inventory Entries

By : PName : $PartyLedgerName

By : IName : $StockItemName

Aggr Compute : BilledQty : SUM : $BilledQty

Search Key : $PName + $IName

[Field : CFBK Rep Party]

Use : Qty Primary Field

Set as : $$ReportObject:$$CollectionFieldByKey:$BilledQty:@MyFormula:CFBKSummVoucher

MyFormula : ##PName + #CFBKRepName

Here, the function $$ReportObject, during its first execution, retains the collection within the Voucher Object (which is the Data Object associated with the ‘Report’ Object). During subsequent calls, method values are fetched from the Objects available in the ‘Report’ Data Object, instead the entire Collection being regathered again. This helps in improving the performance drastically.

Function - $$ReqObject

This function evaluates the given expression in context of the Data Object associated with the Interface (Requestor) Object. There may be scenarios where during expression evaluation, Data Object context changes automatically and all the methods referred to are evaluated in context of the changed Data Object. The Data Object associated with the Interface (Requestor) Object is lost. Specifically in those cases, where we need to evaluate methods in context of the data object associated with the Interface (Requestor) Object, we will use the function $$ ReqObject .

Syntax

$$ReqObject : <Expression>

Example:

A Report is r e quired to display Ledgerwise Sales T otals

[Field : Fld LedSalesTotal]

Set As : $LedgerSalesTotal

[#Collection : Ledger]

Compute : LedgerSalesTotal : $$FilterAmtTotal:LedVouchrs:MyParty:$Amount

[Collection : Led Vouchers]

Type : Voucher

Filter : OnlySales

[System : Formula]

My Party : $PartyLedgerName = $$ReqObject : $Name

Only Sales : $$IsSales:$VoucherTypeName

In this example, a new method LedgerSalesTotal is added in the Ledger Object to compute the Sales Total from all the Vouchers filtered for the current Party Ledger Object. The Interface Object (Requestor) for this method is the field “FldLedSalesTotal”. In the Formula My Party, current Ledger Name must be checked with the Party Ledger Name of the Voucher Object, which is the current Data Object context. The Data Object associated with the Requestor is Ledger Object. So, in order to evaluate the method $name from the Interface (Requestor) Object's Data Object context, the function $$ Reqobject must be used.

Function - $$ObjectOf

As we are already aware, there is the capability to identify a Part and Line Interface Object using a unique Access Name. A Form/Report can be identified from any level using the Definition Type. The function $$ ObjectOf is used to evaluate the expression in context of the Data Object associated with the Interface Object identified by the Access Name.

The Interface Object being referred to, should be assigned a unique AccessName via Access Name attribute.

Syntax

$$ObjectOf : <DefinitionType> : <AccessNameFormula> : <Evaluation Formula>

Example

[Part : Cust Object Association]

Lines : Cust Object Association

;; Object associated at Part

Object Ex : (Ledger, "Customer").

;; Access Name specified so that this part can be accessible

Access Name : “CustLedger”

;; In some other fields across parts, we can access the methods of the Ledger Object associated with the part “CustObjectAssocia- tion”, using the function $$ObjectOf

[Field : Ledger Parent]

Set as : $$ObjectOf:Part:"CustLedger":$Parent

The Part “ Cust Object Association ” is associated with the Ledger Object “Customer”. It is identified by the Access Name “CustLedger” . The Field Ledger Parent from a different Part accesses the method $Parent from the Ledger object ‘Customer’, as it is the Object associated with the part Cust Object Association, identified by Access Name “CustLedger”.

Function - $$Table

It eval u ates the e x pr e ssion in the con t ext o f ‘ T able’ object, w h ich is selected in the given F i eld .

Syntax

$$Table : <Field Name> : <expression>

Example

[Field : Vehicle Number]

Table : List of Vehicles

Show Table : Always

[Field : Vehicle Type]

Set as : $$Table:VehicleNumber:$VehType

[Field : Vehicle YOP]

Set as : $$Table:VehicleNumber:$VehYOP

[Collection : List of Vehicles]

Type : Veh AggUDF : Company

ChildOf : ##SVCurrentCompany

Format : $VehNo, 20

Format : $VehType, 40

Format : $VehYOP, 4

Fetch : VehNo, VehType, VehYOP

;; For Remote Client End

In this code, the table is displayed in the field “Vehicle Number”. In the other fields ‘Vehicle Type’ and ‘Vehicle YOP’, $$Table is used to evaluate the methods $VehType and $VehYOP in context of the Data Object selected in the field “Vehicle Number”.

Function - $$TableObj

$$ TableObj is similar to the function $$Table. The expression is evaluated in context of the Data Object selected in the Table in the field specified. The difference of this function from the function $$Table is that, in case no object is selected in the Table, or expression evaluation fails, $$Table returns a blank string. In such a case, $$TableObj returns a logical value (FALSE) as the result.

Syntax

$$TableObj : <Field Name> : <expression>

Example:

A field needs to be skipped based on the selection of the table in a field.

[!Field : VBOrdDueDRNote]

Skip : $$TableObj:VCHBATCHOrder:$$IsOrder

In this example, if the Object selected in the Field VchBatchOrder is an Object Order, then the current field needs to be skipped.

Interface Object Context switching functions

Objects used for designing the User Interface are referred to as Interface objects. Interface objects like Report and Menu are independent items and can exist on their own. The objects Form, Part, Line and Field can't exist independently. A Report can have more than one Form, Part, Line and Field definitions but at least one has to be there. The hierarchy is as follows:

Report uses a F orm

Form uses a Part

Part u ses a Line

Line uses a Field

A Field is whe r e the conten t s are dis p layed or e n tered

Figure_3._Interface_Object_Hierarchy_(1.8).jpg

We can take an example of the Simple Customized Invoice Report (as given in the diagram) in order to understand the containment hierarchy of Interface Objects.

A set of available attributes of interface objects have been predefined by the platform. A new attribute cannot be created for an interface object. Interface objects are always associated with a Data Object and essentially add, retrieve or manipulate the information in Data Objects.

At run time, when a report is constructed after the evaluation of all of the above, a complete hierarchy of Interface Objects is created. As we have already discussed, an expression is evaluated in the context of the current Interface Object, which is referred to as the Requestor, and the Data Object associated to it. We will now discuss the switching functions which will change the Interface Object Context for expression evaluation.

Note: Switching the Interface (Requestor) Object Context does not imply a change in the current Data Object context.

Function - $$AsReqObj

The function $$AsReqObj is used to save the Interface (Requestor) context to the current object, for the evaluation of the expression. All the future references done using $$ReqObject will point to the saved Interface Object context. The actual requestor is overridden using the function $$AsReqObject .

Syntax

$$AsReqObj : <Expression>

Example

Here, a Table of Company Vehicles is displayed in a Field “Select Vehicle”, which exists in the context of the Voucher Object. The table is filtered on the basis of Unused Vehicles.

[Field : Select Vehicle]

;; In Voucher Entry

Table : CMP Vehicles

Storage : VCHVehicle

[Collection : CMP Vehicles]

Type : Company Vehicles : Company

Childof : ##SVCurrentCompany

Format : $VehicleNumber, 20

Format : $VBrand, 10

Title : “Company Vehicles”

Filter : Unused Veh

[System : Formula]

Unused Veh : $$AsReqObj:$$FilterCount:PrevSalesVchs:UsedVehicle = 0

Used Vehicle : $$ReqObject:$VehicleNumber=$VCHVehicle

Only Sales : $$IsSales:$VoucherTypeName

[Collection : PrevSalesVchs]

Type : Voucher

Filter : Only Sales

In t h is exampl e :

Field Select Vehicle is the Interface (requestor) object, associated with the data object Voucher.

Table/Collection of Company Vehicles is displayed in the Field.

Table is filtered for Unused vehicles.

This collection contains the list of Vehicle Numbers which need to be compared with the ones used in the previous sales vouchers. Since Requestor is the Field with the data object ‘Voucher’, Function $$ReqObject will get evaluated in the context of ‘Voucher’ Object, which is not expected. Hence to make the current collection, i.e., CMP Vehicles, as requestor object for future reference, Function $$AsReqObj is used.

In the Function $$FilterCount, when the object context changes to the list of sales vouchers, the Function $$ReqObject evaluates the parameter $VehicleNumber in the context of the requestor Collection CMP Vehicles set earlier using $$AsReqObj, and compares the same with the Voucher UDF VchVehicle stored in the respective vouchers.

Function - $$ReqOwner

The Function $$ReqOwner evaluates the given expression in the context of the Interface (Requestor) object’s Owner in the current Interface object hierarchy. For instance, Report is an owner requestor for Form, Form is an owner requestor for Part, and so on. From the Line, when the function $$ReqOwner is used, the expression gets evaluated in the context of the Part containing the current line.

Syntax

$$ReqOwner : <Expression>

Example

[#Menu : Gateway of Tally]

Add : Key Item : ReqOwner Sample : W : Alter : ICCF ReqOwner

[Report : ICCF ReqOwner]

Form : ICCF ReqOwner

Variable : VarReqOwner : String : “Keshava”

[Form : ICCF ReqOwner]

Parts : ICCF ReqOwner

[Part : ICCF ReqOwner]

Lines : ICCF ReqOwner

[Line : ICCF ReqOwner]

Fields : ICCF ReqOwner

[Field : ICCF ReqOwner]

Set As : $$FunctoreturnReqOwner

Set Always : Yes

[Function : FunctoreturnReqOwner]

Variable : VarReqOwner : String : “Madhava”

Variable : Temp : String : $$ReqOwner:##VarReqOwner

01 : MSGBOX : ##VarReqOwner : ##Temp

10 : RETURN : $$ReqOwner:##VarReqOwner

In this example, the Variable VarReqOwner is declared & initialized in a Report as well as in a function. From the Field, the function $$ReqOwnerFunc is referred to perform some computation and return the result. Since, $$ReqOwner is used in the Function and Field is the Requestor Owner for Function, the Field walks back the Interface (Requestor) Object hierarchy to fetch the Variable value. Hence, the Variable value Keshava of the nearest Interface Object, i.e., of the Report is returned.

Function - $$AccessObj

As we are already aware, there is the capability to identify a Part and Line Interface Object using a unique Access Name. The function $$AccessObj changes the Interface Object context to the one identified by the Access name to evaluate the expression

The Interface Object being referred to should be assigned a unique Access Name via Access Name attribute.

Syntax

$$AccessObj : <DefinitionType> : <AccessNameFormula> : <Evaluation Formula>

Example

[Line : ABC]

Access Name : “AccABC”

[Field : XYZ]

Set As : $$AccessObj:Line:“AccABC”:##VarABC

In this example, the function $$AccessObj changes the Interface Object context from the field “XYZ” to the line “ABC”, which is identified by the Access Name “AccABC”. The variable value is evaluated in context of the line “ABC”.

Function - $$ExplodeOwner

The f u nction $$Expl o deOwner ch a nges the Interface (Requestor) Object to the Li n e owning the current e xploded Part, and evaluates the given expression, i.e . , Field and V ariable Values, in the c o ntext of Interface Object .

Syntax

$$ExplodeOwner : <Expression>

Example

[Line : Smp InvEntries]

Fields : Name Field

Local : Field : Name Field : Set As : $StockItemName

Explode : Smp Expl Part

[Part : Smp Expl Part]

Lines : Smp Batch Allocations

Repeat : Smp Batch Allocations : Batch Allocations

Scroll : Vertical

[Line : Smp Batch Allocations]

Fields : Name Field

Local : Field : Name Field : Set As : $$ExplodeOwner:#NameField

In this example, the field NameField is being evaluated in the context of the Line Smp InvEntries, which owns the current exploded part Smp Expl Part.

Function - $$PrevLine

When the line is repeating, we may require evaluating an expression in the context of the previous line. For example, we might require to fetch the field values stored in the previous line for an expression in the current line. The function $$ PrevLine is used to change the Requestor to the Previous Line for expression evaluation.

Syntax

$$PrevLine : <Expression>

Note: The function $$PrevLine not only changes the Interface (Requestor) Object context, but also changes the Data Object context to the Object associated with the Requestor.

Example

[Line : PrevParticulars]

Explode : PrevParticulars ExpPart : $$PrevLine:#PartyParticulars!=#PartyParticulars

In this example, in case of repeated lines, where subtotals are required to be displayed or printed for the same party, we can explode a subtotal line after comparing the previous line’s and the current line's Ledgers. If the field values are not the same, then the subtotal line is exploded.

Variable Framework with Compound Variables Introduced

Variables in TDL (Tally Definition Language) are entities which can hold values during the execution of a program. The values of these variables are initialized when they are created and can change during the entire execution of program. The Program can change the variable value by specifying expressions which are evaluated to set the values of the variables.

Variables are context-free structures which do not require any specific object context for manipulation. They are declared by name and can be operated using the same name. It is also possible to access and operate variables declared at the parent scope.

Variables are lightweight data structures, which are simple to operate and provide the capability of storing multiple values of the same type and different types as well. It is also possible to perform various manipulation operations like insert/update/delete/sort/find. These are mainly used to perform complex computations.

Variable can hold a single value, or more than one value of same type or different types. It can be declared at various scopes such as Report, Function and System Level.

Classification of Variables

The various types of variables in TDL are:

1. Simple V a riable

Simple variables allow st o rage o f a single value of the specified da t a type.

2. Simple Repeat Variabl e s

The Simple Variable can h old m ethod val u es of multiple o bjects of a coll e ction based on an implicit index. This concept is used in Columnar Repo r ts onl y , where t h e lin e s s h ould be repeat e d vertically and the fields s h ould be repeated horizon t ally .

3. Compound Var i able

Compound Variables allow us to s tore v alues of di f ferent da t a ty p es. This is ac h ieved by making the variable it s elf c o mpound, by all o wing v a riable declaration insi d e i t self. These sub vari a bles are called member variables of the main variable .

A member variable can be a single ins t ance or a list vari a ble. A member variable can be a compo u nd varia b le a n d can have members again, a n d ther e fore a n y hierarc h y can be crea t ed.

Compound variables help g rouping o f r e lated i n formation togeth e r into one s pecification. In another te r ms, we can thi n k ab o ut c ompound variables as an ‘object’.

Foll o wing t able s h ows the similarities between an object and a compound variabl e:

Object

Compound Variable

Can have methods

Can have Simple Variables as its members

Can have repeated methods (simple collections)

Can have a Simple List Variable as member

Can have collections (compound collections)

Can have Compound List Variable as its member

*Cannot have objects under it directly*

Can have Compound Variables as members

We can have a comparison between the internal Da t a Object V ouche r ’ and a Compound V ariable ‘C L V Emp to unders t and the simil a rities betw e en an Object a nd Com p ound V ariable.

For ins t ance, t h e Comp o und V ariable ‘C L V Emp’ is defined as f o llows:

[Variable : CLV Emp]

Variable : Name : String

Variable : Designation : String

Variable : Age : Number

Variable : Salary : Amount

List Variable : Contact Nos : String

List Variable : Relatives

Variable : Contact Address

;; Defining Compound Variable

[Variable : Relatives]

Variable : Name : String

Variable : Age : Number

Variable : Relation : String

Variable : Salary : Amount

;;Defining another compound variable

[Variable : Contact Address]

Variable : Street Name : String

Variable : City Name : String

Object: Voucher

Compound Variable: CLV Emp

Object “Voucher” is having methods directly under it such as Date, Voucher Number, Narration, etc.

Compound Variable “CLV Emp” is having Simple Member Variables such as Name, Age, Salary, etc.

Voucher is having the repeated method BasicBuyerAddress (Simple Collection)

CLV Emp is having the Simple List Member Variable ‘Contact Nos’

Voucher is having the collection “Inventory Entries” (Compound

Collection).

CLV Emp is having the Compound List

Member Variable ‘Relatives’

Voucher object is not having another voucher (primary object) under it directly.

CLV Emp is having the another Compound Member Variable ‘Contact Address’

4. List Varia b le

A variable at declaration time can be declared as a single instance or as a list. List variable is a container (data structure) variable and hence it is not defined. Variables can be declared as list.

List Variable can hold one or more variables which can be either a simple or a compound variable. Each of these is called Element Variable. Element Variable holds value as well as key, if specified. The key is optional, and hence without a key also, elements can be added to list variables. The value of key specified for each of the element variables must be unique.

Simp l e List Vari a ble

Simple Variable can be declared as a list. Simple List Variables can hold multiple values of single data type.

Comp o und List V a riable

Compound Variable can be declared as a list. Compound List Variables can hold multiple values of different data types.

‘Variable’ Definition and its Attributes

Definition - V ARIABLE

A Variable definition is similar to any other definition. The behaviour of the variable is specified by the programmer via ‘Variable’ definition.

Syntax

[Variable : <Variable Name>]

Attribute : Value

A meaningful name which determines its purpose can be given as a variable name.

Attributes of ‘Variable’ Definition

Let us discuss the attributes of ‘Variable’ definition in detail.

Attribute - TYPE

This attribute determines the Type of value that will be held by the variable. All the data types

supported by TDL such as String, Number, Date, etc., can be used to specify the variable data type. In the absence of this attribute, a variable assumes to be of the Type ‘String’ by default.

Syntax

[Variable : <Variable Name>]

Type : <Data Type>

Example:

[Variable : GroupNameVar]

Type : String

In this example, a variable which holds the data of Type ‘String’ is defined.

Attribute- DEFAULT

The default value of variables can be specified during definition, using DEFAULT attribute. It is the initial value assigned to the variable when it is instantiated / declared. We can also specify the default value during declaration / instantiation. The difference is that the default value specified using this attribute at definition time will be applicable to all instances of the variable declared (at any scope). Default value specified while declaration will apply only to the specific instance.

Note: Declaration and scope will be covered in detail in the subsequent topics. The above explanation will be more clear after that.

Syntax

[Variable : <Variable Name>]

Default : <Default Value>

Example

[Variable : GroupNameVar]

Type : String

Default : $$LocaleString:"SundryDebtors"

In this example, the default value for the variable is set as “Sundry Debtors”.

Attribute - VOLATILE

If the Volatile attribute in Variable definition is set to Yes, then the variable is capable of retaining previous values from the caller scope. The default value of this attribute is Yes, i.e., if the variable by the same name is declared in the called Report/Function and the ‘Volatile’ attribute is set to “Yes”, then in the called Report, it will assume the last value from the caller Report. The default value of the attribute ‘Volatile’ is always YES.

For better understanding, let us elaborate it further. When a variable is declared / instantiated, it assumes a default value. The default value which it assumes is controlled by the following factors:

1. If ‘Volatile’ is set to “Yes” for a variable in its definition which is instantiated / declared inside a function/report, and the variable by the same name exists in the parent scope, then it will take its default value from the Parent scope. If no variable by the same name exists in the parent scope, it will take the default value specified within the definition.

2. If the default value is specified within the declaration itself, it will assume that value.

If a new report Report2 is initiated, using a volatile variable GroupNameVar , from the current report Report1, the same variable in Report 2 will have the default value as the last value saved in Report 1. Within Report 2, the variable can assume a new value. Once the previous report Report1 is returned back from Report2, the previous value of the variable will be restored. A classic example of this is a drill down Trial Balance.

Syntax

[Variable : <Variable Name>]

Volati l e : <Logical Value>

Example

[Variable : GroupNameVar]

Type : String

Volatile : Yes

Volatile Attribute of GroupNameVar Variable is set to Yes, which means that ‘GroupNameVar’ can inherit values from one Report to another.

Variables defined at the function level are Non Volatile by default. They do not inherit the values from the caller scope.

Note: Scope will be discussed in detail in the subsequent topics.

Attribute - PERSISTENT

This Attribute decides the retention periodicity of the variable, i.e., till when it will retain the value: i) till application termination, or ii) after application termination as well. Setting the attribute Persistent to Yes, means that the value saved during the last application session will be retained permanently in the system. When the next session of Tally is started, it will take its initial value from the value saved in the previous session, i.e., the latest value of the variable will be retained across the sessions. Please note that Variables declared at the system scope can only be persisted.

A List variable at System scope can also be persisted by specifying the ‘Persistent’ attribute for its element variable (whether it is simple/compound) within the definition. Inline variables even at system scope cannot be persisted. Inline variable declaration will be discussed in further topics.

Syntax

[Variable : <Variable Name>]

Persis t ent : <Logical Value>

Example:

[Variable : SV Backup Path]

Type : String

Persistent : Yes

The attribute Persistent of the variable SV Backup Path has been set to Yes, which means that it retains the latest path given by the user, even during the subsequent sessions of Tally.

Note: All the Persistent Variable Values are stored in a File Named TallySav.Cfg in the folder path specified for Tally Configuration file in F12 -> Data Configuration. Each time Tally is restarted, these variable values are accessed from this file.

Attribute - REPEAT

The attribute Repeat for a variable is used for its usage in Columnar Reports. It accepts Collection name and optional Method name, as parameters. Multiple values are stored in the variable based on an implicit Index. Method value of each object of the collection will have to be picked up and stored in the variable, based on implicit index. In case the method name is not specified, the variable name is considered as the method name and picked up from the collection.

Syntax

[Variable : <Variable Name>]

Repeat : <Collection Name> [:<Method Name>]

Where,

< Variable Name > is the name of the variable.

< Collection Name > can be any expression which evaluates to a Collection name.

< Method name > is the name of the method whose value needs to be picked up from each object of the collection. If not specified, the variable name is considered as the method name.

Example

[Variable : SVCurrentCompany]

Volatile : Yes

Repeat   : ##DSPRepeatCollection

Suppose ‘DSPRepeatCollection’ holds the value “List of Primary Companies”. Method value ‘SVCurrentCompany’ will be gathered from each object of the collection and stored in index 1, index2, and so on.

Note: Repeat attribute will be elaborated further under the topic “Implication of Repeat Variables in Columnar Report”.

Attribute - VARIABLE

The attribute Variable is used to define the member variables (Simple/Compound) for a Compound Variable.

Syntax

[Variable : <Variable Name>]

Variable : <Variable Names> [:<Data Type> [:<Va l ue>]]

Where,

< Variable Names > is the list of Simple or Compound Variables, separated by comma.

< Data Type > is used to specify the data type of Simple Variable. In case of Compound Variable, data type cannot be specified, as it consists of members belonging to various data types. If the data type is not mentioned, the primary variable definition is mandatory.

< Value > is the default/initial value provided for the variable.

Specifying < Data Type > and < Value > is optional. If data type is specified, then it is called inline declaration of variable. [We will learn about inline declarations and Compound Variables further].

Example

[Variable : CLV Emp]

Variable : Name : String

Variable : Age : Number : 25

Variable : Salary : Amount

Variable : Relatives

In this example, the simple variables Name, Age and Salary and the compound variable ‘Relatives’ are defined as members for the Compound Variable CLV Emp.

Attribute - LIST VARIABLE

The attri b ute List V ariable is used to specify a list of Simple/Compound Va r iables.

Syntax

[Variable : <Variable Name>]

List V a riable : <Variable Names> [:< Data Type> [:<Value>]]

Where,

< Variable Names > is the list of Simple or Compound Variables, separated by comma.

< Data Type > is the data type of Simple Variable. In case of Compound Variable, data type cannot be specified, as it consists of members belonging to various data types.

< Value > denotes the no. of elements in the list. Specifying <Data Type> and <Value> is optional.

Example

[Variable : CLV Emp]

Variable : Name : String

Variable : Age : Number

Variable : Salary: Amount

List Variable : City : String : 3

List Variable : Relatives

[Variable : Relatives]

Variable : Name : String

Variable : Age : Number

Variable : Relation : String

Variable : Salary : Amount

In this example, in addition to simple variables, a simple list variable City and a compound list variable Relatives are defined as members using the attribute List Variable. A separate definition is required for the compound list variable Relatives, as it holds the multiple values of different data types.

Varia b le Declaratio n and Scope

Variables can be declared at various scopes. The availability of the variable within the definition under which it is declared is called as the scope. The lifetime of the variable will be within the scope. For example, if the scope of a particular variable is within a function, then the variable will last till the function is executing, and then it is destroyed.

Variables can be declared at System, Report and Function scopes. Let us have a detailed look on the variable scopes.

System Scope declaration

Variables declared at the system level will start their life when the application starts, and will be alive till the application’s termination. System variables are declared using a special [System: Variable] definition. The variables declared at system scope are accessible everywhere in the system.

Syntax

[System : V a riable]

Variable Name : <Initial Type Based Value>

Or

Variable : <Variable Names> [ :<Data Type>[:<Val u e>]]

List Va r iable : <Variable Names> [:<Data Type>[ : <Value>]]

Where,

< Initial Type Based Value > is the initial value specified to the variable.

The variables can be declared at the system scope by using the above. The usage of the attributes ‘Variable’ and ‘List Variable’ is same as described above in the “Variable Definition”.

Example

[System : Variable]

BSVerticalFlag : No

The BSVerticalFlag Variable is declared in System Scope. Hence, this variable value being modified in a Report, is retained even after we quit and re-enter the report.

Report Scope declaration

Variables declared at Report definition are termed as having ‘Report’ Scope. These variables will exist till the life of the report. The variables declared at Report scope are accessible from the report itself and all the TDL elements which are executed from within this report such as another report, function, etc.

Report variables get their default value from definition specification, or from the declaration specification, or the values are inherited from the owner scope, if the variable is marked as Volatile.

Report allows two special attributes SET and PRINT SET to set / override the values of the variable during the startup of the report in Display / Print mode respectively.

‘Form’ definition also has a SET attribute, which overrides the variable’s value during startup creation and subsequent re-creation of the form during any refresh / regeneration. We will study about these value specification attributes in detail under the topic “Manipulating Simple and Compound List Variables”.

Syntax

[Report : <Report Name>]

Variable : <Variable Names>

Or

Variable : <Variable Names> [:<Data Type> [:<Va l ue>]]

Or

List V a riable : <Variable N ames> [:<Data Type> [:<Value>]]

The variables can be declared at Report scope by using the above. The usage of attributes Variable and List Variable is same as described above in the “Variable definition”.

Example

[#Report : Balance Sheet]

Variable : Explode Flag

‘Explode Flag’ Variable is made local to the Report ‘Balance Sheet’ by associating it using the Report attribute ‘Variable’. This variable retains its value as long as we work with this Report. On exiting the Report, the variable is destroyed and the values are lost.

Function Scope declaration

Function (User Defined Function) also allows the variables to be declared at its scope. Function variables have lifetime till the end of execution of the function. Function variables can also be declared with default value. Function variables will never inherit the value from the parent context. This means that ‘Volatile’ attribute on function variables has no effect. Functions allow actions to change the values of the variables.

Function allows a special scope called STATIC. A static variable declared in a function is equivalent to a system variable, but can be accessed only within the defined function. Its initial value is set only during the first call to the function, and later it retains the value for further calls. Only simple or compound variables can be declared as static. List variables are not currently supported at ‘Static’ scope.

Syntax

Variable : <Variable Names>

Or

Variable : <Variable Names> [:< D ata Type> [:<Value>]]

Or

List Varia b le : <Variable Names> [:<Data Type> [:<V a lue>]]

Or

Static Var i able : <Variable Names> [:<Data Type> [:<Value>]]

The variables can be declared at ‘Function’ scope by using the above. The usage of the attributes Variable and List Variable is the same as described above in the “Variable” definition.

Example

[Function : FactorialOf]

Variable : Factorial

The Function ‘FactorialOf’ requires variable ‘Factorial’ for calculation within the Function.

Example:

[Function : Sample Function]

Static Variable : Sample Static Var : Number

The static variable ‘Sample Static Var’ retains the value between successive calls to the Function ‘Sample Function’.

Inline Declaration

Variables can also be defined (with limited behaviour) during declaration itself; so a separate definition would not be mandatory. This is called inline variable specification (i.e., during declaration itself, the variables are defined inline).

Only the DATA TYPE and the DEFAULT VALUE can be specified as the behaviour for inline variables. If the DATA TYPE is specified as a variable name (i.e., not an implicit data type key word such as String, Amount, etc.) or is left blank, it is treated as a pre-defined variable.

Persistence: Inline variables even at system scope cannot be persisted.

Declaring S imple Var i able I n l ine

The ‘Variable’ attribute allows declaring Simple Variable inline by specifying the data type. Initial value to the variable can also be specified optionally.

Syntax

Variable : <Variable Names> [:<Data Type> [:<Value>]]

Where,

< Variable Names > is a list of Simple Variables, separated by comma.

< Data Type > is the data type of the Simple Variable.

< Value > is the default/initial value provided for the variables, and this value specification is optional.

Example

[Report : Cust Group Report]

Variable : VarGroupName1, VarGroupName2 : String : “Sundry Debtors”

In this example, the Simple Variables ‘VarGroupName1’ and ‘VarGroupName2’ of type ‘String’ are declared in a Report; hence, the following separate variable definitions are not required, which will help to reduce the coding complexity.

[Variable : VarGroupName1]

Type : String

[Variable : VarGroupName2]

Type : String

Declaring S imple List Variable Inline

‘List Variable’ attribute allows declaring Simple List Variable inline by specifying the Data Type. If the default value is specified, it is treated as the count to initialize the list with the specified elements by default.

Syntax

List Varia b le : <Variable Name s > [: <Data Type> [: <Value>]]

Where,

< Variable Names > is a list of Simple Variables, separated by comma.

< Data Type > is the data type of the Simple Variable.

< Value > is treated as the count to initialize the list with the specified elements by default. The number of elements can be specified only for an index-based list.

Example:

[System : Variable]

List Variable : VarGroupName1, VarGroupName2 : String : 10

In this example, the variables ‘VarGroupName1’ and ‘VarGroupName2’ of ‘String’ data type are declared as inline simple list variables at System level, and each variable will have 10 elements by default.

Declaring Com p ound List Varia b le Inline

For Compound List Variables , definition is mandatory. They cannot be declared inline.

Using Modifiers with Variables

Variable allows static modifiers such as Add/Delete/Change and Dynamic modifier ‘Local’.

Static Modification

Add/Delete/change modifiers can be used on variables to change the behaviour.

Example:

[#Variable : SV From Date]

Delete : Default

Locally modifying variables

When different reports require the same Compound Variable, and some modifications are required specific to respective reports, like adding additional members (local to the report); this is possible through the Dynamic Modifier ‘Local’.

Example:

In this example, a Compound Variable CLVEMP is defined as shown:

[Variable : CLV Emp]

Variable : Name : String

Variable : Designation : String

Variable : Age : Number

Variable : Salary : Amount

List Variable : Contact Nos : String

List Variable : Relatives

Variable : Contact Address

;; Defining Compound List Variable

[Variable : Relatives]

Variable : Name : String

Variable : Age : Number

Variable : Relation : String

Variable : Salary : Amount

;;Defining another compound variable

[Variable : Contact Address]

Variable : Street Name : String

Variable : City Name : String

In ‘Employee Report1’, the variable is declared and no modifications are required locally.

[Report : Employee Report1]

Variable : CLV EMP

In ‘Employee Report2’, the same variable is declared but locally one member variable is added and one existing member variable is deleted.

[Report : Employee Report2]

Variable : CLV EMP

Local : Variable : CLV EMP : Add : Variable : Qualification : String

Local : Variable : CLV EMP : Delete : Variable : Age

Also, member variables can be localized within a compound variable. This provides the ability to re-use a compound structure defined earlier and do any local modifications, as required.

Example:

[Variable : CLVEMP]

Variable : Contact Address

Local : Variable : Contact Address : Add : Variable : State : String

List Variable Manipulations

Simple and Compound List variables support various data manipulation operations such as Adding/Deleting/Expanding List elements, Value Specifications, Retrieving values from the list elements, Searching and Sorting, Populating List Variable from a Collection, etc. New Actions and Functions specific to List Variables have been introduced for these manipulations. Before looking into these manipulations, let us understand the concept of Key, Index and Variable Path Specificaton using Dotted Notation Syntax.

Concept

Key

List variables can hold multiple values of variable types using a string based ‘Key’ specification. ‘Key’ is of type String, by default. We can specify a different data type for a key only in scenarios where we require key-based sorting. It is optional to specify key value while adding values to the list variable. The TDL Programmer has to explicitly specify the key value. Key is unique for all elements in the list. If an element is added with duplicate key, the existing element is overwritten. It is advisable to use a key only if we require frequent access to elements of the list based on key.

Index

An element of the list can be accessed via 'Index'. Index of an element is the location/position of the variable from the first element in the current sorting order. Even if we have specified keys for elements of a list, index is generated internally. It is always possible to access each element in the list by specifying the index within square brackets [ ] in the dotted notation syntax. This is explained below. Index can be negative as well. In that case, it is possible to access the elements in the reverse order of entry.

Variable Path Specification using Dotted Notation Syntax

We aware that in Tally.ERP 9, method value of any object including its sub-collections to any level can be accessed or modified with dotted notation syntax. The behaviour of the symbol prefix $ was enhanced to access the method value of any object, and an action MODIFY OBJECT was introduced to modify multiple values of any object.

Compound Variables allow us to store values of different data types. A member variable can be a single instance or a list variable. A member variable can be a compound variable and can have members again, and thus, any hierarchy can be created. In short, it is similar to a Data Object. Hence, all the attributes and actions which operate the Variable, have now been enhanced to take extended variable path syntax, i.e., the variable path can be specified using dotted notation syntax. The syntax can be used to fetch any value from any member within the hierarchy. This syntax is applicable wherever we need to specify either the variable identifier or access the value of the variable. In case of value access the operator ## is used. Value access using operator ## has been discussed in detail in the topic Index Based Retrieval using ## Operator.

Syntax

<Element Variable Specification>.<Member Variable Specification>. <Simple Member Value specification>

Where,

< Element Variable Specification > can be a Compound Variable or Compound List Variable [Index Expression].

< Member Variable Specification > can be a Compound Variable Member or Compound List Member Variable [Index Expression].

< Simple Member Value Specification > refers to the name of the simple member in the specified path.

< Index Expression > is an expression evaluating to a number. Suffixing a variable with index refers to an Element Variable. It can be positive or negative. Negative index denotes reverse access.

Example: 1

Consider the compound variable defined below:-

[Variable : CLV Emp]

Variable : Name : String

Variable : Age : Number

Variable : Salary : Amount

List Variable : Relatives

[Variable : Relatives]

Variable : Name : String

Variable : Age : Number

Variable : Relation : String

Variable : Salary : Amount

The same is declared at System Scope, and hence can be accessed anywhere in the system.

[System : Variable]

List Variable : CLV Emp

Example: 2

Suppose we want to set the value of a simple variable ‘Employee Name’, which is declared at Report Level:

[Report : Employee Report]

Variable : Employee Name : String

SET : Employee Name : ##CLVEMP[1].Name

The variable Employee Name will be set with the value of the member “Name” of the first element of the Compound List Variable “CLVEMP” .

Example: 3

In case the age of first relative of the second employee needs to be displayed, the following statement would be used in the field in a report.

[Field : RelAge]

Set As : ##CLVEMP[2].Relatives[1].age

The value specification attributes and actions, with the enhanced variable path specification, will be discussed in detail in the further topics.

List Variable Manipulations – A Detailed Look

Let us have a detailed look on List Variable manipulations with examples:-

Adding/Deleting/E x panding Elements

Adding Elements to the List Variable

Action - LIST ADD

The Action LIST ADD is used on a list variable to add an element to the list variable based on KEY. This is mandatory before we set value into the element. KEY is compulsory in this case. Key is unique for all elements in the list. If an element is added with duplicate key, then the existing element is overwritten.

Syntax

LIST ADD : <List Variable Specification> : <Key Formula> [:<Value Formula> [:<Member Specification>]]

Where,

< List Variable Specification > is the Simple List or Compound List Variable specification.

< Key Formula > can be any expression which evaluates to a unique string value.

< Value Formula > can be any expression which returns a value. It sets the initial value of the element variable, and is optional.

< Member Specification > is required only if the value needs to be added to a specific member of a Compound List Variable. If member specification is not provided, the first member variable is considered for the value.

Note: The actions LIST APPEND and LIST SET are aliases for the action LIST ADD.

To add multiple values dynamically to the List variable, we can use LIST ADD within a looping construct like While, Walk Collection, etc.

Example:

Adding elem e nts to Sim p le L i s t V a r i a ble using LIST ADD

1. Adding an element to the Simple List Variable SLV Emp with a Key

LIST ADD : SLV Emp : “E001”

2. Adding an element to the Simple List Variable SLV Emp with a Key and a value

LIST ADD : SLV Emp : “E001” : “Kumar”

3. Adding an element to the Simple List Variable SLV Emp with a Key and a value, and subsequently overriding a value corresponding to a particular key

LIST ADD : SLV Emp : “E001” : “Kumar”

LIST SET : SLV Emp : “E001” : “Keshav”

The value corresponding to the Key ‘E001’ is changed to Keshav

Adding Elements to Compound List Variable using LIST ADD

A Compound Variable CLV Emp is defined, which stores employee details such as Name, Age, Salary, etc., and the details of the Relatives.

[Variable : CLV Emp]

;;simple member variable

Variable : Name : String

;;simple member variable

Variable : Age : Number

;;simple member variable

Variable : Salary : Amount

;;compound list member variable

List Variable : Relatives

;; Compound Variable is defined here

[Variable : Relatives]

Variable : Name : String

Variable : Age : Number

Variable : Relation : String

Variable : Salary : Amount

The same is declared at the System Scope; hence, can be accessed anywhere in the system.

[System: Variable]

List Variable: CLV Emp

1. Adding an element to Compound List Variable CLV Emp with a Key

LIST ADD : CLVEmp : “E001”

2. Adding an element to Compound List Variable CLV Emp with a Key and a Value.

LIST ADD : CLVEmp : “E001” : “Kumar”

Since member specification is not provided, the first member variable is considered for value.

3. A dding an element to Compound List Vari a ble C LV Emp with a K ey and a value with memb e r spec i fication

LIST ADD : CLVEmp : “E001” : 25 : Age

Since member specificatio n is provided , member variable ‘Age’ is considered.

4. A dding an element to the Compound List Member of a C ompound List Variable with a Key and a value with mem b er s p ecific a tion

LIST ADD : CLVEmp[1].Relatives : “R001” : “Prem” : Name

In this example, we are adding an element to the Compound List Variable “Relatives” and the member variable ‘Name’ is considered for the value. ‘Relatives’ is a Compound List Member variable of the Compound List Variable CLVEMP.

Note: The values are hard coded in the examples for explanation purpose. The above Simple and Compound List Variable examples are used to explain further list variable manipulations.

Action - LIST ADD EX

This action is used on a list variable to a d d an element to t he list variable without KE Y .

Syntax

LIST ADD EX : <List Variable Specification> [:<Value Formula> [:<Member Specification>]]

Where,

< List Variable Specification > is the Simple List / Compound List Variable specification.

< Key Formula > can be any expression which evaluates to a unique string value.

< Value Formula > can be any expression which returns a value. It sets the initial value of the element variable, and is optional.

< Member Specification > is required only if the value needs to be added to a specific member of a Compound List Variable. If member specification is not provided, the first member variable is considered for the value.

Note: Action LIST APPENDEX is an alias for the action LIST ADDEX.

Adding elements to Simple List Variable using LIST ADD EX

1. Adding an element to Simple List Variable SLV Emp

LIST ADD EX : SLV Emp

2. Adding an element to Simple List Variable SLV Emp, with Value

LIST ADD EX : SLV Emp : “Kumar”

Adding elements to Compound List Variable using LIST ADD EX

1. Ad d ing a n el e ment to Compound List Variable CLV Emp

LIST ADD EX : CLV Emp

2. Ad d ing a n el e ment to Compound List Variable CLV Emp, with value

LIST ADD EX : CLV Emp : “Kumar”

Here, since member specification is not provided, first member variable is considered for value.

3. Ad d ing a n el e ment to Compound List Variable CLV Emp, with val u e and member specification

LIST ADDEX : CLV Emp : 25 : Age

Here, member specification is provided, hence member variable ‘Age’ is considered for the value.

4. A dding an element to t h e C o mpound List Member variable of a Compo u nd List Variable with value and member specifica t ion

LIST ADDEX : CLVEmp[1].Relatives : “Prem” : Name

In this example, we are adding an element to the Compound List Variable “Relatives” and the member variable ‘Name’ is considered for the value. ‘Relatives’ is a Compound List Member variable of the Compound List Variable CLVEMP.

Deleting Elements from the List Variable

Action - LIST DELETE

The Action LIST D ELE T E is used to delete an element from t h e list based on Ke y . Key formula is optional. If n o t sp e cified, a ll t h e el e men t s in the list are del e ted.

Syntax

LIST DELETE : <List Variable S pecification> [ : <Key Formula>]

Where,

<List V ar i able S p e cificati o n> is the Simple List or Compound List V a riable s p ecification.

<Key F o r m ula> can be a ny e xpression which evaluates to a unique string v a lue . It is optional

Note: Action LIST REMOVE is an alias for the action LIST DELETE.

Dele t i n g elemen t s f rom Simple List V aria b le u sing LIST DELETE

Deleting a single element f rom a Simple List Varia b le

LIST DELETE : SLV Emp : “E001”

The element identified by key ‘E001’ will be deleted from the Simple List Variable S L V Emp .

Deleting all elemen t s fr o m a Simple List V ariable

LIST DELETE : SLV Emp

Since key formula is not specified, all el e men t s from simple l i st v a riable S L V E m p will be d e leted .

Dele t i n g elemen t s f rom a C o mpound L i s t V ari a ble using LIST DELE T E

Deleting an eleme n t from a Com p ound L ist V ariable

LIST DELETE : CLV Emp : “E001”

The el e ment identi f ied by key ‘E0 0 1’ w ill be delet e d fr o m the Compound List Variable “CLV Em p ”.

Deleting all elemen t s fr o m a Compo u nd List Varia b le

LIST DELETE : CLV Emp

Since key formula isn’t specifi e d, all elemen t s from compound list varia b le C L V E m p are delet e d.

Action - LIST DELETE EX

This a ction is used to delete an e lement fr o m t he list based on index. INDEX f ormula is optio n al. I f not specified, all the elements in the list are deleted. A ne g ative i n dex d enotes reverse position .

Syntax

LIST DELETE EX : <List Variab l e Specification> [:<Index Formula>]

Where,

<List V ar i able S p e cificati o n> is the Simple List or Compound List V a riable s p ecification.

<Ind e x Formula> can be any expression w h ich ev a luates to a n i n dex n umbe r . It i s op t ional.

Note: Action LIST REMOVE EX is an alias for the action LIST DELETE EX.

D e l e t i n g E l em e n t s fr o m Simple List V a r i able using LIST DELETE EX

Deleting a single element f rom a Simple List Varia b le

LIST DELETE EX : SLVEmp : 2

The element identified by index number ‘ 2 ’ will be deleted from Simple List Variable S L V Emp .

Deleting all elemen t s fr o m a Simple List V ariable

LIST DELETE EX : SLVEmp

Since index formula is not s pecifi e d, all elemen t s fr o m S imple List Varia b le S L V Em p are delete d .

Dele t i n g elemen t s f rom a C o mpound L i s t V ari a ble using LIST DELE T E EX

Deleting an eleme n t from a Com p ound L ist V ariable

LIST DELETE EX : CLVEmp : 10

The element identified by index ‘1 0 ’ will be delet e d from the Compou n d List V a riable C L V Em p .

Deleting all elemen t s fr o m a Compo u nd List Varia b le

LIST DELETE EX : CLVEMP

Since i n dex form u la isn’t specified, all elemen t s of compound list variable C L V EM P are delete d .

5. Ex p anding Elemen t s in the List Varia b le

Action - LIST EX P AND

The Action LIST EXPAND is u sed to create the specified number o f blank elemen t s and ins e rt them i nto t he lis t . All these elemen t s a re created without a key . If key specification is required f o r each eleme n t, then either LIST FI L L or a loop can b e used to a dd eleme n ts individuall y .

Syntax

LIST EXPAND : <List Variable S p ecification> : <Count Formula>

Where,

<List V ar i able S p e cificati o n> is the Simple List or Compound List variable specific a tion.

<Count F o r m ula> can be a ny e xpression which evaluates to a numbe r .

Example:

Exp a nding Simple Li s t V a r i able using LIST EX P A N D

LIST EXPAND : SLVEMP : 10

Here, cou n t formula is 10. Henc e , 10 bla n k e lements are added to Simple List V ariabl e S L VEMP’.

Exp a nding Compo u nd List V a riable u s ing L I ST EX P AND

LIST EXPAND : CLVEMP : 5

Here, co u nt f ormula is 5. Thus, 5 bl a nk el e ments are ad d ed t o th e C ompound List Variable ‘C L VEMP’.

LIST EXPAND : CLVEMP[1].Relatives : 10

Here, count formula is 1 0 . Hence, 10 blank elemen t s are added to Compound List V ariable ‘Rel a tives’. ‘Relatives’ is a Compound List Member vari a ble o f the Compound List V ariable ‘CLVEMP’.

Value Specific a tions

The value for the Simple/List Variables (Simple & Compound) can be specified using Attributes at Report and Form Level, and using Actions in User Defined Functions.

Value s peci f ication at Re p ort L evel

The attri b utes S ET a nd PRINTSET are used to sp e cify the variable values at Report L evel.

Attribute - SET

The Rep o rt a ttribute SET c a n b e used to specify a v a riable n ame a n d i ts value, w hich w ill be set during the startup of the report.

Syntax

SET : <Variable Specification> : <Value Expression>

Where,

< V ariable S pecifi c ation> is the variable path specification.

< V alue E x pression> c an be any e xpression, which evaluates to a v a lue f o r the var i able of the specified data type.

Example:

;; Setting value to a Simple Variable

SET : Var : “ABC”

;; Setting value to a Simple List Variable element

SET : ListVar[1] : “XYZ”

;; Setting value to Compound List Variable element's member

SET : CLVEMP[1].Name : “Kumar”

Attribute - PRINT SET

The Re p ort attribute Print Set is similar to the S ET a t tribute but s ets the value o f the variables to the specified value w h en the report is st a rted in Print mode.

Syntax

PRINT SET : <Variable Specification> : <Value Expression>

Where,

< V ariable S pecifi c ation> is the variable path specification.

< V alue E xpre s sion> can be any expression which e valuates to a value for the variable of the specified data type.

Example:

;; Setting value to a Simple Variable

PRINTSET : Var : “ABC”

;; Setting value to a Simple List Variable element

PRINTSET : ListVar[1] : “XYZ”

;; Setting value to Compound List Variable element's member

PRINTSET : CLVEMP[1].Name : “Kumar”

V alue s pe c i f ica t ion at F orm Le v el

Attribute - SET

The Form attribute SET i s simil a r to the R e port a ttribute SET , the difference being that w hile the rep o rt se t s the value once in i t s lifetime, the form SET is execut e d during every r e generation/ refr e sh of the re p ort.

Syntax

SET : <Variable Specification> : <Value Express i on>

Where,

< V ariable S pecifi c ation> is the variable path specification.

< V alue E x pression> c an be any e xpression, which evaluates to a v a lue f o r the var i able of the specified data type.

Example:

;; Setting value to a Simple Variable

SET : Var : “ABC”

;; Setting value to a Simple List Variable element

SET : ListVar[1] : “XYZ”

;; Setting value to Compound List Variable element's member

SET : CLVEMP[1].Name : “Kumar”

V alue s pe c i f ica t ion at F unc ti on Le v el

Actions SE T , MULTISE T , EXCHANGE, INCREMENT and DECREMENT are u s ed.

Actio n - SET

Values of variables can be set / updated via the SET action. This action is available as a global action, and can be used within a function also. List variables and compound variables cannot have values; they can have only element/member variables inside them, respectively. If SET action is used on compound variables, the value will be set to the FIRST member variable. If the first member variable is again compound, the program would search for the first non-compound leaf member and set the value.

For list variables, the value is treated as the count, and the list is expanded by the number of elements provided in the expression.

Syntax

SET : <Variable Specification> : <Value Expression>

Where,

< V ariable S pecifi c ation> is the variable path specification.

< V alue E xpre s sion> can be any expression which e valuates to a value for the variable of the specified data type.

Example:

;; Setting value to a Simple Variable

SET : Var : “ABC”

;; Setting value to a Simple List Variable element

SET : SLVEMP[1] : “XYZ”

;; Setting value to Compound List Variable element's member

SET : CLVEMP[1].Name: “Kumar”

Action - MU L TISET

The ac t ion MU L TI SET is used to s et t h e v alues of compound member variables in one call. All m e mber specifications are rela t ive to the comp o und varia b le sp e cification given.

Syntax

MULTI SET : <CompoundVariable Specification> + : <Member Specification :

Value> [, <Member Specification : Value>, …]

Where,

<Compo u nd V ariable S pecific a tion> is the C o mpound V a riable s p ecification.

<Member S pe c ification : V alue> is the list of name-value pairs for setting member values.

Example: 1

MULTISET : CLVEMP[1] : Name : “Vimal”,Age : 26, Salary :($$AsAmount:10000)

All memb e r varia b les of 1st eleme n t of Compound List Variable C L VEM P are set with MU L TISET .

Example: 2

MULTISET : CLVEMP[1].Relatives[1] : Name : “Hari”, Age : 20, +

Relation:“Brother”

Here, a ll member v ariables for t h e first element of t he Compound List V a riable Rel a tives are set .

Relatives is a Compound List M e mber vari a ble of the Compou n d List Variab l e C L V EM P .

Action - E X CHANGE

This action is used to swap the values of two variables, provided both belong to the same data type. This cannot be done for Simple List or Compound List as a whole. However, values of elements of Simple List and Compound List member variables having same data type can be exchanged.

Syntax

EXCHANGE : <First Variable Specification> : <Second Variable Specification>

Where,

<First V ari a ble S pec i fication> is the simple varia b le specificatio n .

<Seco n d V ariable S p ecifica t ion> is the simple variable specification.

Exch a nging v a lue of a S i mple V aria b le w i th anoth e r Si m ple V ari a ble

EXCHANGE : EmpVarOld : EmpVarNew

Both t h e variabl e s are of ‘ S tring’ da t a ty p e. The value o f the variable Emp V arOld is ex changed with that of the varia b le Emp V arNew on execution of the action.

Exch a nging value of an ele m ent o f Simple List V ariable with that of a nother S im p le Li s t V ariable

EXCHANGE : SlvEmpOld[1] : SlvEmpNew[1]

The value of the first elem e nt of Sl vE mpOld is exchanged with that of the first e lement of SlvEmpNe w . Both the Simple List V ariables are of ‘String’ da t a type

Exch a nging v a lue of a S imple variable with a me m ber variable of a C o m pound Li s t variable

EXCHANGE : EMP Salary : CLVEmp[1].Salary

The v a lue o f a variable Emp Salary i s exch a nged wi t h that of the memb e r variable ‘Salary’ of the Compound List Variable C L VEm p . Both the simple v a riables a re of ‘S t ring’ data type.

Action - INCREMENT

INCREMENT is a special action provided in ‘Function’ scope to i ncrement values of the variable. This is support e d only on simple variables of type Numbe r .

Syntax

INCREMENT : <Simple V a riable Specifica t ion> [:<NumI n crement Expressi o n>]

Where,

<Simple V ariable S p e cificat i on> is the simple variable specification.

<NumIn c r e ment E xpres s ion> is an e xpression which eval u ates to a numbe r . Based on this, the v a riable v a lue is increment e d. It is o p tional. If n ot s p ecified , variable value is incremented by 1 .

Example:

INCREMENT : Counter

;; Incrementing the variable value by 1

INCR : Counter : 2

;; Incrementing the variable value by 2

Actio n - D E CREMENT

Decrement is a special action provided in ‘Function’ scope to decrement values of the variable. It is supported only on simple variables of type Number.

Syntax

DECREMENT : <Simple Variable Specification> [:< N u mIncrementExpressio n >]

Where,

<Simpl e V ar S pecific a tion> is the simple variable specification.

<NumIn c r e mentExpres s ion> i s a n expression evaluating to a no., bas e d on whic h , the var i able value is d ecremented. It is optional. If n o t sp e cified, the variable value is d ecremented by 1.

Note: Action DECR is an alias for the action DECREMENT.

Example:

;; Decrementing the variable value by 1

DECREMENT : Counter

;; Decrementing the variable value by 2

DECR : Counter : 2

V alue M odific a tion at Field Le v el

Attribute - MODIFIES

The Field attribute ‘Mo d ifies’ is u sed t o mo d ify the value of the variabl e .

Syntax

Modifies : <Variable Specifica t ion> [:<Logical Flag>]

Where,

< V ariable S pecifi c ation> is the variable path specification.

<Log i cal F lag> can be a logical v a lue TRUE / FALSE. TRUE w ould set the value a f ter the fi e ld's acceptance, while F ALSE will set it duri n g the acc e ptance of t h e report having the field.

Example:

[Field : EMP Age]

Modifies : EMPAgeVar : Yes

Here, value of t he vari a ble E MPA g eVar will be modified with the val u e s tored/keyed in the field EMP Age af t er the fiel d 's acce p ta n ce.

Retrieving value from List

Fu n ction - $ $ ListValue

It is used to retrieve the v a lue of an el e ment in t he list for a given key . If the list i s of compound v a riables, an optional m e mber specification can be giv e n to extract v a lue o f a specific member .

Syntax

$$ListValue : <List Variable Specification> : <Key Formula> [:<Member Specification>]

Where,

<List V ar i able S p e cificati o n> is the Simple List or Compound List V a riable s p ecification.

<Key F o r m ula> can be a ny e xpression which eval u ates to a string value.

<Member S p ecific a tion> i s required only if the value needs to be extract e d fr o m a spec i fic member of a Compound List V a riable.

Example:

Re t rieving v a lue f r om Simple L i st V a riable u s i n g $ $Li s t V alue

$$ListValue:SLVEMP:"E001"

In this example, t h e function returns the value of the element identified by the key ‘E001’ f rom the simple list vari a ble ‘S L V Emp’.

$$ListValue:SLVEMP:##KeyVar

In this example, the variable ‘KeyVa r h olds the key val u e. T h e fu n ction r e turns the value of the eleme n t ide n tified by the key from t h e simple list vari a ble ‘S L V Emp’.

Re t rieving v a lue f r om Comp o und List V ariable u s ing $$ L i s t V a l u e

$$ListValue:CLVEmp:##KeyVar:Age

In this example, t h e v ariable ‘KeyVa r ’ holds the key value. The function returns the iden t ified Compound List V ariable el e ment's memb e r v a riable v a lue. In this c ase , the member s pecification has been sp e cified as ‘Age’.

Fu n ction - $ $ ListValueEx

The Function $$List V alueEx returns the value of an element at the specified index in the list.

Syntax

$$ListValueEx : <List Variable Specification>:<Index Formula> [:< Member Specification>]

Where,

<List V ar i able S p e cificati o n> is the Simple or Compound List V ariable sp e cification.

<Ind e x Formula> can be any expression w h ich ev a luates to a n i n dex n umbe r .

<Member S p ecific a tion> i s required only if the value needs to be extract e d fr o m a spec i fic member of a Compound List V a riable.

Example:

Re t rieving v a lue f r om Simple List V a riable u s i n g $ $Li s t V alu e Ex

$$ListValueEx:SLVEmp:##IndexVar

In t his ex a mple, the variable ‘I n dexVa r ’ hol d s t h e in d ex value. The function returns the value of the element identified by t h e in d ex fr o m t h e simple list varia b le ‘ S LV Emp’.

Re t rieving v a lue f r om Comp o und List V ariable u s ing $$ L i s t V a l u eEx

$$ListValueEx:CLVEmp:##IndexVar:Age

Here, v a riable ‘Key V ar’ holds the index value. The functi o n returns the identifi e d C ompound List V a riable eleme n t's mem b er variab l e value. Here , the member specified is ‘Age’.

In d ex Based Retri e val us i ng ## Operator

The o p erator ## is us e d to access t he value of the variable. It also allows dotted no t ation s yntax to access variables/m e mber variables/elem e nt v a riables o f a list at any level.

When ## is used on a compound variable (without path specification), it ret u rns t he value of the first member variable , by default. Similarl y , on a list varia b le, it returns the no. of items in the list.

Syntax

##<Element Variable Specification>.<Member Variable Specification>.<Simple Member Value specification>

Where,

<Elem e nt V ari a ble S pecific a tion> can be a Compound Variable or C ompound List Variable [In d ex Expressio n ].

<Member V ariable S p e cificat i on> can be a Comp o und V ariable Member or Compound List Member Variable [Index Expr e ssion].

<Simple Me m ber V alue S p e cificat i on> refers to t h e name of a simple member in speci f ied p ath.

<Ind e x Expressi o n> is an expression that evaluates to a no. S uffixing a variable with i ndex refers to an element variable . It can be p ositive or negative. Negative index denotes reverse access.

Example:

Re t rieving V a lue from Simple Li s t V a r i a ble using # # Op e ra t or

SET : TempVar : ##SLVEMP[3]

V a lue o f el e ment in SLVEM P , identifi e d by the index ‘3’, will be set to t h e v a riable ‘ T emp V ar’.

Re t rieving V a lue from Compo u nd List V a riable using # #O p er a tor

LOG : ##CLVEmp[2].Relatives[1].Name

Here, we are re t rieving value of the identified C o mpound List V ariable (R e latives) el e ment s member variable value. ‘Relatives’ is a member variable of the Comp o und List Vari a ble C L VEMP .

Loop i ng Construct – For In/For Each

The F OR IN loop is used to iterate over the values in t he list variable. The n u mber o f itera t ions depends on the number of items in the list variable .

Syntax

FOR IN : < I terator Variable> : <List Variable Name >

.

.

END FOR

Where,

<Iterator V ariable> is the name of the variable w h ich hol d s the Key value in e very iter a tion.

<List V ar i able Nam e > is the n a me o f the Simple Li s t or Compound List V ariable.

This construct will w a lk o nly the elemen t s in the list which a r e having a ke y . Since the iterat o r variable is filled with a key for e ach el e ment , all elemen t s w h ich do not have a k e y a re ignore d . This is useful to w alk keyed list v a riable e lements in the current sorting orde r . If t he e lement does not have a k e y , t hen oth e r loo p s like WHILE, FOR, etc., can be used and the elem e nts can be op e rated via index.

Example:

Iterat i n g the Simple List V a riable V alues

FOR IN : KeyVar : SLV Emp

LOG : $$ListValue:SLVEmp:##KeyVar

END FOR

Here, t h e iter a tor v a riable “Key V ar” holds the Key val u e in every occurrence of the iteration. In every iter a tion, the value of the element identified by t h e key is logged using the function $$Li s t V alue .

It e ra t i n g the Comp o und List V ariable V a l u es

FOR IN : KeyVar : CLV Emp

LOG : $$ListValue:CLVEmp:##KeyVar:Age

END FOR

Here, t h e it e rator v ariable “KeyVar” holds the Key value in every iteration. In every iteration, the v a lue o f the member “Age” of the element o f “C L VEMP” iden t ified by the key is logged using the function $$Li s t V alue .

Note: The looping construct FOR EACH is an alias for the looping construct FOR IN.

List V ariable S pecific Functions

Fu n ction - $ $ ListKey

The function $$ListKey returns the corresponding key f o r the given index.

Syntax

$$ListKey : <List Variable Spe c ification> : <Index Specification>

Where,

<List V ar i able S p e cificati o n> is the Simple List or Compound List V a riable s p ecification.

<Ind e x S pecif i cation> can be any ex p ression which evaluates to a num b er.

Example:

Retrieving key from a Simple L ist V ariable using $ $ListKey

01 : LOG : $$ListKey:SLVEMP:2

In this example, the fu n ction $ $ListKey retrieves the Key of t h e sec o nd element of the Simple List V a riable ‘S L VEMP’.

Retrieving key from a Compound List V ariab l e using $$ListKey

02 : LOG : $$ListKey:CLVEmp[1].Relatives:1

Here, key of first element of Compou n d L ist V ariable ‘Relative s ’ is retrieved. ‘Relatives’ i s a m e mber of Compound List Variable 'CLVEMP'.

Fu n ction - $ $ ListIndex

The function $ $ListIn d ex ret u rns t h e Corresponding index for the given Key .

Syntax

$$ListIndex : <List Variable Specification> : <Key Specification>

Where,

<List V ar i able S p e cificati o n> is the Simple List or Compound List V a riable s p ecification.

<Key S p e cificat i on> c a n be any expression which evalu a tes to a s t ring val u e.

Example:

Retrieving index from a Simple List V ariab l e using $$ListI n dex

01 : LOG : $$ListIndex:SLVEMP:E001

Here, index of the element identifi e d by the key value ‘E00 1 ’ is retrieved from ‘SLVEMP’.

Retrieving index from a Compound List V ariable using $$Lis t Index

02 : LOG : $$ListIndex:CLVEmp:E001

Here, index value of the elem e nt i d entified by the key value ‘ E 001’ is retrieved from ‘C L VEMP’.

Fu n ction - $ $ ListCount

The function $$ListCount retrieves the number o f items in the list.

Syntax

$$ListCount : <List Variable Specification>

Where,

<List V a ri a ble S pe c ificatio n > is the Simple List or Compound List Variable speci f ication.

Example:

01 : LOG : $$ListCount:SLVEMP

02 : LOG : $$ListCount:CLVEMP

Fu n ction - $ $ ListFind

It is used to check if a given key exis t s in the list or n ot. I t r e turns a logic a l fl a g as a result.

Syntax

$$ListFind : <List Variable Specification> : <Key For m ula>

Where,

<List V ar i able S p e cificati o n> is the Simple List or Compound List V a riable s p ecification.

<Key F o r m ula> can be a ny e xpression which eval u ates to a string value.

Example:

01 : LOG : $$ListFind:SLVEMP : E001

02 : LOG : $$ListFind:CLVEMP : E001

Fu n ction - $ $ List V alueF i nd

This function can be used to check if a giv e n v alue exis t s in the lis t . If a given list has more th a n one same value, the index can be used to r etrieve the n'th matc h ing val u e.

Syntax

$$ListValueFind : <List Variable Specification> : < Occurance Specification> : <Value Formula> [:<Member Specification>]

Where,

<List V ar i able S p e cificati o n> is the Simple List or Compound List V a riable s p ecification.

<Occurance S pecifi c ation> can be any expression which e valuates to a numb e r.

< V alue Formula> can be any ex p ression w h ich evaluates to a value.

<Member S pe c ificatio n > can be specified if the list eleme n t is compound. It is option al.

Example:

;; Finding value from the Simple List Variable

01 : LOG : $$ListValueFind:SLVEMP:1:RAMESH

;;Finding value from the Compound List Variable with member specification

03 : LOG : $$ListValueFind:CLVEmp:1:PRIYA:Name

The function will return YES if the value exists in the list, e lse it will r e turn NO.

Popula t ing a List from a Collection

Action - LIST FILL

It is used to fill a list from a c ollecti o n ins t ead of using t he looping co n struct s . The specified collection is walked and the key formula and v a lue f ormula is evalua t ed in the conte x t of each object to create list elemen t s.

Syntax

LIST FILL : <List Variable Specification> : <CollectionName> [:<Key Formula> [:<Value Formula> [:<Member Specification>]]]

Where,

<List V ar i able S p e cificati o n> is the Simple List or Compound List V a riable s p ecification.

<Colle c tion N a me> is t h e n ame of the collection from which the valu e s need to be fetched to fill the list v a riable.

<Key F o r m ula> can be a ny e xpression which evaluates to st r ing val u e. It is o ptional.

< V alue Formula> c an be any expression w hich returns a value. The data type of the value must be same as th a t of the L ist v a riable. V alue form u la is option a l. I f not specified , only KE Y i s s e t f or each added element.

<Member S pe c ificatio n > can be given if the list contains a compound variable

Note: If both key and value are not specified, blank elements are added to the list.

Example

Popu l a ting a Simp l e L i st V ar i able from a Collection

LIST FILL : SLV Emp : Employees : $Name : $Name

All the employee names from the collection ‘Employees’ will b e ad d ed to the Simple List Variabl e , once the action LIST Fill is execute d .

Pop u l a ting a Compo u nd List V a ri a ble f r om a Colle c tion

LIST FILL : CLV Emp : Employees : $Name : $Name

In this example, a ll the employee names from the collection ‘Em p loyees’ will be ad d ed to the first m e mber variabl e , as t here is no member specification.

LIST FILL : CLV Emp : Employees : $Name : $Designation: Designation

In this example, D esignatio n s of all the employees from the collection ‘Employees’ will be added to t h e m e mber variable ‘Designation’.

LIST FILL : CLV EMP[1].Relatives:Employees : $Name : $SpouseName : Name

Spouse name o f all empl o yees from the collecti o n ‘Employees’ will be added to m e mber variable ‘Name’ of Compound List V ariable ‘Relatives’. ‘Relatives’ is a member v a riable of ‘CLVEMP’.

Sorting of List Elemen t s

Initially , w hen t h e list variable is create d , it is sorted on the order of inser t ion. TDL provi d es the facility to sort the v a lues in the list varia b le based either on key or on value. The following actions allow changing the sort order:

o List Key S ort

o List V a lue Sort

o List Res e t Sort

Action - LIST KEY S O RT

The action LIST KEY SORT allows the user to sort the elements of the list based on t h e k e y .

Keys are by default of type ‘Stri n g’; so, the absence of key da t a type specification will consid e r key da t a type as S tring while s o rting. The user c an overri d e t hi s by speci f ying a k ey d ata type . Keys are option a l for elemen t s . All elemen t s in the list may not have a key . In such cases, comparisons of eleme n ts would be done based on the inser t ion o rder .

Syntax

LIST KEY SORT : <List Variable Specification> [:<Ascending/DescendingFlag> [:<Key Datatype>]]

Where,

< List Variable Specification > is the Simple List or Compound List Variable specification.

< Ascending/DescendingFlag > can be YES/NO. YES is used to sort the list in ascending order and NO for descending. If the flag is not specified, then the default order is ascending.

< Key Data Type > can be String, Number, etc. It is optional.

Note: The action LIST SORT is an alias for the action LIST KEY SORT .

Example

Sorting Simp l e List b ased on K e y

LIST KEY SORT : SLVEmp : Yes : String ;;Ascending Order

LIST KEY SORT : SLVEmp : No : String ;;Descending Order

Sorting Comp o und List based o n Key

LIST KEY SORT : CLVEmp : Yes : String ;;Ascending Order

LIST KEY SORT : CLVEmp[1].Relatives : No : String ;;Descending Order

Action - LIST V A LUE SO R T

The action LIST VALUE SORT allows the user to sort the elements of the list based on value.The data are sorted as per the data type specified for the list variable in case of simple list, and the member specification data type in case of compound list. If a compound list is chosen and member specification is not specified, then the list is sorted by value of the first member variable.

If duplicate values are in the list, the key data type passed is considered to sort by key, and then in absence of key, insertion order is used.

Syntax

LIST VALUE SORT : <List Variable Specification> [:<Ascending/Descending Flag> [:<Key Datatype> [:<Member Specification>]]]

Where,

< List Variable Specification > is the Simple List or Compound List Variable specification.

< Ascending/DescendingFlag > can be YES/NO. YES is used to sort the list in ascending order and NO for descending. If the flag is not specified, then the default order is ascending.

< Key Data Type > can be String, Number, etc. It is optional.

< Member Specification > is the member specification in case of compound list. If not specified, the list is sorted by the value of first member variable.

Example

Sorting Simp l e List b ased on V alue

;;Ascending Order

LIST VALUE SORT : SLVEmp : Yes : String

;;Descending Order

LIST VALUE SORT : SLVEmp : No : String

Sorting Comp o und List based o n V alue

;;Ascending Order

LIST VALUE SORT : CLVEmp : Yes : String

;;Descending Order

LIST VALUE SORT : CLVEmp[1].Relatives : No : String

Actio n - LIS T RES ET S O RT

This action resets the sorting method of the list and brings it back to the insertion order.

Syntax

LIST RESET SORT : <List Variable Specification>

Where,

< List Variable Specification > is the Simple List or Compound List Variable specification.

Example:

LIST RESET SORT : SLVEMP LIST RESET SORT : CLVEMP

Some Common Functions Used

Fu n ction - $ $ IsSysNam e V ar

This function checks if the variable has a value which is a SysName like ‘Not Applicable’, ‘End of List’, etc. In case of repeated variables, if any one value is a non-sysname, it returns FALSE.

Syntax

$$IsSysNameVar : <Variable Speci f ication>

Where,

< Variable Specification > is the simple variable path specification.

Example

$$IsSysNameVar:EmpVar

Here, $$IsSysNameVar returns YES if variable EmpVar has Sysname as value, else returns NO.

Fu n ction - $ $ IsDefaultVar

This function determines if the content of the variable has a “Default” or blank as the value. This function is applicable only for Simple variables. In case of simple repeated variable, if any one value is non-default, then this is not a default variable, and the function returns NO.

Syntax

$$IsDefaultVar : <Variable Speci f ication>

Where,

< V ariable S pecifi c ation> is the simple variable path specification.

Example:

[Field : DefaultVar]

Set as : $$IsDefaultVar:SVValuationMethod

$$IsDefaultVar returns YES if value of SV V aluationMethod is blank or Default, else returns NO.

Fu n ction - $ $ IsActuals V ar

This fu n ction c h ecks if the con t ent of t h e variable is bla n k or sysname or “ACTUALS”.

Syntax

$$IsActualsVar : <Variable Speci f ication>

Where,

< V ariable S pecifi c ation> is the simple variable path specification.

Example:

$$IsActualsVar:SVBudget

YES is returned if the valu e o f variabl e SVBud g et is Blank or Sysname or “ACTUALS”, else NO.

Fu n ction - $ $ IsCurr e nt V a r

This fu n ction c h ecks if the con t ent of t h e variable is Blank or Sysname or “ S tock in hand”.

Syntax

$$IsCurrentVar : <Variable Specification>

Where,

< Variable Specification > is the simple variable path specification.

Example

$$IsCurrentVar:DSPOrderCombo

YES is returned if value of DSPOrderCombo is Blank or Sysname or Stock-In-Hand, else NO.

Fu n ction - $ $ ExecVar

This fu n ction ret u rns t h e value of a variable in the p arent report chain.

Syntax

$$ExecVar : <Variable Specification>

Where,

<Variable Specification> is the simple variable path specification.

Example:

$$ExecVar:DSPShowMonthly

Function $$ExecVar returns the value of the variable DSPShowMonthly from the parent report.

Fu n ction - $ $ FieldVar

This function returns the value of the field which is acting as a variable with the specified name.

Syntax

$$FieldVar : <Variable Specifica t ion>

Where,

< V ariable S pecifi c ation> is the simple variable path specification.

Example:

[Collection : GodownChildOfGodownName]

Type : Godown

Child of : $$FieldVar:DSPGodownName

In this example, $$FieldVar is used to fetch the value of the variable DSPGodownName whose value is modified in a field. This value becomes the value for the ‘ChildOf’ attribute.

Fu n ction - $ $ ParentField V ar

This function gets the field variable value from its parent report.

Syntax

$$ParentFieldVar : <Variable Spe c ification>

Where,

<Variable Specification> is the simple variable path specification.

Example:

[Field : ParentFieldVar]

Set as : $$ParentFieldVar:SVStockItem

Here, the function returns field variable value from its parent report for the variable “SVStockItem”.

Field Acting as a Variable

The ‘Variable’ attribute in a ‘Field’ Definition is used to make the field behave as a variable, with the specified name. The variable need not be defined as it inherits data type from the field itself. Field can act as a simple variable only, since it can hold only simple value.

Syntax

[Field : <Field Name>]

Variable : <Variable Name>

Where,

<Fie l d Name> is the name of t h e field.

< V ariable Name> is the name of t h e variable.

Example:

[Field : EmployeeName]

Variable : EmpNameVar

Implication of Repeat Variables in Columnar Report

The re p ort in which a number of columns can be added or delet e d as per the user inpu t s, is refe r red to as Col u mnar R eport. In a C olumnar Report, Lines are re p eated vertically and Fields are repeat e d horizon t ally . The Columnar Rep o rt can be a:

MultiColumn R e port - Column c a n be repeated based on the user inpu t s.

AutoColu m n R eport - M ultiple columns can b e rep e ated b ased on the user i nput, on the single click of a b utton.

Autom a tic Auto C olumns - R eport can be started with predefined multi p le columns w it h out user intervention.

The Attribute ‘Repeat’ V ariable, R e port and Li n e

Let us see the implications of Repeat Attribute of Vari a ble / R eport / Line Definitions in context of Columnar Repor t s.

1. Repeat Attribu t e of V ariable definiti o n

Please refer to t h e topic “Varia b le Definition and Attributes”.

2. ‘Repeat’ Attribute of Report definition

The Repeat A ttribu t e of ‘Report’ d e finition is us e d specifically in Columnar Repor t s. When we specify ‘Repeat’ attribute with a v ariable name, the report becomes a C olumnar Report and the number of columns depen d s u p on the values st o red in the variab le . Only simple variabl e s c an be rep e ated. A lso , a report c a n h a ve more than one varia b les rep e ated. In such c ases, the n umber of columns in t h e rep o rt dep e nds o n the maximum value a Repeat V ariable hol d s.

The ‘Rep e at’ attri b ute o f the report is d eclaration cum repeat specific a tion; so a se p arate declar a tion is not required. Even if a declaration is done usi n g ‘Vari a ble’ attribute, ‘Repe a t’ is con­sidered as a rep e at s p ecification.

Syntax

[Report : < R eport Name>]

Repeat : <Variable Names>

Where,

<Report Nam e > is the n a me of the Rep o rt.

< V ariable Names> is the comm a -separa t ed list of variables.

3. Repeat Attribute of Line Def i nition

The ‘Repea t ’ Attri b ute of ‘Line’ Definition is used to repeat the Field h orizontally in columns.

Syntax

[Line : <Li n e Name>] Repeat : <Field Name>

Where,

<Line Name> is the name of the line.

<Fie l d Name> is the name of t h e Field which n e eds t o be repeate d .

Example:

Let us look into the usage of ‘Re p eat’ At t ribute at Variable/Re p ort/Line Definitions in designing the C o lumnar S tock Item-wise Customer-wise Sales Report . In this report , S tock Item names should be r e peated ve r tically and C ustomer/Party names horizon t all y . The columns should be automatically available when the report is started.

Repeat A ttribute of V ariable Definition

[Variable : PName]

Type : String

Repeat : ##DSPRepeatCollection

The variable ‘DSPRepeatCollection’ holds the collection name ‘CFBK Party’. This collection contains a method name ‘PName’. In this case, the variable ‘PName’ would be filled with the method value from each object of the collection “CFBK Party”.

[Collection : CFBK Party]

Source Collection : CFBK Voucher

Walk : Inventory Entries

By : PName : $PartyLedgerName

Aggr Compute : BilledQty : SUM: $BilledQty

Filter : NonEmptyQty

Variable ‘PName’ holds multiple values based on implicit index. Method value of each object of collection ‘CFBK Party’ is picked up and stored in the variable's 1st index, 2nd index, and so on.

‘Repe a t’ Attri b ute of Report Defi n ition

[Report : CFBK Rep]

Use : DSP Template

Form : CFBK Rep

Variable : DoSetAutoColumn, PName Repeat : PName

Set : DoSetAutoColumn : Yes

Set : DSPRepeatCollection : “CFBK Party”

Set : SVFromDate : $$MonthStart:##SVCurrentDate

Set : SVToDate : $$MonthEnd:##SVCurrentDate

The attribute “Repeat” determines that it is a Columnar Report. The number of columns depends on the number of values available in the variable “PName”.

Repeat A ttribute of Line Definition

[Line : CFBK Rep Details]

Fields : CFBK Rep Name, CFBK Rep Party, CFBK Rep Col Total

Repeat : CFBK Rep Party

Total : CFBK Rep Party

Field ‘CFBK Rep Party’ is repeated based o n the no. o f values of varia b le (NumSe t s). So, those many numbers of instanc e s of the field are created. E ach field will have a n implicit index n umber (s t arting fr o m 1). This impli c it index is us e d to evaluate expressi o ns in the cont e xt of the field.

Common Functions used with Columnar Reports

Fu n ction - $ $ NumSets

It returns the number of columns in the report. It does not take any parameter. If the report is an auto report or sub report, it returns the number of columns in the parent of the auto/sub report. Number of set is the maximum number of values a repeated variable can hold in that report.

Syntax

$$NumSets

Example:

[Field : CFBK Rep Col Total]

Use : Qty Primary Field

Set as : $$Total:CFBKRepParty

Border : Thin Left

Invisible : $$Numsets=1

In this example, the ‘Total’ column will be invisible if there is only one column in the report.

Fu n ction - $ $ Low V alue

This fu n ction c a n be used to get the low e st value in a set o f values in t h e repe a ted varia b le.

Syntax

$$LowValue : <Variable Specifica t ion>

Where,

< V ariable S pecifi c ation> is a simple variable specification.

Example:

Let us suppose that the Repeat Variables in a Columnar Report are SVFromDate and SVToDate. Consider the following Field Definition in the same report:

[Field : VariableLowValue]

Use : Name Field

Set as : $$LowValue:SVFromDate

$$Lowvalue returns the lowest value in a set of values in the repeat variable SVFromDate.

Fu n ction - $ $ H i gh V a lue

This function can be used to get the highest value in a set of values in the repeated variable.

Syntax

$$HighValue : <Variable Specific a tion>

Where,

<Variable Specification> is a simple variable specification.

Example:

Suppose that the Repeat Variables in a Columnar Report are SVFromDate and SVToDate. Consider the following Field definition in the same report:

[Field : VariableHighValue]

Use    : Name Field

Set as : $$HighValue:SVToDate

$$HighValue returns the highest value in a set of values in the repeat variable SVToDate.

Fu n ction - $ $ IsCommon

This function is used with repeated variable to check if all the values in the repeat set are same.

Syntax

$$IsCommon : <Variable Specifica t ion>

Where,

<Variable Specification> is a simple variable specification.

Example:

Suppose the Repeat Variable in a columnar report is SVCurrentCompany. Consider the following Field Definition in the same report:

[Field : VariableIsCommon]

Use    : Logical Field

Set as : $$IsCommon:SVCurrentCompany

$$IsCommon returns YES if all values in SVCurrentCompany are same, otherwise returns NO.

Fu n ction - $ $ VarRang e Va l ue

This function gets a list of variable values, separated by the specified separator character. If no separator character is specified, comma (,) is taken as the separator character by default.

Syntax

$$VarRangeValue : <Variable Specification> [:<Separator Character> [:<Start Position> [:<End Position>]]]

Where,

< V ariable S pecifi c ation> is the simple variable sp e cific a tion.

<Se p a r a tor C h a r a cter> is the se p arator char a cter.

< S t art Pos i tion> is the index which de n otes the star t ing p osition.

<End Pos i tion> is the index which denotes the ending position.

Note: Specifying Start and End Positions is optional. If not specified, the function will return all the values of the specified Repeat variable separated by comma(,).

If Start and End Positions are specified, the function will return the values of repeat variable within the Specified index Range. Again, specifying End Position is optional. If the End Position is not specified, the function will return the entire set of values from the starting position.

Example:

$$VarRangeValue:SVFromDate

In this example, the function returns the entire set of values of the Repeat Variable SVFromDate.

$$VarRangeValue:SVFromDate:",":1:5

Here, the function returns the value of specified index range (1 to 5) of the Repeat Variable SVFromDate

$$VarRangeValue:SVFromDate:",":3

The entire set of values from Starting Index position of the repeat variable SVFromDate are returned.

Variables Usage and Behaviour in Auto Report

A report can be marked as an auto report via AUTO attribute, which indicates the system that the report cannot instantiate its own variables. It will inherit variables from parent scope. It is mainly used for configuration reports which require modifying configuration variables of parent report.

Syntax

[Report : < R eport Name>]

Auto : <Logical Value>

Where,

<Report Nam e > is the n a me of the re p ort.

<Log i cal V alu e > can be YES / NO. The d e fault value is NO.

Example:

[Report : Voucher Configuration]

Auto : Yes

Title : $$LocaleString:"Voucher Configuration"

This is a d efault co n figuration report mark e d as Auto rep o rt, t o modify variables of p arent report. A report can be launched in ‘Auto’ mode using Actio n s Modify V aria b le and Modify System

Actions MODIFY VARIABLE and MODIFY SYSTEM

Action - MODIFY V ARIABLE

It l a unches the given rep o rt in ‘auto’ mode. Since the launch e d report is in ‘auto’ mode, it cann o t have i t s own instance of v a riables a nd a n y modification would a f fect the parent context.

Syntax

MODIFY VAR I ABLE : <Report Name>

Where,

<Report Nam e > is the n a me of the re p ort which is to be launch e d in ‘Auto Mo de’.

Example:

[Button : F2 Change Period]

Key : F2

Action : Modify Variables : Change Period

Title : $$LocaleString:"Period"

The Action ‘Modify Variable’ launches the report ‘Change Period’ in ‘Auto’ Mode. The report is having two fields SVFromDate and SVToDate

[Field : SVFromDate]

Use : Short Date Field

Modifies : SVFromDate

Variable : SVFromDate

[Field : SVToDate]

Use : Short Date Field

Format : Short Date, End : #SVFromDate

Modifies : SVToDate

Variable : SVToDate

The variable value changes would affect the parent report context only (i.e., it will affect values of the variables SVFromDate and SVTodate, which are associated to the report, from which the report Change Period is launched in Auto Mode).

Action - MODIFY S Y STEM

The action MODIFY SYSTEM launches the given report in ‘auto’ mode. Even if the report is called under some other report context, this action makes the new report to get the system context and thereby modify the system scope variables.

Syntax

MODIFY SYS T EM : <Report Name>

Where,

< Report Name > is the name of the report which is to be launched in 'Auto Mode'.

Example:

[Button: Change System Period]

Key : Alt+F2

Action : Modify System : Change Menu Period

Title : $$LocaleString:“Period”

The Action ‘Modify System’ has launched the report ‘Change Menu Period’ in ‘Auto’ Mode. The report is having two fields SVFromDate and SVToDate.

[Field : SVFromDate]

Use : Short Date Field

Modifies : SVFromDate

Variable : SVFromDate

[Field : SVToDate]

Use : Short Date Field

Format : Short Date, End : #SVFromDate

Modifies : SVToDate

Variable : SVToDate

The value changes would affect the variables at system scope, as the report is launched using the Action ‘Modify System’.

Repeat Lin e with Option a l Collection

We are aware that the ‘Repeat’ Attribute of a Part is used to Repeat a line over a Collection.

Existing Syntax

Syntax

[Part : <Pa r t Name>]

Repeat : <Line Name> : <Co l lection>

Where,

< Part Name > is the name of the part.

< Line Name > is the name of the line to be repeated.

< Collection > is the name of the collection on which the line is repeated. This was mandatory prior to this release. In this case, the same line will be repeated for each object of the collection. Each line will be associated with an Object of the collection. Report created in Create/Alter/ Display mode will either store method values into the object or fetch method values from the Object. Any expression evaluation within this line will happen with an object in context.

With the introduction of List Variable (Simple/Compound), there will be a requirement to store values into the Variable by accepting user inputs and also to display or use it for expression evaluation. Since Variables are Context free structures there is no need to associate element variables with the line. For this purpose the ‘Repeat’ Attribute of the part has been enhanced to have the collection as Optional. Now, it is possible to Repeat a Line with or without a Collection. In cases where the collection is not specified, the number of lines to be repeated is unknown. Hence, specifying the SET attribute is mandatory. In case of Edit, SET can be optional if ‘Break On’ is specified.

New Enhanced Syntax

Syntax

[Part : <Part Name>]

Repeat : <Line Name> [: <Collection>]

Where,

<Part Name> is the name of the part.

<Line Name> is the name of the line to be repeated.

<Colle c tion> is the name of the collection o n which the line is repeat e d. It is n o w OPTIONAL.

Storing Values into List Variables

With this enhancement, values can be added to List Variable (Simple/Compound) dynamically by accepting user inputs by repeating a line without a Collection. Multiple lines can be added dynamically or a fixed number of lines can be added as per user requirement, while repeating the line.

Example

To accept the values from a user to the Simple List Variables SLVEMP, a report is opened in ‘Create’ Mode. Let us look into the ‘Part’ Definition:

[Part : SLV List Values]

Lines  : SLV List Title, SLV List Values

Repeat : SLV List Values

BreakOn: $$IsEmpty:#SLVAlias

Scroll : Vertical

Here, the line is repeated without a collection and it will break if the field value ‘SLV Alias’ is empty. Let us look into the Field Definitions:

[Line : SLV List Values]

Fields : SLV Alias, SLV Name

[Field : SLV Alias]

Use : Name Field

[Field : SLV Name]

Use : Name Field

Delete : Key

Add : Key : SLV List Key

Inactive: $$IsEmpty:#SLVAlias

[Key: SLV List Key]

Key : Enter

Action List : Field Accept, SLV List Add

[Key : SLV List Add]

Key : Enter

Action : LIST ADD : SLVEMP : #SLVAlias : #SLVName

Values are added to the List Variable “SLVEMP” using the Action “LIST ADD”. Similarly, user inputs can be added / altered dynamically to the Compound List Variable also.

Retrieving Values from List V ariables

In the previous example, we had stored values into a Simple List Variable “SLVEMP”. Let us suppose that the values need to be retrieved from a Simple List Variable SLVEMP and displayed in a report.

This report “SLV List Values with Key Display” is opened in ‘Display’ mode. Let us look into the code snippet of the Part definition:

[Part : SLVList ValuesDisplay]

Lines  : SLV List DisplayTitle, SLV List DisplayValues

Repeat : SLV List DisplayValues

Set    : $$ListCount:SLVEmp

Scroll : Vertical

CommonBorder : Yes

In Part level, the number of lines is fixed using the Attribute ‘SET’, based on the number of elements in the Simple List Variable “SLVEmp”.

[Line : SLV List DisplayValues]

Fields : SLV Alias, SLV Name

[Field : SLV Alias]

Use    : Name Field

Set as : $$ListKey:SLVEMP:$$Line

[Field : SLV Name]

Use    : Name Field

Set as : $$ListValue:SLVEMP:#SLVAlias

Key and Value from the Simple List Variable “SLVEMP” are retrieved using the functions $$ListKey and $$ListValue at the field level. Similarl y , the values can be retrieved from a Compound List Variable also.

Variables in Collection

The inline variables can be declared at the Collection using the Attributes Source Var, Compute Var and Filter Var. In case of Simple Collection, during the evaluation, only current objects are available. Whereas in case of Aggregate/Summary collection, during the evaluation, the following three sets of objects are available:

Source Objects : Objects of the collection specified in the ‘Source Collection’ attribute.

Current Objects : Objects of the last collection specified in the Walk path.

Aggregate Objects : Objects obtained after performing the grouping and aggregation.

There are scenarios where some calculation is to be evaluated based on the source object or the current object value and the filtration is done based on the value evaluated with respect to the final objects before populating the collection. In these cases, to evaluate the value based on the changing object context is tiresome, and sometimes impossible as well.

The collection level variables provide Object-Context Free processing. The values of these inline variables are evaluated before populating the collection.

The sequence of evaluation of collection attributes has been changed to support attributes ComputeVar, Source Var and Filter Var. The variables defined using the attributes Source Var and ComputeVar can be referred to in the collection attributes By, Aggr Compute and Compute. The variable defined by ‘Filter Var’ can be referred to in the collection attribute ‘Filter’. The value of these variables can be accessed from anywhere, while evaluating the current collection objects.

Attributes SOURCE VAR, COMPUTE VAR and FILTER VAR

Attribute - Source Var

The attribute ‘Source Var’ evaluates the value of the variable based on the source object.

Syntax

Source Var : <Variable Name> : <Data Type> : <Formula>

Where,

< Variable Name > is the name of the variable.

< Data Type > is the data type of the variable.

< Formula > can be any expression, which evaluates to a value of ‘Variable’ data type.

Example

Source Var : Log Var: Logical : No

The value of the variable ‘LogVar’ is set to NO.

Attribute - Compute Var

The attribute ‘Compute Var’ evaluates the value of the variable based on the current objects.

Syntax

Compute Var : <Variable Name> : <Data Type> : <Formula>

Where,

< Variable Name > is the name of the variable.

< Data Type > is the data type of the variable.

< Formula > can be any expression which evaluates to a value of ‘Variable’ data type.

Example

Compute Var : IName : String : if ##LogVar then $StockItemName else ##LogVar

Attribute - Filter Var

The attribute ‘Filter Var’ evaluates the value of the variable based on the objects available in the collection after the evaluation of the attributes ‘Fetch’ and ‘Compute’.

Syntax

Filter Var : <Variable Name> : <Data Type> : <Formula>

Where,

< Variable Name > is the name of the variable.

< Data Type > is the data type of the variable.

< Formula > can be any expression which evaluates to a value of ‘Variable’ data type.

Example

Filter Var : Fin Obj Var : Logical : $$Number:$BilledQty > 100

Using V aria b l e as a Data Source for Collections

Collection attribute ‘Data Source’ has been enhanced to support ‘Variable’ as a data source. Now, variable element(s) can be gathered as objects in collection and their respective simple member variables will be available as methods. Member List Variables will be treated as sub-collections.

Syntax

Data Source : <Type> : <Identity> [:<Encoding>]

Where,

< Type > is the type of data source, i.e., File XML, HTTP XML, Report, Parent Report, Variable.

< Identity > can be file path/ scope keywords/ variable specification, based on type of data source.

< Encoding > can be ASCII or UNICODE. It is applicable for data types File XML and HTTP XML.

Example:

Simple List Variable as Data Source

[Collection : LV List Collection]

Data Source : Variable : SLVEmp

The elements of the Simple List Variable ‘SLVEmp’ will be available as objects in the collection ‘LV List Collection’. Let us suppose that a Line is repeated over the collection ‘LV List Collection’. The value can be retrieved in the field level as shown below:

[Field : SLVEmp Field]

Use : Name Field

Set as : $SLVEmp

Compound List Variable as Data Source

[Collection : CV List Collection]

Data Source : Variable : CLVEmp

The elements of the Compound List Variable CLVEmp will be available as objects in the collection CV List Collection. It is used as a Source Collection in the following Summary Collection:

[Collection : CV List SummaryCollection1]

Source Collection : CV List Collection

Walk : Relatives

By : Relation : $Relation

Aggr Compute : MaxAge : Max : $Age

Aggr Compute : MinAge : Min : $Age

Aggr Compute : TotSal : Sum : $Salary

Here, we are walking to the sub-collection ‘Relatives’ and performing grouping and aggregation.

Variables in Remoting

In a Tally.NET Environment, where Tally at the remote end sends request to the Tally Company at the Server, all client requests must contain the dependencies, based on which data is gathered. In other words, any request sent to the server must accompany the values configured at the client to extract data from the server. For example, a Collection of Ledgers falling under a user selected group must accompany the request sent to the server. Hence, the request to the server must contain the Variable value which signifies the Group name.

Only the configuration information which is relevant to the data to be fetched from the Server needs to be sent to the Server, and not the ones which are User Interface related, like Show Vertical Balance Sheet, Show Percentages, etc.

When a Collection is sent to the Server, all the dependencies, i.e., variable values, are enclosed within the requests automatically.

Example: 1

[Collection : User Ledger Coll]

Type : Ledger

Child of : ##UserSelectedGroup

While sending this collection to the server, the value for the variable UserSelectedGroup is also passed to the server automatically and the server responds accordingly.

Example: 2

[Collection : Emp Coll]

Type : Cost Centre

Filter : EmpSpouseName

[System : Formula]

EmpSpouseName : $SpouseName = ##CLVEMP[1].Relatives[1].Name

Value of CLVEMP[1].Relatives[1].Name will be enclosed within the request to the server.

In some cases, variable values will not be remoted automatically like Child Of : $FuncName, which in turn returns the variable value through the Function. Such variables need to be remoted using an adhoc ‘Compute’ within the collection. This ‘Compute’ is required to set a manual dependency on the variable and hence, consider it while sending request to Server. Consider the following example:

[Collection : User Ledger Coll]

Type : Ledger

Child of : $$UserFunc

[Function : UserFunc]

00 : RETURN : ##FuncVar

In this example, the function UserFunc returns the value through the variable ‘FuncVar’. Hence, the variable ‘FuncVar’ needs to be remoted using an adhoc ‘Compute’ as follows:

[Collection : User Ledger Coll]

Type : Ledger

Child of : $$UserFunc

Compute : FuncVar : ##FuncVar

Use Case – Report Configuration

Scen a rio

ABC Company Limited, which is into trading business, is using Tally.ERP 9. It deals with purchase and sale of computers, printers, etc. The company management likes to view the Stock Summary Report in various dimensions. Hence, every time, they need to set configurations for the report and view it. They want to have multiple configurations for the same report and set it at one time.

Requirement Statement

By default, in Tally, the user has to set the configurations in Stock Summary Report as per the requirement every time. The requirement can be customized using the Compound List Variable.

Functional Demo

The solution has been developed using Compound Variables and User Defined Functions. Before looking into the design logic, we will have a functional demo.

A new stock summary report is created for demonstration purpose and the same is available as a part of “TDL Language Enhancements” sample TDLs. The TDL is enabled in Tally.ERP 9.

Saving Multiple Configurations

Gateway of Tally > TDL Language Enhancements > What's New > Release 1.8 > Variable Framework > Stock Summary > F12. Set the required configuration.

Figure_4._Setting_required_Configurations_(1.8).jpg

The above configuration has to be saved using the button Alt+S (Save Config). Enter the Configuration Name and accept it as shown in the following figure:

Figure_5._Saving_the_Configuration_with_a_suitable_name_(1.8).jpg

Similarly, we can save another configuration for the same report, as shown in the following figure:

Figure_6._Saving_another_Configuration_(1.8).jpg

Retrieving Configuration to view the Report in Different Dimensions

Gateway of Tally –> TDL Language Enhancements –> What's New –> Release 1.8 –> Variable Framework –> Stock Summary –> F12 –> Alt+R (Retrieve Config) .

Select the Required Configuration and press Enter.

Figure_7._Retrieving_and_Selecting_the_Required_Configuration_(1.8).jpg

The configuration will be set automatically as shown in the following figure:

Figure_8._Applying_the_selected_Configuration_(1.8).jpg

Accept the screen to view the Report:

Figure_9._Report_configured_as_per_the_selection_(1.8).jpg

To view the same Report with another configuration, Press F12 –> Alt+R, select the required configuration, and press Enter.

Figure_10._Retrieving_and_Selecting_another_Configuration_(1.8).jpg

The configuration will be set automatically as shown in the following figure:

Figure_11._Applying_the_selected_Configurations_(1.8).jpg

Accept the Screen to view the Report.

Figure_12._Report_configured_as_per_the_selection_(1.8).jpg

Deleting the Configuration

Gateway of Tally –> TDL Language Enhancements –> What's New –> Release 1.8–> Variable Framework –> Stock Summary –> F12 –> Alt+D (Delete Config).

Figure_13._Selecting_the_configuration_name_for_deletion_(1.8).jpg

Select the Configuration to be deleted and press Enter.

Figure_14._Confirmation_before_deleting_the_selected_configuration_(1.8).jpg

Accept it to delete the configuration. Press Alt+R . The report is not displaying the configuration “Detailed Stock Summary” (as shown in the next figure).

Figure_15._Report_of_Configuration_List_post_deletion_(1.8).jpg

Solution Development

The solution (Setting different configurations for the same report, saving and retrieving them as and when required) was possible by using Compound List Variable.

The steps followed to achieve the requirement are:

1. Defining Compound Variables with the required members having Persistence behaviour

Figure_16._Defining_Compound_Variables_(1.8).jpg

2. Declaring Compound List in System Scope

Figure_17._Declaring_Compound_List_Variable_in_System_Scope_(1.8).jpg

3. Adding Relevant Buttons

Figure_18._Adding_relevant_buttons_(1.8).jpg

4. When the user chooses to save a configuration,

Add an element with current Report Name as Key

Figure_19._Adding_an_element_to_the_list_variable_(1.8).jpg

Add an element within the above element with Config Name (specified by user) as Ke y .

Figure_20._Adding_a_sub-element_(1.8).jpg

Set the variable values in the current Configu r ation Screen to the respective Mem b ers within the above sub element.

Figure_21._Setting_the_member_variable_values.jpg

5. When the user chooses to retrieve a configuration,

Display a Report showing the list of available Configurations in a Table.

Figure_22._Report_to_display_list_of_configurations_(1.8).jpg

6. On selecting the desired configuration, retrieve the saved values from the compound varia- ble and set the values to the respective configuration variables.

Figure_23._Applying_selected_configuration_values_to_the_Report_variables_(1.8).jpg

7. When the user chooses to delete a confi g uration,

Display a Rep o rt s h owing t h e list of available Configurations in a Table.

On s e lecting the desired co n figuration, delete saved values from the compound variable.

Figure_24._Deleting_the_selected_configuration_from_the_List_Variable_(1.8).jpg

TDL Cap a bilities U s ed

User Defined Functions

Compound List V ariable

Note: Code Snippets have been extracted from the working solution provided with the Samples.

Licensing Binding Mechanism

Nowadays, it is a common practice to have multiple applications for various business operations at different branches/ locations and then integrate their data and/or reports, as and when required. Tally being the most common and popular product across all industries, many Third Party Applications look forward to integrate their applications with Tally.

To ensure a secure environment, Third Party Applications need to build a robust licensing mechanism in order to validate the users of their application, which may be time consuming and costly. Alternatively, they can opt to use the robust licensing mechanism already built in Tally and stitch it together with the Tally Application.

License Information like Tally Serial Number, Account Email ID, etc., can be retrieved from Tally and validated with the current instance of an external application. In order to use the Tally licensing mechanism, Third Party Applications need to send various XML Requests to Tally running at a predefined IP Address and a Port. On receiving the XML Request in Tally understandable format, Tally responds with the required information, data or Report requested.

Note : For any further information on XML Formats, please refer to the documents and samples available at www.tallysolutions.com in the path Developer Network -> Tally Technology -> Integration Capabilities.

The various approaches for retrieving License Information from Tally that can be followed by Third Party Applications have been broadly classified based on the desired level of security, ranging from simple to the most complex one.

The Approaches that can be used by Third Party Applications to retrieve License Information from Tally, based on the level of Security desired, are as follows:

License Info Retrieval using Open XML

This approach is one of the simplest approaches with minimal security wherein the Third Party Applications will be able to send an XML Request to invoke platform functions in Tally to retrieve the required License Information. This is a less secured environment, as the license data returned will be available as an Open XML

In Tally, a platform function $$ LicenseInfo is available which accepts a parameter to determine the type of License details required and returns the value accordingly. For example, $$LicenseInfo:SerialNumber returns the Serial Number of the running copy of Tally.

Following is the list of parameters allowed for the Function $$ LicenseInfo :

Parameters permissible for LicenseInfo

Return Type

Description

SerialNumber

Number

Serial Number

AccountID

String

Account ID

SiteID

String

Site ID

AdminEmailID

String

Admin Email ID

IsAdmin

Logical

Whether the System logged in user is Administrator or not

IsIndian

Logical

Whether the country is India or not

IsSilver

Logical

Whether the Product flavour is Silver or not

IsGold

Logical

Whether the Product flavour is Gold or not

IsEducationalMode

Logical

Whether the Product is running in Educational mode

IsLicensedMode

Logical

Whether Product is running in Licensed mode

LicServerDate

Date

License Server Date

LicServerTime

String

License Server Time

LicServerDateTime

String

License Server Date & Time

The following XML Request is required to fetch Tally Serial Number:

<!-- XML Request -->

<ENVELOPE>

<HEADER>

<VERSION>1</VERSION>

<TALLYREQUEST>EXPORT</TALLYREQUEST>

<TYPE>FUNCTION</TYPE>

<!-- Platform Function Name in Tally.ERP 9 -->

<ID>$$LicenseInfo</ID>

</HEADER>

<BODY>

<DESC>

<FUNCPARAMLIST>

<!-- Parameter for the function $$LicenseInfo -->

<PARAM>Serial Number</PARAM>

</FUNCPARAMLIST>

</DESC>

</BODY>

</ENVELOPE>

The previous XML Request fetches the following XML Response:

<!-- XML Response -->

<ENVELOPE>

<HEADER>

<VERSION>1</VERSION>

<STATUS>1</STATUS>

</HEADER>

<BODY>

<DESC>

</DESC>

<DATA>

<RESULT TYPE="Long">790003089</RESULT>

</DATA>

</BODY>

</ENVELOPE>

In this response received from Tally, Serial Number is retrieved within the RESULT Tag.

Similarly, to fetch the Account ID of the current Tally Application, replace the Parameter Serial Number with Account ID within Param Tag in the XML Request.

License Info Retrieval using Encoding Procedure built in a TCP

This approach is a slightly better approach than the previous one, since the Response received here is encoded using some encoding mechanism built within TDL.

The Third Party Application will send a Validation String within the XML Request. At Tally's End, the validation string and the required License Info will be encoded using the encoding mechanism built within TDL. The converted Strings will then be sent back within the XML Response to the Third Party Applications, which will decode the strings at their end.

Following needs to be made available for this approach to be executed:

At Tally End

A TDL needs to be written containing the encryption mechanism to encrypt a string.

Following is an example of String encryption in Tally using TDL Function:

;; TDL Function to Encrypt an input String, by reversing it

[Function : StrEnc]

Parameter : pStringtoReverse : String

Variable : ReverseString : String

00 : FOR RANGE : IteratorVar : Number : ($$StringLength:##pStringtoReverse - 1) : 0: 1

10 : SET : ReverseString : ##ReverseString + $$StringPart:##pStringToReverse : ##IteratorVar:1

20 : END FOR

30 : RETURN : ##ReverseString

This was a sim p le exam p le o f S tring e ncryption in Tall y . Similarl y , much robust encryption mech a nisms c a n be built in TDL and used in Third Party A pplications.

Report havi n g a string variable, a nd t riggering the encrypt function with s tring v a riable a s a p aramete r , returning the e n crypted value within the requir e d X M L T ags.

;; TDL Report to invoke the above Function

[Report : Sec XML Request2]

Form : Sec XML Request

;; Variable for received String

Variable : EncString: String

[Form : Sec XML Request]

Parts : Sec XML Request

[Part : Sec XML Request]

Lines : Sec XML Req SerialNo, Sec XML Req EncString

Scroll : Vertical

XMLTAG : "TALLYLICENSEINFO"

;; Serial Number of Tally

[Line : Sec XML Req SerialNo]

Fields : Name Field

Local : Field : Name Field : Set As : $$StrEnc:@@LicSlNo

Local : Field : Name Field : XMLTAG : "SerialNumber"

;; To Encrypt the received String

[Line : Sec XML Req EncString]

Fields : Name Field

Local : Field : Name Field : Set As : $$StrEnc:##EncString

Local : Field : Name Field : XMLTAG : "EncryptedString"

On receiving the XML Request, the report is executed and both the Serial Number and the String received within the XML Request are encrypted and sent back to Third Party Applications.

At Third Party Application End

An XML Request to trigger the Tally Report with request String to be encrypted. Following XML Request triggers the previous Report associated with Tally:

<!-- XML Request -->

<ENVELOPE>

<HEADER>

<VERSION>1</VERSION>

<TALLYREQUEST>Export</TALLYREQUEST>

<TYPE>Data</TYPE>

<ID>Sec XML Request2</ID>

</HEADER>

<BODY>

<DESC>

<STATICVARIABLES>

<SVEXPORTFORMAT>$$SysName:XML</SVEXPORTFORMAT>

<EncString>Keshav</EncString>

</STATICVARIABLES>

</DESC>

</BODY>

</ENVELOPE>

Sec XML Request2 is the TDL Report which is requested and variables SVExportFormat (format in which response is required) and EncString (Variable Name specified in TDL Report for string to be encrypted) are enclosed within the XML Request.

The following response is received from Tally on sending the above request

<!-- XML Response -->

<ENVELOPE>

<TALLYLICENSEINFO>

<SERIALNUMBER>980300097</SERIALNUMBER>

<ENCRYPTEDSTRING>vahsek</ENCRYPTEDSTRING>

</TALLYLICENSEINFO>

In this response, Serial No. and String sent as request are returned encrypted, i.e., reversed from Tally. On receiving the response, the Third Party Application needs to decrypt the Serial Number as well as String and validate the current instance. It is a much secure environment as the response is in encrypted form.

License Info Retrieval using Encryption Functions provided within Tally

This Approach is similar to the previous approach except that it uses an in-built Platform Function to encrypt the string. In Tally, the validation string and the required License Info can be encrypted using the function $$EncryptStr provided within the platform. The encrypted Strings will be sent back within the XML response to the Third Party Application. The Third Party Application will decrypt the Strings at their end using the standard DLL shipped by Tally for decryption.

XML Request is similar to the Request in the previous approach, except that:

An additional variable value Password must be specified with the XMLTag Password (Variable Name used in TDL Report for Password), and

The requested Report triggers the platform function $$EncryptStr for encryption mechanism.

A supporting DLL File EncryptDecrypt.DLL is provided along with Sample Files to decrypt the Encrypted String in Tally, using the Function $$DecryptStr available in DLL. This Function accepts 4 parameters viz.,

Input String to be decrypted

Password specified while encoding an XML request

Output String Variable to hold the decrypted return Value

Output String Buffer Length

Note : The above DLL can be copied either to the local path of the Third Party Application or to the Windows System Directory.

On decrypting the above string, the Third Party Application can validate the returned String and Serial Number, and continue if the validation is successful.

License Info Retrieval using Encryption Algorithms built using Third Party DLLs

This Approach is the most secured approach, wherein an external DLL is written to encrypt the given string. The Third Party Application will send a Validation String within the XML Request. At Tally's End, the validation string and the required License Info will be encrypted using an External DLL, which can have its own Encryption Routines.

Tally uses the function $$CallDllFunction to trigger the DLL written for encryption and returns the encrypted strings to the Third party Application within the XML Response. At Third Party Application End, decryption algorithms will be required, which can again be provided inside the same DLL used for encryption.

Function - $$CallDLLFunction

The Platform Function CallDLLFunction is used to trigger the function enclosed within an external DLL (written in C++/VC++)

Syntax

$$CallDLLFunction : <DLL Name> : <Function Name> : <Param 1> : <Param 2> :…<Param N>

Where,

< DLL Name > is any DLL written in C++/VC++,

< Function Name > is a Function available in the DLL,

< Param 1 to N > are arguments, which depend upon the number of parameters needed by the Function designed.

Note: DLL must exist in the Tally Application folder or Windows System Folder.

XML Request for this approach is similar to the Request in the previous approach, except that

The requested Report triggers the function written within DLL for encryption mechanism using CallDLLFunction.

Subsequently, the Third Party Application can decrypt the encrypted String and the Serial Number using the decrypt function within the same DLL or any other DLL.