Option Explicit ' $File: //depot/GenERD.tsc $ ' $DateTime: 2012/05/06 23:36:43 $ ' $Revision: #2 $ ' $Change: 2 $ ' $Author: pthompson $ ' provides: main ' This script will dump the primary and aux tables for a project, table or ' workflow. The script is run in the URL context like this: ' http://myserver/tmtrack/tmtrack.dll?ScriptPage&scriptName=GenErd ' or ' http://myserver/tmtrack/tmtrack.dll?ScriptPage&scriptID=xxx ' where "xxx" is the TS_ID of this script. ' See the AppScript manual section "URL Direct Access Context" for more info. ' Note that while the params "ScriptPage" and "scriptName" are NOT case- ' sensitive, the name of the script *IS* case sensitive. ' To use, add this script plus the "vb_constants.tsl" and "DB Schema Constants.tsl" ' teamscript library files to an SBM Process App or to the Global Process App. ' Make sure the "INCLUDE" lines below specify the name of the included scripts by ' script name. Note that the file names may be identical to the script names. ' Deploy the PA. ' To run the script, log into SBM then change the URL to include the ScriptPage and ScriptName ' params as per above. If you want to report on a specific project, table, or workflow ' include the params described below. If you don't include any other params you ' get all Primary tables, all aux tables, plus Companies and Contacts. ' You'll notice the following: ' 1 line that says "". Confirmation that "beyond this point there be data". ' 1 line of database & system configuration stuff (with it's header line), ' Database field header line followed by a bunch-o-lines of database field information. ' 1 line that says "". Confirms that the program ran ' all the way to the end. ' You probably want the field information in Excel. To do that, copy the database field ' header line and the lines after to an editor and save as a "CSV" file, then open it in Excel. ' Go through the Excel dialogs to specify how to parse the contents and there you have it. ' Parameters may be added to the URL to specify the project name, ' table name (or dB name), workflow name or Output format. ' Parameters *must* be properly URL-encoded (see http://en.wikipedia.org/wiki/Percent-encoding). ' Parameters are not case sensitive and values are automatically "wild-carded" ' so that a param "work" will match "Work Groups" and "non-working". The ' default without any params is to basically print all application-related ' fields ' The following params may be specified : ' proj project name or ID ' tbl table name or ID ' wfl workflow name or ID ' delim delimiter to use between fields. Default is SEMI-COLON (';') ' format text, html, css, xls ' Default is "text": delimited text using the delimiter specified by "delim" param. ' "html" uses HTML tables ' "css" uses CSS with "div" and "span" elements. WORK IN PROCESS - NOT FUNCTIONAL ' "xls" outputs content as "Content-Type: application/vnd.ms-excel". WORK IN PROCESS - NOT FUNCTIONAL ' examples ' All fields for the "Work Groups" project ' http://myserver/tmtrack/tmtrack.dll?ScriptPage&scriptName=GenErd&proj=work ' or ' http://myserver/tmtrack/tmtrack.dll?ScriptPage&scriptName=GenErd&proj=Work%32Groups ' All fields for SharePoint Project Servers table (TS_SHAREPOINTPROJECTSERVERS) ' http://myserver/tmtrack/tmtrack.dll?ScriptPage&scriptName=GenErd&tbl=sharepoint ' or ' http://myserver/tmtrack/tmtrack.dll?ScriptPage&scriptName=GenErd&tbl=SHAREPOINTPROJECTSERVERS ' If you know Excel, you can create a Web query in Excel and have it import the data directly. ' Data / From Web / New Web Query ' Address = http://myserver/tmtrack/tmtrack.dll?ScriptPage&scriptName=GenErd&format=html ' NOTE the added "&format=html" which helps Excel parse the data ' ----------------------------------------------------------------------------- ' ----------------------------------------------------------------------------- $INCLUDE(DB Schema Constants.tsl) $INCLUDE(vb_constants.tsl) ' NOTE: We don't use the "EmitWebPageX.tsl" library because we need to send ' output to a string buffer ... not the output stream. ' ----------------------------------------------------------------------------- CONST URL_CONTEXT = "URL" CONST SOLUTION_PARAM = "sol" CONST PROJECT_PARAM = "proj" CONST TABLE_PARAM = "tbl" CONST WORKFLOW_PARAM = "wfl" CONST DELIM_PARAM = "delim" CONST FORMAT_PARAM = "format" CONST FORMAT_TEXT_PARAM = "text" CONST FORMAT_TEXT_MODE = 1 CONST FORMAT_HTML_PARAM = "html" CONST FORMAT_HTML_MODE = 2 CONST FORMAT_CSS_PARAM = "css" CONST FORMAT_CSS_MODE = 3 CONST FORMAT_XLS_PARAM = "xls" CONST FORMAT_XLS_MODE = 4 ' ----------------------------------------------------------------------------- ' Global Output buffer. All output text is appended to this string then ' sent to Stream using appropriate call Dim gstrOutputBuffer ' ----------------------------------------------------------------------------- ' Call LogIt("context=" & Shell.Context & "vbCrLf ->" & vbCrLf & " <- vbCrLf vbHtmlNewLine ->" & vbHtmlNewLine & "<- vbHtmlNewLine") If LCase(Shell.Context) = LCase(URL_CONTEXT) Then Call EmitWebPageHead() Dim strSolution , strProject , strTable , strWorkflow , strDelim , strFormatMode, nFormatMode , strEmptyString strSolution = Shell.Params.Item(SOLUTION_PARAM) strProject = Shell.Params.Item(PROJECT_PARAM) strTable = Shell.Params.Item(TABLE_PARAM) strWorkflow = Shell.Params.Item(WORKFLOW_PARAM) strDelim = Shell.Params.Item(DELIM_PARAM) strFormatMode = Shell.Params.Item(FORMAT_PARAM) ' Select output formatting mode. Default is TEXT If LCase(strFormatMode) = FORMAT_HTML_PARAM Then nFormatMode = FORMAT_HTML_MODE strEmptyString = " " ElseIf LCase(strFormatMode) = FORMAT_CSS_PARAM Then nFormatMode = FORMAT_CSS_MODE strEmptyString = " " ElseIf LCase(strFormatMode) = FORMAT_XLS_PARAM Then ' I have yet to figure out the formatting for output directly to XLS. nFormatMode = FORMAT_XLS_MODE strEmptyString = "" Else nFormatMode = FORMAT_TEXT_MODE strEmptyString = "" End If If Len(strDelim) < 1 Then strDelim = ";" ' Call LogIt("strSolution='" & strSolution & "' strProject='" & strProject & "' strTable='" & strTable & "' strWorkflow='" & strWorkflow & "' strDelim='" & strDelim & "' nFormatMode=" & nFormatMode & " strFormatMode='" & strFormatMode & "'" ) Dim arlFields , arecField , strWhere Set arlFields = Ext.CreateAppRecordList(Ext.TableID("TS_FIELDS","database")) ' Call LogIt("arlFields is a " & typename(arlFields)) ' projects -> workflows -> tables -> solutions ' Project has TS_WORKFLOWID ' Workflow has TS_TABLEID ' Table has TS_SOLUTIONID ' Field has TS_TABLEID ' The WHERE is querying TS_FIELDS If Len(strProject) > 0 Then If Len(strWhere) > 0 Then strWhere = strWhere & " OR " strWhere = "(ts_TableId In (Select wfl.ts_TableId from ts_Workflows wfl, ts_Projects prj Where prj.ts_WorkflowID=wfl.ts_id AND prj.ts_Name like '%" & strProject & "%'))" End if If Len(strWorkflow) > 0 Then If Len(strWhere) > 0 Then strWhere = strWhere & " OR " strWhere = "(ts_TableId In (Select wfl.ts_TableId from ts_Workflows wfl Where wfl.ts_Name like '%" & strWorkflow & "%'))" End if If Len(strTable) > 0 Then If Len(strWhere) > 0 Then strWhere = strWhere & " OR " strWhere = "(ts_TableId In (Select tbl.ts_id from ts_Tables tbl where tbl.ts_name like '%" & strTable & "%' OR tbl.ts_DbName like '%" & strTable & "%'))" Else ' If no options specified, default to all custom tables plus companies and contacts table If Len(strWhere) > 0 Then strWhere = strWhere & " OR " strWhere = "(ts_TableId = 37 OR ts_TableId = 38 Or ts_TableId >= 1000)" End if ' Add an Order by Clause strWhere = strWhere & " ORDER BY TS_TABLEID, TS_NAME" ' Call LogIt("strWhere='" & strWhere & "'") If arlFields.ReadWithWhere(strWhere) Then ' Call LogIt("ReadWithWhere returned " & arlFields.Count() & " records.") ' Some helpful identifying info about this instance: ' ts_systemsettings Dim n_SystemSettings_TblId , str_StrValFldName n_SystemSettings_TblId = CInt(Ext.TableId("TS_SYSTEMSETTINGS","database")) Call EmitSectionStart("SystemSettings") Call EmitHeaderStart("SystemSettingsHeader") Call EmitLineStart("SystemSettingsLabels") Call OutputChunk( "Database ODBC DSN" ) Call OutputChunk( "Database Name" ) Call OutputChunk( "Database Server" ) Call OutputChunk( "Is remote" ) Call OutputChunk( "DatabaseIdentifier" ) Call OutputChunk( "CharSet" ) Call OutputChunk( "Locale" ) Call OutputChunk( "TimeZone" ) Call OutputChunk( "LicenseServer" ) Call OutputChunk( "EnvironmentSet" ) Call OutputChunk( "AdminEmailToolbar" ) Call OutputChunk( "SMTPServer:SMTPPort" ) Call OutputChunk( "SMTPDomain" ) Call OutputChunk( "NSHTTPLinkAddress:NSHTTPLinkPort" ) Call OutputChunk( "SMTPAuthUsername") Call EmitLineEnd() Call EmitHeaderEnd() Dim strDsn , strDbName , strServerName , bRemote Call Shell.Db.GetConnectionInfo(strDsn , strDbName , strServerName , bRemote) Call EmitLineStart("SystemSettingsValues") Call OutputChunk( strDsn ) Call OutputChunk( strDbName ) Call OutputChunk( strServerName ) Call OutputChunk( bRemote ) Call OutputChunk( GetField(n_SystemSettings_TblId,"STRINGVALUE","ts_Name='DatabaseIdentifier'") ) Call OutputChunk( GetField(n_SystemSettings_TblId,"STRINGVALUE","ts_Name='CharSet'") ) Call OutputChunk( GetField(n_SystemSettings_TblId,"STRINGVALUE","ts_Name='Locale'") ) Call OutputChunk( GetField(n_SystemSettings_TblId,"STRINGVALUE","ts_Name='TimeZone'") ) Call OutputChunk( GetField(n_SystemSettings_TblId,"STRINGVALUE","ts_Name='LicenseServer'") ) Call OutputChunk( GetField(n_SystemSettings_TblId,"STRINGVALUE","ts_Name='EnvironmentSet'") ) Call OutputChunk( GetField(n_SystemSettings_TblId,"STRINGVALUE","ts_Name='AdminEmailToolbar'") ) Call OutputChunk( GetField(n_SystemSettings_TblId,"STRINGVALUE","ts_Name='SMTPServer'") & ":" & GetField(n_SystemSettings_TblId,"LONGVALUE","ts_Name='SMTPPort'") ) Call OutputChunk( GetField(n_SystemSettings_TblId,"STRINGVALUE","ts_Name='SMTPDomain'") ) Call OutputChunk( GetField(n_SystemSettings_TblId,"STRINGVALUE","ts_Name='NSHTTPLinkAddress'") & ":" & GetField(n_SystemSettings_TblId,"LONGVALUE","ts_Name='NSHTTPLinkPort'") ) Call OutputChunk( GetField(n_SystemSettings_TblId,"STRINGVALUE","ts_Name='SMTPAuthUsername'") ) Call EmitLineEnd() Call EmitSectionEnd() Call EmitBlankLine() ' Write a CSV-formatted header line for all field data columns Call EmitSectionStart("MainFields") Call EmitHeaderStart("MainFieldsHeader") Call EmitLineStart("MainFieldsLabels") Call OutputChunk( "Table_Name" ) Call OutputChunk( "Table_dB_Name" ) Call OutputChunk( "Table_ID" ) Call OutputChunk( "Field Name" ) Call OutputChunk( "Description" ) Call OutputChunk( "Field_dB_Name" ) Call OutputChunk( "Field ID" ) Call OutputChunk( "Field UUID" ) Call OutputChunk( "Deleted" ) Call OutputChunk( "SysCode:Descr" ) Call OutputChunk( "Type" ) Call OutputChunk( "Attributes" ) Call OutputChunk( "Length" ) Call OutputChunk( "Reqd" ) Call OutputChunk( "Property" ) Call OutputChunk( "Prefix" ) Call OutputChunk( "Suffix" ) Call OutputChunk( "FK_to" ) Call OutputChunk( "Dependent on" ) Call OutputChunk( "SubRel Fld Displayed" ) Call EmitLineEnd() Call EmitHeaderEnd() For Each arecField in arlFields ' Exit For Call OutputField(arecField) Next Call EmitSectionEnd() Else ' Call LogIt("ReadWithWhere returned 0 items") End If Call EmitWebPageTail() Select Case nFormatMode Case FORMAT_TEXT_MODE ' Downloads & saves the CSV content as "tmtrack.dll". ' When opened in Excel it needs "text to columns". Doesn't really save a lot of work. ' Call writeResponse(gstrOutputBuffer , "application/csv") Call Ext.WriteStream(gstrOutputBuffer) Case FORMAT_HTML_MODE Call Ext.WriteStream(gstrOutputBuffer) Case FORMAT_CSS_MODE ' TODO: Need styles to do presentation with the contant. Call Ext.WriteStream(gstrOutputBuffer) Case FORMAT_XLS_MODE ' TODO: content needs the formatting detailed here in http://en.wikipedia.org/wiki/Microsoft_Excel Call writeResponse(gstrOutputBuffer , "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") End Select Else Call Ext.LogErrorMsg("Expected URL context") End If ' ***************************************************************************** ' Typical headers: ' Date: Mon, 09 Apr 2012 21:07:56 GMT ' Server: Microsoft-IIS/6.0 ' X-Powered-By: ASP.NET ' Expires: 0 ' Cache-Control: no-cache ' Content-Type: text/html; charset=UTF-8 ' Content-Length: 429853 Sub EmitWebPageHead() ' Call Ext.WriteStream("" & vbCrLf) ' Call Ext.WriteStream("" & vbCrLf) ' Call Ext.WriteStream("" & vbCrLf) ' Call Ext.WriteStream("GenERD" & vbCrLf) ' Call Ext.WriteStream("" & vbCrLf) ' Call Ext.WriteStream("" & vbCrLf) ' Call Ext.WriteStream("

