This is not, generally a good idea to insert potentially long and slow code inside of object constructor.

Why? %OnNew should contain code which is absolutely required on object initiation regardless of the execution speed. There is no use case for this class to construct an object and not call %Connect, so %Connect should be moved into %OnNew. That way client code needs to make one mandatory call instead of two.

Here's working example:

Class Sample.XSLTransform [ Abstract ]
{

ClassMethod test(tData = "<HHSOS><DIAGNOSES><DIAGNOSIS_DATA><DIAGNOSIS_DATA_GUID>3762875</DIAGNOSIS_DATA_GUID><DIAGNOSIS_DATA_GUID>37628752</DIAGNOSIS_DATA_GUID></DIAGNOSIS_DATA><DIAGNOSIS_DATA></DIAGNOSIS_DATA><DIAGNOSIS_DATA></DIAGNOSIS_DATA><DIAGNOSIS_DATA_GUID>37628753</DIAGNOSIS_DATA_GUID></DIAGNOSES></HHSOS>", tSelect = "//DIAGNOSIS_DATA_GUID[1]", tXSL = "ExampleXSL")
{
    set tXML= ##class(%GlobalCharacterStream).%New()
    do tXML.Write(tData)
    set tXSL=##class(%Dictionary.CompiledXData).%OpenId($classname() _ "||" _ tXSL ).Data

    kill tParams
    set tParams("selectParam") = tSelect
    set tSC=##class(%XML.XSLT.Transformer).TransformStream(tXML,tXSL,.tOutput,,.tParams)
    zwrite tSC
    set tSC=tOutput.OutputToDevice()
}

XData ExampleXSL
{
<?xml version="1.0"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:param name="selectParam"/>
<xsl:template match="/">
    <xsl:copy-of select="$selectParam"/>
</xsl:template>
</xsl:stylesheet>
}

}

Example:

Do ##class(Sample.XSLTransform).test()
tSC=1
<?xml version="1.0" encoding="UTF-8"?><DIAGNOSIS_DATA_GUID>3762875</DIAGNOSIS_DATA_GUID><DIAGNOSIS_DATA_GUID>37628753</DIAGNOSIS_DATA_GUID>

Time Stamp Specifications for Filenames - while configuring business operations and business services that transmit data to and from files, you can often specify input and output filenames in a string that includes date and time format codes, such as %Y%M%d%h%m%s_%f.txt. At runtime, the format codes within this string resolve dynamically based on the current date and time.

That's generally a questionable idea, here's why:

  • It's the slowest possible method - if we're iterating over result set the application logic may decide to end processing not after the last row but earlier. If a whole result set is returned, then we still spent CPU/RAM to calculate something we may not even need
  • Result set may be quite large which would cause application logic errors
  • Result set may be larger than amount of RAM available
  • Time to first result is usually smaller than getting all results, so the user can start working with the first row, while an application fetches more rows

Well, that depends.

  1. If an index definition includes an explicitly specified collation for a property, the index uses that collation.
  2. If an index definition does not include an explicitly specified collation for a property, the index uses the collation explicitly specified in the property definition.
  3. If the property definition does not include an explicitly specified collation, then the index uses the collation that is the default for the property data type.
  4. If the property data type does not include an explicitly specified collation, then the index uses namespace default collation
  5. If the namespace default collation is not specified, then SQLUPPER is used.

I use the following code:

