Lescasse Consulting
 Home    Company    News    Prices    Download    Buy    Forums   
Read Me
Buy
Forums
Resume
AntiSpam 1.2
wBackup 1.11
NetAccess 2.0
Visual APL 1.0 
APL+Win 8.0 
APL+Win Products 
APL+Win Objects™ 
APL+Win Training 
APL+Web Services
APL+Web Component 
APL+ History
Dyalog.Net Tutorial
Conferences 
Powerpoint
White Papers
Web Hosting
References
Links
 
APL+Win Objects™ 6.0

TADO5
TADO5 Tutorial
TAPLDraw5
TAPLEdit5
TAPLSession5
TAbale5
TAboutBox5
TAccess5
TAgent5
TBlatMail5
TButton5
TCDO5
TCRC5
TCancelButton5
TCheck5
TCheckGroup5
TChildForm5
TChooseColor5
TChooseFont5
TClipBoard5
TClock5
TCodeStats5
TColors5
TCombo5
TComboDrive5
TComboFilter5
TComboList5
TComboTree5
TCommandBar5
TCommandButton5
TControlClass5
TCueCard5
TDHTML5
TDHTMLEditor5
TDateTime5
TDateTimeFr5
TDates5
TDemoHandlers5
TDisplay5
TDOS5
TDualSelect5
TEdit5
TEditAmount5
TEditDir5
TEditEnter5
TEditFile5
TEditGrid5
TEditList5
TEditListview5
TEditMenu5
TEditNum5
TEditSelect5
TEditSpin5
TEmail5
TError5
TExampleForm5
TExcel5
TExcel5 Tutorial
TFindReplace5
TFOne5
TFTP5
TFTP5 Tutorial
TFileCompare5
TFileMenu5
TFileMenuDef5
TFlatButton5
TForm5
TFormClass5
TFormEditor5
TFrame5
TGetDir5
TGif5
TGifForm5
TGifWb5
TGoMenu5
TGraphX5
TGrid5
TGridDisplay5
TGridPrint5
TGUID5
THLine5
THTML5
THTML5 Tutorial
THTTP5
THelp5
THelpMenu5
TImagelist5
TInfo5
TIniFile5
TInstall5
TInternet5
TJpg5
TJpgWb5
TLabel5
TList5
TListview5
TLock5
TLogs5
TMAPI5
TMath5
TMDIForm5
TMSOutlook5
TMaskEdit5
TMedia5
TMenu5
TMessage5
TModalCall5
TMsgBox5
TNavigator5
TNetwork5
TNonVisualClass5
TODBC5
TOKButton5
TObject5
TOpenFile5
TOption5
TOptionGroup5
TOutlook5
TOutlookMail5
TOWCSpread5
TPDF5
TPFKeys5
TPage5
TPassword5
TPicture5
TPing5
TPopupMenu5
TPowerpoint5
TPowerpoint5 Tutorial
TPrinter5
TProgress5
TProgressDlg5
TQuestion5
TRegistry5
TRegistryKey5
TResource5
TRichEdit5
TSPX5
TSQLDMO5
TScheduler5
TScroll5
TSelector5
TSpinner5
TSplitter5
TStatus5
TStopWatch5
TTest5
TTestError5
TTextFile5
TTimer5
TTip5
TTipForm5
TTLI5
TToolBar5
TToolbox5
TToolsMenu5
TTrackbar5
TTranslate5
TTree5
TVLine5
TViewMenu5
TWebBrowser5
TWebServer5
TWebSite5
TWebSiteNet5
TWinMenu5
TWord5
TYesNo5
    Visits:  3829 (41 on line) Last Update: Apr 15, 2004  
    APL+Win Grid White Paper    Printer Friendly  

 
The APL+Win Grid in a Real Life Application

I have been working as a Consultant for TF1, the major French TV Channel, for the last 4 years, developing and maintaining APL applications for them.

A year ago,   just after the APL2000 2000 User Conference, TF1 came to me and mentioned that one of their departments was looking for a way to display daily TV programs in a visual graphic grid.

Since I was interested in the subject and wanted to show once again how much APL is efficient to solve problems, I decided to invest one of my weekends, building a sample application for them.

I asked them for a set of real data to play with and the next week I came up with a complete small APL application which was able to draw and display the above grid in an APL form with menus, context menus, etc.

Because of the nature of the problems, I had decided to use APL+Win drawing facilities, therefore using Œwi'Draw'... to draw the various TV programs on a Picture object on the form.

The above grid displays TV programs by hour of the day (vertically) and by day of the week (horizontally).

Before going further on, let me apologise for displaying screen shots in French:  I have not had time to translate this application.

