Tomas Vaverka · Nov 10, 2016 go to post

It is not client name but Caché Username ($USERNAME). The 'Username' cookie is set by Management Portal, it's just to remember last user who was logged on. You cannot depend on this cookie in your application.

To get the client name, you should check some other CGIENV variables, like REMOTE_ADDR resp. REMOTE_USER. But it doesn't always exist.

Please, let us know what information you are looking for. Do you need to know name of the remote user connecting to the application?

Tomas Vaverka · Nov 9, 2016 go to post

You can also use syntax:

 set currPath=$SYSTEM.Process.CurrentDirectory()
 set oldPath=$SYSTEM.Process.CurrentDirectory(newPath)

The CurentDirectory method is an API covering the internal $ZUTIL functions:

ClassMethod CurrentDirectory(dir As %String) As %String
{
 quit:'$d(dir) $zu(168)
 quit $zu(168,dir)
}

Therefore in older Caché versions you can use:

 set currPath=$ZU(168)
 set oldPath=$ZU(168,newPath)
Tomas Vaverka · Nov 8, 2016 go to post

There is also comma after the ColumnA column, which causes invalid SQL. You should also check value of SQLCODE variable, because ouput host variables are valid only for SQLCODE=0 as described in Caché documentation:
http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY…

"It is good programming practice to check the SQLCODE value immediately after exiting Embedded SQL. Output host variable values should only be used when SQLCODE=0."

So the code should look as follows:

 <script language="cache" method="retrieveDetail" arguments="pVariable" returntype="%String">
 &sql( select ColumnA into :tempVariable1 from  MyTable where  COLUMNC = :pVariable)
 If SQLCODE=0 QUIT tempVariable1}
 Else {quit ""}
</script>

Will it help?

Tomas Vaverka · Nov 8, 2016 go to post

Can you also post how do you get the status and how/where do you get the 5034 error? Is it directly from saving the object? E.g.:

 Set status=object.%Save()
 Do $system.OBJ.DisplayError(status)

What Caché version do you use? In newer versions the error also returns status in parameter:
5034 Invalid status code structure (%1)

E.g.:

USER>Set sc=$lb(0,"xxx")
 
USER>Do $system.OBJ.DisplayError(sc)
 
ERROR #5034: Invalid status code structure ($lb(0,"xxx"))
Tomas Vaverka · Nov 2, 2016 go to post

Regarding your first question:

You can use a runtime expression as the value of excelSheetName.  This is described in following documentation:

http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GRPT_report_running#GRPT_excel_multisheet

For example you can define property, which takes value from URL request:

Property SheetName As %String(ZENURL = "sheetname") [ InitialExpression = "Person" ];
 

And in the report definition:

< group name="Persons" excelSheetName='!..SheetName'
    sql="SELECT top 2 name,Home_City as city,age,dob from Sample.Person order by Home_City"
    runtimeMode="1">

Then you call your report like:

/csp/samples/ZEN.ExcelReport.cls?sheetname=SalesPerson

Tomas Vaverka · Nov 2, 2016 go to post

I am sorry, I should read it more carefully, it is in the name of the topic - "Zen" Excel Report.

Tomas Vaverka · Nov 2, 2016 go to post

Could you please provide some example how do you create an Excel report? What tools, what functions are used? Are you using Zen Reports?

Tomas Vaverka · Nov 2, 2016 go to post

I am not sure if this is correct Community you posted your question. Please, what InterSystems technology (Caché, Ensemble) do you use to create your Excel MultipleSheet Report?

Tomas Vaverka · Nov 1, 2016 go to post

This is probably because you logged there with your iscinternal domain account. You need to log there as a customer. 

Tomas Vaverka · Oct 31, 2016 go to post

Without your code we cannot guess what can cause the error. If you send us example of your code, we can check what is not working as expected.

Anyway, this is en example which works. According to your request/response I think you are talking about web service, therefore I created simple Caché WebService classes:

Class  
tv.party Extends  
(%RegisteredObject, %XML.Adaptor)
{
Property  to As  list Of  tv.to( XMLPROJECTION =  "ELEMENTREF");
}

 Class  tv.to Extends  (%RegisteredObject , %XML.Adaptor )
{
Property name As %String(XMLPROJECTION = "ATTRIBUTE");
Property address1 As %String(XMLPROJECTION = "ATTRIBUTE");
}

 Class tv.PartyService Extends %SOAP.WebService [ ProcedureBlock ]
{
Parameter SERVICENAME = "PartyService";
Parameter NAMESPACE = "http://tempuri.org";
Parameter USECLASSNAMESPACES = 1;
Method CheckData(party As tv.party) As %Integer [ WebMethod ]
{
Quit party.to.Count()
}
}

