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 "<BEGINNING OF DOCUMENT>". 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 "<END OF DOCUMENT>". 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("<!DOCTYPE HTML PUBLIC " & vbQuote & "-//W3C//DTD HTML 4.01//EN" & vbQuote & " " & vbCrLf & _
' vbQuote & "http://www.w3.org/TR/html4/strict.dtd" & vbQuote & ">" & vbCrLf)
' Call Ext.WriteStream("<HTML>" & vbCrLf)
' Call Ext.WriteStream("<HEAD>" & vbCrLf)
' Call Ext.WriteStream("<TITLE>GenERD</TITLE>" & vbCrLf)
' Call Ext.WriteStream("</HEAD>" & vbCrLf)
' Call Ext.WriteStream("<BODY>" & vbCrLf)
' Call Ext.WriteStream("<P><BEGINNING OF DOCUMENT>" & vbHtmlNewLine)
gstrOutputBuffer = gstrOutputBuffer & "<!DOCTYPE HTML PUBLIC " & vbQuote & "-//W3C//DTD HTML 4.01//EN" & vbQuote & " " & vbCrLf & _
vbQuote & "http://www.w3.org/TR/html4/strict.dtd" & vbQuote & ">" & vbCrLf & _
"<HTML>" & vbCrLf & _
"<HEAD>" & vbCrLf & _
"<TITLE>GenERD</TITLE>" & vbCrLf & _
"</HEAD>" & vbCrLf & _
"<BODY>" & vbCrLf & _
"<P><BEGINNING OF DOCUMENT>" & vbHtmlNewLine
End Sub
' * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * **
Sub EmitWebPageTail()
' Call Ext.WriteStream("<P><END OF DOCUMENT>" & vbHtmlNewLine)
' Call Ext.WriteStream("</BODY>" & vbCrLf)
' Call Ext.WriteStream("</HTML>" & vbCrLf)
gstrOutputBuffer = gstrOutputBuffer & "<P><END OF DOCUMENT>" & vbHtmlNewLine & _
"</BODY>" & vbCrLf & _
"</HTML>" & 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 & "<table id='" & str & "' border='1'><tbody>" & vbCrLf
Else
gstrOutputBuffer = gstrOutputBuffer & "<table border='1' id='ESS'><tbody>" & vbCrLf
End If
Case FORMAT_CSS_MODE
gstrOutputBuffer = gstrOutputBuffer & "<div>"
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 & "</tbody></table>" & vbCrLf
Case FORMAT_CSS_MODE
gstrOutputBuffer = gstrOutputBuffer & "</div>"
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 & "<thead id='" & str & "'>" & vbCrLf
Else
gstrOutputBuffer = gstrOutputBuffer & "<thead id='EHS'>" & vbCrLf
End If
Case FORMAT_CSS_MODE
gstrOutputBuffer = gstrOutputBuffer & "<div>"
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 & "</thead>" & vbCrLf
Case FORMAT_CSS_MODE
gstrOutputBuffer = gstrOutputBuffer & "</div>" & 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 & "<tr id='" & str & "'>" & vbCrLf
Else
gstrOutputBuffer = gstrOutputBuffer & "<tr id='ELS'>" & vbCrLf
End If
Case FORMAT_CSS_MODE
gstrOutputBuffer = gstrOutputBuffer & "<div>" & 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 & "</tr>" & vbCrLf
Case FORMAT_CSS_MODE
gstrOutputBuffer = gstrOutputBuffer & "</div>" & 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 & "<td>" & str & "</td>"
Case FORMAT_CSS_MODE
gstrOutputBuffer = gstrOutputBuffer & "<span>" & str & "</span>"
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 = "<Unknown FLDTYPE>"
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 = "<Unknown ATTRIBUTE value for TS_FLDTYPE_TEXT>"
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 = "<Unknown ATTRIBUTE value for TS_FLDTYPE_NUMERIC>"
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 = "<Unknown ATTRIBUTE value for TS_FLDTYPE_DATETIME>"
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 = "<Unknown ATTRIBUTE value for TS_FLDTYPE_BINARY>"
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 = "<unknown SYSCODE " & strSysCode & ">"
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 = "<Unknown DELETE status>"
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 = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>" & 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