On the way to a much larger application

Seeing the results and the time it had taken to build this sample application, TF1 decided to ask me to write the complete application they had in mind, and in fact this proved to be a rather huge application.

What they really wanted was the following:  they wanted to have an application to help their Marketing Representatives sell special kinds of ads called “sponsorship ads”.  Some TV programs are sponsored by advertisers who play their jingles at the beginning and/or end of the program.

This meant being able to:

  • Display the daily TV Programs for any given week
  • Navigate through 2 years of such grids
  • Display a grid showing TV Programs by Weeks over 2 years
  • Display a grid showing TV Programs by Days over 2 years
  • Display a grid showing Weeks by Days for a given DayPart
  • Display a specific grid showing short Programs
  • Display TV Program Powerpoint Pages
  • Select Programs with a multi-criteria selection system
  • Show the Ad booking level for each program on all these grids
  • Display information tooltips about the advertisers and products for each Program
  • Print all the grids
  • Print additional reports
  • Select programs over periods of times and auto-generate proposals to advertisers
  • Allow the application to work on the company network with 50 simultaneous users
  • Allow the application to work on portable computers not connected to the company network
  • Import data from other TF1 applications
  • Instantly inform simultaneous users that new data has been imported
  • Grant various levels of user rights
  • Have a very sophisticated and comprehensive Help System
  • Spy application errors
  • Spy users connections and disconnections
  • Create, change, delete users
  • Create an automatic installation program working with no prompts

And there was a 60 days budget available for developing the whole application.

When they asked me if I could do all that, I said “yes”, putting all my belief in Patrick Park’s and APL2000’s ability to develop a Beta version of a Grid robust enough to run in production environments.

As a matter of fact, I knew there would be no way to write such an application in the allotted time, without using a Grid object.  Happily I was just returning from the APL2000 2000 Conference and knew how the new APL+Win Grid object would be able to help me.

The other reason why I accepted this contract is that I knew I could use my library of objects from my “APL+Win 3.6 Objects” product.

Deciding for an (Object) strategy

I immediately decided to develop this application in a pure Object Oriented manner, exclusively using objects from “APL+Win 3.6 Objects[1]” and creating new objects for every aspect of the application.

So everything became an Object, with its own properties and methods.

This proved over time to have considerably helped me since it happened many times that I could reuse already written object properties and methods in places where I had not even anticipated I would need them.

All objects used in this application are working on the same model which is reproduced on the next page.

The TPicture object shown on next page is an excerpt from the “APL+Win 3.6 Objects” TPicture object with one property (bitmap) and one method (AdjustSize).

An object is an APL function having a structure similar to TPicture, where there always is a New method, which is the object Constructor.  In the New method, you build your object based on one or more native existing APL+Win objects.

Most of the time the APL+Win object(s) upon which you base your object is(are) visual object(s).  If you need to create a non visual object like a TRegistry object to cope with the Windows Registry, it is a good idea to use the APL+Win Menu object which is the object having the smallest memory footprint. 

TPicture inherits from TObject (line 16): this means that TPicture can call any TObject property or method.

You add properties and methods to your object, by adding :case'property' or :case'Method' sections under the :case'Action' section (see lines 35-50 for the bitmap property and lines 52-62 for the AdjustSize method).

Lines 64-65 are used when you invoke a property or method which is not one of your specific object properties or methods (i.e. not class, bitmap or AdjustSize). 

Then the system looks for such a property or method in higher object in the hierarchy (here TObject) and if it does not find it there, finally looks for it in the APL+Win object upon which your object is derived (here Picture).  If it still does not find it, it falls through to lines 68-69, displaying an error message.


     ’ A TPicture B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;W;X;Y;Z;Œio;Œwself
