Appendix 1 - PixieWeb Documentation: 

 Description, Properties and Methods


"Pixie" is used as the example object name throughout this document.
Method explanations have an example call as a heading eg
Call Pixie.ExecuteET(request, expected_response)
Property explanations have just the lone keyword as a heading eg
ResponseRaw


Which Class (Object-providing file ) ?

"PixieWMA.clsAgent"   - latest version, use in most cases
"PixieSerialA.clsAgent" -  serial line version, for use with older servers or for dial-up.
"PixieWeb.clsAgent"  -  older version, included for backwards compatibility, or for non-MV servers eg "FilePro"

Note, for those upgrading, the new main active file is "PixieWMA.dll" with the most common function used being "ExecuteET".
But, the PixieWeb package also installs a "PixieWeb.dll" designed for backward compatibility with your existing scripts and applications.  "PixieWeb.dll" --> "PixieWeb.clsAgent" delivers best performance with the new "ExecuteET" function but it also supports the old "Execute" syntax.

Creating the object

For ASP scripts:

Dim Pixie
Set Pixie = Server.CreateObject("PixieWMA.clsAgent")

We use "Pixie" as the object name, but you can call it anything you like as long as you are consistent.

"Pixie" can also be stored as a "Session Object", which gives it a continuous PICK user session matching the IIS WebServer User session.  This is especially useful with FBF interactive apps using XML-Download or IFRAMEs  For more details refer Chapters 6 and 7.  The supplied "Terminal Emulators" are the simplest examples of this principle in action.


Making and validating a connection, example first:

'-- Start of example code
Pixie.Port = 23
Pixie.Host = "127.0.0.1"
Pixie.TimeOut = 4
Call Pixie.Connect("{AUTO}")  
Call Pixie.ExecuteET("myusername", "password:")
Call Pixie.ExecuteET("mypassword", "<<< Pick Systems")
Call Pixie.ExecuteET("term mm-mon", ":")
Call Pixie.ExecuteET("echo off", ":")

'-- Simplified validation to show the general idea.
'   In real life, we do several steps then check the state
If Pixie.State = "ERROR" Then
    s = "<HTML><BODY>"
    s = s & "ERROR in connecting to Server, Please try again"
    s = s  & "</BODY></HTML>"      
    Response.Write s           
    Response.End
End If
'-- End of example code
Port	 Integer, TCP/IP port, usually 23

Host	 String, can be dot address as above, or network name
     eg "ntserver"
     
CommPort	 (PixieSerialA) Integer, Serial Port number, default is 3

Settings	 (PixieSerialA) String, default is "19200,N,8,1"
     Usually the only alteration needed is the first value, which
     you can tune higher for fast hosts or newer modems,
     or reduce eg to "9600,N,8,1" for older hosts.

TimeOut	 Numeric with decimals allowed, eg 4, 8, 2.5 
     Default = 3 sec
     Time in seconds allowed to wait for PICK responses.
     NOTE, in a significant change for ver 3.2 December 2000,
     the TimeOut starts counting from the most recent chunk
     of data received from PICK etc.  
     IF for example, a long	 report takes 12 sec to output, 
     AND the TimeOut = 4, THEN 
         The TimeOut error fires at 12 + 4 = 16 seconds. 
         ie 4 seconds after PICK stops feeding out  
         chunks. You can choose to ignore the error 
         and use the value Pixie.ResponseRaw,                  
         and this can be a good technique 
         in "screen-scraping" situations.
     END IF

State    Returns a string to let you check the state of 
     the object, possible returned values are: 
	 "STARTUP" = not connected to PICK etc 
	 "TCL"     = connected and last execution was successful
	 "PAGE"    = working through a page-by-page response
	 "ERROR"   = error on last execution

     PixieWeb does NOT stop when in a state of "ERROR",
     rather it will happily allow you to try to execute
     something else.
     
Call Pixie.Connect(expected_response)
     "expected response" is a string, case-sensitive by default although
     you can change that with Pixie.ExecuteCompareMethod = 1
     "{AUTO}" is a special argument to switch on automatic detection. eg:
     Call Pixie.Connect("{AUTO}")
     If auto-detection does not work, try some characters 
     from the server connection response.
     Eg "er" covers "user id", "user name", "kernel"