Then I created SOAP web client using SoapUI and sent following request with 3 'to' items:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:s="http://tempuri.org">
   <soapenv:Header/>
   <soapenv:Body>
      <s:CheckData>
         <s:party>
            <s:to name="mohan" address1="India"/>
            <s:to name="sujay" address1="USA"/>
            <s:to name="tomas" address1="Europe"/>
       </s:party>
      </s:CheckData>
   </soapenv:Body>
</soapenv:Envelope>

And I received the correct response:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:s="http://www.w3.org/2001/XMLSchema">
   <SOAP-ENV:Body>
      <CheckDataResponse xmlns="http://tempuri.org">
         <CheckDataResult>3</CheckDataResult>
      </CheckDataResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope> 
Tomas Vaverka · Oct 31, 2016 go to post

Without your code we cannot guess what can cause the error.

Anyway, this is en example which works. According to your request/response I think you are talking about web service, therefore I created simple Caché WebService classes:

Class  tv.party Extends  (%RegisteredObject, %XML.Adaptor)
{
Property  to As  list Of  tv.to( XMLPROJECTION = "ELEMENTREF");
}
 
Class  tv.to Extends  (%RegisteredObject , %XML.Adaptor )
{
Property name As %String(XMLPROJECTION = "ATTRIBUTE");
Property address1 As %String(XMLPROJECTION = "ATTRIBUTE");
}
Class tv.PartyService Extends %SOAP.WebService [ ProcedureBlock ]
{
Parameter SERVICENAME = "PartyService";
Parameter NAMESPACE = "http://tempuri.org";
Parameter USECLASSNAMESPACES = 1;
Method CheckData(party As tv.party) As %Integer [ WebMethod ]
{
Quit party.to.Count()
}
}

Then I created SOAP web client using SoapUI and sent following request with 3 'to' items:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:s="http://tempuri.org">
   <soapenv:Header/>
   <soapenv:Body>
      <s:CheckData>
         <s:party>
            <s:to name="mohan" address1="India"/>
            <s:to name="sujay" address1="USA"/>
            <s:to name="tomas" address1="Europe"/>
       </s:party>
      </s:CheckData>
   </soapenv:Body>
</soapenv:Envelope>

And I received the correct response:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:s="http://www.w3.org/2001/XMLSchema">
   <SOAP-ENV:Body>
      <CheckDataResponse xmlns="http://tempuri.org">
         <CheckDataResult>3</CheckDataResult>
      </CheckDataResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

If you send as your code, we can check what is not working as expected.

Tomas Vaverka · Oct 11, 2016 go to post

What kind of users it is? Are you talking about Caché users created/seen in Management Portal > Security > Users?  

Tomas Vaverka · Oct 7, 2016 go to post

The %Stream.GlobalBinary/GlobalCharacter doesn't support to add/save Attributes. You would need to use the %Library stream classes to be able to do it - %Library.GlobalBinaryStream/%Library.GlobalCharacterStream.

The reason is in difference how the ID of the stream is created and saved in persistent data. For %Stream.GlobalBinary/GlobalCharacter only the ID number is stored in database, while for %Library.GlobalBinaryStream/%Library.GlobalCharacterStream the full OID is saved to database and it contains also name of the global (=stream location) and type of the stream. The ID of such stream contains also all added attributes.

Here is an example:

 Class Test.streamtest Extends %Persistent
{
Property Stream1 As %Stream.GlobalCharacter;

Property Stream2 As %GlobalCharacterStream;

ClassMethod FillData() As %Status
{
  // kill existing data
 DO ##class(Test.streamtest).%KillExtent()
 KILL ^Test.streamtestS
  // create a new record
 SET obj=##class(Test.streamtest).%New()
 DO obj.Stream1.Write("Stream1 data")
 DO obj.Stream2.Write("Stream2 data")
 DO obj.Stream2.SetAttribute("ContentDisposition","inline; filename=test.txt")
 SET sc=obj.%Save()
  // display id of streams
 SET id1=obj.Stream1.%Id() ZWRITE id1
 SET id2=obj.Stream2.%Id() ZWRITE id2
  // display stored data
 WRITE ! ZWRITE ^Test.streamtestD,^Test.streamtestS
 QUIT sc
}

}