[1]   ©’ A TPicture B -- TPicture class
[2]   ©’ A „… object name
[3]   ©’ B „… 'property'
[4]   ©’   or 'property'value
[5]   ©’   or 'Method'
[6]   ©’   or 'Method'argument1 ... argumentN
[7]   ©’ Requires: (F)
[8]   ©’ (c)2000 Eric Lescasse[11jul00]
[9]
[10]  Œio„1
[11]  :if 2¬Œnc'A' ª A„Œwself ª :end
[12]  :select B
[13]  :case'New'
[14]      Œwself„A Œwi'*Create' 'Picture'
[15]          C„'TPicture"Action"'
[16]          C„C,Œtcnl,'TObject"Action"'               © inherit from TObject
[17]          Œwi'*onAction'C
[18]          Œwi'*scale'(†Œwi'*..scale')
[19]          Œwi'*font'(Œwi'*..font')
[20]          Œwi'*onDelete' 'Common"onDelete"'
[21]          Œwi'*onExit' 'Common"onExit"'
[22]          Œwi'*onExitError' 'Common"onExitError"'
[23]          Œwi'*onMove' 'Common"onMove"'
[24]          Œwi'*onResize' "TPicture'onResize'"
[25]          Œwi'clipsiblings'1
[26]
[27]  :case'onResize'
[28]      Œwi'*imagesize'(Œwi'*size')
[29]
[30]  :case'Action'
[31]      :select†Œwarg
[32]      :case'class'
[33]          Œwres„'TPicture'
[34]
[35]      :case'?bitmap'
[36]          Œwres„"Get or Set the bitmap file name for the TPicture object"
[37]          Œwres„Œwres,Œtcnl,"Syntax:  'object'Œwi'bitmap'filename"
[38]          Œwres„Œwres,Œtcnl,"filename:  a .BMP file name"
[39]      :case'bitmap'
[40]          :if 1=½Œwarg
[41]              Œwres„Œwi'*‘‘bitmap'
[42]          :else
[43]              C„2œŒwarg
[44]              :if~Ÿ/':\'¹C
[45]                  C„(Œwi'installdir'),C
[46]              :end
[47]              Œwi'*‘‘bitmap'C
[48]              Œwi'*bitmap'C
[49]              Œwi'*style'4
[50]          :end
[51]
[52]      :case'?AdjustSize'
[53]          Œwres„'Forces TPicture object to get the exact image size'
[54]          Œwres„Œwres,Œtcnl,"Syntax:  'object'Œwi'AdjustSize'"
[55]      :case'AdjustSize'
[56]          :if~0­F„Œwi'*‘‘bitmap'
[57]              (C D)„Œwi'GetBitmapSize'F
[58]              Œwi'*suppress'1
[59]              Œwi'*size'C D
[60]              Œwi'*imagesize'(Œwi'*size')
[61]              Œwi'*suppress'0
[62]          :end
[63]
[64]      :else
[65]          Œwres„Œwi'*'
[66]      :end
[67]  :else
[68]      Œerror'Unknown TPicture command: ',B
[69]  :end
    ’

To create an instance of the TPicture object we may use:

       0 0½'ff'Œwi'Create' 'Form'('scale'5)('caption' 'TPicture Example')('where'30.0625 85.25 11.5625 29.5)
       0 0½'ff.pic'Œwi'Create' 'TPicture'('where'5 5)

Now let’s invoke the bitmap property:

      'ff.pic'Œwi'bitmap' 'skating.bmp'

and now the AdjustSize method:

      'ff.pic'Œwi'AdjustSize'

So it’s possible to create new objects and manipulate them with the Œwi system functions as if they were internal APL+Win objects.

Moreover, if we did not remember about a property or method syntax, we can always do:

      'ff.pic'Œwi'?bitmap'

Get or Set the bitmap file name for the TPicture object

Syntax:  'object'Œwi'bitmap'filename

filename: a .BMP file name (path may be omitted if install directory)

      'ff.pic'Œwi'?AdjustSize'

Forces TPicture object to get the exact image size

Syntax:  'object'Œwi'AdjustSize'

as long as we have added the object property and method documentation within our object as done in lines 35-38 and 52-54.

Finally, all objects inheriting from TObject, they may call any property or method resigstered within TObject, in particular the Properties and Methods which inform about the properties and methods in any object:

      'ff.pic'Œwi'Properties'

 bitmap

      'ff.pic'Œwi'Methods'

 AdjustSize

Thus, at any time, you may know the object specific properties and method names and then query how to use such properties and methods.  This means that objects are always auto-documented and this makes them very simple to use.

For all this to work, you need to:

  1. Register your object to the APL+Win system

    This is done by adding your object to the
    newclasses property of the system object:

          '#'Œwi'newclasses'(('#'Œwi'newclasses'),›'TPicture')

  2. Use the following instruction:

          '#'Œwi'*onNew' 'OnNew'

    In conjunction with the following utility:

        ’ OnNew
    [1]   ©’ OnNew -- Handler for all new classes
    [2]   ©’ The class handler function must have the same name as the class
    [3]   ©’ Example: object 'TForm' must be handled by function 'TForm'
    [4]
    [5]   :if(›Œwarg)¹'#'Œwi'newclasses' © if new class...
    [6]       –Œwarg,'"New"'             © send to class handler
    [7]   :end
        ’

This is the structure which has been adopted for all objects in “APL+Win 3.6 Objects” and for all objects in the TF1 application.

Where does the APL+Win Grid fit in?

The APL+Win Grid is used literally everywhere in this application.