Call Pixie.ExecuteConnect(request_to_server,  expected_response)
     Special for PixieSerialA.  When using a modem for dial-ups you connect
     in 2 stages.  Pixie.Connect gets you to the modem, then you need
     Pixie.ExecuteConnect for first contact with host when you dial the number. 
     eg
     Set Pixie = Server.CreateObject("PixieSerialA.clsAgent")
     Pixie.TimeOut = 4
     Pixie.CommPort = 2
     Pixie.Settings = "115200,N,8,1"   '-- fast modern modem
     Call Pixie.Connect("")
     'Now initialise the modem, modems reply to this with "OK"
     Call Pixie.ExecuteET("AT&F&C1&D2", "OK")
     Call Pixie.ExecuteET("ATE1S0=0", "OK")
     If Pixie.State = "ERROR" Then Call ErrorHandler("Modem not available")
     'If this machine has more than one modem then   
     'we can use a loop to work through the possible CommPorts
     '
     'Ready to make the call, give lots of timeout for dialling
     'Make sure the ASP script timeout is generous, at least 40 sec
     Pixie.TimeOut = 40
      
     Call Pixie.ExecuteConnect("ATDT3338885555", "{AUTO}")   
     If Pixie.State = "ERROR" Then Call ErrorHandler("Dial-up failed")
     Pixie.TimeOut = 8

(Deprecated: Use ExecuteET)

Call Pixie.Execute(request_to_server,  expected_response)
 Or
sResponse = Pixie.Execute(request_to_server,  expected_response)
     Older syntax provided only for backward compatibility 
     and only by creating your object from class "PixieWeb.clsAgent".
     Use Pixie.ExecuteET for all new work.

Call Pixie.ExecuteET(request_to_server,  expected_response)
 Or
sResponse = Pixie.ExecuteET(request_to_server,  expected_response)
     Both arguments are strings.
     "expected_response" is any text which you would
     expect to find at or near the end of a successful response.  
     We suggest "</TX>" within PICKBASIC as a 
     standard end-of-transmission tag.  When working in TCL you can
     often use ":" for PICK and ">" for UNIVERSE.
	 
     NOTE that by default, Pixie will add a carriage return CHAR(13) 
     to the end of any request but you can suppress that 
     by ending your request string with the escape {NOCR}
     eg, to send a CTRL-BREAK
     Call Pixie.ExecuteET(Chr(3) & "{NOCR}", "*")
	 
     The new function syntax "sResponse =  ..."  gives a result in 
     one process call instead of the old 2-step. 
     The "Call ..." syntax is useful where you do not need results at 
     every conversation step. It will also be a preferred syntax
     of Microsoft's new "dotNET" technologies.
	
Call Pixie.ExecuteTX(request_to_server)
  Or 
sResponse = Pixie.ExecuteTX(request_to_server)
     Similar to ExecuteET, with an  expected_response of "</TX>".
     but it ALSO returns a string extracted from between 
     the  "<TX>" and "</TX>" tags. 
     eg
     raw string = "Debug: ItemID=NN8088<TX>Michael</TX>"
     ExecuteTX returns "Michael"
     eg
     raw string = "John Calder</TX>"
     ExecuteTX returns "John Calder"
     
Call Pixie.ExecutePM(request, expected1 [, expected2 [, ...]])
Or
sResponse = Pixie.ExecutePM(request, expected1 [, expected2 [, ...]])
     Similar to ExecuteET, but you can give a number of 
     alternative expected responses.  This is useful
     when getting data from legacy apps where you do not
     have source code access to do web-friendly changes.
     eg:
     sResponse = Pixie.ExecutePM(sRequest, "(Y/N)", "F9=Find", Chr(27) & " =   ")

Executing commands to MV and handling MV responses

Methods/Functions

Call Pixie.ExecuteET(request,  expected_response)
sResponse = Pixie.ExecuteET(request,  expected_response)
Call Pixie.ExecuteTX(request)
sResponse = Pixie.ExecuteTX(request)
     See above

Call Pixie.ExecuteRaw(request)
     "Request" is a string
     With ExecuteRaw, Pixie does NOT check that a 
     response from PICK is complete.
     It is up to you to code analysis of the
     raw response into your ASP or other code.
     We use this ourselves for requests which could result in 
     a variety of responses, BUT we nearly always then find
     a way of using the more efficient ExecuteET or ExecutePM instead.

Call Pixie.ExecutePage(request,  expected_response,   lines_per_page)
Call Pixie.ContinuePage           
     "Lines_per_page" = 25 on every MV Engine we have worked with so far.
     "ExecutePage" and "ContinuePage" work together to handle 
     very long expected responses.  You can stream a response
     to the user 1 page at a time.  This makes it possible for
     very large responses to appear on the user's screen as they
     come from PICK rather than waiting for the entire response 
     to arrive before displaying it. 
     This also lets you set an upper limit to
     how much data you are prepared to let a user have before 
     issuing "Q" or CHAR(24) to put a stop to the stream.
	 
