Document Macro

IFS/Document Management can automatically start computer files by using specifically written macros. A macro is often associated with commands such as Print, Edit, View, Check In, Check Out, etc. Normally, the editing or viewing application is started, the macros are executed, and then normal work with the document can be performed. Macros are often used for inserting document headers, frames, updating the document with information from the database, and more.

Different macros can be used for editing documents in different applications or for doing different work (processes), such as printing the document to a printer.

To disable the macros defined, configure a document class process action with NoMacro in the Macro Option field for a process of a particular document class.

Important Terms

Available Macro Languages

VBScript and JavaScript are the programming languages available for writing macros. VBScript is the recommended language (all examples are written in it), but feel free to experiment with JavaScript as well.

The Macro Process

1 - Create new macro blocks

A macro block is the place where the macro code itself is stored. Usually you create a couple of Subs or Functions in each block, trying to make them as general as possible so that they can be used in more than one macro.

A new macro block is defined in Macro Basic / Document Macro Blocks tab by giving a user preferred name for the block name and code in the script language.

2 - Create macro header

The macro header is where you specify on which file type/application the macro should be used, and for which process (VIEW, CHECKIN, CHECKOUT etc). A new macro header is defined in Macro Basic / Document Macros tab. A macro header does not do anything by itself, you need to connect macro blocks to it.

Field Explanation
Time Out The maximum number of seconds you would like a macro to be executed. If the actual execution time of the macro is longer than the value specified, you will receive a question asking if you want to continue with the execution or not. 
Action Must always be filled in but the reason it exists only becomes evident if you want to create more than one macro for a specific combination of File Type/Application and Process.
Script Language Is used to specify which macro language you want to use. We recommend using VBScript because that is what we have tested out and know works. Using Javascript may or may not work.
Main Function The Main Function field is VERY important. It tells the macro execution engine exactly which sub-procedure or function to call when starting up the macro. 

3 - Connect the macro blocks to the header

This is where we attach the code onto the macro header to actually specify what should happen. The macro blocks are connected to the header in Macro Basic / Document Macros tab.

For an already created/existing macro header, connect the macro blocks by creating new rows in the table. Use the List of Values to pick the macro blocks or enter the names manually.

4 - Configure how macros are going to be handled for each document class

This is done in the Document Class Process Action. Possible settings are:

These settings are optional and if you do not specify any document class process actions, macros will always run, if available.

5 - Register macros for a certain document class

Use the Macro tab in the Document Class Management  to register the macros that will be applied to a process within a document class. If no macros are defined per class, all macros will be available.

 

Example of a Macro

This is an example of a macro that causes a message box to open when the connected process is performed.

Macro block MESSAGEBOXTEST:

        Public Sub MessageBoxTest()
          MsgBox "This is a very simple macro."
        End Sub
      

Available Attributes to Use in Macros

The macro creator has a long list of attributes that can be used when writing macros using the macro support functionality. Here is a complete list of the attributes and a description:

ClientScript Values

The ClientScript values are for values that does not come from the database.

LOCAL_FILE_X - X will be a number starting from 1 and ending with the number specified by LOCAL_FILE_COUNT, another macro attribute. For example, if LOCAL_FILE_COUNT = 2 then there will be LOCAL_FILE_1 and LOCAL_FILE_2. LOCAL_FILE_X instances will contain the client side file names of the files to be checked in.
LOCAL_FILE_COUNT - Number of files to be checked in e.g, Original, View, Raster, Hybrid.
CHECK_OUT_PATH - User defined check out path entered in the User Settings dialog box. Temp\ will be appended for processes VIEW and PRINT.
CHECK_IN_PATH - Directory path from which the files are being checked in.
EXTERNAL_VIEWER - User defined external viewer path defined in the User Settings dialog box.
REDLINE_VIEWER - User defined redline viewer application path defined in the User Settings dialog box.
COPY_TO_PATH - Directory path to which the files are copied. This value can be used in copy document file process only.
COPY_TO_FILE_COUNT - Number of files copied. This value can be used in copy document file process only.
COPY_TO_FILE_NAME_N - N will be a number starting from 1 and ending with the number specified by COPY_TO_FILE_COUNT. COPY_TO_FILE_NAME_N instances contain names of the files copied. This value can be used in copy document file process only.