This application has been written to be used by various TV channels including TF1.  When a marketing representative opens a channel database he immediately sees a form with alerts being displayed on the screen:

This display him everyday which proposals to advertisers have become obsolete and should be converted to real orders.

This is a simple use of an APL Grid to display a list of records:  but it is more flexible to use than the Listview object for such a purpose.

Here are the instructions used to create this Grid object:

     Z„Œwi'*.grid.Create' 'TGrid'('wherelc'30 0 '>>' '>>')('attach'1 2 3 4)('*xRows'E)('*xCols'F)('*xTabWidth'0)
     Z„Œwi'*.grid.xFontName'0 0'MS Sans Serif'
     Z„Œwi'*.grid.xFontName'¯1(¼F)'MS Sans Serif'
     Z„Œwi'*.grid.xFontName'(¼E)¯1'MS Sans Serif'
     Z„Œwi'*.grid.xFontSize'0 0 14
     Z„Œwi'*.grid.xFontSize'¯1(¼F)14
     Z„Œwi'*.grid.xFontSize'(¼E)¯1 14
     Z„(E+1)F½Œwi'*:Draw'('Font' 'MS Sans Serif'8 0'ansi')((›'?Text'),,D)
     Z„Œwi'*.grid.xColSize'(¯1,¼F)(G„30,16+¹1‡¨—šZ)
     :if(E>0)^F>0
         Z„Œwi'*.grid.xColorBack'(¼E)(¼F)(E F½256ƒ0 255 255)
     :end
     Z„Œwi'*.grid.xText'(¯1,¼E)(¯1,¼F)(((›''),¼¯1+†½D),AV2ANSI D)
     Z„Œwi'*.grid.xAlign'0(¼F)(1 2 2 1 1 2)
     Z„Œwi'*.grid.xProtect'0 0 1

These instructions use the TGrid object which is a cover for APL.Grid, capable of additional properties:  wherelc  and  attach  to position and size the grid and to resize it automatically when its mother form is resized.

Then the next place where an APL grid was needed was to display ad reservations per TV Program and per week over the selected period of time.  Here it is:

Lines in this grid represent TV Programs and columns represent weeks.  The Grid cells do not contain texts but their color represent the level of  booking for the corresponding TV program within the concerned week.

White means that the TV Program is not yet booked.

Pink and Red means that the TV Program has been sold.

Green means that one or more advertisers have taken a booking option on the Program.

Yellow means that several main advertisers have booked the program.

TF1 wanted to be able to represent the fact that the some TV Program dates were not yet firmly decided.

Since this could happen for all TV Programs level of bookings we could not use another color.  Instead we needed a mean to add this additional information over the currently colored cells.

Happily the APL Grid allows to display small images in cell corners and we have used this feature extensively.  When the TV Program date is yet temporary, we display a blue triangle in its upper left corner.

This is done with the following instructions:

images„1 2 3 4°.×26 13[1+mcol2]

Œwi'*.grid.Image'(1 2 3 4)(¼1†½mcol2)(¼1‡½mcol2)images  

mcol2 being the boolean APL matrix indicating if the TV Programs are temporary or not.

Also note that we used the APL Grid Join method to display titles above group of columns.  This is done with the following instructions:

X„+\1,¯1‡Y„½¨weeksn
(S T)„Œsplit 0 100‚monthsn
S„Œwi(›'Av2Ansi'),('Jan' 'Fév' 'Mar' 'Avr' 'Mai' 'Jun' 'Jul' 'Aug' 'Sep' 'Oct' 'Nov' 'Déc')[T],¨¯2†¨•¨S
:for I :in ¼½weeksn
    :if 1<IœY
        Œwi'*.grid.Join'¯3(IœX)1(IœY
    :end
     Œwi'*.grid.text'¯3(IœX)(IœS)
:end

where weeksn is a nested vector of week numbers per months:

      ]display 2†weeksn
.…--------------------------------------------------.
|.…------------..…---------------------------------.|
||200138 200139||200140 200141 200142 200143 200144||
|'~------------''~---------------------------------'|
'¹--------------------------------------------------'

and where monthsn is the corresponding list of months:

      ]display 2†monthsn
.…------------.
|200109 200110|
'~------------'

TF1 wanted the application to automatically display dynamic information when the mouse cursor was hovering grid cells.

So I used one of my objects, called TTipForm, which was able to display a form with a shade and no title bar and no border.  I used the onXCellMouseEnter and onXCellMouseLeave events to show and then hide the TTipForm  objects.  My TTipForm object was a simple form with a Listview object using the entire client area of the form.

The tip forms were entirely dynamic, i.e. their sizes were calculated depending on their content which was itself depending on the cells.

