home *** CD-ROM | disk | FTP | other *** search
- *:*********************************************************************
- *:
- *: Procedure file: C:\FOXPRO2\GENXTAB\GENXTAB.PRG
- *:
- *: System: GENXTAB
- *: Author: Walter J. Kennamer
- *: Copyright (c) 1993, Microsoft Corp.
- *: Last modified: 1/4/93 10:17
- *:
- *: Procs & Fncts: APPERROR
- *: : ESC_PROC
- *: : JUSTFNAME()
- *: : JUSTSTEM()
- *: : BAILOUT
- *: : DEFAULTEXT()
- *: : ALERT
- *: : ACTTHERM
- *: : UPDTHERM
- *: : MAPNAME()
- *: : DEACTTHERMO
- *: : FORCEEXT
- *: : JUSTPATH
- *: : ADDBS
- *: : MAKESTRG
- *:
- *: Calls: APPERROR (procedure in GENXTAB.PRG)
- *: : ESC_PROC (procedure in GENXTAB.PRG)
- *: : JUSTFNAME() (function in GENXTAB.PRG)
- *: : JUSTSTEM() (function in GENXTAB.PRG)
- *: : BAILOUT (procedure in GENXTAB.PRG)
- *: : DEFAULTEXT() (function in GENXTAB.PRG)
- *: : ALERT (procedure in GENXTAB.PRG)
- *: : ACTTHERM (procedure in GENXTAB.PRG)
- *: : UPDTHERM (procedure in GENXTAB.PRG)
- *: : MAPNAME() (function in GENXTAB.PRG)
- *: : DEACTTHERMO (procedure in GENXTAB.PRG)
- *:
- *: Uses: XTABTEMP.DBF
- *:
- *:*********************************************************************
- ***********************************************************************
- *
- * Notes: This program is intended to be called by RQBE or a program
- * generated by RQBE. On entry, a table should be open in the
- * current work area, and it should contain at most one record
- * for each cell in a cross-tabulation. This table *must* be in
- * row order, or you will receive an "unexpected end of file"
- * error when you run GENXTAB.
- *
- * The rowfld field in each record becomes the y-axis (rows) for
- * a cross-tab and the colfld field becomes the x-axis (columns)
- * The actual cross-tab results are saved to the database name
- * specified by "outfname."
- *
- * The basic strategy goes like this. Produce an empty database
- * with one field/column for each unique value of input field
- * colfld, plus one additional field for input field rowfld values.
- * This process determines the column headings in the database.
- * Next fill in the rows, but only for the first field in the output
- * database--the one that contains values for input field rowfld.
- * At this point, we have column headings "across the top"
- * and row identifiers "down the side." Finally, look up
- * the cell values for the row/column intersections and put
- * them into the output database.
- *
- *
- * Calling example:
- * DO genxtab WITH 'XTAB.DBF',.T.,.T.,.T.,1,2,5,.T.
- *
- * This command causes GENXTAB to write the output database to
- * 'XTAB.DBF'. However, XTAB.DBF will be deleted and the output
- * stored to a cursor called XTAB. The input database will be closed
- * at the conclusion of the program. The rows in XTAB.DBF will
- * contain the unique values of field 1 in the database that is
- * selected when GENXTAB is called, the columns will contain
- * unique values of field 2 in the input database, and the
- * cell values will come from field 5 in the input database.
- * The thermometer will be shown. A total field will be created.
- *
- ***********************************************************************
-
- PARAMETERS outfname, ;
- cursonly, ;
- closeinput, ;
- showtherm, ;
- rowfld, ;
- colfld, ;
- cellfld, ;
- xfoot
-
- PRIVATE ALL
-
- #DEFINE c_dlgface "MS Sans Serif"
- #DEFINE c_dlgsize 8.000
- #DEFINE c_dlgstyle "B"
-
- EXTERNAL ARRAY coluniq
- EXTERNAL ARRAY colcnt
-
- * -------------------------------------------------------------------------
- * Do opening housekeeping
- * -------------------------------------------------------------------------
- IF SET("TALK") = "ON"
- SET TALK OFF
- xtalk_stat = "ON"
- ELSE
- xtalk_stat = "OFF"
- ENDIF
- xsafe_stat = SET("SAFETY")
- SET SAFETY OFF
- xesc_stat = SET("ESCAPE")
- SET ESCAPE ON
-
- in_esc = ON('ESCAPE')
- in_err = ON('ERROR')
-
- ON ERROR DO apperror WITH PROGRAM(),MESSAGE(),MESSAGE(1),LINENO(),ERROR()
- ON ESCAPE DO esc_proc
-
- * -------------------------------------------------------------------------
- * Set default values for parameters
- * -------------------------------------------------------------------------
- IF PARAMETERS() < 1
- m.outfname = 'XTAB.DBF'
- ENDIF
- IF PARAMETERS() < 2
- * Default to creating the same kind of output as we got as input.
- * If the input "database" is a cursor, make the output a cursor.
- * If the input "database" is an actual database, make the output a table.
- cname = justfname(DBF())
- DO CASE
- CASE EMPTY(cname) && create a table if nothing is currently selected
- cursonly = .F.
- CASE ISDIGIT(LEFT(cname,1))
- cursonly = .T.
- OTHERWISE
- cursonly = .F.
- ENDCASE
- ENDIF
- IF PARAMETERS() < 3
- * Close the input database
- closeinput = .T.
- ENDIF
- IF PARAMETERS() < 4
- * show the thermometer
- showtherm = .T.
- ENDIF
- IF PARAMETERS() < 5
- * the field position in the input database for the crosstab rows
- m.rowfld = 1
- ENDIF
- IF PARAMETERS() < 6
- * the field position in the input database for the crosstab columns
- m.colfld = 2
- ENDIF
- IF PARAMETERS() < 7
- * the field position in the input database for the crosstab cells
- m.cellfld = 3
- ENDIF
- IF PARAMETERS() < 8
- * Create a total field?
- m.xfoot = .F.
- ENDIF
-
- * Define characters that are not allowed in field names
- m.badchars = 'üéâäàåçêëèïîÄÅÉæÆôöòûùÿÖÜáíóúñÑ /\,-=:;{}[]!@#$%^&*.<>()'+;
- '+|Ç¢£¥₧ƒªº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧'+;
- '╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■'+CHR(39)
- * Map European characters to these
- m.stdascii = 'ueaaaaceeeiiAaEaAooouuyouaiounN'
-
- IF !showtherm
- m.recthresh = 100000000 && don't show the thermometer
- ELSE
- m.recthresh = 1 && show it if more than this many input records
- ENDIF
- m.g_thermwidth = 0 && Thermometer width
- m.outstem = juststem(m.outfname)
-
- * -------------------------------------------------------------------------
- * Construct the output database structure
- * -------------------------------------------------------------------------
-
- m.dbfname = ALIAS()
-
- m.dbfstem = Juststem(m.dbfname)
-
- therm_on = (RECCOUNT() >= recthresh)
-
- * Select one, if no database is open in the current workarea
- m.ok = .F.
- DO WHILE NOT ok
- DO CASE
- CASE EMPTY(m.dbfname)
- m.dbfname = GETFILE('DBF','Please locate the input database')
- m.dbfstem = juststem(m.dbfname)
- IF EMPTY(m.dbfname)
- * User canceled out of dialog, so quit the program
- DO bailout WITH .T.
- ENDIF
- CASE FULLPATH(defaultext(m.dbfname,'DBF')) == ;
- FULLPATH(defaultext(m.outfname,'DBF'))
- SET CURSOR OFF
- WAIT WINDOW "The input and output databases must be different."
- SET CURSOR ON
- m.dbfname = ''
- OTHERWISE
- IF USED(m.dbfstem)
- SELECT (m.dbfstem)
- ELSE
- SELECT 0
- USE (m.dbfname) ALIAS (m.dbfstem)
- ENDIF
- IF FCOUNT() < 3
- DO alert WITH "Crosstab input databases require; at least three fields"
- m.dbfname = ''
- ELSE
- ok = .T.
- ENDIF
- ENDCASE
- ENDDO
-
- IF RECCOUNT() = 0
- DO alert WITH "Cannot prepare crosstab on empty database"
- DO bailout WITH .T.
- ENDIF
-
- * Gather information on the currently selected database fields
- DIMENSION inpfields[FCOUNT(),4]
- m.numflds = AFIELDS(inpfields)
-
- * Map the physical input database field to logical field positions
- m.rowfldname = inpfields[m.rowfld,1]
- m.colfldname = inpfields[m.colfld,1]
- m.cellfldname = inpfields[m.cellfld,1]
-
- * None of these fields are allowed to be memo fields
- IF inpfields[1,2] $ 'MGP'
- DO alert WITH "The crosstab row field in the input; database cannot be a memo, general or picture field."
- DO bailout WITH .T.
- ENDIF
- IF inpfields[2,2] $ 'MGP'
- DO alert WITH "The crosstab column field in the input; database cannot be a memo, general or picture field."
- DO bailout WITH .T.
- ENDIF
- IF inpfields[3,2] $ 'MGP'
- DO alert WITH "The crosstab cell field in the input; database cannot be a memo, general or picture field."
- DO bailout WITH .T.
- ENDIF
-
- IF therm_on
- DO acttherm WITH "Generating cross-tabulation ..."
- DO updtherm WITH 5
- ENDIF
-
- * Set the mouse off to avoid flicker on some systems
- SET MOUSE OFF
-
- * Count the number of columns we need to create the cross tab.
- * This step could be combined with the following one so that there
- * would only be one SELECT operation performed. It is coded in this
- * way to avoid running out of memory if there are an unexpectedly
- * large number of unique values of field 2 in the input database.
- SELECT COUNT(DISTINCT &colfldname) FROM (m.dbfname) INTO ARRAY colcnt
-
- DO CASE
- CASE colcnt[1] > 254
- DO alert WITH "Too many unique values of "+PROPER(m.colfldname);
- + ".; The maximum is 254."
- DO bailout WITH .T.
- CASE colcnt[1] = 0
- DO alert WITH "No columns found."
- DO bailout WITH .T.
- ENDCASE
-
- * Get the number of decimal places in numeric fields
- * and extract all the unique values of colfldname
- IF inpfields[m.colfld,2] $ 'NF' && numeric or floating field
- m.cdec = inpfields[m.colfld,4]
- * Handle numbers separately to preserve correct sort order
- SELECT DISTINCT &colfldname ;
- FROM (m.dbfname) INTO ARRAY coluniq
- FOR i = 1 TO ALEN(coluniq)
- coluniq[i] = mapname(coluniq[i],m.cdec)
- ENDFOR
- ELSE && non-numeric field
- m.cdec = 0
- * Create an array to hold the output database fields.
- SELECT DISTINCT mapname(&colfldname,m.cdec) ;
- FROM (m.dbfname) INTO ARRAY coluniq
- ENDIF
-
- IF therm_on
- DO updtherm WITH 15
- ENDIF
-
- * The field type, length and decimals in the output array control the
- * cross-tab cells
- IF !m.xfoot
- DIMENSION outarray[ALEN(coluniq)+1,4]
- ELSE
- DIMENSION outarray[ALEN(coluniq)+2,4]
- ENDIF
-
- * Field 1 in the output DBF holds the unique values of the row input field.
- * It is handled separately from the other fields, which take their names
- * from input database colfld and their parameters (e.g., length) from
- * input database cellfld.
-
- outarray[1,1] = mapname(inpfields[1,1])
- outarray[1,2] = inpfields[1,2]
- outarray[1,3] = inpfields[1,3]
- outarray[1,4] = inpfields[1,4]
-
- FOR i = 2 TO ALEN(coluniq) + 1
- outarray[i,1] = mapname(coluniq[i-1],m.cdec)
- outarray[i,2] = inpfields[3,2] && field type
- outarray[i,3] = inpfields[3,3] && field length
- outarray[i,4] = inpfields[3,4] && decimals
- ENDFOR
-
- * Create a field for the cross-footing, if that option was selected
- IF m.xfoot
- outarray[ALEN(coluniq)+2,1] = 'XTOTALS'
- outarray[ALEN(coluniq)+2,2] = inpfields[3,2]
- outarray[ALEN(coluniq)+2,3] = inpfields[3,3]
- outarray[ALEN(coluniq)+2,4] = inpfields[3,4]
- ENDIF
-
- * Make sure that the output file is not already in use somewhere
- IF USED(m.outstem)
- SELECT (m.outstem)
- USE
- ENDIF
-
- IF !cursonly
- CREATE TABLE (outfname) FROM ARRAY outarray
- ELSE
- CREATE CURSOR (outfname) FROM ARRAY outarray
- ENDIF
-
- IF therm_on
- DO updtherm WITH 25
- ENDIF
-
- * Get rid of the temporary arrays
- RELEASE outarray, coluniq, inpfields
-
- * -------------------------------------------------------------------------
- * Add output database rows and replace the first field
- * -------------------------------------------------------------------------
-
- * Select distinct rows into a table (instead of an array) so that
- * there can be lots of rows. If we select into an array, we may
- * run out of RAM if there are many rows.
-
- SELECT DISTINCT &rowfldname FROM (m.dbfname) INTO TABLE xtabtemp
-
- IF therm_on
- DO updtherm WITH 30
- ENDIF
-
- SELECT (m.outstem)
- APPEND FIELD (FIELD(1)) FROM xtabtemp
-
- IF therm_on
- DO updtherm WITH 35
- ENDIF
- * -------------------------------------------------------------------------
- * Look up and replace the cell values
- * -------------------------------------------------------------------------
- *
- * This algorithm makes one pass through the input file, dropping its
- * values into the output file. It exploits the fact that the output
- * file is known to be in row order.
- *
-
- * Start at the top of the output file
- SELECT (m.outstem)
- GOTO TOP
- outf1name = FIELD(1)
-
- * Start at the top of the input file
- SELECT (m.dbfstem)
- GOTO TOP
-
- SCAN
- m.f1 = EVAL(m.rowfldname) && get next row value from input
- m.f2 = mapname(EVAL(m.colfldname),m.cdec) && get corresponding column value
- m.f3 = EVAL(m.cellfldname) && get cell value
-
- * Find the right row in the output file
- SELECT (m.outstem)
- DO WHILE !(EVAL(outf1name) == m.f1) AND !EOF()
- SKIP
- ENDDO
-
- IF !EOF()
- REPLACE (m.f2) WITH &f2 + m.f3
- ELSE
- DO alert WITH "Unexpected end of output file.;" ;
- + "The input file may be out of sequence."
- DO bailout WITH .T.
- ENDIF
-
- SELECT (m.dbfstem)
-
- * Map thermometer to remaining portion of display
- IF therm_on
- DO CASE
- CASE RECCOUNT() > 1000
- IF RECNO() % 100 = 0
- DO updtherm WITH INT(RECNO() / RECCOUNT() * 65)+ 35
- ENDIF
- OTHERWISE
- IF RECNO() % 10 = 0
- DO updtherm WITH INT(RECNO() / RECCOUNT() * 65)+ 35
- ENDIF
- ENDCASE
- ENDIF
- ENDSCAN
-
- * Cross-foot the columns and put the results into the total field
- IF m.xfoot
- SELECT (m.outstem)
- m.totfldname = FIELD(FCOUNT())
- SCAN
- * Sum the relevant fields
- m.gtotal = 0
- FOR i = 2 TO FCOUNT() - 1
- m.gtotal = m.gtotal + EVAL(FIELD(i))
- ENDFOR
-
- REPLACE (m.totfldname) WITH m.gtotal
- ENDSCAN
- ENDIF
-
- IF therm_on
- DO updtherm WITH 100
- DO deactthermo
- ENDIF
-
- IF USED("XTABTEMP")
- SELECT xtabtemp
- USE
- ENDIF
- IF FILE("xtabtemp.dbf")
- DELETE FILE xtabtemp.dbf
- ENDIF
-
- * Close the input database
- IF closeinput
- SELECT (m.dbfstem)
- USE
- ENDIF
-
- * Leave the output database/cursor selected
- SELECT (m.outstem)
- GOTO TOP
-
- * Do closing housekeeping
- DO bailout WITH .F.
-
-
- RETURN
-
-
- *!*********************************************************************
- *!
- *! Function: MAPNAME()
- *!
- *! Called by: GENXTAB.PRG
- *!
- *! Calls: ALERT (procedure in GENXTAB.PRG)
- *! : BAILOUT (procedure in GENXTAB.PRG)
- *!
- *!*********************************************************************
- FUNCTION mapname
- * Translate a field value of any type into a string containing a valid
- * field name.
-
- PARAMETER in_name, in_dec
- IF PARAMETERS() = 1
- in_dec = 0
- ENDIF
- DO CASE
- CASE TYPE("in_name") $ 'CM'
- DO CASE
- CASE EMPTY(m.in_name)
- m.retval = 'C_BLANK'
- OTHERWISE
- m.retval = SUBSTR(CHRTRAN(m.in_name,m.badchars,m.stdascii),1,10)
- IF !ISALPHA(LEFT(m.retval,1))
- m.retval = 'C_'+LEFT(m.retval,8)
- ENDIF
- ENDCASE
- CASE TYPE("in_name") $ 'NF'
- m.retval = 'N_'+ALLTRIM(CHRTRAN(STR(m.in_name,8,in_dec),'.',''))
- CASE TYPE("in_name") = 'D'
- DO CASE
- CASE EMPTY(m.in_name)
- m.retval = 'D_BLANK'
- OTHERWISE
- m.retval = 'D_' + CHRTRAN(DTOS(m.in_name),m.badchars,m.stdascii)
- ENDCASE
- CASE TYPE("in_name") = 'L'
- IF m.in_name = .T.
- m.retval = 'T'
- ELSE
- m.retval = 'F'
- ENDIF
- CASE TYPE("in_name") = 'P'
- DO alert WITH "Picture type fields are not allowed here."
- DO bailout WITH .T.
- OTHERWISE
- DO alert WITH "Unknown field type."
- DO bailout WITH .T.
- ENDCASE
- m.retval = PADR(UPPER(ALLTRIM(m.retval)),10)
- RETURN m.retval
-
- *!*********************************************************************
- *!
- *! Procedure: ACTTHERM
- *!
- *! Called by: GENXTAB.PRG
- *!
- *!*********************************************************************
- *
- * Activates thermometer. Update the thermometer with UPDTHERM().
- * Thermometer window is named "thermometer." Be sure to RELEASE
- * this window when done with thermometer. Creates the global
- * m.g_thermwidth.
- *
- PROCEDURE acttherm
- PARAMETER m.prompt
- DO CASE
- CASE _WINDOWS OR _MAC
- IF txtwidth(m.prompt, c_dlgface, c_dlgsize, c_dlgstyle) > 43
- DO WHILE txtwidth(m.prompt+"...", c_dlgface, c_dlgsize, c_dlgstyle) > 43
- m.prompt = LEFT(m.prompt, LEN(m.prompt)-1)
- ENDDO
- m.prompt = m.prompt + "..."
- ENDIF
-
- DEFINE WINDOW thermomete ;
- AT INT((SROW() - (( 5.615 * ;
- FONTMETRIC(1, c_dlgface, c_dlgsize, c_dlgstyle )) / ;
- FONTMETRIC(1, wfont(1,""), wfont( 2,""), wfont(3,"")))) / 2), ;
- INT((SCOL() - (( 63.833 * ;
- FONTMETRIC(6, c_dlgface, c_dlgsize, c_dlgstyle )) / ;
- FONTMETRIC(6, wfont(1,""), wfont( 2,""), wfont(3,"")))) / 2) ;
- SIZE 5.615,63.833 ;
- FONT c_dlgface, c_dlgsize ;
- STYLE c_dlgstyle ;
- NOFLOAT ;
- NOCLOSE ;
- NONE ;
- COLOR rgb(0, 0, 0, 192, 192, 192)
- ACTIVATE WINDOW thermomete NOSHOW
-
- @ 1.5,3 SAY m.prompt FONT c_dlgface, c_dlgsize STYLE c_dlgstyle
- @ 0.000,0.000 TO 0.000,63.833 ;
- COLOR rgb(255, 255, 255, 255, 255, 255)
- @ 0.000,0.000 TO 5.615,0.000 ;
- COLOR rgb(255, 255, 255, 255, 255, 255)
- @ 0.385,0.667 TO 5.231,0.667 ;
- COLOR rgb(128, 128, 128, 128, 128, 128)
- @ 0.308,0.667 TO 0.308,63.167 ;
- COLOR rgb(128, 128, 128, 128, 128, 128)
- @ 0.385,63.000 TO 5.308,63.000 ;
- COLOR rgb(255, 255, 255, 255, 255, 255)
- @ 5.231,0.667 TO 5.231,63.167 ;
- COLOR rgb(255, 255, 255, 255, 255, 255)
- @ 5.538,0.000 TO 5.538,63.833 ;
- COLOR rgb(128, 128, 128, 128, 128, 128)
- @ 0.000,63.667 TO 5.615,63.667 ;
- COLOR rgb(128, 128, 128, 128, 128, 128)
- @ 3.000,3.333 TO 4.231,3.333 ;
- COLOR rgb(128, 128, 128, 128, 128, 128)
- @ 3.000,60.333 TO 4.308,60.333 ;
- COLOR rgb(255, 255, 255, 255, 255, 255)
- @ 3.000,3.333 TO 3.000,60.333 ;
- COLOR rgb(128, 128, 128, 128, 128, 128)
- @ 4.231,3.333 TO 4.231,60.500 ;
- COLOR rgb(255, 255, 255, 255, 255, 255)
- m.g_thermwidth = 56.269
-
- CASE _DOS OR _UNIX
- PRIVATE m.therm_x1, m.therm_y1, m.therm_x2, m.therm_y2
- m.therm_x1 = INT((SROW()-6)/2)
- m.therm_y1 = INT((SCOL()-57)/2)
- m.therm_x2 = m.therm_x1 + 6
- m.therm_y2 = m.therm_y1 + 57
-
- DEFINE WINDOW thermomete;
- FROM m.therm_x1, m.therm_y1 TO m.therm_x2, m.therm_y2;
- FLOAT DOUBLE COLOR SCHEME 5
-
- ACTIVATE WINDOW thermomete
- @ 0,3 SAY m.prompt
- m.g_thermwidth = 54
- @ 2,1 TO 4,m.g_thermwidth
- ENDCASE
- SHOW WINDOW thermomete TOP
-
- *!*********************************************************************
- *!
- *! Procedure: UPDTHERM
- *!
- *! Called by: GENXTAB.PRG
- *!
- *!*********************************************************************
- PROCEDURE updtherm
- PARAMETER m.percent
- PRIVATE m.nblocks, m.percent
-
- IF !WEXIST("thermomete")
- DO acttherm WITH "Generating cross-tabulation ..."
- ENDIF
- ACTIVATE WINDOW thermomete
-
- DO CASE
- CASE _WINDOWS OR _MAC
- m.nblocks = (m.percent/100) * (m.g_thermwidth)
- @ 3.000,3.333 TO 4.231,m.nblocks + 3.333 ;
- pattern 1 COLOR rgb(128, 128, 128, 128, 128, 128)
- CASE _DOS OR _UNIX
- PRIVATE nblocks, percent
- ACTIVATE WINDOW thermomete
- nblocks = (percent/100) * (m.g_thermwidth-4)
- @ 3,3 SAY REPLICATE("█",nblocks)
- RETURN
- ENDCASE
- *!*********************************************************************
- *!
- *! Procedure: DEACTTHERMO
- *!
- *! Called by: GENXTAB.PRG
- *!
- *!*********************************************************************
- PROCEDURE deactthermo
- RELEASE WINDOW thermomete
- RETURN
-
- *!*********************************************************************
- *!
- *! Function: JUSTSTEM()
- *!
- *! Called by: GENXTAB.PRG
- *!
- *!*********************************************************************
- FUNCTION juststem
- * Return just the stem name from "filname"
- PARAMETERS filname
- PRIVATE ALL
- IF RAT('\',m.filname) > 0
- m.filname = SUBSTR(m.filname,RAT('\',m.filname)+1,255)
- ENDIF
- IF AT(':',m.filname) > 0
- m.filname = SUBSTR(m.filname,AT(':',m.filname)+1,255)
- ENDIF
- IF AT('.',m.filname) > 0
- m.filname = SUBSTR(m.filname,1,AT('.',m.filname)-1)
- ENDIF
- RETURN ALLTRIM(UPPER(m.filname))
-
- *!*********************************************************************
- *!
- *! Procedure: FORCEEXT
- *!
- *! Calls: JUSTPATH (procedure in GENXTAB.PRG)
- *! : JUSTFNAME() (function in GENXTAB.PRG)
- *! : ADDBS (procedure in GENXTAB.PRG)
- *!
- *!*********************************************************************
- FUNCTION forceext
- * Force the extension of "filname" to be whatever ext is.
- PARAMETERS filname,ext
- PRIVATE ALL
- IF SUBSTR(m.ext,1,1) = "."
- m.ext = SUBSTR(m.ext,2,3)
- ENDIF
-
- m.pname = justpath(m.filname)
- m.filname = justfname(UPPER(ALLTRIM(m.filname)))
- IF AT('.',m.filname) > 0
- m.filname = SUBSTR(m.filname,1,AT('.',m.filname)-1) + '.' + m.ext
- ELSE
- m.filname = m.filname + '.' + m.ext
- ENDIF
- RETURN addbs(m.pname) + m.filname
-
- *!*********************************************************************
- *!
- *! Function: DEFAULTEXT()
- *!
- *! Called by: GENXTAB.PRG
- *!
- *! Calls: JUSTPATH (procedure in GENXTAB.PRG)
- *! : JUSTFNAME() (function in GENXTAB.PRG)
- *! : ADDBS (procedure in GENXTAB.PRG)
- *!
- *!*********************************************************************
- FUNCTION defaultext
- * Add a default extension to "filname" if it doesn't have one already
- PARAMETERS filname,ext
- PRIVATE ALL
- IF SUBSTR(ext,1,1) = "."
- m.ext = SUBSTR(m.ext,2,3)
- ENDIF
-
- m.pname = justpath(m.filname)
- m.filname = justfname(UPPER(ALLTRIM(m.filname)))
- IF !EMPTY(m.filname) AND AT('.',m.filname) = 0
- m.filname = m.filname + '.' + m.ext
- RETURN addbs(m.pname) + m.filname
- ELSE
- RETURN filname
- ENDIF
- *!*********************************************************************
- *!
- *! Function: JUSTFNAME()
- *!
- *! Called by: GENXTAB.PRG
- *! : DEFAULTEXT() (function in GENXTAB.PRG)
- *! : FORCEEXT (procedure in GENXTAB.PRG)
- *!
- *!*********************************************************************
- FUNCTION justfname
- * Return just the filename (i.e., no path) from "filname"
- PARAMETERS filname
- PRIVATE ALL
- IF RAT('\',m.filname) > 0
- m.filname = SUBSTR(m.filname,RAT('\',m.filname)+1,255)
- ENDIF
- IF AT(':',m.filname) > 0
- m.filname = SUBSTR(m.filname,AT(':',m.filname)+1,255)
- ENDIF
- RETURN ALLTRIM(UPPER(m.filname))
-
- *!*********************************************************************
- *!
- *! Procedure: JUSTPATH
- *!
- *! Called by: DEFAULTEXT() (function in GENXTAB.PRG)
- *! : FORCEEXT (procedure in GENXTAB.PRG)
- *!
- *!*********************************************************************
- FUNCTION justpath
- * Return just the path name from "filname"
- PARAMETERS filname
- PRIVATE ALL
- m.filname = ALLTRIM(UPPER(m.filname))
- IF '\' $ m.filname
- m.filname = SUBSTR(m.filname,1,RAT('\',m.filname))
- IF RIGHT(m.filname,1) = '\' AND LEN(m.filname) > 1 ;
- AND SUBSTR(m.filname,LEN(m.filname)-1,1) <> ':'
- m.filname = SUBSTR(m.filname,1,LEN(m.filname)-1)
- ENDIF
- RETURN m.filname
- ELSE
- RETURN ''
- ENDIF
-
- *!*********************************************************************
- *!
- *! Procedure: ADDBS
- *!
- *! Called by: DEFAULTEXT() (function in GENXTAB.PRG)
- *! : FORCEEXT (procedure in GENXTAB.PRG)
- *!
- *!*********************************************************************
- FUNCTION addbs
- * Add a backslash to a path name, if there isn't already one there
- PARAMETER pathname
- PRIVATE ALL
- m.pathname = ALLTRIM(UPPER(m.pathname))
- IF !(RIGHT(m.pathname,1) $ '\:') AND !EMPTY(m.pathname)
- m.pathname = m.pathname + '\'
- ENDIF
- RETURN m.pathname
-
-
- *!*********************************************************************
- *!
- *! Procedure: APPERROR
- *!
- *! Called by: GENXTAB.PRG
- *!
- *! Calls: ALERT (procedure in GENXTAB.PRG)
- *! : BAILOUT (procedure in GENXTAB.PRG)
- *!
- *!*********************************************************************
- PROCEDURE apperror
- * Simple ON ERROR routine
-
- PARAMETERS e_program,e_message,e_source,e_lineno,e_error
- ON ERROR
- SET MOUSE ON
- m.e_source = ALLTRIM(m.e_source)
- DO alert WITH 'Line No.: '+ALLTRIM(STR(m.e_lineno,5))+';' ;
- +'Program: '+m.e_program +';' ;
- +' Error: '+m.e_message +';' ;
- +' Source: '+IIF(LEN(m.e_source)<50,;
- m.e_source,SUBSTR(m.e_source,1,50)+'...')
- DO bailout WITH .T.
-
- *!*********************************************************************
- *!
- *! Procedure: ALERT
- *!
- *! Called by: GENXTAB.PRG
- *! : APPERROR (procedure in GENXTAB.PRG)
- *! : MAPNAME() (function in GENXTAB.PRG)
- *!
- *!*********************************************************************
- PROCEDURE alert
- * Display an error message, automatically sizing the message window
- * as necessary. Semicolons in "strg" mean "new line".
- PARAMETERS strg
- PRIVATE ALL
-
- SET MOUSE ON
- in_talk = SET('TALK')
- SET TALK OFF
- in_cons = SET('CONSOLE')
-
- m.numlines = OCCURS(';',m.strg) + 1
-
- DIMENSION alert_arry[m.numlines]
- m.remain = m.strg
- m.maxlen = 0
- FOR i = 1 TO m.numlines
- IF AT(';',m.remain) > 0
- alert_arry[i] = SUBSTR(m.remain,1,AT(';',m.remain)-1)
- alert_arry[i] = CHRTRAN(alert_arry[i],';','')
- m.remain = SUBSTR(m.remain,AT(';',m.remain)+1)
- ELSE
- alert_arry[i] = m.remain
- m.remain = ''
- ENDIF
- IF LEN(alert_arry[i]) > SCOLS() - 6
- alert_arry[i] = SUBSTR(alert_arry[i],1,SCOLS()-6)
- ENDIF
- IF LEN(alert_arry[i]) > m.maxlen
- m.maxlen = LEN(alert_arry[i])
- ENDIF
- ENDFOR
-
- m.top_row = INT( (SROWS() - 4 - m.numlines) / 2)
- m.bot_row = m.top_row + 3 + m.numlines
-
- m.top_col = INT((SCOLS() - m.maxlen - 6) / 2)
- m.bot_col = m.top_col + m.maxlen + 6
-
- DEFINE WINDOW alert FROM m.top_row,m.top_col TO m.bot_row,m.bot_col;
- DOUBLE COLOR SCHEME 7
- ACTIVATE WINDOW alert
-
- FOR i = 1 TO m.numlines
- @ i,3 SAY PADC(alert_arry[i],m.maxlen)
- ENDFOR
-
- SET CONSOLE OFF
- keycode = INKEY(0,'HM')
- SET CONSOLE ON
-
- RELEASE WINDOW alert
- IF m.in_talk = "ON"
- SET TALK ON
- ENDIF
- IF m.in_cons = "OFF"
- SET CONSOLE OFF
- ENDIF
-
- RETURN
-
- *!*********************************************************************
- *!
- *! Procedure: MAKESTRG
- *!
- *!*********************************************************************
- FUNCTION makestrg
- PARAMETER in_val
- DO CASE
- CASE TYPE("in_val") = "C"
- RETURN in_val
- CASE TYPE("in_val") $ "NF"
- RETURN ALLTRIM(STR(in_val))
- CASE TYPE("in_val") = "D"
- RETURN DTOC(in_val)
- CASE TYPE("in_val") = "L"
- IF in_val
- RETURN ".T."
- ELSE
- RETURN ".F."
- ENDIF
- OTHERWISE
- RETURN in_val
- ENDCASE
-
- *!*********************************************************************
- *!
- *! Procedure: ESC_PROC
- *!
- *! Called by: GENXTAB.PRG
- *!
- *! Calls: BAILOUT (procedure in GENXTAB.PRG)
- *!
- *!*********************************************************************
- PROCEDURE esc_proc
- WAIT WINDOW "Cross tabulation terminated." TIMEOUT 1
- CLEAR TYPEAHEAD
- DO bailout
-
- *!*********************************************************************
- *!
- *! Procedure: BAILOUT
- *!
- *! Called by: GENXTAB.PRG
- *! : APPERROR (procedure in GENXTAB.PRG)
- *! : ESC_PROC (procedure in GENXTAB.PRG)
- *! : MAPNAME() (function in GENXTAB.PRG)
- *!
- *! Uses: XTABTEMP.DBF
- *!
- *!*********************************************************************
- PROCEDURE bailout
- PARAMETER docancl
- PRIVATE docancl
- DO CASE
- CASE PARAMETERS() = 0
- m.docancl = .T.
- ENDCASE
- IF WONTOP('THERMOMETE')
- RELEASE WINDOW thermomete
- ENDIF
-
- IF USED("XTABTEMP")
- SELECT xtabtemp
- USE
- ENDIF
- IF FILE("xtabtemp.dbf")
- DELETE FILE xtabtemp.dbf
- ENDIF
-
- IF m.xsafe_stat = "ON"
- SET SAFETY ON
- ENDIF
- IF m.xesc_stat = "ON"
- SET ESCAPE ON
- ELSE
- SET ESCAPE OFF
- ENDIF
- IF m.xtalk_stat = "ON"
- SET TALK ON
- ENDIF
-
- ON ERROR &in_err
- ON ESCAPE &in_esc
-
- SET MOUSE ON
- IF m.docancl
- m.outfname = ''
- CANCEL
- ENDIF
- *: EOF: GENXTAB.PRG