Example usage:

        ClientScriptValues.Item("LOCAL_FILE_COUNT")
      

The above expression would return the local file count.

The Following Macro block can be used to retrieve macro attributes relevant to copy document file process.

	
'<<<<<<<<Block Name: VIEW_COPY_FILE_INFO >>>>>>>>
Public Sub MacroInfo()
          
    sCopyPath = "Copy Path   -    " & ClientScriptValues.Item("COPY_TO_PATH").Value
    nCopyFileCount = ClientScriptValues.Item("COPY_TO_FILE_COUNT").Value
    sCopyFileCount = "File Count   -  " & nCopyFileCount
          
    For Index = 1 To nCopyFileCount
        sItem = "COPY_TO_FILE_NAME_" & Index
        sItemVal = ClientScriptValues.Item(sItem).Value
        sFileList = sFileList & sItemVal & vbCrLf
    Next
          
    sMsgTitle = "Copy File - Macro Information"
    sMsg = sCopyPath & vbCrLf & sCopyFileCount & vbCrLf & vbCrLf & "File List - " & vbCrLf & sFileList

    MsgBox sMsg, 0, sMsgTitle

End Sub

 

Script Values

The Script values comes from the database.

DOCUMENT_CLASS
DOCUMENT_CLASS_DESCRIPTION
DOCUMENT_NUMBER
DOCUMENT_SHEET
DOCUMENT_REVISION
APPROVAL_TEMPLATE_ID
REVISION_NUMBER
REVISION_TEXT
REVISION_DATE
LANGUAGE_CODE
DOCUMENT_REVISION_NOTE
RESPONSIBLE_DEPARTMENT
RESPONSIBLE_PERSON
NUMBER_OF_SHEETS
DATE_RELEASED
DATE_OBSOLETE
ACCESS_CONTROL
ACCESS_CONTROL_DB
PLANNED_START
PLANNED_FINISH
ACTUAL_FINISH
FORMAT_SIZE
FORMAT_SIZE_DESCRIPTION
DATE_MODIFIED
MODIFIED_BY
DATE_CREATED
CREATED_BY
DAYS_TILL_DOCUMENT_EXPIRES
REASON_FOR_ISSUE
REASON_FOR_ISSUE_DESC
UPDATE_ALLOWED_DURING_APPROVAL
OBJSTATE
DOCUMENT_STATUS
DOCUMENT_PROGRESS
MAX_REVISION_NUMBER
MAX_APPROVED_REVISION_NUMBER
DOCUMENT_TITLE
DOCUMENT_TITLE_INFO
DESCRIPTION1
DESCRIPTION2
DESCRIPTION3
DESCRIPTION4
DESCRIPTION5
DESCRIPTION6
NEXT_DOC_SHEET
SHEET_ORDER
SCALE
VIEW_FILE_REQUIRED
VIEW_FILE_REQUIRED_DB
OBJECT_CONNECTION_REQUIRED
OBJECT_CONNECTION_REQUIRED_DB
DESTROY_DOCUMENT
DESTROY_DOCUMENT_DB
SAFETY_COPY_REQUIRED
SAFETY_COPY_REQUIRED_DB
DOCUMENT_TITLE_DATE_CREATED
DOCUMENT_TITLE_CREATED_BY
ISO_CLASSIFICATION
CONFIDENTIAL
BASED_ON_DOCUMENT_CLASS
BASED_ON_DOCUMENT_NUMBER
BASED_ON_DOCUMENT_REVISION
REPLACED_BY_DOCUMENT_CLASS
REPLACED_BY_DOCUMENT_NUMBER
ALTERNATE_DOCUMENT_NUMBER
DOC_TYPE
FILE_NAME
LOCAL_PATH
LOCAL_FILE_NAME
COPY_OF_FILE_NAME
COPY_OF_VIEW_FILE_NAME
CHECKED_IN_SIGN
CHECKED_IN_DATE
CHECKED_OUT_SIGN
CHECKED_OUT_DATE
LOCATION_NAME
FILE_TYPE
PATH
EDM_STATUS
DOC_CLASS
DOC_NAME
DOC_NO
DOC_SHEET
DOC_REV
FILE_STATE
REV_NO
STATE
TITLE
USER_CREATED
DT_CRE
LOCATION_USER
LOCATION_PASSWORD
LOCATION_ADDRESS
LOCATION_PORT
LOCATION_TYPE
NUMBER_OF_FILES
LOCAL_FILE_NAME_01
LOCAL_FILE_NAME_02
LOCAL_FILE_NAME_03
...
COPY_OF_FILE_NAME_01
COPY_OF_FILE_NAME_02
COPY_OF_FILE_NAME_03
...
RIGHTS
IFS_CAD_DB_ALIAS
FND_USER
FIRSTREV_DRAWN_BY
FIRSTREV_ISSUED
FIRSTREV_CHECKED_BY
FIRSTREV_CHECKED
FIRSTREV_APPROVED_BY
FIRSTREV_APPROVED
FOLDER_IDENTIFIER
DESCRIPTION
FOLDER_NAME
RESPONSIBLE_PERSON
REV_00
REV_00_DATE
REV_00_REASON
REV_00_REASON_DESC
REV_00_REV_TEXT
REV_00_DRAWN_BY
REV_00_APP_SIGN_01
REV_00_APP_DATE_01
REV_00_APP_SIGN_02
REV_00_APP_DATE_02
OLD_REV_01
OLD_REV_01_DATE
OLD_REV_01_REASON
OLD_REV_01_REASON_DESC
OLD_REV_01_REV_TEXT
OLD_REV_01_DRAWN_BY
OLD_REV_01_APP_SIGN_01
OLD_REV_01_APP_DATE_01
OLD_REV_01_APP_SIGN_02
OLD_REV_01_APP_DATE_02
OLD_REV_02
OLD_REV_02_DATE
OLD_REV_02_REASON
OLD_REV_02_REASON_DESC
OLD_REV_02_REV_TEXT
OLD_REV_02_DRAWN_BY
OLD_REV_02_APP_SIGN_01
OLD_REV_02_APP_DATE_01
OLD_REV_02_APP_SIGN_02
OLD_REV_02_APP_DATE_02
OLD_REV_03
OLD_REV_03_DATE
OLD_REV_03_REASON
OLD_REV_03_REASON_DESC
OLD_REV_03_REV_TEXT
OLD_REV_03_DRAWN_BY
OLD_REV_03_APP_SIGN_01
OLD_REV_03_APP_DATE_01
OLD_REV_03_APP_SIGN_02
OLD_REV_03_APP_DATE_02
OLD_REV_04
OLD_REV_04_DATE
OLD_REV_04_REASON
OLD_REV_04_REASON_DESC
OLD_REV_04_REV_TEXT
OLD_REV_04_DRAWN_BY
OLD_REV_04_APP_SIGN_01
OLD_REV_04_APP_DATE_01
OLD_REV_04_APP_SIGN_02
OLD_REV_04_APP_DATE_02
OLD_REV_05
OLD_REV_05_DATE
OLD_REV_05_REASON
OLD_REV_05_REASON_DESC
OLD_REV_05_REV_TEXT
OLD_REV_05_DRAWN_BY
OLD_REV_05_APP_SIGN_01
OLD_REV_05_APP_DATE_01
OLD_REV_05_APP_SIGN_02
OLD_REV_05_APP_DATE_02
...
CORRESPONDENT
ATTENTION
LETTER_DATE
CLOSE_BY
DOC_ARCH_NO
DOC_ARCH_STATUS
REFERENCE
DOC_POST_TYPE