<BEGINNING OF DOCUMENT>" & vbHtmlNewLine) gstrOutputBuffer = gstrOutputBuffer & "" & vbCrLf & _ "" & vbCrLf & _ "" & vbCrLf & _ "GenERD" & vbCrLf & _ "" & vbCrLf & _ "" & vbCrLf & _ "

<BEGINNING OF DOCUMENT>" & vbHtmlNewLine End Sub ' * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** Sub EmitWebPageTail() ' Call Ext.WriteStream("

<END OF DOCUMENT>" & vbHtmlNewLine) ' Call Ext.WriteStream("" & vbCrLf) ' Call Ext.WriteStream("" & vbCrLf) gstrOutputBuffer = gstrOutputBuffer & "

<END OF DOCUMENT>" & vbHtmlNewLine & _ "" & vbCrLf & _ "" & vbCrLf End Sub ' * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** ' Beginning of a header Sub EmitSectionStart(str) Select Case nFormatMode Case FORMAT_TEXT_MODE ' Text mode doesn't care about headers or sections ' gstrOutputBuffer = gstrOutputBuffer & "" Case FORMAT_HTML_MODE If Len(str)>0 Then gstrOutputBuffer = gstrOutputBuffer & "" & vbCrLf Else gstrOutputBuffer = gstrOutputBuffer & "
" & vbCrLf End If Case FORMAT_CSS_MODE gstrOutputBuffer = gstrOutputBuffer & "
" End Select End Sub Sub EmitSectionEnd() Select Case nFormatMode Case FORMAT_TEXT_MODE ' Text mode doesn't care about headers or sections gstrOutputBuffer = gstrOutputBuffer & vbHtmlNewLine Case FORMAT_HTML_MODE gstrOutputBuffer = gstrOutputBuffer & "
" & vbCrLf Case FORMAT_CSS_MODE gstrOutputBuffer = gstrOutputBuffer & "" End Select End Sub ' * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** Sub EmitHeaderStart(str) Select Case nFormatMode Case FORMAT_TEXT_MODE ' Text mode doesn't care about headers or sections ' gstrOutputBuffer = gstrOutputBuffer & "" Case FORMAT_HTML_MODE If Len(str)>0 Then gstrOutputBuffer = gstrOutputBuffer & "" & vbCrLf Else gstrOutputBuffer = gstrOutputBuffer & "" & vbCrLf End If Case FORMAT_CSS_MODE gstrOutputBuffer = gstrOutputBuffer & "

