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
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
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
}You can also use the open exchange solution from Lorenzo Scalese :
https://openexchange.intersystems.com/package/IO-Redirect
Thanks @Danny Wijnschenk & @Robert Barbiaux !
^SPOOL is a great global !!!
welcome to my world
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{11USER>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{11As 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.
Therefore it's good practice to start with
Kill ^SPOOL($J) Open 2:$J Use 2 .....
as we did in 1978
^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.
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.
^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.
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).