Class Form.File Extends %Persistent
{

/// Full filepath (path+name)
Property name As %String(MAXLEN = 1000, MINLEN = 1) [ Required ];

/// Description
Property description As %String(MAXLEN = 500);

/// Attachmentt SHA Hash in Base64
Property attachmentHASH As %String;

/// The file itself (data is stored on disk, it's just a link)
Property stream As %FileBinaryStream;

/// Save file
Method %OnNew(name As %String = "", description As %String = "", stream As %Stream.Object = {##class(%FileBinaryStream).%New()}) As %Status [ Private, ServerOnly = 1 ]
{
    #dim sc As %Status = $$$OK
    set ..name = ##class(%File).GetFilename(name)
    set ..description = description
    set ..stream.Filename = name
    set ..attachmentHASH = $system.Encryption.Base64Encode($zcvt($system.Encryption.SHAHashStream(512, ..stream, .sc),"O","UTF8"), 1)  
    return:$$$ISERR(sc) sc
    set sc = ..stream.CopyFromAndSave(stream)
    quit sc
}

/// Serve file in web context
Method serve() As %Status
{
    #dim sc As %Status = $$$OK
    #dim %response As %CSP.Response
    kill %request.Data
    set %request.Data("STREAMOID",1)= ##class(%CSP.StreamServer).Encrypt(..stream.%Oid())
    if ##class(%CSP.StreamServer).OnPreHTTP() {
        set %response.Headers("Content-Disposition")="attachment; filename*=UTF-8''"_##class(%CSP.Page).EscapeURL(..name,"UTF8")
        set st = ##class(%CSP.StreamServer).OnPage()
    }

    quit sc
}

During file upload new Form.File class object gets created and saved, and for download the requested object and calls the serve method.

Note, that this code is not specific to ZEN Mojo, but rather a generic CSP version.

%Label is the way to go.

Its fifth argument is a CSS applied to a cell. So the following MDX:

SELECT NON EMPTY %LABEL([Measures].[%COUNT],,,,"width:100%") ON 1 FROM [HOLEFOODS]

Would be displayed like this in analyzer:

And its sixth argument is a CSS applied to the cell header:

SELECT NON EMPTY %LABEL([Measures].[%COUNT],,,,,"width:80%") ON 1 FROM [HOLEFOODS]

Alternatively you can use DeepSeeWeb to display dashboards with pivots. In there cells width can be easily modified.

Here's the one I thought up. Does not use indirection.

/// Returns true if arrays <var>pFirst</var> and <var>pSecond</var> have all the same subscripts and all
/// the same values at those subscripts. <br />
/// If <var>pFirst</var> and <var>pSecond</var> both happen to be either undefined or unsubscripted variables
/// returns true if they're both undefined or have the same value or one is undefined and the other empty
/// <var>pMessage</var> has details of the first difference found, if any.
ClassMethod CompareArrays2(ByRef pFirst, ByRef pSecond, Output pMessage) As %Boolean
{
    Set pMessage = ""
    Return:(($Data(pFirst) '= 10) || ($Data(pSecond) '= 10)) $Get(pFirst) = $Get(pSecond)
    Merge First = pFirst
    Merge Second = pSecond
    Set Key = $Order(First(""))
    
    /// Iterate over first array
    While (Key '= "") {
        
        /// $Data on undefined var does not modify second argument
        Kill SecondVal
        
        /// If the second array does not have the same subscript
        /// or the values are different, quit
        If (($Data(Second(Key), SecondVal) = 0) || ($Get(SecondVal) '= First(Key))) {
            Set pMessage = "Different subscripts at " _ Key
            Return $$$NO
        } Else {
            /// Otherwise remove this element from the second array
            /// In here: Second(Key) = First(Key)
            Kill Second(Key)
        }
        Set Key = $Order(First(Key))
    }
    
    /// Second array should have no subscripts
    /// If there are any, that means they are not present
    /// in the first array, and so different
    If $Data(Second) = 10 {
        Set pMessage = "Different subscripts at " _ $Order(Second(""))
        Return $$$NO        
    }
    
    Return $$$YES
}

 Another question what is the sense to check "val" for IS NULL for Unique Index?

This check, if hit returns first Id with empty val.

So, "val" should exactly match the value of property, case sensitive?

That depends on property collation. For EXACT/ TRUNCATE/SQLSTRING collation, yes "val" should exactly match the value of the property (compared part of the value), case sensitive. For SQLUPPER - no.