Call Pixie.ResponseCleanup
     Removes non-printing characters eg CHAR(0), CHAR(1)
     from Pixie.Response

Properties

ResponseRaw
     Returns a string giving the "raw response" from PICK.
     Like all TCP/IP servers, PICK sends larger strings by
     the "packet" method which breaks them up into pieces
     called "chunks".  So the value Pixie.ResponseRawmay
     be incomplete.  PixieWeb therefore gives you the
     ExecuteET etc methods to do a test-for-completeness for you
     and give you the nicely processed Pixie.Response

Response Returns a string giving a complete PICK response 
     already validated for you by the ExecuteET, ExecuteTX,
     ExecutePage or ContinuePage methods.  
     If validation fails, Pixie.Response returns an error 
     message giving details of the problem, while 
     Pixie.State returns "ERROR"
     Pixie.ResponseRaw returns whatever string has been received.

ExecuteCompareMethod
     Sets whether end-of-transmission is to be recognised
     by a case-sensitive comparison, eg
     whether "</tx>" recognised as an alternative to
     "</TX>". Default value is 0,
     giving case-sensitive comparisons. 
     The alternative value is 1
     eg, to allow case-insensitivity for end-of-transmission marks:
     Pixie.ExecuteCompareMethod = 1  
property = Pixie.ExecutePS("propertyname")
     A device to make future expansion smoother by letting us add properties 
     without changing the external "COM Interface" structure.
     At present only one propertyname "PATH" is implemented, where 
     PixieWMA.dll reports back what folder it is in. eg
     sPath = Pixie.ExecutePS("PATH")
     A typical returned value would be "C:\Program Files\PixieWeb\"
     Note that such PATHs include "\" on the end.


Data Read/Write and manipulation routines. 

Until now (June 2001), we always wrote custom backservers in PICKBASIC for data handling.  But some users have been asking for a way for VB etc to be a one-stop-shop for all operations.  Our experience with another of our products, PixieEditor, has given us the idea of a PICKBASIC "Universal Backserver Program", now supplied with this package in source code form as   PX.BACKSRV.   It should be clear from its code that while you could run everything "raw" with Pixie.ExecuteTag, the conversation strings need to be heavily "escaped", "delimited" and "tagged" and so we have provided friendly  functions "PxRowset", "RRead", "WWrite" etc with similar syntaxes to their traditional PICKBASIC equivalents.  eg the INPUT buffers in PICK D3 and UNIVERSE can handle 4096 bytes max at each pass so our WWrite function automatically measures the data you want to Write and if longer than 4096 bytes it will break it up and feed it in for you via the necessary number of conversational steps.

For ALL of these functions, you must get PX.BACKSRV running first, usually by login to TCL then:

If Pixie.ExecuteTag("PX.BACKSRV", "<TXA>", "</TXA>") <> "OK" Then
  Call ErrorHandler("Backserver not available")
End If

PICK engines, eg D3, need an extra configuration step to give well-behaved output.
Call Pixie.ExecuteTag("PICK" & Chr(254) & "1", "<TXA>", "</TXA>")
Ultimate Plus also has a custom step:
Call Pixie.ExecuteTag("ULTPLUS" & Chr(254) & "1", "<TXA>", "</TXA")

File RRead-ing and WWrite-ing , general syntax:
Pixie.RRead Item, FileName, ItemID
or
Call Pixie.RRead(Item, FileName, ItemID) 'VB7 will require this syntax

or
If Not Pixie.RRead(Item, FileName, ItemID) Then sMsg =  Pixie.ErrorDetail
similar general syntax for: RReadU, WWrite, WWriteU

RReadV
general syntax:
Pixie.RReadV Value, FileName, ItemID, FieldNumber
or
If Not Pixie.RReadV(Value, FileName, ItemID, FieldNumber) Then ...
similar syntax for: RReadVU, WWriteV, WWriteVU

Delete to delete an item(record) from a file(table).  General syntax:
Call Pixie.Delete(FileName, ItemID)
or

If Pixie.Delete(FileName, ItemID) = False Then ...

PxRowset takes a PICK etc query sentence and returns the result as a 2-dimensional "SelectResult"
Or, you can query for only a list of ItemIDs and work through that with RRead statements giving
a similar way of working to the "Select list .... ReadNext" of PICKBASIC.
boolSuccess = PxRowSet(FileName [[[[,FieldCount], Query], FieldList], RetTimeOut ])