And result:

USER>d ##class(Test.streamtest).FillData()
id1=1
id2=$c(0,24,1,19,1)_"^Test.streamtestS"_$c(3,4,2)_"3"_$c(1)_"1"_$c(1,20,1)_
"ContentDisposition"_$c(27,1)_"inline; filename=test.txt"
 
^Test.streamtestD=1
^Test.streamtestD(1)=$lb("","1",$lb($c(0,24,1,19,1)_
"^Test.streamtestS"_$c(3,4,2)_"3"_$c(1)_"1"_$c(1,20,1)_
"ContentDisposition"_$c(27,1)_"inline; filename=test.txt","%Library.GlobalCharacterStream"))
^Test.streamtestS=2
^Test.streamtestS(1)=1
^Test.streamtestS(1,0)=12
^Test.streamtestS(1,1)="Stream1 data"
^Test.streamtestS(2)=1
^Test.streamtestS(2,0)=12
^Test.streamtestS(2,1)="Stream2 data"
Tomas Vaverka · Oct 5, 2016 go to post

Parsing is not difficult using the $PIECE COS function:

 

test
parseURLQuery(sURL,data) PUBLIC {
  Do ##class(%Net.URLParser).Parse(sURL,.aComponents)
  Set query=aComponents("query")
  For i=1:1:$Length(query,"&") {
    Set qry=$Piece(query,"&",i),name=$Piece(qry,"=",1),value=$Piece(qry,"=",2)
    Set data(name)=value
  }
  Quit
}

 

And result:

 

USER>Set url="http://www.intersys.com/main.csp?QUERY=abc&NAME=tomas#anchor"
 
USER>Do parseURLQuery^test(url,.data) ZWrite data
data("NAME")="tomas"
data("QUERY")="abc"

 

You may also consider encoding of given page, because the URL query can be encoded and in different charset (e.g. UTF-8), so in such case you should also decode the value and translate it from given charset:

   Set data(name)=$zconvert($zconvert(value,"I","URL"),"I","UTF8")
Tomas Vaverka · Oct 3, 2016 go to post

For file character streams you need to specify TranslateTable property, which is internal translation table based on your locale. 

For translation to utf-8 you need to set:

 set  fileStream   ##class( %FileCharacterStream). %New()
 set  fileStream .Filename  fileLocation

 set fileStream .TranslateTable ="UTF8"

 set status  fileStream .CopyFromAndSave (rtn .Code )

It should help.

Tomas Vaverka · Sep 21, 2016 go to post

You can use Caché Studio > New Property wizard to get correct definition of "collection" property, select options - "A collection of Type" = array/list , "Containing elements of type" = %Date.

It then creates a definition:

Property DOB As array Of %Date;

You can set and access array data as follows:

ClassMethod Test()
{
 // Get values
 Set obj=##class( collect.arraylist).%New()
 Do obj.DOB.SetAt($h,"key1")
 Do obj.DOB.SetAt($h-1,"key2")
 Do obj.DOB.SetAt($h-2,"key3")
 
 // Get values
 Write "Count: ",obj.DOB.Count(),!
 Set key=""
 Set date=obj.DOB.GetNext(.key)
 IF key'="" Write "Data:",!
 while (key'="")
   Write key,?5,$zd(date),!
   Set date=obj.DOB.GetNext(.key)
 }
 
 Write !,"Data at key2: ",$zd(obj.DOB.GetAt("key2"))
 Quit
}

Tomas Vaverka · Sep 21, 2016 go to post

You can use Caché Studio > New Property wizard to get correct definition of "collection" property, select options - "A collection of Type" = array/list , "Containing elements of type" = %Date.

It then creates a definition:

Property DOB As array Of %Date;

You can set and access array data as follows:

ClassMethod Test()
{
 // Get values
 Set obj=##class( collect.arraylist).%New()
 Do obj.DOB.SetAt($h,"key1")
 Do obj.DOB.SetAt($h-1,"key2")
 Do obj.DOB.SetAt($h-2,"key3")
 
 // Get values
 Write "Count: ",obj.DOB.Count(),!
 Set key=""
 Set date=obj.DOB.GetNext(.key)
 IF key'="" Write "Data:",!
 while (key'="")
   Write key,?5,$zd(date),!
   Set date=obj.DOB.GetNext(.key)
 }
 
 Write !,"Data at key2: ",$zd(obj.DOB.GetAt("key2"))
 Quit
}