Written by

CEO at Ellipse
Question Pierre LaFay · Feb 17, 2024

Get ZW display in a variable

Hello everyone,

I'm looking for a way to retrieve the result of the ZW command in a global, is this possible?

Comments

Danny Wijnschenk · Feb 17, 2024

You can use the spool device : 

Set a(100)="test"
Set a(100,100)="encore"
Open 2 Use 2 zwrite a Close 2
The global ^SPOOL will contain the contents of the zwrite
0
Robert Barbiaux  Feb 19, 2024 to Danny Wijnschenk

Yes, ^SPOOL is the simplest way to achieve this. If you need a string rather than a global, you can just get all lines from ^SPOOL, for example :

ClassMethod ZWriteToString() As%String
{
 #Dim result as%String#Dim i,lineCount as%Integerkill^SPOOL($j)
 open2:$juse2zwrites result=""s lineCount=$select($data(var):$za-1,1:$za-2)
 close2for i=1:1:lineCount s result=result_^SPOOL($j,i)	
 return result
}
0
Alexey Maslov  Feb 22, 2024 to Pierre LaFay

Yeah, but it should be used with precautions. Let's see what happens when two processes access spooling device concurrently: 

USER>f {q:'($zh\1#20)} k a o 2 f i=1:1:10 {s a(i)=i*100} u 2zw a c 2; process #1
USER>s i="" f  {s i=$o(^SPOOL(1,i),1,line) q:i=""w line} ; look inside ^SPOOL(1)...
a(1)=100
a(2)=200
a(3)=300
a(4)=400
a(5)=500
a(6)=600
a(7)=700
a(8)=800
a(9)=900
a(10)=1000
{66892,65205{11
USER>f {q:'($zh\1#20)} k a o 2 f i=1:1:10 {s a(i)=i} u 2zw a c 2; process #2
USER>s i="" f  {s i=$o(^SPOOL(1,i),1,line) q:i=""w line} ; look inside ^SPOOL(1)...
a(1)=100
a(2)=200
a(3)=300
a(4)=400
a(5)=500
a(6)=600
a(7)=700
a(8)=800
a(9)=900
a(10)=1000
{66892,65205{11

As you can notice, one process's output suppressed the other's one. To avoid it, firstly RTFM: OPEN and USE Commands for Spooling Device, and implement some synchronization pattern, e.g. 

USER>f {q:'($zh\1#20)} s docIdx=$i(^SPOOL) k a o 2:(docIdx) f i=1:1:10 {s a(i)=i*100} u 2zw a c 2; process #1
USER>s i="" f  {s i=$o(^SPOOL(docIdx,i),1,line) q:i=""w line}
a(1)=100
a(2)=200
a(3)=300
a(4)=400
a(5)=500
a(6)=600
a(7)=700
a(8)=800
a(9)=900
a(10)=1000
{66892,66645{11{
USER>f {q:'($zh\1#20)} s docIdx=$i(^SPOOL) k a o 2:(docIdx) f i=1:1:10 {s a(i)=i} u 2zw a c 2; process #2
USER>s i="" f  {s i=$o(^SPOOL(docIdx,i),1,line) q:i=""w line}
a(1)=1
a(2)=2
a(3)=3
a(4)=4
a(5)=5
a(6)=6
a(7)=7
a(8)=8
a(9)=9
a(10)=10
{66892,66645{11{

Each process has got it's own output in ^SPOOL(docIdx) now. This approach works if every consumer of spooling facility follows the same pattern; incrementing ^SPOOL is just an easiest approach, while it would be better avoid touching system globals and increment something else according to your taste.

0
Robert Cemper  Feb 22, 2024 to Alexey Maslov

Therefore it's good practice to start with

Kill ^SPOOL($J) Open 2:$J Use 2 .....
as we did in 1978

0
Alexey Maslov  Feb 23, 2024 to Robert Cemper

^SPOOL(docIdx) approach allows spooling sharing across ECP network, while ^SPOOL($j) does not :)

%IS is an utility which allows to choose devices by CHUI routines users and %SPOOL utility can manipulate with spool files opened using the %IS utility only.

It seems that initial purpose of spooling facility has gone with such a users and such a printers (strictly character based, w/o ability of font selection, etc), while its usage still can be actual in rather exotic cases like this one.

0
Enrico Parisi · Feb 22, 2024

And last but not least, don't forget to cleanup.

Who/when ^SPOOL is cleaned?
What part should I clean? Just a shameless Kill ^SPOOL ?

IMHO, in addition to @Alexey Maslov notes, that's another (good) reason why device 2, the spool device, has been log forgotten (and buried) for good.

0
Robert Barbiaux  Feb 22, 2024 to Enrico Parisi

^SPOOL is not buried 😁, it is well documented, along with %IS and %SPOOL utilities.
It is simple and effective when used to it's intended purpose, that is, spooling text written to the currently in use device.

0
Mike.W · Feb 26, 2024

Hi,

After many years of development and support I've become wary of one-line requests. 🤔 I wonder why you need this (Five whys - Wikipedia). For example, if you are trying to debug a mysterious state in a background job then maybe you just need "D LOG^%ETN" to store the variables in the error log. Or, at least you could look in there for ways to use $ORDER and $QUERY  to scan local variables without involving ^SPOOL (or, as we once did, opening a file to ZW to, closing, and then reading it back).

0