PxRowset creates  Pixie.SelectResult(Field, Rowfrom where you can read values.
Field is zero-based, Row is one-based.
FieldCount is 1 by default, giving a list of keys where Field is always 0.
Query is an optional SELECT or SSELECT query in the syntax of your MV Engine.
FieldList (1) for raw data is a list of attribute numbers separated by CHAR(253) marks eg "4ý6ý7ý13".
         OR (2) can be a LIST statement including dictionary item names, eg "LIST CUST CONTACT TEL FAX"
         in which case PX.BACKSRV looks up dictionary processing codes and applies them.
         When using LIST, give 0 as the argument for FieldCount.
RetTimeout is an optional Timeout in seconds for this function because you may need to give complex queries
more time than your usual timeout.

Pixie.SelectUbound(1) gives the highest number column.  This is the number-of-columns-minus-one because columns count from 0.
Pixie.SelectUbound(2) returns the number of rows.  Rows do count from 1.  There is a Row 0 but this is used only when "FieldList" starts with "LIST" and it is used to return additional column information from the dictionary, eg column width.

Examples:

' Using a "Select List" approach
Call Pixie.PxRowSet("PROD", 1, "SELECT PROD WITH A1 = ""[MOUSE]"" ")
For i = 1 To Pixie.SelectUbound, 2)
  Call Pixie.RRead(sRow, "PROD", Pixie.SelectResult(0,i))
  Response.Write "<tr><td>Pixie.SelectResult(0,i)</td>"
  Response.Write "<td>Pixie.Extract(sRow,1)</td>"
  Response.Write "<td>Pixie.Extract(sRow, 4)</td>"
  Response.Write "<td>Pixie.Extract(sRow, 5)</td></tr>"
Next

'Using the SelectResult directly. 
'Note that if the attribute selection arg 4 is used then
'its number of multivalues must match arg 2 FieldCount
Call Pixie.PxRowSet("PROD", 4, "SELECT PROD WITH A1 = ""[MOUSE]"" ", "0ý1ý4ý5")
For i = 1 To Pixie.SelectUbound(2)
   Response.Write "<tr><td>Pixie.SelectResult(0,i)</td>"
   Response.Write "<td>Pixie.SelectResult(1,i)</td>"
   Response.Write "<td>Pixie.SelectResult(2,i)</td>"
   Response.Write "<td>Pixie.SelectResult(3,i)</td></tr>"
Next

The first approach is better for very large quantities of data because it breaks up the conversation into a greater number of timeout-manageable steps.  However for one-shot retrieval in web apps, the second approach will be faster and easier in most circumstances.  Success depends heavily on having well designed queries that run reasonably fast.  You can check them first from TCL using a trad terminal. A good safety net for web apps is to add limiting clauses like " SAMPLING 1000" to your queries.  Be warned that the "SAMPLING" syntax varies slightly between different PICK-like engines.

Note the subtle but effective error handling built into the above.  If   Pixie.PxRowset should fail then
Pixie.SelectUbound(2), which returns the number of rows, will return 0,
and so the For .. Next will not happen.

Note that VBSCRIPT and the new VB7 insist on  Next by itself rather than the Next i we know and love.

For a good example of SelectResult in action, and its alternatives, look at the source code of the "PixieExcelW.xls" example spreadsheet provided.  Chapter 8  gives a code commentary on "PixieExcelW.xls".

(Deprecated: use SelectResult)
Pixie.SelectArray
- returns a 2-dimensional array after Pixie.Rowset is run. But it can be slow to return after a large query and some environments have problems passing arrays across object boundaries, eg VBSCRIPT fails with SelectArray. It is included for backwards compatibility only: use Pixie.SelectResult instead.


Escape and Descape functions: use to handle binary data and some languages.

PICK etc have CHAR(251) to CHAR(255) as reserved characters, used to separate
records, fields and subvalues(multivalues) of data.  This can cause problems with languages
eg Russian, German where such characters can appear in documents for storage.  Images and
other binary data stored as ANSI strings can also have problems.
PxEscape changes "problem" characters into 2 characters, the first one being "`", the back-apostrophe.
The back-apostrophe itself becomes doubled to "``".

The source code is no secret and is a good way of documenting the method.  You may choose to code your own version based on this idea, eg if you only have a small number of difficult characters, or if you have other escaping systems you want to be compatible with.