" End Select End Sub Sub EmitHeaderEnd() Select Case nFormatMode Case FORMAT_TEXT_MODE ' Text mode doesn't care about headers or sections ' gstrOutputBuffer = gstrOutputBuffer & vbHtmlNewLine Case FORMAT_HTML_MODE gstrOutputBuffer = gstrOutputBuffer & "" & vbCrLf Case FORMAT_CSS_MODE gstrOutputBuffer = gstrOutputBuffer & "
" & vbCrLf End Select End Sub ' * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** 'Eventually format Line as a Table Line Sub EmitLineStart(str) Select Case nFormatMode Case FORMAT_TEXT_MODE ' Text mode doesn't care about headers or sections ' gstrOutputBuffer = gstrOutputBuffer & "" Case FORMAT_HTML_MODE If Len(str)>0 Then gstrOutputBuffer = gstrOutputBuffer & "" & vbCrLf Else gstrOutputBuffer = gstrOutputBuffer & "" & vbCrLf End If Case FORMAT_CSS_MODE gstrOutputBuffer = gstrOutputBuffer & "
" & vbCrLf End Select End Sub Sub EmitLineEnd() Select Case nFormatMode Case FORMAT_TEXT_MODE ' Text mode doesn't care about headers or sections gstrOutputBuffer = gstrOutputBuffer & vbHtmlNewLine Case FORMAT_HTML_MODE gstrOutputBuffer = gstrOutputBuffer & "" & vbCrLf Case FORMAT_CSS_MODE gstrOutputBuffer = gstrOutputBuffer & "
" & vbCrLf End Select End Sub ' * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** Sub EmitBlankLine() Select Case nFormatMode Case FORMAT_TEXT_MODE gstrOutputBuffer = gstrOutputBuffer & vbHtmlNewLine Case FORMAT_HTML_MODE gstrOutputBuffer = gstrOutputBuffer & vbHtmlNewLine Case FORMAT_CSS_MODE gstrOutputBuffer = gstrOutputBuffer & vbHtmlNewLine End Select End Sub ' * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** 'Eventually format chunk as a Table Cell Sub OutputChunk(str) Select Case nFormatMode Case FORMAT_TEXT_MODE gstrOutputBuffer = gstrOutputBuffer & str & strDelim Case FORMAT_HTML_MODE gstrOutputBuffer = gstrOutputBuffer & "" & str & "" Case FORMAT_CSS_MODE gstrOutputBuffer = gstrOutputBuffer & "" & str & "" End Select End Sub ' ***************************************************************************** Sub LogIt(str) If Ext.OutputStreamExists() Then ' Call Ext.WriteStream( str & vbCrLf ) gstrOutputBuffer = gstrOutputBuffer & str & vbHtmlNewLine Else Call Ext.LogInfoMsg(str) End If End Sub ' ***************************************************************************** ' Param is an AppRecord point to a record in TS_FIELDS Sub OutputField(objFld) Dim strTableId , strTblType Dim strFldType , strFldUuid , strAttribs , strLen, strStatus , strProp , strReqd , strSysCode , strOptions Dim strPrefix , strSuffix , strMasterId , strRelationId , strSubRelFldId ' We need the table ID and type. Call objFld.GetFieldValue("TABLEID",strTableId) strTblType = GetField("TS_TABLES","TYPE","TS_ID=" & strTableId) Call objFld.GetFieldValue("FLDTYPE",strFldType) Call objFld.GetFieldValue("UUID",strFldUuid) Call objFld.GetFieldValue("ATTRIBUTES",strAttribs) Call objFld.GetFieldValue("LEN",strLen) Call objFld.GetFieldValue("STATUS",strStatus) Call objFld.GetFieldValue("PROPERTY",strProp) Call objFld.GetFieldValue("REQUIRED",strReqd) Call objFld.GetFieldValue("SYSCODE",strSysCode) Call objFld.GetFieldValue("OPTIONS",strOptions) Call objFld.GetFieldValue("DISPLAYPREFIX",strPrefix) Call objFld.GetFieldValue("DISPLAYSUFFIX",strSuffix) Call objFld.GetFieldValue("MASTERID",strMasterId) Call objFld.GetFieldValue("RELATIONID",strRelationId) Call objFld.GetFieldValue("FIELDID",strSubRelFldId) ' Field's Table name, db name, ID Call EmitLineStart("") Call OutputChunk(Ext.TableDisplayName(strTableId)) Call OutputChunk(Ext.TableDatabaseName(strTableId)) Call OutputChunk(strTableId) ' Field name, Description, db Name, ID, Deleted, SysCode Call OutputChunk( objFld.GetDisplayName() ) ' Only need to quote when in TEXT mode If nFormatMode=FORMAT_TEXT_MODE Then Call OutputChunk( vbQuote & GetFld(objFld,"DESCRIPTION") & vbQuote ) Else Call OutputChunk( GetFld(objFld,"DESCRIPTION") ) End If Call OutputChunk( "TS_" & GetFld(objFld,"DBNAME")) Call OutputChunk( objFld.GetID() ) Call OutputChunk( strFldUuid ) Call OutputChunk( Deleted(strStatus) ) ' diagnostic SYSCODE stuff ' Decoding SYSCODE requires taking into account the Table ID and type. Call OutputChunk( strSysCode & ":" & SyscodeDescr(strSysCode,strTableId,strTblType) ) ' Field type, Attributes, Length, Required, Property Call OutputChunk(FieldTypeDescr(strFldType)) Call OutputChunk(AttribDescr(strFldType,strAttribs)) Call OutputChunk(strLen) If CInt(strReqd)=0 Then Call OutputChunk(strEmptyString) Else Call OutputChunk("Reqd") Call OutputChunk(PropDescr(strProp)) ' Display Prefix, Suffix Call OutputChunk(strPrefix) Call OutputChunk(strSuffix) ' Relational stuff ' If strRelationId is non-zero and strFldType is relational (a relational ' selection field, or a user/group field, etc), then strRelationId is a foreign ' key into the TS_TABLES table indicating the table from which possible ' values are obtained. If strFldType is TS_FLDTYPE_SUBRELATIONAL, strRelationId ' is the relational field that supplies the current selection value ' allowing for more than one relational field based on the same table. ' FK_to If (CInt(strRelationId) <> 0) THen If (strFldType = TS_FLDTYPE_SUBRELATIONAL) Then ' Relation ID is relational field ID Call OutputChunk(GetFieldFullName(strTableId,strRelationId,-1)) Else ' Relation ID is table ID Call OutputChunk(Ext.TableDatabaseName(strRelationId)) End If Else Call OutputChunk(strEmptyString) End If Call OutputChunk(MasterField(strTableId, strMasterId)) ' "Dependent on" ' Properly formatting subrelational FIELDID is a bit more work than I have time for right now.... If strSubRelFldId=0 Then Call OutputChunk(strEmptyString) Else If (strFldType = TS_FLDTYPE_SUBRELATIONAL) Then ' strRelationId points to relational field in this field's table that determines "driving" value ' strSubRelFldId is field to actually display ' Call Ext.LogInfoMsg("Subrelational field ID=" & strSubRelFldId) ' =680 ' Call Ext.LogInfoMsg("GetFieldFullName()=" & GetFieldFullName(strTableId,strRelationId,-1)) ' =Business Unit (USR_SANDBOX.TS_BUSINESS_UNIT) ' Call Ext.LogInfoMsg("GetFieldTableId()=" & GetFieldTableId(strSubRelFldId) ) ' =1031 ' Call Ext.LogInfoMsg("GetFieldFullName()=" & GetFieldFullName(GetFieldTableId(strSubRelFldId) ,strSubRelFldId,-1) ) '=Biz Unit User Z (USR_BUSINESS_UNIT.TS_BIZ_UNIT_USER_Z) Call OutputChunk( GetFieldFullName(GetFieldTableId(strSubRelFldId) ,strSubRelFldId,-1) ) ' Call OutputChunk(strSubRelFldId) 'SubRel End If End If Call EmitLineEnd() End Sub ' ***************************************************************************** ' Field name is either UPPERCASE DATABASE NAME without "TS_", or Mixed Case Display Name Function GetFld(arec,strFldName) Dim str If arec.GetFieldValue(strFldName,str) Then GetFld = Trim(str) Else GetFld = strFldName End If End Function ' ***************************************************************************** ' Return a fully qualified db name (tablename.fieldname) given the table and field IDs ' 3rd param (flag) ' < 0 format result as "Field Display Name (TBL_DBNAME.FLD_DBNAME)" ' = 0 format result as "TBL_DBNAME.FLD_DBNAME" ' > 0 format result as "TBL_DBNAME.FLD_DBNAME (Field Display Name)" ' Field ID may be a numeric value or field name. ' system field names in all lowercase ' VARIABLE FIELD DATABASE NAMES IN UPPERCASE WITHOUT "TS_" PREFIX, Or any Case but with "TS_" prefix. ' Variable Field Display Names In Mixed Case ' If isNumeric(fldId) Then ' arec.Read(fldId) ' ElseIf fldId = UCase(fldId) or UCase(Left(fldId),3) = "TTS_" Then ' nTblId = Ext.TableId(varTblId,"database") ' Else ' nTblId = Ext.TableId(varTblId,"display") ' End If Function GetFieldFullName(ByVal tblId,fldId,flg) Dim arec , strFldName set arec = Ext.CreateAppRecord(Ext.TableID("TS_FIELDS","database")) If arec.ReadWithWhere("ts_tableid=" & tblId & " and ts_id=" & fldId) Then strFldName = Ext.TableDatabaseName(tblId) & "." & "TS_" & GetFld(arec,"DBNAME") If flg < 0 Then GetFieldFullName = arec.GetName & " (" & strFldName & ")" ElseIf flg > 0 Then GetFieldFullName = strFldName & " (" & arec.GetDisplayName & ")" Else GetFieldFullName = strFldName End If Else GetFieldFullName = "Can't read fldID '" & fldId & "' for tableID '" & tblId & "' in TS_FIELDS" End If End Function ' ***************************************************************************** Function FieldTypeDescr(n) Select Case n Case TS_FLDTYPE_NUMERIC FieldTypeDescr = "Numeric" Case TS_FLDTYPE_TEXT FieldTypeDescr = "Text" Case TS_FLDTYPE_DATETIME FieldTypeDescr = "Date/Time" Case TS_FLDTYPE_SELECTION FieldTypeDescr = "Single selection" Case TS_FLDTYPE_BINARY FieldTypeDescr = "Binary" Case TS_FLDTYPE_STATE FieldTypeDescr = "System state" Case TS_FLDTYPE_USER FieldTypeDescr = "User selection" Case TS_FLDTYPE_PROJECT FieldTypeDescr = "System project" Case TS_FLDTYPE_SUMMATION FieldTypeDescr = "Summation" Case TS_FLDTYPE_MULTIPLE_SELECTION FieldTypeDescr = "Multi-select" Case TS_FLDTYPE_CONTACT FieldTypeDescr = "Contact" Case TS_FLDTYPE_COMPANY FieldTypeDescr = "Company (Obsolete)" Case TS_FLDTYPE_INCIDENT FieldTypeDescr = "Incident selection" Case TS_FLDTYPE_PRODUCT FieldTypeDescr = "Product (Obsolete)" Case TS_FLDTYPE_SERVICEAGREEMENT FieldTypeDescr = "Service Agreement (Obsolete)" Case TS_FLDTYPE_FOLDER FieldTypeDescr = "Folder link" Case TS_FLDTYPE_KEYWORDLIST FieldTypeDescr = "Keyword List (Obsolete)" Case TS_FLDTYPE_PRODUCTLIST FieldTypeDescr = "Product List (Obsolete)" Case TS_FLDTYPE_PROBLEM FieldTypeDescr = "Problem (Obsolete)" Case TS_FLDTYPE_RESOLUTION FieldTypeDescr = "Obsolete." Case TS_FLDTYPE_MERCHANDISE FieldTypeDescr = "Obsolete." Case TS_FLDTYPE_RELATIONAL FieldTypeDescr = "Single relational" Case TS_FLDTYPE_SUBRELATIONAL FieldTypeDescr = "Sub-relational" Case TS_FLDTYPE_SYSTEM FieldTypeDescr = "System" Case TS_FLDTYPE_MULTIPLE_RELATIONAL FieldTypeDescr = "Multi-relational" Case TS_FLDTYPE_MULTIPLE_USER FieldTypeDescr = "Multi-user" Case TS_FLDTYPE_MULTIPLE_GROUP FieldTypeDescr = "Multi-group" Case Else FieldTypeDescr = "" End Select End Function ' ***************************************************************************** Function AttribDescr(fldtype,attr) Select Case fldtype Case TS_FLDTYPE_TEXT Select Case attr Case TS_FLDATTRIB_MEMO AttribDescr = "Memo" Case TS_FLDATTRIB_FIXEDTEXT AttribDescr = "Fixed length" Case TS_FLDATTRIB_JOURNAL AttribDescr = "Journal" Case TS_FLDATTRIB_JOURNAL_RO AttribDescr = "Append-Only Journal" Case Else AttribDescr = "" End Select Case TS_FLDTYPE_NUMERIC Select Case attr Case TS_FLDATTRIB_INT AttribDescr = "Integer" Case TS_FLDATTRIB_FLOAT AttribDescr = "Floating Point" Case TS_FLDATTRIB_FIXED_PRECISION AttribDescr = "Fixed Precision" Case Else AttribDescr = "" End Select Case TS_FLDTYPE_DATETIME Select Case attr Case TS_FLDATTRIB_DT_DATEONLY AttribDescr = "Date only" Case TS_FLDATTRIB_DT_DATETIME AttribDescr = "Date/Time" Case TS_FLDATTRIB_DT_TIMEOFDAY AttribDescr = "Time only" Case TS_FLDATTRIB_DT_ELAPSEDTIME AttribDescr = "Elapsed time" Case Else AttribDescr = "" End Select Case TS_FLDTYPE_BINARY Select Case attr Case TS_FLDATTRIB_BIN_LISTBOX AttribDescr = "Listbox" Case TS_FLDATTRIB_BIN_RADIOBUTTON AttribDescr = "Radio Buttons" Case TS_FLDATTRIB_BIN_CHECKBOX AttribDescr = "Checkbox" Case TS_FLDATTRIB_BIN_TRINARY AttribDescr = "Trinary" Case Else AttribDescr = "" End Select End Select End Function ' ***************************************************************************** ' The schema docs are a vague on SysCode. Function SyscodeDescr(ByVal strSysCode,strTblId,strTblType) Dim strDescr strSysCode = CInt(strSysCode) ' Values for TS_SYSCODE column: ' System fields are fields that have special, application-defined semantics. ' They are identified by a non-zero TS_SYSCODE value. ' Note: the documentation is not clear what "application-defined" means, but ' Syscode values *appear* to be dependent on table ID and Table type. ' Table ID ' TS_TBLID_CASES 1 Deprecated. See note below. ' TS_TBLID_INCIDENTS 36 Deprecated. See note below. ' TS_TBLID_MERCHANDISE 39 Deprecated. See note below. ' TS_TBLID_SERVICEAGREEMENTS 40 Deprecated. See note below. ' TS_TBLID_PRODUCTS 43 Deprecated. See note below. ' TS_TBLID_COMPANIES 37 ' TS_TBLID_CONTACTS 38 ' TS_TBLID_PROBLEMS 41 ' TS_TBLID_RESOLUTIONS 42 ' TableType ' TS_TBLTYPE_SYS 0 System table, e.g. TS_USERS. ' TS_TBLTYPE_PRI 1 Primary table, e.g. TTT_ISSUES. ' TS_TBLTYPE_AUX 2 Auxiliary table, e.g. TTS_PRODUCTS. ' TS_TBLTYPE_SYSAUX 3 System auxiliary table, e.g. TS_CONTACTS. If strTblId=TS_TBLID_CASES OR strTblId=TS_TBLID_INCIDENTS Then ' System fields for both Issues and Incidents: Select Case strSysCode Case TS_SYSFLD_ID strDescr = "Issue/Incident: ID - Reserved for future use." Case TS_SYSFLD_PARENTID strDescr = "Issue/Incident: Project ID - Reserved for future use." Case TS_SYSFLD_PROJECTID strDescr = "Issue/Incident: Project ID." Case TS_SYSFLD_TITLE strDescr = "Issue/Incident: Title." Case TS_SYSFLD_DESC strDescr = "Issue/Incident: Description." Case TS_SYSFLD_STATE strDescr = "Issue/Incident: State." Case TS_SYSFLD_DT_CREATE strDescr = "Issue/Incident: Submit date." Case TS_SYSFLD_DT_LASTMODIFIED strDescr = "Issue/Incident: Last modified date." Case TS_SYSFLD_DT_LASTSTATECHANGE strDescr = "Issue/Incident: Last state change date." Case TS_SYSFLD_DT_CLOSE strDescr = "Issue/Incident: Close date." Case TS_SYSFLD_DT_REOPEN strDescr = "Issue/Incident: Reserved for future use." Case TS_SYSFLD_USER_OWNER strDescr = "Issue/Incident: Owner field" Case TS_SYSFLD_USER_SUBMITTER strDescr = "Issue/Incident: Submitter field" Case TS_SYSFLD_USER_LASTMODIFIER strDescr = "Issue/Incident: Last Modifier." Case TS_SYSFLD_USER_LASTSTATECHANGER strDescr = "Issue/Incident: Last state changer." Case TS_SYSFLD_TEXT_DISPLAYID strDescr = "Issue/incident id field displayed to the user." Case TS_SYSFLD_SEL_CASETYPE strDescr = "Issue/incident type." Case TS_SYSFLD_BIN_ACTIVEINACTIVE strDescr = "Issue/Incident: Active/inactive." Case TS_SYSFLD_FOLDERID strDescr = "Issue/Incident: Folder ID." Case TS_SYSFLD_LASTINCIDENT strDescr = "Issue/Incident: Last referenced incident ID" Case TS_SYSFLD_MULTIUSER_SECONDARYOWNER strDescr = "Issue/Incident: Secondary owner." ' Additional system fields for Incidents: Case TS_SYSFLD_COMPANY strDescr = "Incident: Associated company." Case TS_SYSFLD_CONTACT strDescr = "Incident: Associated contact." Case TS_SYSFLD_MERCHANDISE strDescr = "Incident: Associated merchandise." Case TS_SYSFLD_SERVICEAGREEMENT strDescr = "Incident: Associated service agreement." Case TS_SYSFLD_PROBLEM strDescr = "Incident: Knowledge Base problem related to this incident." Case TS_SYSFLD_RESOLUTION strDescr = "Incident: Knowledge Base resolution related to this incident." Case TS_SYSFLD_RESOLUTIONTITLE strDescr = "Incident: Resolution title" Case TS_SYSFLD_RESOLUTIONDESC strDescr = "Incident: Resolution description" End Select ' System fields for Companies: ElseIf strTblId=TS_TBLID_COMPANIES Then Select Case strSysCode Case TS_SYSFLD_TITLE strDescr = "Company: name." Case TS_SYSFLD_LASTINCIDENT strDescr = "Company: Last incident." Case TS_SYSFLD_COMPANY_NUMBER strDescr = "Company: number." Case TS_SYSFLD_COMPANY_PRICONTACT strDescr = "Company: primary contact." Case TS_SYSFLD_COMPANY_SECCONTACT strDescr = "Company: secondary contact." Case TS_SYSFLD_COMPANY_ADDRESS1 strDescr = "Company: first address line." Case TS_SYSFLD_COMPANY_ADDRESS2 strDescr = "Company: second address line." Case TS_SYSFLD_COMPANY_CITY strDescr = "Company: city." Case TS_SYSFLD_COMPANY_STATE strDescr = "Company: state." Case TS_SYSFLD_COMPANY_COUNTRY strDescr = "Company: country." Case TS_SYSFLD_COMPANY_ZIPCODE strDescr = "Company: zip code." Case TS_SYSFLD_COMPANY_FAXNUMBER strDescr = "Company: fax telephone number." Case TS_SYSFLD_COMPANY_PHONENUMBER strDescr = "Company: telephone number." End Select ' System fields for Contacts: ElseIf strTblId=TS_TBLID_CONTACTS Then Select Case strSysCode Case TS_SYSFLD_TITLE strDescr = "Contact: name." Case TS_SYSFLD_LASTINCIDENT strDescr = "Contact: Last incident." Case TS_SYSFLD_CONTACT_COMPID strDescr = "Contact: Company ID" Case TS_SYSFLD_CONTACT_FNAME strDescr = "Contact: First name." Case TS_SYSFLD_CONTACT_MNAME strDescr = "Contact: Middle name." Case TS_SYSFLD_CONTACT_LNAME strDescr = "Contact: Obsolete, use TS_SYSFLD_TITLE." Case TS_SYSFLD_CONTACT_USERID strDescr = "Contact: User ID." Case TS_SYSFLD_CONTACT_PHONE strDescr = "Contact: Phone number." Case TS_SYSFLD_CONTACT_EMAIL strDescr = "Contact: Email." Case TS_SYSFLD_COMPANY_ADDRESS1 strDescr = "Contact: Company first address line." Case TS_SYSFLD_COMPANY_ADDRESS2 strDescr = "Contact: Company second address line." Case TS_SYSFLD_CONTACT_CITY strDescr = "Contact: city." Case TS_SYSFLD_CONTACT_STATE strDescr = "Contact: state." Case TS_SYSFLD_CONTACT_COUNTRY strDescr = "Contact: country." Case TS_SYSFLD_CONTACT_ZIPCODE strDescr = "Contact: zip code." Case TS_SYSFLD_CONTACT_FAXNUMBER strDescr = "Contact: fax telephone number." Case TS_SYSFLD_CONTACT_MOBILENUMBER strDescr = "Contact: mobile telephone number." End Select ' System fields for Problems/Resolutions: ElseIf strTblId=TS_TBLID_PROBLEMS OR strTblId=TS_TBLID_RESOLUTIONS Then Select Case strSysCode Case TS_SYSFLD_TITLE strDescr = "Problem/Resolution: Title." Case TS_SYSFLD_DESC strDescr = "Problem/Resolution: Description." Case TS_SYSFLD_DT_LASTMODIFIED strDescr = "Problem/Resolution: Last modified date." Case TS_SYSFLD_FOLDERID strDescr = "Problem/Resolution: Folder ID." Case TS_SYSFLD_PROBLEM strDescr = "Problem/Resolution: Knowledge Base problem related to this resolution." Case TS_SYSFLD_VISIBILITY strDescr = "Problem/Resolution: Visibility." Case TS_SYSFLD_PRODUCTS strDescr = "Problem/Resolution: Products affected." End Select ' System fields for Service Agreements: ElseIf strTblId=TS_TBLID_SERVICEAGREEMENTS Then Select Case strSysCode Case TS_SYSFLD_TITLE strDescr = "Service agreement: name." Case TS_SYSFLD_CONTACT strDescr = "Service agreement: Associated company." Case TS_SYSFLD_DT_EXPIRATION strDescr = "Service agreement: Expiration date." End Select ' System fields for user-created primary tables: ElseIf strTblType=TS_TBLTYPE_PRI Then Select Case strSysCode Case TS_SYSFLD_PROJECTID strDescr = "Project ID." Case TS_SYSFLD_TITLE strDescr = "Title." Case TS_SYSFLD_DESC strDescr = "Description." Case TS_SYSFLD_STATE strDescr = "State." Case TS_SYSFLD_DT_CREATE strDescr = "Submit date." Case TS_SYSFLD_DT_LASTMODIFIED strDescr = "Last modified date." Case TS_SYSFLD_DT_LASTSTATECHANGE strDescr = "Last state change date." Case TS_SYSFLD_DT_CLOSE strDescr = "Close date." Case TS_SYSFLD_USER_OWNER strDescr = "Owner field" Case TS_SYSFLD_USER_SUBMITTER strDescr = "Submitter field" Case TS_SYSFLD_USER_LASTMODIFIER strDescr = "Last Modifier." Case TS_SYSFLD_USER_LASTSTATECHANGER strDescr = "Last state changer." Case TS_SYSFLD_TEXT_DISPLAYID strDescr = "Item id field displayed to the user." Case TS_SYSFLD_SEL_CASETYPE strDescr = "Item type." Case TS_SYSFLD_BIN_ACTIVEINACTIVE strDescr = "Active/inactive." Case TS_SYSFLD_MULTIUSER_SECONDARYOWNER strDescr = "Secondary Owner." Case TS_SYSFLD_RESOLUTIONTITLE strDescr = "Resolution title" Case TS_SYSFLD_RESOLUTIONDESC strDescr = "Resolution description" End Select ' System fields for user-created auxiliary tables: ElseIf strTblType=TS_TBLTYPE_AUX Then Select Case strSysCode Case TS_SYSFLD_TITLE strDescr = "Title." Case TS_SYSFLD_DESC strDescr = "Description." Case TS_SYSFLD_DT_CREATE strDescr = "Submit date." Case TS_SYSFLD_DT_LASTMODIFIED strDescr = "Last modified date." Case TS_SYSFLD_USER_SUBMITTER strDescr = "Submitter field" Case TS_SYSFLD_USER_LASTMODIFIER strDescr = "Last Modifier." Case TS_SYSFLD_TEXT_DISPLAYID strDescr = "Item id field displayed to the user." Case TS_SYSFLD_BIN_ACTIVEINACTIVE strDescr = "Active/inactive." End Select ' System fields for SharePoint auxiliary tables: ElseIf strTblType=TS_TBLTYPE_AUX Then Select Case strSysCode Case TS_SYSFLD_URL strDescr = "SharePoint Url." Case TS_SYSFLD_DOC_LIB strDescr = "SharePoint Document Library." Case TS_SYSFLD_PARENT_SITENAME strDescr = "SharePoint Parent site name." Case TS_SYSFLD_URL_ADDUSER strDescr = "SharePoint AddUser Url." Case TS_SYSFLD_SHAREPOINT_USER strDescr = "SBM proxy SharePoint user id." Case TS_SYSFLD_SHAREPOINT_PASS strDescr = "SBM proxy SharePoint password." End Select End If If Len(strDescr) > 0 Then SyscodeDescr = strDescr ElseIf strSysCode = 0 Then SyscodeDescr = "" Else SyscodeDescr = "" End If End Function ' ***************************************************************************** ' Return the specified field from specified table using specified where Function GetField(strTblId,strFldId,strWhere) Dim nTblId Dim arecTbl , strVal 'Table can be either a numeric ID, database name, or display name. If IsNumeric(strTblId) Then nTblId = CLng(strTblId) Else nTblId = Ext.TableId(strTblId) Set arecTbl = Ext.CreateAppRecord(nTblId) If arecTbl.ReadWithWhere(strWhere) Then If arecTbl.GetFieldValue(strFldId,strVal) Then GetField = strVal Else Call Ext.LogErrorMsg("GetField() : can't read field '" & strFldId & "'") Else Call Ext.LogErrorMsg("GetField() : ReadWithWhere(" & strWhere & ") failed") End If End Function ' ***************************************************************************** ' Given a field ID, return it's table ID Function GetFieldTableId(strFldId) Dim arecField , strTblId Set arecField = Ext.CreateAppRecord(Ext.TableID("TS_FIELDS","database")) If arecField.Read(strFldId) Then Call arecField.GetFieldValue("tableid",strTblId) Set arecField = Nothing GetFieldTableId = strTblId End Function ' ***************************************************************************** Function Deleted(status) Select Case status Case 0 Deleted = strEmptyString Case 1 Deleted = "Deleted" Case Else Deleted = "" End Select End Function ' ***************************************************************************** Function MasterField(tblId, fldId) MasterField = strEmptyString If fldId > 0 Then MasterField = GetFieldFullName(tblId, fldId,-1) End If End Function ' ***************************************************************************** Function PropDescr(prop) Dim strDesc If prop And TS_FLDPROP_NONEDITABLE Then strDesc = "R/O;" If prop And TS_FLDPROP_CALC_BEFORE Then strDesc = strDesc & "**x;" If prop And TS_FLDPROP_CALC_AFTER Then strDesc = strDesc & "x**;" If prop And TS_FLDPROP_CALC_ADD_CUR Then strDesc = strDesc & "CV+=;" If prop And TS_FLDPROP_CALC_EMPTY_INVALID Then strDesc = strDesc & "no '';" If prop And TS_FLDPROP_CALC_EMPTY_SKIP_CALC Then strDesc = strDesc & "''==skip calc;" If prop And TS_FLDPROP_CALC_EMPTY_TREAT_ZERO Then strDesc = strDesc & "''== FV=0 & calc;" If prop And TS_FLDPROP_CHECKBOXES Then strDesc = strDesc & "[ ];" If Len(strDesc) > 1 Then strDesc = Left(strDesc,Len(strDesc)-1) PropDescr = strDesc End Function ' ***************************************************************************** ' Use of shell.redirectHTTP suggested by Jeff Malin ... ' return a string as Excel data (rather than ext.writeStream which returns as HTML) Function writeResponse(strContent , strContentType) dim Response Response = "HTTP/1.1 200 OK" & vbcrlf & _ "Date: " & now & vbcrlf & _ "Server: Microsoft-IIS/6.0" & vbcrlf & _ "Expires: 0" & vbcrlf & _ "Connection: close" & vbcrlf & _ "Content-Type: " & strContentType & "; charset=UTF-8" & vbcrlf strContent = "" & vbcrlf & strContent shell.redirectHTTP = Response & vbcrlf & strContent ' Must separate the headers from the Content with a linefeed end function ' see: http://en.wikipedia.org/wiki/Microsoft_Excel ' application/vnd.openxmlformats-officedocument.spreadsheetml.sheet ' application/vnd.ms-excel ' application/msexcel ' application/csv ' text/csv