All that worked fine, but quickly TF1 requested that the tip form could display various colors in their various columns.

In order to do so, and thanks to Object technology, I merely had to change one property of the TTipForm object to now use a Grid object instead of a Listview object.

Here are a few examples of tip forms displayed when hovering various cells with the mouse cursor:

or:

or

In these cases, an APL.Grid object was created with no border, no grid lines, various background colors for the various columns, various font colors for the various columns and column width was calculated depending on the largest text in the column.

The tip form grids are created using the following instructions:

Z„Œwi'*.grid.Create' 'APL.Grid'('*scale'5)('*where'0 0 L M)('*border'0)('*edge'0)
Z„Œwi'*Set'('*.grid.xGuideLines'0)('*.grid.xColorGrid'0)
Z„Œwi'*Set'('*.grid.xHeadCols'0)('*.grid.xHeadRows'0)
Z„Œwi'*Set'('*.grid.xTabWidth'0)
Z„Œwi'*Set'('*.grid.xRows'P)('*.grid.xCols'Q)
Z„Œwi'*Set'('*.grid.xText'(¼P)(¼Q)D)('*.grid.xAlign'(¼P)(¼Q)8)
Z„Œwi'*Set'('*.grid.xRowSize'(¼P)(14))('*.grid.xColSize'(¼Q)(J+13-(½J)†1))
Z„Œwi'*Set'('*.grid.xFontSize'(¼P)(¼Q)14)('*.grid.xColorText'0 1(256ƒ255 255 255))
Z„Œwi(›'*size'),1+(C D)„L M+Œwi'*‘‘shadedepth'
Z„Œwi(›'*size'),(C D)

Another part of the application using a Grid object was the Day Grid.  Similar to the Weeks grid, it displays the various booking levels per TV program and per day.  Here it is:

Note the various column header groupings, each week days being under the week header (S38, S39, S40, etc.) and the various weeks of a given month being under the month header (Sep01, Oct01, etc.)

This application included still 2 other types of grids:  the DayPart grid, showing the various levels of TV program ad bookings per month and day of the weeks.

This particular grid is showing the various possible TV programs for a given day and hour knowing that there may be more than one.


Finally a special grid has been added to the application to display what TF1 calls “Programmes Courts” i.e. Short Programs, usually of less than 5 minutes like the Weather Forecasts which are also sponsored by advertisers.

This grid displays these Short Programs per hour of the day and per day of the week.


Here is the Short Programs grid:

This application is used on the company network and is used by about 50 users.  TF1 wanted a mean to maintain a database of these users and the possibility to grant them some rights.

Guess what we’ve used for this purpose?

A grid of course.  But this time we have used the possibility to include check boxes in grid cells:  this was handy since one may grant or not grant a given right to a user and this could easily be expressed by checking or unchecking a check box.


Here is the grid we’ve used:

The code used to create this grid is the following one:

    Œwself„'fmUsers.grid'Œwi'Create' 'APL.Grid'('scale'5)('border'1)('where'0 0,'fmUsers'Œwi'size')
    Œwi'Set'('xHeadRows'2)('xHeadCols'1)('xRows'R)('xCols'C)
    Œwi'onXCellMouseUp' 'TUsers_Handlers'
    :if Œwi'*‘newgrid'
        Œwi'onXEditKeyPress' 'TUsers_Handlers'
    :end
    Œwi'Set'('xJoin'¯2 1 1 D)('xJoin'¯2(D+1)1(C-D))('xTabWidth'0)
    Œwi'xText'¯2(1(D+1))(1 2½AV2ANSI¨'Caractéristiques Utilisateur' 'Droits Utilisateur')
    Œwi'xText'¯1(¼C)(1 C½AV2ANSI¨'Nom réseau' 'Nom' 'Prénom' 'Abbréviation' 'Admin' 'Dispo' 'Bilbao' 'Alertes' 'Portable')
    Œwi'xText'(¼R)¯1(R 1½¼R)
    Œwi'Set'('xFontName'0 0'Arial')('xFontName'(¯2 ¯1)(¼C)'Arial')
    Œwi'Set'('xFontName'(¼R)¯1'Arial')
    Œwi'Set'('xFontSize'0 0 14)('xFontSize'(¯2 ¯1)(¼C)14)('xFontSize'(¼R)¯1 14)
    Œwi'xAlign'(¼R)(D+¼C-D)4
    Œwi'xCellType'(¼R)(D+¼C-D)2         © check boxes
    Œwi'xRowSize'(¼R)16
    Œwi'xColSize'(¼C)(E„127 180 110 65 40 40 40 40 40)
    Œwi'*:‘oldsize'(W„2œ'fmUsers'Œwi'*size')
    Œwi'*‘sizedif'(W-+/3†E)
    Œwi'XRedraw'