Public Function PxEscape(ByVal sItem As String _
, Optional ByVal bQuote As Boolean = False) As String
If InStr(sItem, "`") > 0 Then sItem = Replace(sItem, "`", "``")
If InStr(sItem, Chr(255)) > 0 Then sItem = Replace(sItem, Chr(255), "`*")
If InStr(sItem, Chr(254)) > 0 Then sItem = Replace(sItem, Chr(254), "`^")
If InStr(sItem, Chr(253)) > 0 Then sItem = Replace(sItem, Chr(253), "`]")
If InStr(sItem, Chr(252)) > 0 Then sItem = Replace(sItem, Chr(252), "`[")
If InStr(sItem, Chr(251)) > 0 Then sItem = Replace(sItem, Chr(251), "`~")
If InStr(sItem, Chr(13)) > 0 Then sItem = Replace(sItem, Chr(13), "`C")
If InStr(sItem, Chr(10)) > 0 Then sItem = Replace(sItem, Chr(10), "`L")
If bQuote Then
  If InStr(sItem, "\") > 0 Then sItem = Replace(sItem, "\", "`B")
  If InStr(sItem, Chr(34)) > 0 Then sItem = Replace(sItem, Chr(34), "`Q")
  If InStr(sItem, "'") > 0 Then sItem = Replace(sItem, "'", "`A")
End If
PxEscape = sItem
End Function

sProcessed = PxEscape(string_to_process  [, quote_process_flag])
  Use PxEscape to process data before storing in an MV engine.
  The optional flag can be set to True to do additional escaping on the quotation marks.
  The quote_process_flag is for PICK database engines where the fastest way of feeding data in
  is via the TCLREAD technique, also known as SENTENCE(), but that technique is intolerant
  of quote marks and needs them escaped. This also explains
  why we have used back-apostrophe as our escape character rather than
  the backslash beloved of Java and C aficionados.

sRetrieved = PxDescape(raw_retrieved_string_from_MV)
  Use PxDescape to "unpack" or "decode" data previously processed with PxEscape

Example of use
  Call Pixie.WWriteV(PxEscape(sData), "PROD", sItemID, 1)

Note that Dynamic Variable strings should not be escaped because that would mangle the separator marks.  Instead apply PxEscape to separate attributes(fields, segments) within such strings.  Also be careful with WWrite; PxEscape usually goes best with WWriteV.


"Screen Scrapers" - special functions for reading output of terminal programs

Example

Pixie.FormAnalyse 
Pixie.ItemTop = 4 
Pixie.ItemLeft = 22 
Pixie.FormItemGet 
sDescription = Pixie.Response

Methods

Call Pixie.FormAnalyse
     Call this first before calling FormItemGet.
     Analyses the PICK response by tagging all separate text
     strings with their associated @(x,y) co-ordinates

Call Pixie.FormItemGet
     Loads a text string into Pixie.Response based on what
     ItemTop (y co-ordinate) and ItemLeft (x co-ordinate) location
     you nominate to look for it. Properties
	 
ItemTop  Integer. y co-ordinate
ItemLeft Integer. x co-ordinate
     Use these properties to nominate where on a terminal
     screen you want to read from.  You can find out what
     these values should be by:
     EITHER running the Terminal program with PixiePeekaboo
	 OR looking in its DATABASIC code for the @(x,y) functions

WebServer file Functions: 
FileGetText, FileGetStream, LogBook

byteArray = Pixie.FileGetStream(   filename_with_full_path)
         Get disk file as an array of bytes.  Useful for
         detailed manipulation and control of binary files
         such as page image and sounds, or executable downloads.
s = Pixie.FileGetText(   filename_with_full_path)
         Get disk file contents as a string.  
         Especially useful for keeping control of the 
         issuing of .htm pages-as-templates by feeding them out 
         through a controlling .asp script.
         The <% = myVariable %> facility in IIS does much the
         same thing, but FileGetText gives flexibility like:
         *  Select from several templates depending on
            the situation.
         *  Enables use of the nice Response.End statement
            which does not work with the <% = myVariable %>
            technique.
         *  Use this within your compiled ActiveX .dll
            web app to get a "webclass" effect without
            the ugly "webclass" baggage.
Call Pixie.LogBook(   log_stub_name, log_message)
         Keep logs of your site visitors and their activities.
         The "log stub name" is a path plus the generic log file name.
         PixieWeb adds suffixes .. "book.txt", "bak1.txt", 
         "bak2.txt", "bak3.txt"
         eg with a "stub" of "C:\InetPub\wwwRoot\Log", you will get
         files "Logbook.txt", "Logbak1.txt", "Logbak2.txt", "Logbak3.txt"
         Logbooks are allowed to reach a max size of 32K, the limit for 
         easy reading with "Notepad", before they are moved to bak1, with 
         bak1 moving to bak2, bak 2 moving to bak3, and the former contents
         of bak3 being discarded.
eg Use of LogBook for privilege-controlled file download.

sUserID = Session("UserID")
If Vartype(sUserID) <> vbString Then sUserID = ""
If sUserID > "" Then
  Call Pixie.LogBook(Session("LogStub"), sUserID & " download Maestro") 
  Response.Redirect "http://www.mysite.com/downloads/Maestro.zip"       
Else
  'Enforce login before allowing download
  s = Pixie.FileGetText(Session("Folder") & "login.htm")
  Response.Write s
End If


String and other utility functions

SegmentReplace equiv of VB6 "Replace" for those on VB5, Word 97 and below.
Syntax:
sTextNew = SegmentReplace(sTextOriginal, sFind, sReplace)
eg
sSpacesRemove = SegmentReplace("47,85,76, 554, 33,12", " ", "")
sDynamicArray = SegmentReplace(sSpacesRemove, ",", Chr(254))
results
sSpacesRemove <-- "47,85,76,554,33,12"
sDynamicArray <-- "47þ85þ76þ554þ33þ12"


Sleep x 
or Call Sleep(x)   idle app for x seconds
Delay x  or Call Delay(x)   same as Sleep, idle app for x seconds


Index
   returns position in a string of the nth occurrence of a substring, eg
n = Index(s, "*", 4)


Matches
    returns True or False depending on whether or not the string matches a formatting code.
Note that PixieEngine requires text constants to be quoted in single quotes.
eg
b = Pixie.Matches(s, "0N")
eg
If Not Pixie.Matches(s, "0N'.'2N") Then ...  useful for testing user input of money amounts, here we are testing for any numerical input "0N", then a decimal point, then 2 numeric digits "2N".
Formatting Codes:
N = Numeric only, A = Alphabetical only,  X = accept any character
0 (zero)= any number of characters; other integer values set number of characters.
Examples:
b = Pixie.Matches("kbl%&* blah blah blah FRED876", "0X'FRED'3N")
b <-- True
b = Pixie.Matches("1234567890123-1234-12", "13N'-'4N'-'2N")
b <-- True


Num  
returns True or False depending on whether argument is numeric. eg Num("89") returns True
eg
If Pixie.Num(s) Then ...


Dcount  
returns number of subsections in a string as defined by a given delimiter. The delimiter can be of more than one character.   Eg:
n = Pixie.DCount(s, " ")


Field  
returns a substring, given delimiter and number. The delimiter can be of more than one character. eg:
sTRow = Pixie.Field(s, "<tr>", 4)


Col1() , Col2()   
functions returning extra information from the last Field function: Col1() and Col2() give positions-in-string of the characters immediately before and after any found substring. Largely obsolete, functions like SegmentReplace or the new "Replace" in VB6 can handle most of the operations these were intended for.


Extract  
returns substrings of "dynamic variables" eg
sSub = Pixie.Extract(s, 4)  equivalent to modern MV s<4>
sSub = Pixie.Extract(s, 2, 5)    equivalent to modern MV s<2, 5>

RReplace    returns result of replacing a substring of a "dynamic var iable" eg
s = Pixie.RReplace(s, 4, sNew)
s = Pixie.RReplace(s, 4, 7, 2, sNew)

Insert    returns result of inserting a substring into a "dynamic variable"  eg
s = Pixie.Insert(s, 4, 3, sNew)

Dylete   function "Dynamic Array Delete"  returns the result of deleting a substring from a dynamic array. 
eg
s = Pixie.Dylete(s, 3) 
s = Pixie.Dylete(s, 1, 5)
s = Pixie.Dylete(s, 4, 7, 2)

eg
s = "111þ222þ333þ444"
sDel = Pixie.Dylete(s, 3)
'
Result: sDel  <-- "111þ222þ444"

NOTE: Differences between these emulations and some MV behaviours:
1. As of June 2000, RReplace, Insert and Dylete only work down to
the CHAR(252) level. The "text mark" CHAR(251) is not yet supported.
eg
s = Pixie.Insert(s, 4, 3, 3, sNew) - OK
s = Pixie.Insert(s, 4, 3, 3, 1, sNew) - NOT SUPPORTED


2. Arguments of zero used as dummy placeholders are not yet supported.
eg
s = Pixie.Insert(s, 4, 3, sNew) - OK
s = Pixie.Insert(s, 4, 3, 0, sNew) - NOT SUPPORTED


Locate returns True or False depending on whether or not a substring is found in a string, or a sub-substring found in a substring. 
Emulating Locate using VB was especially challenging because of the variable number and type of arguments.  This led us to use "IN", "BY" and "SETTING" as dummy arguments to flag special meanings for their following arguments. The argument following "IN" is the string or substring to look in. The argument following optional "BY" gives a flavour of assumed sorting of the substrings when looking for a position to fit a new one into. The argument following "SETTING" returns the position into which the substring-to-look-for fits, or should fit considering any "BY".

Syntax:
b = Pixie.Locate(sFind, "IN", sStringIn [,iOccurrence][,"BY", sSortCode][, "SETTING", iPos])
Where
b           -  returned Boolean value: True or False
sFind       -  substring to find
"IN"        -  placeholder
sStringIn   -  dynamic array or attribute in which to look for sFind
iOccurrence -  optional, default = 1, occurrence to take
               if sFind is expected to repeat
"BY"        -  placeholder, tells the function that sSortCode follows.
               Also switches on a method that if sFind is not found, Locate
               will nominate a position where it should go based on an
               assumption that there is a sorted list to fit it into.
sSortCode   -  2 characters:  eg "ar", "al", "dr", "dl"; upper case is OK
               1st character: "a" for "ascending" or "d" for "descending"
               2nd character: "r" for "right-justified" usually used for numeric
               data; "l" for "left-justified" usually used for general text.
"SETTING"   -  placeholder
iPos        -  value, sub-value or sub-sub-value position in sStringIn 
               where sFind is found...
               OR, if a "BY" clause is present, the recommended position 
               into which to insert sFind to add it to a sorted list.

Locate is most commonly used with the "BY" clause to create and maintain sorted lists.
Step 1: Locate is used to obtain iPos 
Step 2:  iPos is used in the Insert function.
eg
If Not Pixie.Locate(SEL, "IN", MODS, 1, "SETTING", YY) Then ...
eg
If Not Pixie.Locate(DEKNO, "IN", FDLIST, 1, "BY", "ar", "SETTING", Pos) Then
    FDLIST = Pixie.Insert(FDLIST, 1, Pos, DEKNO)
    FDITEM = Pixie.RReplace(FDITEM, 4, FDLIST)
End I
f


OConv "Output Conversion" returns result of applying a "processing code" to a value.
Syntax:
sOutput = Pixie.OConv(sInternal, sProcessCode)
eg
sInternal = 47500
sOutput = Pixie.OConv(sInternal, "mr2")
'sOutput <-- 475.00

Processing codes, OK as upper or lower case, fall into 3 categories depending on the starting one or 2 characters:
"d..." - date formatting and conversion
"mr.." - numeric scaling, formatting and rounding-off
         (older "md.." syntax also supported)
"mc.." - character filtering

"d..."  Dates   formats for date output.  sInternal argument is an MV internal date format of days-since-31-Dec-1967

PixieWeb looks at the "Regional Settings" of its host machine to automatically select "USA" date format eg "12/31/2000" versus British date format "31/12/2000". When publishing web material for an international audience, we use and highly recommend the "d" code, giving results like "31 Dec 2000" which are clearly understood by all.

"d", "d4"  -  date --> dd mmm yyyy
              eg OConv("11846", "d") ---> "06 Jun 2000"
"d4/"      -  OConv("11846", "d4/") ---> "06/06/2000"
"d4."      -  OConv("11846", "d4.") ---> "06.06.2000"
"d4-"      -  OConv("11846", "d4-") ---> "06-06-2000"

"d2"       -  date --> dd mmm yy
              eg OConv("11846", "d2") ---> "06 Jun 00"
"d2/"      -  OConv("11846", "d2/") ---> "06/06/00"
"d2."      -  OConv("11846", "d2.") ---> "06.06.00"
"d2-"      -  OConv("11846", "d2-") ---> "06-06-00"

"dj"       -  OConv("11846", "dj") ---> "2000158"  Julian date

"dq"       -  OConv("11846", "dj") ---> "2"  June is in the 2nd quarter
"dm"       -  OConv("11846", "dm") ---> "6"  June is the 6th month
"dd"       -  Oconv("11846", "dd") ---> "6"  Day 6 of the month

"dmm", "dmmm" - OConv("11846", "dmm") ---> "Jun"  1st 3 letters of month name
"dma"      -  OConv("11846", "da") ---> "June"  Full name of month

"dwa"      -  OConv("11846", "dwa") ---> "Wednesday"  day-of-week
"dw"       -  OConv("11846", "dw") ---> "3" day-of-week with MV
                                        convention Monday=1
"dy"       -  OConv("11846", "dy") ---> "2000"
"d2y"      -  OConv("11846", "dy") ---> "00"
     

"mr.." Numerical scaling and formatting
General syntax "mrIJ" or "mdIJ" (upper case OK eg "MR43")
where I, J represent integers 0 to 9
eg "mr12", "mr32", "mr2", "mr4"
I is how many decimal places to show and round off to.
J is how far to the left to shift the decimal point.
Where only one digit is shown, eg "mr2", it is treated as
both I and J eg "mr2" and "mr22" mean the same thing.

In practice, the most common code by far is "mr2",
used to take internal amounts of money stored
as cents, and display in dollars and cents.

Examples:
OConv(12345, "mr2")  ---> "123.45"
OConv(12345, "mr4")  ---> "1.2345"
OConv(12345, "mr34") ---> "1.235"
OConv(12345, "mr53") ---> "12.34500"

"mc.." Character Formatting: by example:
OConv("Brown's Cows", "mcu") ---> "BROWN'S COWS"  (make uppercase)
OConv("Brown's Cows", "mcl") ---> "brown's cows"  (make lowercase)
OConv("a1b2c3", "mca") ---> "abc" (extract alpha)
OConv("a1b2c3", "mcn") ---> "123" (extract numeric)
OConv("a1b2c-3", "mc/a" ---> "12-3" (extract non-alpha)
OConv("a1b2c-3", "mc/n" ---> "abc-" (extract non-numeric)
OConv("a1b2c-3", "mcan") ---> "a1b2c3" (extract alphanumeric)
  Note "mcna" is equivalent to "mcan"
OConv("a1b2c-3", "mc/an") ---> "-" (extract non-alphanumeric)
  Note "mc/na" is equivalent to "mc/an" 


IConv  
"Internal Conversion".  PixieEngine/PixieWeb implements 
a simplified inverse of OConv.
Syntax:
nInternal = Pixie.IConv(sExternal, sProcessCode )
eg
sExternal = "475.00"
nInternal  = Pixie.IConv(sExternal, "mr2")
'nInternal <-- 47500

Codes: "d", "dj", "mrI"

"d"
Conversion to internal date values, by example:
IConv("23 Dec 99", "d") --> 11680
IConv(Now, "d") ---> (today's MV date)
NOTES: There is no need to specify "d4", "d2/" etc
as the VB date recognition functions used behind the
scenes here automatically date-convert a wide range
of formats, and any other "d...." code except "dj" will be
treated as "d".  That means that automatic conversions
giving "d2/", "d2." etc will run just fine.
Handling of USA vs British/European date formats is
also handled automatically with results depending
on the machine's Windows Regional settings.
The PxUSADate property only affects OConv.

"dj"  Julian Date
By example:
IConv("2000107" , "dj") ---> 11795
IConv("00107", "dj") --> 11795
IConv("107", "dj") --> 11795  a 3-digit Julian date is taken as
   belonging to the current year which at time of writing is 2000.
The argument is tested for being 3, 5 or 7 characters long, with
the right 3 characters representing a number between 1 and 366.
Any argument failing that test is output unchanged as the result.
eg
IConv("2000403", "dj") ---> "2000403"

"mrI" ( or "mdI")
Only the single-digit syntax for scaling is supported:
eg
IConv("123456.78", "mr2") --> 12345678
IConv("12345.678", "mr2") -->  1234568
IConv("123456", "mr2") -->    12345600

"MVX2D"
Use for a derived parallel multivalued calculation. MVX2D(Attr1, Attr2) where
Attr1 is multiplied by Attr2 and the result presented in a new attribute.
Example of use is the query "ORDERS_Query":

SELECT ORDERS.A0 AS ItemID, ORDERS.A1 AS CustCode, OConv([A2],"d") AS InvDate,
ORDERS.A3 AS Rep, ORDERS.A4 AS OrdNo, ORDERS.A5 AS Source, ORDERS.A6 AS Freight,
MVR([A7]) AS ProdCode, MVOconv([A9],"mr4") AS Qty, MVOconv([a10],"mr2") AS Price,
MVX2D(Price, Qty) AS ExtPrice, FROM ORDERS ORDER BY ORDERS.A0;

Note in the above, that ExtPrice is the result of multiplying Qty and Price together.


MV Special Functions for GUI interfacing

VB/ MS Office/ functions to help with "friendly" grid and form displays via Char(253) <--> Char(13):Char(10) and use made of output codes in dictionaries.
MVR   "MultiValue Read" converts Chr(253) eg to Chr(13) & Chr(10)
s = Pixie.MVR(s) 

MVW   "MultiValue Write" is the inverse of MVR eg
s = Pixie.MVW(s)

MVOConv   "MultiValue Read" with processing code applied eg
s = Pixie.MVOConv(s, "d")

MVIConv   "MultiValue Write" with processing code applied eg
s = Pixie.MVIConv(s, "d")

Refer to our Microsoft Access example "testpxe1.mdb" for more details on these
in the context of a working example.


 

Top     Back to Chapter 6     Chapter 1