Most of the attributes should be self-explanatory. All the date attributes (XX_DTand XX_DATE) are in ISO-format (YYYY-MM-DD); if you want another format you have to change this in your macro or customize the function used to retrieve the information (see below).

The attributes above that may need some explanation are:

FIRSTREV_ISSUED
FIRSTREV_CHECKED_BY
FIRSTREV_CHECKED
FIRSTREV_APPROVED_BY
FIRSTREV_APPROVED

NUMBER_OF_FILES
LOCAL_FILE_NAME_XY
COPY_OF_FILE_NAME_XY
IFS_CAD_DB_ALIAS

If these attributes (or the values they contain) are not enough for your needs there are a couple of ways to fix this:

  1. Read section Handling Extra set of Macro Attributes below
  2. Get the attributes from a connected object (read on below).
  3. Customize the Get_Document_Data function in Doc_Issue_API
  4. Make a macro that uses the COM Access Provider and do the necessary database calls yourself.
  5. Retrieve the values from some other place such as files or windows registry, using available functions in VBScript.

Object Attributes for Macros

It is possible to include attributes of business objects connected to the document in the document macro code by defining the business objects in Basic Data. This is a very useful feature that allows you to make good use of the document's connected objects. You could for example create a change report document and have the attributes from the actual change report printed in the document via a macro. Custom field views and even custom/alternative database views, to get the attributes from, are also supported. The latter makes it easy to add extra attributes that are not normally part of an object.