Another place where a grid is used in this application is the form which tracks User Connections.  As a matter of fact, we record every user connection and disconnection within a database and the application Administrators may view this kind of information at any time.


Here is the User Connections grid:

This grid shows who used the application, on which date, at which time and for how long and records the number of Simulations the user has made.

Indeed, most of the users are TF1 Marketing Representatives and they use the Week Grid  we has seen before to send automatic proposals to Advertisers.

They may use their mouse to select one or more TV Programs, for one or more weeks, for which their customers want to buy ads and then choose “New Simulation” from the “File” menu to automatically produce a proposal.

Since selecting programs with the mouse is too complex for Marketing Representatives we created an assisted mode to more easily select various TV programs over various period of times.

Clicking on the Assist Mode check box opens 3 more (yellow) columns in the week grid, where they can enter for each concerned TV Programs:

  • The ad campaign start week
  • The ad campaign end week
  • The number of weeks

The start week is required, but the user my enter either the End Week or the Number of Weeks and the system computes the third data.

Example:

Here they have selected 2 TV Programs:  first “Attention à la Marche” for 6 weeks starting October 10 and “C’est quoi l’Amour” for 2 weeks starting October 22.  Clicking on the “Show Selection” (=Montrer la selection) button shows in black what they have selected within the grid.

The grid code used to compute the total number of weeks when they are entering the End Week date use the onXEditEnd event.  During this event, the dates in columns 1 and 2 (start and end dates) are used to calculate the number of weeks which is then displayed in column 3.

They can choose File/New Simulation (=Fichier/Nouvelle Simulation) to start a new simulation.

This starts the TExcel object which opens a pre-formatted Excel spreadsheet, fills it with data retrieved from the application database, including prices depending on TV Programs, period of the year etc.  All this is done automatically in a couple of seconds and Marketing Representatives have their proposal displayed in front of them in a summary table.

The produced TExcel object also contains one Excel sheet per selected TV Program with more detailed data as shown on the next page.

Users may interact with the Excel sheet by clicking various check boxes to include or exclude rebates within their proposals.

The Excel worksheet contains Visual Basic for Application code to handle internal calculations within the Spreadsheet.

This is a good example of how APL can nowadays coexist with other popular software like Excel and VBA in real life applications.

Once again, this entire application has been written with objects:  many were pre built objects from my “APL+Win 3.6 Objects” product, all the others being application specific objects created for the sole purpose of this application.

One of the decisions I had to take during the development of this application, was the choice of a printing technique to print the various grids.

How could I do that, knowing the APL Grid had no XPrint method available?

Since my customer wanted the grid print outs to print in color and resemble as much as possible to the grids on the screen I decided to pilot Excel from APL to do the job.

Therefore I used my ”APL+Win 3.6 Objects” TExcel object.

As an example of how TExcel can be used to print the content of an APL+Win Grid object, the next page displays  PrintWeekGrid , the program which prints the Week Grid.

Although the PrintWeekGrid program may seem complex at first sight, it really is not.  Basically, it simply calls properties and methods built in the TExcel object or of its sub-objects.

Such a program takes between half a day and a day to fully write and test.

It would be too long here to comment the PrintWeekGrid program.  However just a couple of notes:  this program is using a method called ApplyMatrixProperty (see lines 91 and 96) which I have built into TExcel and allows to apply any Excel property to any range of cells in one instruction.

This is very useful, because only APL knows about matrices!  If we want to set the background color of a range of cells in the APL Grid we can do so in one instruction specifying the concerned lines and columns and specifying a matrix of color codes.  But in Excel, we must write a double loop, looping on lines and then on columns to apply the right color property to each cell in the range.  The ApplyMatrixProperty method is handy  and prevents from having to write all this loopy code.

    ’ PrintWeekGrid;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;W;X;Y;Z;‘;AA;Œio;weeksn;Blanc;Violet;Vert;Rouge;Gris;Ver2;Viole2;Roug2;AB;Jaune
