I don't knoow the best way to categorize this so when it gets cluttered,
I will reorg it somehow. This section is here b/c I always forget how to do some
of this stuff.
Wiki on Clarion history - http://en.wikipedia.org/wiki/Clarion_(programming_language)
QuickLinks (on this page)
Links - external
General Un-Categorized
WSLDIAL.DLL GPF ...yeah it doesnt exist http://www.dka.net.au/kb/100023.html
Clarion SQL error - "Connection is busy with
results for another hstmt" "S1000"
"Connection is busy with
results for another hstmt" - "S1000"
set
/BUSYHANDLING=2 ***default is
3
in Clarion Help - "Database
Drivers and Interfaces", "All SQL Accelerators...", "SQL Drivers strings", "Busy
Handling"
SQL in Clarion
?Button:Print{prop:text} = 'No Stuff to Print'
sqlfile{prop:sql} = 'select count(*) from
YOURFILE where YOURFIELD = ' & PRE:YOURCOMPARE if
errorcode() then stop(fileerror()).
buffer(sqlfile, 20) !
set(sqlfile)
loop
next(sqlfile) if errorcode() then
break. if SQLf:f1 >
0
?Button:Print{prop:disable} =
0
?Button:Print{prop:text} = 'Print the
Stuff' end
end
Access database in Clarion -file
defs database driver = ODBC owner = !glo:owner
-in code in the Main procedure...right before it tries to open a
file glo:owner = 'driver=microsoft access driver
(*.mdb);dbq=database1.mdb;'
SETCURSOR(Cursor:Wait) OPEN(SQLOpenWindow)
ACCEPT IF EVENT() = Event:OpenWindow ! Procedure
setup standard formulas ! [Priority 7300]
! Open Files
Relate:Divisions.Open
! File Divisions used by this procedure, so make sure it's RelationManager is
open SELF.FilesOpened = True ! [Priority
7800]
POST(EVENT:CloseWindow) END END
CLOSE(SQLOpenWindow) SETCURSOR()
!glo:owner
Clearing a queue - delete all entries in a
queue -clear(queuename) does not work, do free(queuename)
which deletes all entries
good descriptive error message on
Gets/Puts
if errorcode() then
message(clip(LOC:ProcedureApplicationName) & '|myroutine ROUTINE - Error on
PUT(myfilename)||PRE:FieldNameonKey : ' & PRE:FieldNameonKey &
'.|Error:' & ERRORCODE() & '-' & error() & '|Fileerror:' &
fileerrorcode() & '-'& fileerror())
.
if errorcode() then message('Procedure/?OK - Error on
get(yourfile, yourkey).|Error:' & ERRORCODE() & '-' & error() &
'|Fileerror:' & fileerrorcode() & '-'&
fileerror()).
if loc:DebugIt then
message(clip(LOC:ProcedureApplicationName) & '|MyROUTINENAME routine top.|'
& '|pre:field : ' & pre:field) .
set a strings text and
color
?mystringfield{prop:text} = 'Whazzzup
dude' ?mystringfield{prop:fontcolor} =
COLOR:GREEN !make sure there is an equate for your
color
change colors at
runtime text ?yourstring{PROP:FONTCOLOR} = COLOR:RED
!look at the equates.clw to get the color your want field
background color (like to hilite on field error or
something) ?yourfield{PROP:BACKGROUND} = COLOR:YELLOW
rounding -
always round up PRE:FIELD = INT(PRE:FIELD2
/ 25.4) + 1 Get to the history fields
when changing a record
***might have to fill it in
ThisWindow.init with History::PRE:Record = PRE:Record
for regular
field history::PRE:record.FIELDNAME for field in a
group history::PRE:record.PRE:GROUPLABEL.FIELDNAME ***lower case
are need to be there, the upper case are your field/label names
force addition of
record
ThisWindow.Update IF
ACCESS:InvoiceHeader.PrimeRecord() THEN RETURN
Level:Notify. LOOP
UNTIL ACCESS:InvoiceHeader.Insert() =
Level:Benign END !end
loop GlobalRequest =
InsertRecord
!REL:ReleaseNumber = 0
UpdateInvoiceHeader()
ThisWindow.Reset
close a file to empty it, if procedure has already
opened it
Relate:FILENAME.close() relate:FILENAME.close()
!double close seemed to work open(FILENAME,12h) if errorcode()
message('Error opening FILENAME - ' & errorcode() & '-' &
error()) end empty(FILENAME) if errorcode() message('Error
emptying FILENAME - ' & errorcode() & '-' &
error()) end Relate:FILENAME.open()
function creation inside a generated
app
- create the MAP the very top of the DATA section and
the function name declaration has to be all the way left
- this function sends a long and receives a long
back
- map
Filesexist
FUNCTION(long),long end
- then before the first procedure, or at the end of the
mainline code (in a generated app there is only 1 line of "GlobalResponse =
ThisWindow.Run()"
- FilesExist
function(long
store)
FileQueue
QUEUE(FILE:Queue),
PRE(FQ)
END LOC:ServerPath string(255) CODE
LOC:ServerPath = '\\server\directory\'
DIRECTORY(FileQueue, CLIP(LOC:ServerPath) & '*.DWN',
ff_:NORMAL) RETURN(RECORDS(FileQueue))
RTF Stuff
https://metacpan.org/pod/The_RTF_Cookbook
RTF in Clarion - C:\clarion6\LIBSRC\rtfctl.clw
RTF removal for browse box create a field on your screen,
make it a local var, and hide it *loc:rtf1 is the var in example
below create a local field in your list box *loc:rtf2 is the var in
example below
inside the BRWx.ValidateRecord procedure, after the NOT=Record:OK
!what your doing is: ! moving the field that contains the RTF controls in
it to the screen var that is an rtf and hidden ! then using that rtf controls
function to remove the RTF controls and put into your field that you put in your
browse ! ***still havent found workaround for XPlore template when doing the
output to CSV loc:rtf1 =
FILE:MyRTFField display(?loc:rtf1)
RTFControl21.GetText( loc:rtf2 ,0 ,1024 )
RTF - add some text at end of what
exists
***name your RTF control class...makes it a little easier to maniplulate
rather than number add ":YOURFIELD"
!check for any text in it, if not the start the rtf code
if RTFControl:YOURFIELD.props.length() = 0 PRE:YOURFIELD =
'<123>\rtf -' & GLO:Initials & ' ' & format(today(),@d2) &
' ' & format(clock(),@T1) & ' - <125>' else PRE:YOURFIELD =
PRE:YOURFIELD[1:INSTRING('}',PRE:YOURFIELD,-1,len(clip(PRE:YOURFIELD)) ) - 1]
& '\par-' & GLO:Initials & ' ' & format(today(),@d2) & ' '
& format(clock(),@T1) & ' - <125>' end
RTF - position cursor at the end of the text
***the key is to do the display first (or nothing will work)
display(?PRE:YOURFIELD) select(?PRE:YOURFIELD,RTFControl:YOURFIELD.props.length()
)
RTF on report - if you need to bold a couple
words in a string add a string to local data and make it text and
rtf populate the field on the report in the code you cant use the { or }
so use the hex of <123> or <125> respectively to assign to a
string
so to bold a couple words rtf: {\rtf Here is your {\b
bolded} word.} clarion: <123>\rtf Here is your <123>\b
bolded<125> word.<125>
Example
{\rtf1 {\fonttbl {\f0\fnil\fprq1\fcharset0
Arial;} {\f1\fnil\fprq1\fcharset0 Georgia;} }
this is line 1 with a bold \b word\b0 right here\par this is
line 2 with a fonted \f1\fs28 word\f0\fs17 right here\par this is line
3 with a sized \fs28 word\fs17 right here\cf2\par }
Path Stuff
check for
backslash in
path if
instring('\',SYS:ImageDir,1,len(clip(sys:imagedir))-1) <>
len(clip(sys:imagedir))
message(' Must have \ at
end!!! ','Path
Error',ICON:Exclamation)
cycle end !end
instring
check for path
existence if
not
exists(sys:imagedir)
message(' Directory does
not exist. ','Path
Error',ICON:Exclamation)
cycle end !end not
exists
strip filename and path off a full path named
file
posstart# =
instring('\',rtn:fullfilename,-1,len(clip(rtn:fullfilename))) +
1 rtn:filename =
sub(rtn:fullfilename,posstart#,len(clip(rtn:fullfilename)) - posstart#
+1) rtn:pathname =
sub(rtn:fullfilename,1,posstart#-1)
Directory() note -
the queue will not clear unless you clear it
yourself get the path only for where your
program is running ProgramPath
= sub(command('0'),1,instring('\',command('0'),-1,len(command('0')) )
)
Window stuff
execute code all the time
In ThisWindow.TakeEvent PROCEDURE put before
EnhancedFocusManager.TakeEvent()
show tooltip for disabled fields - use a region with
tip
tired of looking up code to see why a field isn't showing???
just disable and show a tool tip so the user can fix
with a disabled field you can't display a tool tip, so add a
region around the fields, then add some code for the tooltip(b/c there isn't a
tooltip option on the region properties)
- add a region around the disabled field(s)
****ensure the region is defined after the fields(in
the actual window code)
- in the thiswindow.init section after
self.open(windowname)
?region1{prop:tip} = 'If disabled,
check this other field'
instead of hide(?fil:fieldname) ,
unhide(fil:fieldname)
use disable(?file:fieldname) ,
enable(?fil:fieldname)
other options are:
?fil:fieldname{prop:disable} = 0 (equals
enable(?fil:fieldname) )
?fil:fieldname{prop:disable} = 1 (equals
disable(?fil:fieldname) )
counting clock on window (to display when the window was
refreshed)
-
put your variable on the window
-
on the window, do properties on Frame, goto Extra, then
Timer (digits are in 100ths of a second, so 100 is 1 second) (this tells the
window to retrieve the timer event every however many you set
-
in ThisWindow.Run procedure put LOC:WindowTime =
clock()
-
in ThisWindow.TakeWindowEvent , Event:Timer
put
Cancel/Close a window - after prompt of "Changes
will be lost" "Are your sure you want to Cancel" - do something if really
canceling
***good for if there was an record added to another file that
needs deleted
in ThisWindow.TakeCloseEvent PROCEDURE
after ReturnValue = PARENT.TakeCloseEvent()
IF ReturnValue = Level:Benign
!the user answer "YES"
to are you sure you want to cancel
if self.request =
insertrecord
!do
something
end ELSE
!the user answer "NO" or closed
the prompt box
END
Hide/Disable
everything - remember to enable your
buttons DISABLE(1,LASTFIELD()) ENABLE(?OK) ENABLE(?Cancel)
ignore an accept, (dont want to fire AN accept that is
on a field) if not
0{Prop:AcceptAll} ...do your normal
stuff end !end if not 0
ignoring an accept (dont want to fire NONE the
accepts when the user hits save ???) put this as last embed of
ACCEPT of your save button
put your
edits above the "Generated Code" of your save button
!**** BEWARE - the code below will not fire accepts under input fields
!---- make validation checks before
0{prop:AcceptAll} = 0
put(YOURFILENAME) post(event:closewindow,?ok)
disable the X on a window -inside
Global map: module('') GetSystemMenu(unsigned,
signed),unsigned,PASCAL RemoveMenu(unsigned, signed,
signed),signed,PASCAL
DrawMenuBar(unsigned),signed,PASCAL end
-in your procedure, declare 3
varibles hMenu
UNSIGNED nRemove
SIGNED nDraw
SIGNED
-in your procedure, after OpenWindow (and after any kind of
frame sets, mainly icon) hMenu =
GetSystemMenu(QuickWindow{Prop:Handle}, 0) nRemove =
RemoveMenu(hMenu, 0F060h, 01000h) nDraw =
DrawMenuBar(QuickWindow{Prop:Handle})
capture closing with X or Escape or Closebutton (good
for a lookup window and user getting out without selecting
something) ThisWindow.TakeWindowEvent PROCEDURE ... before
generated code OF
EVENT:CloseWindow ! Start of "Window Event
Handling" ! [Priority 4999] !here if not
(self.response = RequestCompleted) !SAM
09/12/2014 if loc:DebugIT then
message('hello ... here in Window Events.CloseWindow ... NOT RequestCompleted ')
.
clear(CUS:CustomerNumber) end
if (self.response = RequestCancelled) !SAM
09/12/2014 if loc:DebugIT then
message('hello ... here in Window Events.CloseWindow ...
RequestCancelled').
clear(CUS:CustomerNumber) end
capture closing with X or ALT-F4, but allowing
Escape
in ThisWindow.TakeCloseEvent PROCEDURE
!IF Event() =
Event:CloseWindow AND Self.Response <> RequestCompleted !this wont allow
any cancel
IF
Event() = Event:CloseWindow
AND
Self.Response = 0
message('Don''t close the window this way, it''s bad for your health.|'
&
'Self.Response : ' & Self.Response,'Don''t exit this
way',icon:exclamation )
Return(Level:Notify)
END
in ThisWindow.Init PROCEDURE
0{prop:alrt,255} = EscKey
in ThisWindow.TakeEvent PROCEDURE
If
Event() = Event:AlertKey
and
Keycode() = EscKey
!message('hello')
post(Event:accepted,?Cancel)
end
add CTL-ALT-F12 (hidden key stroke) to procedure
ThisWindow.init 0{prop:alrt,255} =
AltShiftF12
ThisWindow.TakeEvent If Event() =
Event:AlertKey and Keycode() =
AltShiftF12
?Group:TaxAndDeductions{prop:disable} =
0
display(?Group:TaxAndDeductions)
?Group:HoursAndPay{prop:disable} =
0
display(?Group:HoursAndPay) end
FDCB File Drop Control Box stuff
this is to set a combo (FDCB) based on another field
being filed in also the FDCB is displaying a display value and the
props itself
FIL:field1
= DSP:field1 get(FILENAME,FIL:Keybyfield1)
Queue:FileDropCombo:2:FIL:field1 =
FIL:Field1
get(Queue:FileDropCombo:2,Queue:FileDropCombo:2:FIL:Field1)
IF ~ERRORCODE()
THEN ?dsp:field1{Prop:Selected} =
POINTER(Queue:FileDropCombo:2) END
dsp:field1 = Queue:FileDropCombo:2:FIL:Field1
display(?dsp:field1)
FDCB drop box - clear it after selection In
your drops control "All Events"
if keycode() = DeleteKey
clear(PRE:FIELDNAME)
?PRE:FIELDNAME{PROP:Selected} = -1
display(?PRE:FIELDNAME)
end
After a FDCB selection, if there is something from the
drop you need to investigate
for the accept in NewSelection embed
FDCBxx.TakeNewSelection()
FDCBxx = name of the class
BROWSE related stuff
display a browse filter on window in
the ThisWindow.TakeEvent Embed (PRIORITY=4000) simply code:
dsp:Filter =
BRW1::View:Browse{PROP:Filter}
reload a browse after file
changes
flush(BRW1.view)
BRW1.ResetQueue(Reset:Queue) ! Reset queue with current highlighted record
retained. BRW1.PostNewSelection
disable right-mouse items
---disable delete options on browse(will disable buttons and
right-mouse options) -this disables the delete key and the right-mouse
options(even if you have xplore template)
in BRWx.UpdateWindow before parent call
SELF.DeleteControl = 0
disable(?Delete)
-to disable others SELF.InsertControl =
0 disable(?Insert)
SELF.ChangeControl = 0
disable(?Change) SELF.DeleteControl =
0 disable(?Delete)
Set a browse to a certain record when
opening
in ThisWindow.init right before the BRWx is
initialized
! [Priority 8122] if prm:yourfield
<> ''
clear(PRE:Record)
PRE:yourfield =
prm:yourfield
LocateTo =
prm:yourfield
display(?LocateTo) end !end if prm:yourfield
<> ''
Locator string definition !!>
IDENT(4294966861),PICTURE(@s80) [SCREENCONTROLS] ! PROMPT('Locate
To:'),USE(?LocateTo:Prompt) !
STRING(@s20),USE(LocateTo),FONT(,,COLOR:Red,,CHARSET:ANSI) [REPORTCONTROLS] !
STRING(@s20),USE(LocateTo) LocateTo
STRING(20)
Browse-NewSelection not getting updated
variables if clicked with mouse in NewSelect embed include this before doing what you need to
do BRWx.UpdateViewRecord()
set to first record in browse (good for if there
are fields at top and setting after a search) Post(Event:ScrollTop,?Browse:1)
select(?Browse:1)
set to browse box(if other fields are on window)
-also can use this to select a different field than the first one in the
window based on some criteria
through embeds - "Window Events\Open Window" -
select(?browse:1)
through source - search for "EVENT:OpenWindow" -
select(?browse:1)
got a column in a list/browse box that is
discolored and showing negative? look for a
column defined TWICE in the list/browse box
color a field in a browse list
box
- properties of the procedure, extensions, colors -
tells you how to do it
- list box properties, hi-lite field you what colored,
and check color
- then back to the procedure extensions, color, your
field should show up, put your condition and color in
there
filter a record from loading into
Browse
Goto: Local Objects >> ABC Objects >> Browse
on "File" (BrowseClass),ValidateRecord (AFTER Parent Call)
If ReturnValue = Record:OK If
File:PartNo = HLD::PartNo
ReturnValue = Record:Filtered End End
HLD::PartNo = File:PartNo
set a variable based on browse
loading in BRWx.ResetFromView PROCEDURE !beginning of code set
your variable somerecordfound = 0
!in load of browse validate(BRWx.ValidateRecord
PROCEDURE)
!at end of procedure set the screen
var if
somerecordfound
?String:MyWarning{prop:hide} = 0
else ?String:MyWarning{prop:hide}
= 1 end
set a variable during load of
browse BRWx.ValidateRecord PROCEDURE !at end of code b/c let the
browse filter take care of the not records If ReturnValue
= Record:OK if
somevariable
somerecordfound = 1
end End
get hi-lited record from browse
queue
get(Queue:Browse,choice(?list))
look up non-related record embed
point
BRWxx.SetQueueRecord()
refresh a browse - you figure out where you
want to put it, like creating a refresh button on the window...
BRW1.ResetFromFile() ThisWindow.Update
do something after
delete message from a browse answered YES
Embeds->Local Objects->ABC objects->Browse on
File->ResetFromAsk->Source: if request = 3 and response = 1
then ! if delete button and answer Yes ! updating
parent end
***IMPORTANT - if you need a piece
of info from the record you are deleting, like to update another file in
procedure: (or just embeds of button) ThisWindow.TakeAccepted
PROCEDURE OF ?Delete
get(Queue:Browse:YOURFILE,choice(?Browse:YOURFILE))
HoldForDelete:PRE:FIELDNAME = queue:browse:YOURFILE.PRE:FIELDNAME
Search criteria on top of the browse box to
build a filter SetSearch routine
!SER: fields are search fields on top of the browse that your allowing input
!Match Flag Values
!Match:Simple EQUATE(0)
!Match:Wild EQUATE(1)
!Match:Regular EQUATE(2)
!Match:Soundex EQUATE(3)
!Match:NoCase EQUATE(10H) ! May be added to Simple,Wild and Regular
gotfilter# = 0
clear(hld:filter)
!Example of doing match on a string field
if ser:frame <> ''
if gotfilter#
hld:filter = clip(hld:filter) & ' and'
end
hld:filter = ' match(sm:frame,<39>' & ser:frame & '<39>,1)'
gotfilter# = 1
end
!EXAMPLE of doing a numeric field with not looking at the decimals
if ser:hp1 > 0
if gotfilter#
hld:filter = clip(hld:filter) & ' and'
end
hld:filter = clip(hld:filter) & ' sm:hp1 >= ' & clip(format(ser:hp1,@n_10.2b)) & ' and sm:hp1 < ' & clip(format(int(ser:hp1+1),@n_10b))
gotfilter# = 1
end
!EXAMPLE of just a straight string
if ser:LocationPrefix <> 'AL'
if gotfilter#
hld:filter = clip(hld:filter) & ' and'
end
hld:filter = clip(hld:filter) & ' inv:locationprefix = <39>' & clip(ser:LocationPrefix) & '<39>'
gotfilter# = 1
else
gotfilter# = 1
end
if gotfilter#
BRW1.SetFilter(hld:filter,2)
dsp:Filter = BRW1::View:Browse{PROP:Filter}
display(?dsp:filter)
BRW1.ApplyFilter()
! stop('after-' & clip(BRW1::View:Browse{PROP:Filter}))
BRW1.ResetQueue(Reset:Queue)
BRW1.ResetFromView()
?Button:Search{prop:color} = color:none
Post(Event:ScrollTop,?Browse:1)
select(?Browse:1)
end
exit
EIP (Edit In Place) validate field
add field as "Column Specific" (in Configure Edit In
Place)...this will create embed points for that field
like: EditInPlace::PRE:FIELDNAME.xxxxxx
This is tricky. Yes, the EIP control's TakeEvent is the
proper method, but you have to put it AFTER the PARENT call; you have to
PRECEED it with an "UPDATE(SELF.Feq)"; you DON'T use the
Level:Benign/Notify/Fatal but the EditAction: equates instead; and you DON'T
update the file field, but the BRW.Q field instead! For instance, from a
test program, this checks for and disallows a blank field. This is AFTER the
PARENT call.
-in EditInPlace::PRE:FIELDNAME.TakeEvent
UPDATE(SELF.Feq) IF ReturnValue AND ReturnValue <>
EditAction:Cancel THEN IF BRW1.Q.File1:Field1 = ''
THEN MESSAGE('Field Cannot Be
Blank','Field
Error',ICON:Exclamation)
ReturnValue = EditAction:None END END
-in BRWx::EIPManager.TakeFocusLoss PROCEDURE ...before the
parent call this is so if the user keeps hitting the insert key or
some other button
if BRWx.Q.PRE:FIELDNAME = ''
Self.Again = true Self.Column =
BRWx.Q.PRE:FIELDNAME
post(event:selected) return end
-on Insert Key embed put this to disable the escape key
outside the browse alert(esckey)
EIP (Edit in Place) update another field on the file and
in the list box
***the key here is to look at the fields declared in the
list/browse and get their queue:browse name
EditInPlace::PRE:FIELD.TakeAccepted PROCEDURE(BYTE
Action)
after ReturnValue =
PARENT.TakeAccepted(Action)
queue:browse:1:PRE:OTHERFIELDTOBEUPDATED =
queue:browse:1:PRE:FIELD * queue:browse:1:PRE:SOMEFIELD
EIP (Edit in Place) get Detailed Interface
goto Global Properties, Classes, Browser, Template Interface - make it
Detailed
Report stuff
Report straight to Printer based on
variable...if not go straight to PDF *** if you have RPM
Standard Report Template(mainly for fancy previewer and/or page renumbering) in
the procedure, REMOVE it -if you
need RPM page renumbering you can add a different RPM that *** if
PDFx is in procedure, REMOVE it *** using the SV(Soft
Velocity)/Clarion PDF template, you will have to open the generated PDF in the
thiswindow.close procedure
-add Global template/extension "Report to PDF -
Global"
-Procedure Properties - "Report Properties"
button - Report Targets Tab, set "Report Target" to "Ask At
Runtime" ***If this tab control does not appear
after including the Advanced Report Generation Global , Extension, make sure to
refresh the template generation sequence by selecting Source or Embeds in the
proper procedure.
-in source, ThisWindow.init - put an
erroneous if statement around
"TargetSelector.AddItem(PDFReporter.IReportGenerator)" with the END after
"SELF.AddItem(TargetSelector)" like so: if
loc:ThisNeverGetsSet# = 1
TargetSelector.AddItem(PDFReporter.IReportGenerator) IF NOT
TargetSelector.ASK(1) THEN
SELF.Kill() RETURN Level:Fatal
END IF NOT TargetSelector.GetPrintSelected()
THEN
SELF.SetReportTarget(TargetSelector.GetSelected())
END SELF.AddItem(TargetSelector) ! [Priority
8420] end - after that code
put: IF loc:SendStraightToPrinter =
1 !do nuttin, let it
go straight to default printer
else
TargetSelector.AddItem(PDFReporter.IReportGenerator)
SELF.SetReportTarget(PDFReporter.IReportGenerator)
SELF.AddItem(TargetSelector)
end
When using SVPDF - want to NOT pop the
PDF(if exists previously from a PDF print) and they selected to go straight to
printer
in ThisWindow.init after the
TargetSelector stuff (this stuff is in C:\clarion6\LIBSRC\ABRPTGEN.INT and
C:\clarion6\LIBSRC\ABPRPDF.CLW and C:\clarion6\LIBSRC\ABRPPSEL.CLW)
loc:PDFSelected =
0 IF ~SELF.ReportTarget &=
NULL IF SELF.ReportTarget.WhoAmI()
=
RepGen:PDF
loc:PDFSelected = 1
end end
Change Jobname, either when goes to print queue
OR goes to a pdf distiller with the filename in
ThisWindow.OpenReport PROCEDURE
settarget(Report) 0{prop:text} =
'Print of - ' & loc:YOURVARIABLEHERE
settarget()
exit report gracefully in
ThisWindow.init
before file opens(not tested after
opens) if
loc:QuitProcedure return
Level:Fatal end
after file opens if
loc:QuitProcedure
SELF.Kill() RETURN Level:Fatal
end
OR if loc:myscenarionotmet
SELF.Kill() RETURN
Level:Fatal end
print another line after normal detail lines are
printed from main file
-in ThisWindow.endreport put your
code
filter a record (without putting it in Report Properties
Record Filter)
Embeds->Local Objects->ABC objects->Process
Manager->ValidateRecord(AFTER Parent Call):
if PRE:FieldName <> Whatyouwant
ReturnValue =
Record:Filtered
end
Image aspect DisplayImage ROUTINE
IF ?Image1{PROP:Height} > 100 AspectRatio$ =
?Image1{PROP:Width}/?Image1{PROP:Height}
?Image1{PROP:Height} = 100 ?Image1{PROP:Width} = 100 *
AspectRatio$ END IF ?Image1{PROP:Width} >
100 AspectRatio$ =
?Image1{PROP:Height}/?Image1{PROP:Width}
?Image1{PROP:Width} = 100 ?Image1{PROP:Height} = 100 *
AspectRatio$ END
change a field color before
printing SETTARGET(Report)
if loc:MyField <= 0
?loc:MyField{PROP:fontcolor} = color:red
else ?loc:MyField{PROP:fontcolor}
= color:none end SETTARGET
PRINT(RPT:detail)
POP a calendar date
selection in a Report before running
--data section add: calendarX calendarclass
--in ThisWindow.init after the open
files Calendar1.SelectOnClose = True Calendar1.Ask('Select a
Date',loc:reportdate)
IF Calendar1.Response = RequestCompleted
THEN loc:reportdate = Calendar1.SelectedDate else ReturnValue =
PARENT.EndReport() End
***notes Loc:reportdate is a local declared
variable…use whatever you want .ask first parameter is whatever you want
the title of the window to be
display filter on report
in proc "ThisWindow.OpenReport PROCEDURE "
loc:reportfilter =
Process:View{PROP:FILTER} !!! message('here in the report:'
& clip(loc:reportfilter) )
do totals on last page only in the footer 1. add a
group break on a variable that wont really change ***ensure you
leave the footer...you can delete the group header, then copy you detail line
into the detail line the group break created(use the report code) 2. data -
add a local var for a counter loc:recordcount 3. in code - after the
print(detail), putin in loc:recordcount += 1 4. on report - add your string
prompt on footer, and hide it 5. on report - add your local var
(loc:recordcount) to the footer and hide it 6. in code add the
following ThisWindow.AskPreview PROCEDURE !***before the parent call to
PARENT.AskPreview
report$?String:NumberofRecordsPrompt{prop:hide} = 0
report$?loc:recordcount{prop:hide} = 0
Report to CSV with GWBCSV template
http://comformark.com/pages/clarion-templates.php
***NOTE - you may want to increase filename, default is
100 -in
GWBCSV.Tpl find "GWBCSVFileName
CSTRING(100)"
-remember not to go over 218 see "ShellExecute"
section
1. add the GWBCSVExport to your Global Extensions 2. on the Report, open
the progress window 2.1 add the Control Template "PauseButton - Pause
the Process" ***NOTE the GWBCSVReportExport will not
show until you add the Pause 2.2 add the GWBCSVReportExport to the
window (this adds the export filename to the window) 2.3 add a close to
the file b/c sometimes it still has lock in
ThisWindow.TakeCloseEvent put:
close(GWBCSVFile) 3. in Source 3.1. find in ThisWindow.init where
the template sets the "GWBCSVFileName" and reset if need
be ***NOTE the default is to create the file in the directory
where the program is running 3.2. if you want to open Excel(or whatever
is associated with CSV) ***see "ShellExecute" for adding
xxxxShellExecute/xxxxGetDesktopWindow procs in
Data section
put: OPN
CSTRING(10) NStr
CSTRING(5) ShowIT
SIGNED NoRecordsFound Byte in
ThisReport.Close put: if ~NoRecordsFound !make sure the report
was produced before trying to open
OPN =
'OPEN' NSTR =
'' Showit =
5 HInst# =
xxxxShellExecute(xxxxGetDeskTopWindow(),OPN,GWBCSVFileName,NStr,NStr,Showit)
IF Hinst#>32
!noerror
ELSE MESSAGE('Shell
launching error:' & hinst# & '|you may need to specify a file type in
Win95|Go to Explorer; View; Options; File Types|and the specify a type for '
& GWBCSVFileName,' PT')
END end !end ~NoRecordFound in
ThisWindow.TakeNoRecords after parent call
put: NoRecordsFound = 1
Report print jumbled either runs together or looks
funky The print can be straight to printer or produced to a PDF.
The Report doesn't have a "default" font to fall back to.
If the DPI is anything other than "Normal" then output of fonts looks
funky
To Resolve in your Report: Add FONT('Arial',10,,,) to the actual REPORT
definition
Arial is installed as default on all systems.
To Resolve in Windows(without modifying Report) Check the DPI settings
in Windows
In Windows XP: • Go to Start > Control Panel • Double
click Display • Select the Settings Tab and click the Advanced
button • Change the drop-down menu under DPI setting to Normal size
(96 DPI) and click OK In Windows Vista: • Go to Start > Control
Panel • Double click Personalization • Click Adjust font size
(DPI) • Select Default scale (96 DPI) - fit more information and
click OK In Windows 7: • Go to Start > Control
Panel • Click Display • Select Smaller - 100%(default) and
click Apply
Font problems with the PDF generation templates taken from: http://www.icetips.com/blog/index.php/2009/04/21/font-problems-with-the-pdf-generation-te
The problem stems from code in the ABPRPDF.CLW file where the
width of the characters is calculated. To fix this Arnor made some changes
to the files.
This involves adding a single method to the PDFGeneratorClass
class in ABPRPDF.INC and ABPRPDF.CLW:
Add to class declaration in ABPRPDF.INC (I put it in at the top
of the method list, around line 195):
AdjustDPIValues PROCEDURE(Long pValue),Long !!
AB 2009-02-19 Adjusts DPI values
In the classfile, ABPRPDF.clw, I added this:
PDFGeneratorClass.AdjustDPIValues PROCEDURE(Long
pValue)!!,Long !! AB 2009-02-19 Adjusts DPI values HDcScreen
UNSIGNED IDPI
Long R
Real L
Long Code R = 1 HDcScreen = GetDC(0) If
HDcScreen <> 0 IDPI = GetDeviceCaps(HDcScreen,
88) L = ReleaseDC(0, HDcScreen) R =
IDPI/96 End Return (pValue / R)
In PDFGeneratorClass.AddFontDescriptor method, you have code
like this:
!SET the fonts Width LOOP LOC:I=SELF.FontsNames.FirstChar TO
SELF.FontsNames.LastChar
LOC:CharToTest=CHR(LOC:I) IF
GetTextExtentPoint32(LOC:DC,LOC:CharToTest, 1,LOC:CharSize)<>0
THEN IF LOC:Subclasing
THEN IF
SELF.FontsNames.CharWidth[LOC:I]
THEN
SELF.FontsNames.CharWidth[LOC:I] =
LOC:CharSize.eW
END
ELSE
SELF.FontsNames.CharWidth[LOC:I] =
LOC:CharSize.eW END
END END
I changed both of the assignments to the CharWidth
to:
SELF.FontsNames.CharWidth[LOC:I] =
|
SELF.AdjustDPIValues(LOC:CharSize.eW)
In PDFGeneratorClass.GetTextWidth method, you have code like
this:
IF SelectObject(LOC:DC, LOC:HFont)
THEN RV = GetTextExtentPoint32(LOC:DC,pText,
LEN(pText),LOC:CharSize)
LOC:OLDMAPMODE=SetMapMode(LOC:DC,LOC:OLDMAPMODE)
DeleteObject(LOC:HFont) RETURN LOC:CharSize.eW +
(LOC:CharSize.eW/20) END
I changed the RETURN to adjust the value:
RETURN SELF.AdjustDPIValues(LOC:CharSize.eW +
(LOC:CharSize.eW/20))
This takes care of the font sizing problem in any DPI
combination that I threw at it:)
API stuff (External
OS stuff)
Clarion Open
Source (cant find how to prototype something?...look here http://www.clarionopensource.com/
WINAPI - Windows information
-take the winapi app from the
C:\clarion6\Examples\RESOURCE\Winapi ***you will probably have to compile
it -run program and pick all the stuff you want (you might also include DWORD
and HANDLE from the data structures part) -it will generate a "winapi.clw" in
whatever directory you put it in -copy the "winapi.clw" whereever your
clarion looks for clw's from (in you C6EE.red file)
in your app: goto "Global Properties",
"Embeds"
Include the Equates section of WINAPI.CLW in the
"After Global INCLUDEs" embed point:
INCLUDE('WINAPI.CLW','Equates')
Include the Prototypes section of WINAPI.CLW in the
"Inside the Global Map" embed point:
INCLUDE('WINAPI.CLW','Prototypes')
most equates are
here C:\clarion6\LIBSRC\winequ.clw C:\clarion6\LIBSRC\windows.inc
you could use OR use it for
ideas C:\clarion6\LIBSRC\hndutil.clw (contains the actual
procedures) -these are everything it
uses --C:\clarion6\LIBSRC\hndapi.inc (defines all the mapped
procedures) --C:\clarion6\LIBSRC\hndequ.clw (all the
equates) --C:\clarion6\LIBSRC\hndutil.inc (is a bunch of other
utils)
ShellExecute If you doing like so below, you
can switch: RUN('cmd /c "'&CLIP(CSVFileName)&'"')
Switch to below...(it wont spawn a dos
window)
---PROTOTYPES-------------------------------- !make sure these
are in your WINAPI.CLW (or put them in Global Embeds, "Inside Global
Map") !replace "xxxx" with your prefix, i would give it a prefix b/c one of
your other templates might also use the shellexecutes !*note - the 2nd 3rd
4th 5th variables must be CSTRINGS
xxxxGetDeskTopWindow(),UNSIGNED,PASCAL,NAME('GetDeskTopWindow')
OMIT('***Width16***',_WIDTH32_)
xxxxShellExecute
(UNSIGNED,*CSTRING,*CSTRING,<*CSTRING>,<*CSTRING>,SIGNED),UNSIGNED,PASCAL,RAW,PROC,NAME('ShellExecute')
!***Width16***
COMPILE('***Width32***',_WIDTH32_)
xxxxShellExecute
(UNSIGNED,*CSTRING,*CSTRING,*CSTRING,*CSTRING,SIGNED),UNSIGNED,PASCAL,RAW,PROC,NAME('ShellExecuteA')
!***Width32***
---DATA------------------------------------- ! these must be
defined, cant do inline b/c its expecting CSTRINGS ! did i mention your
filename must be declared as CSTRING ! *note - if doing a CSV with Excel
make filename 218 just to be safe...see http://www.xldatasoft.com/filename.htm
OPN
CSTRING(10) NStr
CSTRING(5) ShowIT SIGNED
---Example
CODE------------------------------------- !the below is for to open
google maps
fulladdress =
'http://maps.google.com/maps?hl=en&q=' & clip(CM:Address1) & ' '
& clip(CM:City) & ' ' & clip(CM:State) & ' ' &
clip(CM:ZipCode)
OPN =
'OPEN' NSTR =
'' Showit = 5
HInst# =
xxxxShellExecute(xxxxGetDeskTopWindow(),OPN,fulladdress,NStr,NStr,Showit)
IF Hinst#>32
!noerror
ELSE MESSAGE('Shell launching
error:' & hinst# & '|you may need to specify a file type in Win95|Go to
Explorer; View; Options; File Types|and the specify a type for ' &
clip(fulladdress),' PT') END
!this is for opening a CSV file with whatever app is associated
with file extensions of CSV !to test, just goto DOS prompt and type the
filename...if it doesnt open the correct app, then fix with "SHFT-right mouse,
open with" OPN =
'OPEN' NSTR = ''
Showit = 5 HInst# =
xxxxShellExecute(xxxxGetDeskTopWindow(),OPN,CSVFileName,NStr,NStr,Showit)
IF Hinst#>32 !noerror
ELSE MESSAGE('Shell launching error:' &
hinst# & '|you may need to specify a file type in Win95|Go to Explorer;
View; Options; File Types|and the specify a type for ' & CSVFileName,'
PT') END
Procedure to define 1 easy proc to do the file open so you
dont have to define vars and such above
PopFile
PROCEDURE (string prm:filename) ! Declare
Procedure
loc:filename cstring(512) OPN
CSTRING(10) NStr
CSTRING(5) ShowIT SIGNED
CODE loc:filename = prm:filename
OPN =
'OPEN' NSTR =
'' Showit = 5
HInst# =
ShellExecuteDeclaredInWINAPI(PSDSGetDeskTopWindow(),OPN,loc:filename,NStr,NStr,Showit)
IF Hinst#>32
!noerror
ELSE MESSAGE('Shell launching
error:' & hinst# & '|you may need to specify a file type in Win95|Go to
Explorer; View; Options; File Types|and the specify a type for ' &
clip(loc:filename),' PT') END
From the Help File - things you can't
never remember
Implicit variables (declare variables
on the fly) The Clarion language provides three
types of implicit variables: # A label terminated by a # names an
implicit LONG. $ A label terminated by a $ names an implicit
REAL. " A label terminated by a " names an implicit
STRING(32).
Operating Assignments
Operating Assignment |
|
Functional Equivalent |
|
|
|
A += 1 |
|
A = A +
1 |
A -= B |
|
A = A -
B |
A *= -5 |
|
A = A *
-5 |
A /= 100 |
|
A = A /
100 |
A ^= I + 1 |
|
A = A ^ (I +
1) |
A %= 7 |
|
A = A %
7 |
Deep Assignment principle:(from newsgroup) (1) At least 1
VarName in the Target should exactly match that of the Source (2)
Executing the deep assignment assigns the value from the Source for each
matching VarName in the Target, ignoring those unmatched VarName (3)
Assigment syntax File to Queue - ListQueue :=:
RPH:Record Queue To File - XYZ:Record :=:
ListQueue File1 to File2 - DEF:Record :=:
OPQ:Record Queue1 to Queue2 - NameQue2 :=: NameQue1
-Equates InsertRecord EQUATE
(1) !Add a record to table ChangeRecord EQUATE
(2) !Change the current record DeleteRecord EQUATE
(3) !Delete the current record
RequestCompleted EQUATE (1) !Update
Completed RequestCancelled EQUATE (2) !Update
Aborted
BIND
bind('fieldname',fieldname)
NULL if null(myfield) =
1 same as SQL: where myfield is null
so a compound check
if (myfield = '' or null(myfield) = 1 )
message('My field can not be
blank.')
?myfield{prop:background} =
color:yellow
select(?myfield)
cycle
end
Data Types
Clarion |
C++ |
Modula-2 |
BYTE |
unsigned char |
BOOLEAN |
BYTE |
unsigned char |
SHORTCARD |
*BYTE |
unsigned char * |
var SHORTCARD |
USHORT |
unsigned short |
CARDINAL |
*USHORT |
unsigned short * |
var CARDINAL |
SHORT |
short |
INTEGER |
*SHORT |
short * |
var INTEGER |
LONG |
long |
LONGINT |
*LONG |
long * |
var LONGINT |
ULONG |
unsigned long |
LONGCARD |
*ULONG |
unsigned long * |
var LONGCARD |
SREAL |
float |
REAL |
*SREAL |
float * |
var REAL |
REAL |
double |
LONGREAL |
*REAL |
double * |
var LONGREAL |
STRING |
can’t pass by value |
can’t pass by value |
*STRING |
unsigned int, char * |
CARDINAL, ARRAY OF CHAR |
*STRING(with RAW) |
char[] |
var ARRAY OF CHAR |
*CSTRING(with RAW) |
char[] or char * |
var ARRAY OF CHAR |
*PSTRING |
char[] or Char * |
ARRAY OF CHAR |
GROUP |
struct |
var record type |
*GROUP(with RAW) |
struct * |
var record type |
*? |
void far* |
FarADDRESS |
UNSIGNED |
unsigned int |
|
DATE/TIME stuff - date stuff is always a pain
- Display day of week (modulus
function)
DATA DisplayDayString
STRING('Sunday Monday Tuesday WednesdayThursday
Friday Saturday ') DisplayDayText
STRING(9),DIM(7),OVER(DisplayDayString) DayNumber
short CODE AppFrame{Prop:StatusText,3} =
CLIP(DisplayDayText[(TODAY()%7)+1]) mystring =
CLIP(DisplayDayText[(TODAY()%7)+1]) DayNumber = (today()%7) + 1
- 6 digit numeric to real date compare
CSTS:CSDATE = format(CSH:MDATE,@D11) OR csts:csdate =
format(today()-1,@d11)
- date equivalents
1900/01/01 = 36163
1980/01/01 = 65382 2008/01/01 = 75609 2008/12/31 = 75974
- Excel to Clarion and back
Using Formulas
for Dates or Times To use a LONG field containing a Clarion Standard Date
or a Clarion Standard Time, you can create a formula in the product you are
using to access the TopSpeed files. Here are some examples:
- DATE
- Converting a Clarion date to a Microsoft Excel Date:
Subtract 36161 from the Clarion date value.
- Converting a Microsoft Excel date to a Clarion Date: Add
36161 to the Microsoft Excel date value.
- TIME
- Converting a Clarion time to a Microsoft Excel time:
Divide the Clarion time value by 86400 (the number of seconds in one day),
then divide by 100 to express as a decimal value.
- Converting a Microsoft Excel time to a Clarion time:
Multiply the Microsoft Excel time value by 0.0000001157407407407410 (1
divided by the number of seconds in a day; includes the adjustment to
convert back from a percentage).
- Exporting excel time field - change to general(so its a
number it will look like
.270833333)
(cast([EXCELDECIMALTIMETOSQL] as
real)/0.0000001157407407407410) + 1
- TIME - add XX minutes to clock or time field (XX is
minutes you want to add/subtract)
YOURFIELD = clock() + (XX *
6000) OR YOURNEWFIELD = TIMEFIELD + (XX * 6000)
- MISC SQL and Clarion
-Clarion
long - SQL date time field to long Clarion These are all
equal... select datediff( dd,'18001228',DateTimeFieldName ) select
datediff( dd,'18001228','20140717' ) select datediff(
dd,'1800-12-28','2014-07-17' ) select datediff(dd,-36163,'2014-07-17'
)
-time field long(in sql), view in
sql DateAdd(ms, ClarionTimeFieldasLong * 10,
'1801-01-01')
--whole date/time field set to 1801 DateAdd(ms, ClarionTimeFieldasLong *
10, convert(varchar(10),getdate(),120) ) --whole date/time field set to
today DateAdd(ms, ClarionTimeFieldasLong * 10,
0)
--whole date/time zero SQL date part DateAdd(ms, ClarionTimeFieldasLong *
10, (ClarionDateFieldasLong -36163) ) --whole
date/time field using clarion long date and clarion long
time convert(varchar(10), DATEADD(second,
FLOOR((ClarionTimeFieldasLong - 1) / 100), 0) , 108
) --time
part only HH:MM:SS (24hour clock) RTRIM( RIGHT( (CAST(DATEADD(second,
FLOOR((ClarionTimeFieldasLong - 1) / 100), 0) AS CHAR(24))), 13 ) ) --time
part AM/PM
-Time SQL datetime to Long
Clarion
ISNULL ((CAST(DATEDIFF(ss, CONVERT(DATETIME, CONVERT(VARCHAR(10),
getdate(), 120)
+ ' 00:00:00.000'),
getdate()) AS
INT) *
100) + 1,
0)
SQL and Clarion
- Clarion date to display as
YYYYMMDD
convert(datetime,([YOURCLARIONLONGDATEHERE]-36163)) AS
whatevername
- SQL DateTime (from DateTime field) to long -
Clarion is 8,640,000 hundreths of a second in a day
(datepart(hh,YOURDATE)*360000) + (datepart(n,YOURDATE)*6000) +
(datepart(ss,YOURDATE)*100)
- convert a concatenated fields that the date is stored
in 4 spearate integer fields
datediff(day, '18001228',
convert(datetime, cast( cast((CCFIELD * 1000000 + YYFIELD * 10000 + MMFIELD *
100 + DDFIELD)as int(8)) as char(8) ) ) )
- SQL datetime field to Clarion
date
datediff(day,'18001228',SQLDATETIMEFIELD)
- SQL convert Clarion long
date
convert(datetime,([YOURCLARIONLONGDATEHERE]-36163)) AS
whatevername
- SQL to convert clarion date to just date
part
select
convert(date,convert(datetime,([clariondatefield]-36163))),*
from
filename
- SQL date time field to long Clarion (to get to the
number)
These are all equal... select datediff(
dd,'18001228',DateTimeFieldName ) select datediff( dd,'18001228','20140717'
) select datediff( dd,'1800-12-28','2014-07-17' ) select
datediff(dd,-36163,'2014-07-17' )
- Clarion long time field to SQL, view in
sql
DateAdd(ms, ClarionTimeFieldasLong * 10,
'1801-01-01')
--whole date/time field set to 1801 DateAdd(ms,
ClarionTimeFieldasLong * 10, convert(varchar(10),getdate(),120) )
--whole date/time field set to today DateAdd(ms, ClarionTimeFieldasLong *
10,
0)
--whole date/time zero SQL date part DateAdd(ms, ClarionTimeFieldasLong *
10, (ClarionDateFieldasLong -36163) ) --whole
date/time field using clarion long date and clarion long
time convert(varchar(10), DATEADD(second,
FLOOR((ClarionTimeFieldasLong - 1) / 100), 0) , 108
) --time
part only HH:MM:SS (24hour clock) RTRIM( RIGHT( (CAST(DATEADD(second,
FLOOR((ClarionTimeFieldasLong - 1) / 100), 0) AS CHAR(24))), 13 ) ) --time
part AM/PM
- SQL clear the time part of a SQL defined
DateTime
dateAdd(dd,datediff(dd,0,YOURDATETIMEFIELD),0) ***if
your convert datetime fields from a DB that uses both parts, Clarion doesnt
like the time part of a DateTime field, so it needs zeroed ***if you have a
date that is part of a Date group over and that is defined in a browse, you
will probable get error "Fractional Truncation (01004)"
- SQL function (scalar) to convert Clarion date to SQL
datetime field
***this tip taken from
news.softvelocity.com/s.c.thirdparty - Alan Telford ***also FM3 puts
ds_ConvertClarionDateTime if you need to use it for some SQL code
- create a function in your DB
create function dbo.YOURDATABASENAME cladate ( @InClaDate as int )
returns datetime
as
begin
declare @SqlDate int
declare @SqlDateTime datetime
declare @ClaRoot datetime
declare @MssqlRoot datetime
set @ClaRoot = 'Dec 28, 1800'
set @MSSQLRoot = 'Jan 01, 1900'
set @SqlDate = @InClaDate - datediff(day,@ClaRoot,@MssqlRoot)
if @InClaDate > 2994626 -- invalid Clarion Date
return 1
if @InClaDate = 0
return -1 -- zero date and time
else
set @SqlDateTime = convert(datetime,@SqlDate,0)
return(@SqlDateTime)
end
see your function in SQL Manager - under
"YOURDATABASENAME, Programmability, Functions, Scalar"
- to call
select cladate(YOURCLARIONDATE) as YOURDATE, *
from YOURFILENAME
- SQL function (scalar) to convert SQL date to Clarion
int/long
CREATE FUNCTION [dbo].[SQL2ClaDate] (@SQL_Date_Time
DATETIME) RETURNS INT AS BEGIN RETURN
ISNULL(CAST(DATEDIFF(d, '1800-12-28', @SQL_Date_Time) AS INT), 0) END
- SQL function (scalar) to convert Clarion
time(int/long) to SQL
---- to use: SQL time(24hour)
dbo.clatime(myclariontimeinlong,0) ---- to use: clock with AM/PM
dbo.clatime(myclariontimeinlong,1) CREATE FUNCTION dbo.ClaTime (@Cla_Time
INT, @simpletime int = null) RETURNS CHAR(12) AS BEGIN
declare @timechar char(12) if @simpletime = 1 set
@timechar = convert(varchar(10), DATEADD(second,
FLOOR((@Cla_Time - 1) / 100), 0) , 108 ) else set
@timechar = RTRIM( RIGHT( (CAST(DATEADD(second, FLOOR((@Cla_Time - 1) / 100),
0) AS CHAR(24))), 13 ) ) RETURN @timechar END
- JDEdwards date CYYDDD(kinda julian format) to
Clarion in SQL
DATEDIFF (d,
'1800-12-28',
convert(char(10),dateadd(day,convert(int,right(@CYYDDD,3)),'01/01/'+left(right(@CYYDDD,5),2))-1,111)
) as
dateClarion
Day of Week function
DayOfWeek FUNCTION(xDate) ! Return short day of
week name in
xDate !--------------------------------------------------------------------
CODE RETURN CHOOSE(((xDate % 7) +
1),'Sunday','Monday','Tuesday','Wednesday',|
'Thursday','Friday','Saturday')
You are here: Home-Computer Tips & Help-Programming-Clarion
Next Topic: SQL
|