When using this feature, you have to first define which attributes should be available for each kind of business object. The reason for this is that the amount of data that can be used in a macro is limited (a document could potentially be connected to hundreds or even thousands of documents). The maximum size of all macro attributes (the main ones and the ones for objects) is 32768. The available attributes are selected depending on the view that is used. If there is a custom field view for the object, it will be used. Optionally, an alternative view name can be set, to get the attributes from.

For information about how to enter this default data see Activity Define Object Attributes for Macros.

The following are example macro code blocks that can be used to loop through all connected objects and to access their values so that they can be used in a document.

'<<<<<<<< Main Block Name: EXCEL_OBJECT_ATTR_INIT >>>>>>>>
Public Sub Update_Excel()
    Open_Excel
    Write_Cell_Attr "1" , "B","A", "CONNECTED_OBJECT_TYPES"
    oXl.ActiveWorkbook.Save
    MsgBox "Added Object Connection Info..."
End Sub

'<<<<<<<< Block Name: EXCEL_OBJECT_ATTR_FILE_OPEN >>>>>>>>
Option Explicit 

Dim oXl 
Dim sFileName 
Dim sPath 
Dim sSheetExist 
Dim nSheetCount 
Dim nCount 

Public Sub Open_Excel() 
	On Error Resume Next 
	sPath = ScriptValues.Item("LOCAL_PATH").Value 
	sFileName = ScriptValues.Item("LOCAL_FILE_NAME").Value 
	Set oXl = CreateObject("excel.application") 
	If Err.Number <> 0 Then 
		MsgBox "Unable to create object from [excel.application]" 
	Else 
		oXl.Visible = True 
		If sFileName = "" Then 
			' Empty local filename means that this is a checked-in document 
			' Use the COPY_OF_FILE_NAME value instead 
			sFileName = ScriptValues.Item("COPY_OF_FILE_NAME").Value 
		End If 
		If sPath = "" Then 
			' Use the CHECK_OUT_PATH client script value instead 
			sPath = ClientScriptValues.Item("CHECK_OUT_PATH").Value 
		End If 
		oXl.Workbooks.Open(sPath & sFileName) 
		' Added object connection details into ObjectConnectionInfo worksheet 
		' If worksheet does not exist create a new worksheet called ObjectConnectionInfo 
		sSheetExist = "FALSE" 
		nSheetCount = oXl.ActiveWorkbook.WorkSheets.Count 
		For nCount = 1 To nSheetCount 
			If oXl.ActiveWorkbook.Worksheets(nCount).Name = "ObjectConnectionInfo" Then 
			sSheetExist = "TRUE" 
		End If 
	Next 
	If sSheetExist = "FALSE" Then 
		oXl.ActiveWorkbook.Worksheets.Add , oXl.ActiveWorkbook.Worksheets(oXl.ActiveWorkbook.WorkSheets.Count) 
		oXl.ActiveWorkbook.Worksheets(oXl.ActiveWorkbook.WorkSheets.Count).Name = "ObjectConnectionInfo" 
	End If 
	oXl.ActiveWorkbook.Worksheets("ObjectConnectionInfo").Activate 
End If 
End Sub
        