[1]   ©’ PrintWeekGrid -- Prints the week Grid using Excel
[2]
[3]   Œio„1
[4]   'pg.se.p3'Œwi'*pointer'11
[5]   'pg'Œwi'*pointer'11
[6]   Œwgive 0
[7]   Infod'Printing in progress...'
[8]
[9]   © Get data for the report
[10]  R„Œwi'*:‘GridRowTexts'
[11]  C„Œwi'*:‘GridColTexts1'
[12]  D„Œwi'*:‘GridColTexts2'
[13]  O„'pg.se.p3.grid'Œwi'*‘GridColors'
[14]  ‘„Œwi'*:‘GridTriangles'
[15]  (weeksn X Y S)„Œwi'*:‘GridMerge'
[16]  T„(2+½C)œV„'oo'Œwi'SsColumns'       © last occupied column letter
[17]  N„8                                 © number of top lines
[18]  U„N+†½R                             © last occupied row
[19]
[20]  © Create an instance of TExcel
[21]  :if 0¬½'ex'Œwi'self'
[22]      'ex'Œwi'*visible'0
[23]      'ex'Œwi'XQuit'
[24]      'ex'Œwi'*Delete'
[25]  :end
[26]  Œwself„'ex'Œwi'*Create' 'TExcel'
[27]  Z„Œwi'*xDisplayAlerts'0
[28]  Z„Œwi'*onClose' '"ex"Œwi"XQuit" ª "ex"Œwi"*Delete"'
[29]  Z„Œwi'xDefaultFilePath' 'c:\my documents\dispo\simul\'
[30]  Z„Œwi'AddBook'1
[31]  Z„Œwi'Sheet'1
[32]  :if Œwi'CheckPrinter'  © check if a Printer is defined on this computer
[33]      Z„Œwi'sheetname' 'WeekGrid'
[34]      Z„Œwi'*caption' 'Grille Vendable (Semaines)'
[35]
[36]      © Print Parameters
[37]      Z„Œwi'*.wksht.XPageSetup>',Œwself,'.pgsetup'
[38]      Z„Œwi'LeftMargin'1
[39]      Z„Œwi'RightMargin'1
[40]      Z„Œwi'TopMargin'1
[41]      Z„Œwi'BottomMargin'1
[42]      Z„Œwi'Orientation' 'landscape'
[43]      Z„Œwi'CenterHorizontally'1
[44]      Z„Œwi'PaperSize' 'A4'
[45]      Z„Œwi'*.pgsetup.xLeftMargin'0
[46]      Z„Œwi'*.pgsetup.xRightMargin'0
[47]      Z„Œwi'*.pgsetup.xFooterMargin'.5
[48]      Z„Œwi'*.pgsetup.xLeftHeader'(Œwi'Av2Ansi' '&07 &"Verdana" &G DISPO - Sources : Sylvie TIRABOSKI [13237]')
[49]      Z„Œwi'*.pgsetup.xRightFooter'(Œwi'Av2Ansi' '&07 &"Verdana" &G Page &P/&T')
[50]      Z„Œwi'*.pgsetup.xHeaderMargin'.5
[51]      Z„Œwi'*.pgsetup.xRightHeader'(Œwi'Av2Ansi' '&07 &"Verdana" &G &J &H')
[52]      Z„Œwi'FitToPagesWide'2
[53]      Z„Œwi'FitToPagesTall'2
[54]      Z„Œwi'PrintTitleRows'('A1:A',•N)
[55]      Z„Œwi'PrintTitleColumns' 'A1:B1'  © repeat column 1 on each page
[56]      Z„Œwi'*.pgsetup.xCenterHeader'(Œwi'Av2Ansi'('&G &14 &"Verdana" Grille Vendable (Semaines)',Œtcnl,('pg.DAYPART'Œwi'*text')))
[57]
[58]      © Set columns widths
[59]      Z„Œwi'Range' 'B1'
[60]      Z„Œwi'ColumnWidth'30
[61]      Z„Œwi'Range'('A1;C1:',T,'1')
[62]      Z„Œwi'ColumnWidth'4
[63]
[64]      © Install row headings
[65]      Z„Œwi'Add'('A',•N+1)((•¨¼†½R),[1.5]R)
[66]      Z„Œwi'HAlign' 'right'
[67]
[68]      © Install column headings
[69]      Z„Œwi'Add'('C',•N-1)((1,½C)½C)
[70]      Z„Œwi'HAlign' 'center'
[71]      Z„Œwi'Add'('C',•N)((1,½D)½D„•¨D)
[72]      Z„Œwi'HAlign' 'center'
[73]
[74]      © Column headings in merged cells
[75]      :for I :in¼½X
[76]          Z„Œwi'Range'((N-2)(2+IœX)1(IœY))
[77]          Z„Œwi'*.rng.Merge'
[78]          Z„Œwi'Add'((N-2)(2+IœX))(IœS)
[79]          Z„Œwi'HAlign' 'center'
[80]      :end
[81]
[82]      © Handling colors
[83]      P„½O ª O„,O
[84]      (Vert Violet Rouge Blanc Gris Jaune)„256ƒ¨²¨(0 255 0)(255 0 255)(255 0 0)(255 255 255)(192 192 192)(255 255 0)
[85]      (Ver2 Viole2 Roug2)„256ƒ¨²¨(›'pg')Œwi¨'‘‘ColorGreen' '‘‘ColorPurple' '‘‘ColorRed'
[86]      O„P½(Vert Violet Rouge,O)[(Ver2 Viole2 Roug2,O)¼O]
[87]
[88]      © Install cell colors
[89]      Z„Œwi'Range'('A',(•N+1),':B',(•U),';B',(•N-2),':',T,•N)
[90]      Z„Œwi'BackColor'(256ƒ192 192 192) © row & column headings colors
[91]      E„Œwi'ApplyMatrixProperty' 'BackColor'((N+1)3)(0 3‡O)   © body colors
[92]      E„Œwi'Range'('A',(•N-2),':B',•N)
[93]      E„Œwi'BackColor'(256ƒ255 255 255) © top left cell colors
[94]
[95]      © Legend
[96]      E„Œwi'ApplyMatrixProperty' 'BackColor'(2 1)(5 1½Blanc Violet Vert Rouge Jaune)
[97]      Z„Œwi'Add'(2 2)(6 1½'oo'Œwi'Av2Ansi' ' Disponible' ' Vendue à un Co-Partenaire Presse' ' Optionnée' ' Vendue' ' Multi-Sponsor Principal' ' Date Provisoire')  © LES14jun01
added
[98]      Z„Œwi'Range' 'B2:B7'
[99]      Z„Œwi'FontSize'9
[100]     Z„Œwi'Range' 'A7'
[101]     Z„Œwi'FontName' 'Wingdings 3'
[102]     Z„Œwi'FontColor'(256ƒ255 0 0)    © blue triangle
[103]     Z„Œwi'Add'(7 1)(1 1½›,Œav[123])  © Œav[123] in WingDings3 is Upper Left Triangle symbol
[104]     Z„Œwi'Range' 'A2;A3;A4;A5;A6;A7'
[105]     Z„Œwi'Border'1 2                 © borders for "legend" colors
[106]
[107]     © Print upper left triangles
[108]     Z„Œwi'Range'('C',(•N+1),':',T,•U)  © grid content
[109]     Z„Œwi'FontName' 'Wingdings 3'
[110]     Z„Œwi'FontColor'(256ƒ255 0 0)  © triangles must be blue
[111]     Z„Œwi'Add'((N+1)3)(,¨Œav[33 123[1+‘]])
[112]     © Note: Œav[123] in WingDings3 is Upper Left Triangle symbol
[113]
[114]     © Cell borders & border colors
[115]     Z„Œwi'Range'('A',(•N+1),':',T,•U)    © select grid content itself
[116]     Z„Œwi'GridLines'1(256ƒ255 255 255)
[117]     Z„Œwi'Range'('C',(•N-2),':',T,•N)    © select column titles
[118]     Z„Œwi'GridLines'1(256ƒ255 255 255)
[119]
[120]     © Finish report, make it visible & Print Preview
[121]     Info''
[122]     Z„Œwi'visible'1
[123]     Z„Œwi'*.wkbk.PrintOut'1 1000 1 1
[124]     'pg.se.p3'Œwi'*pointer'1
[125]     'pg'Œwi'*pointer'1
[126] :else
[127]     'pg.se.p3'Œwi'*pointer'1
[128]     'pg'Œwi'*pointer'1
[129]     Infod''
[130]     Z„'!'Ok"You must first define a printer!"
[131] :end
[132]
[133]
    ’

I believe that APL+Win Release 4 now contains a utility workspace which allows to print the content of an APL Grid.  I have used a Beta Version of it and it does a real nice job: it’s also a very interesting piece of software to study.

However, the resulting printout is not as perfect as what you can obtain by subcontracting the Excel print engine to work for you.  But it is certainly faster and easier to use.


Printing the Grids with a Screen Capture Utility

In this application, there was also the need for printing parts of the screen.

For this purpose, TF1 Publicité has acquired a Site License for an excellent and extremely useful utility called SPX Instant Screen Capture (SPX hereafter) from MoodySoft.

SPX is a utility which gets installed in the Tray icon and lets you capture any part of your screen, using your mouse and send this to:

  • A file (.BMP or .GIF or .JPG)
  • The Clipboard
  • A Printer or Fax
  • A Mail system
  • A Graphics Editor

When you right click on the SPX icon at the bottom right of your screen, a hierarchical menu helps you choose parameters and configure the software.  Many options are possible.

To capture any part of your screen, simply press the right mouse button for a second or two until the cursor changes for a cross cursor.  Then, click the left mouse button and drag the mouse to define the rectangular area you want to capture.

As soon as you release the left mouse button the part of your screen contained