'<<<<<<<< Block Name:EXCEL_OBJECT_ATTR_UPDATE >>>>>>>>
Dim sLuNames
Dim sArrayLuName
Dim sTag
Dim nCounter
Dim sAttributes
Dim sArrayAttribute
Dim nRowNo
Dim sLu
Dim sAttribute
Dim nRecCount

Public Function attrValue(sVal)
    attrValue = ScriptValues.Item(UCase(sVal)).Value
End Function

Public Sub Write_Cell_Attr(row, colValue,colName, attr)
    On Error Resume Next
    nRowNo = row
    sLuNames = attrValue(attr)
    oXl.Cells(nRowNo, colName) = attr
    oXl.Cells(nRowNo, colValue) = sLuNames
    sArrayLuName = Split(sLuNames, ";", -1, 1)
    For Each sLu in sArrayLuName
        nCounter = 0
        nRowNo = nRowNo + 1
        sTag = sLu & ".COUNT"
        nCounter = attrValue(sTag)
        oXl.Cells(nRowNo, colName) = sTag
        oXl.Cells(nRowNo, colValue) = nCounter
        nRowNo = nRowNo + 1
        sTag = sLu & ".ATTRIBUTES"
        sAttributes = attrValue(sTag)
        oXl.Cells(nRowNo, colName) = sTag 
        oXl.Cells(nRowNo, colValue) = sAttributes 
        sArrayAttribute = Split(sAttributes, ",", -1, 1)
        IF nCounter > 0 Then
            For nRecCount=1 to nCounter
                For Each sAttribute in sArrayAttribute
                    sTag = sLu & "." & nRecCount & "." & sAttribute
                    nRowNo = nRowNo + 1
                    oXl.Cells(nRowNo, colName) = sTag
                    oXl.Cells(nRowNo, colValue) = attrValue(sTag) 
                Next 
            Next
        End If
    Next
    nRowNo = nRowNo + 1
    oXl.Cells(nRowNo, colName) = "DATA_LENGTH_EXCEEDED"
    oXl.Cells(nRowNo, colValue) = attrValue("DATA_LENGTH_EXCEEDED")
End Sub
        

No Support for Object Connection Transformation

Although there is support for using attributes from a connected object in a macro, there is no support for objects that are just related, via Object Connection Transformation. Macro attributes are only available for objects that are directly connected to the document (i.e. objects that are listed under the Objects tab of Document Revision). If there is a need to use attributes from objects that are not directly connected to a document, read the next section on how to add your own, custom, attributes to the macro.

Handling Extra set of Macro Attributes

Optionally, you can make an extra set of attributes available for your macros. It is done by implementing a method called Get_Extra_Attributes in a new package (not part of the IFS Cloud core product) called Doc_Issue_Attribute_Custom_API. When such a package is found, the system will try to run the mentioned method. The method takes the four document keys as parameters.

The method should return a VARCHAR2 containing all the user defined attributes and values appended to it. These attribute names should start with the prefix 'C_' in order to avoid collision with the names of the standard attribute names. See below for an example. Please note that the total length of the attribute string used by the macro system is 32K, including the standard ones, so if you add a lot of attributes, or some have large values, try to keep the attribute names short.

FUNCTION Get_Extra_Attributes (
   doc_class_ IN VARCHAR2,
   doc_no_    IN VARCHAR2,
   doc_sheet_ IN VARCHAR2,
   doc_rev_   IN VARCHAR2 ) RETURN VARCHAR2
IS
   attr_list_ 	 VARCHAR2(32000);
   rec_sep_          CONSTANT VARCHAR2(1) := Client_SYS.record_separator_;
   field_sep_        CONSTANT VARCHAR2(1) := Client_SYS.field_separator_;

BEGIN
   attr_list_ :=
      'C_DOC_NO'         ||  field_sep_ ||  doc_no_                        || rec_sep_  ||
      'C_REPORTED_BY'    ||  field_sep_ ||  FND_SESSION_API.Get_Fnd_User   || rec_sep_  ||  
      'C_REPORTED_DATE'  ||  field_sep_ ||  to_char(sysdate)               || rec_sep_;   
   RETURN attr_list_;	   
END;