VFP 愛用者社區 首頁 VFP 愛用者社區
本討論區為 Visual Foxpro 愛用者經驗交流的地方, 請多多利用"搜尋"的功能, 先查看看有無前例可循, 如果還有不懂的再發問. 部份主題有附加檔案, 須先註冊成為社區居民才可以下載.
 
 常見問題常見問題   搜尋搜尋   會員列表會員列表   會員群組會員群組   會員註冊會員註冊 
 個人資料個人資料   登入檢查您的私人訊息登入檢查您的私人訊息   登入登入

Cross Tab generator (轉貼)

 
發表新主題   回覆主題    VFP 愛用者社區 首頁 -> VFP 討論區
上一篇主題 :: 下一篇主題  
發表人 內容
Ruey



註冊時間: 2003-03-12
文章: 1698
來自: tunglo

第 1 樓

發表發表於: 星期日 一月 25, 2004 9:55 am    文章主題: Cross Tab generator (轉貼) 引言回覆

*************************************************
* gsXtab1.prg
* Parameters:
*
* pcOutFile - output file/cursor name (default "xtab.dbf")
* plOutCursor - Is outfile cursor or table? (default .t. = cursor)
* plCloseInput - close input table after (default .T. = close)
* plThermometer - show thermometer (default .T. = Show)
*
* pnRowFld - row field name - Default is Field number 1
* pnColFld - column field name - Default is Field Number 2
* pnCellFld - Column data field - Default is Field Number 3
*
* plTotal - total rows and create a total column (default .F. = No)
* pnSum - Is plTotal of totaling options (0-sum, 1-count)
* More options can be added such as % etc.)
* If the pcCellField is not number based,
* plTotal and pnSum wiill get disabled.
*
* plNull - display Null values
*
* The above are the VFPxtab.PRGs default parameters.
*
* Extra provisions built in this routine......
*
* pcGroup - Example "1,2,3" etc can be provided to group.
* pcOrder - Example "1,2,3" etc can be provided to sort output
* pcGroup and pcOrder will be prefixed to pcRowFld and
* pcColFld to get proper totals, if necessary.
* plAvg - Create an Average Column in the result - Default = .f.
* plMin - Create a Minimum Column in the result - Default = .f.
* plMax - Create a Maximum Column in the result - Default = .f.
*************************************************
** gsXtab1
*************************************************
PARAMETERS pcOutFile, plOutCursor, plCloseInput, plThermometer, ;
pnRowFld, pnColFld, pnCellFld, plTotal, pnSum, plNull, ;
pcGroup, pcOrder, plAvg, plMin, plMax

** SET ENGINEBEHAVIOR 70
*************************************************
** Create variables for this routine.
LOCAL n, ni, lcAlias, la_CrossTab, lcSQL, llTotal, ;
pcRowFld, pcColFld, pcCellFld, lcField, lcVer, lcEngine

n = 0 && simple counters and variables
n1 = 0 && simple counters and variables
lcAlias = ALIAS() && input alias
DIMENSION la_CrossTab(1,4) && used for cross tab columns
lcSql = '' && SQL Syntax to get output file
llTotal = .t. && To Decide pcCellFld type is numeric.
*************************************************
** Validity and Parameters Verification
n = PARAMETERS() && Number of parameters passed.

IF EMPTY(lcAlias) && A table must be open in the selected area
=MESSAGEBOX("No table selected.",0+16,"Error")
RETURN
ENDIF

IF n < 1 OR VARTYPE(pcOutFile) # "C"
pcOutFile = "GSXTAB"
ELSE
IF EMPTY(pcOutFile)
pcOutFile = "GSXTAB"
ENDIF
ENDIF

IF USED(pcOutFile)
USE IN (pcOutFile)
ENDIF

IF n < 2 OR VARTYPE(plOutCursor) # "L"
plOutCursor = .t.
ENDIF

IF n < 3 OR VARTYPE(plCloseInput) # "L"
plCloseInput = .t.
ENDIF

IF n < 4 OR VARTYPE(plThermometer) # "L"
plThermometer = .t.
ENDIF

** Checking for validity of counts or field names not yet done
IF n < 5 OR VARTYPE(pnRowFld) # "N"
pnRowFld = 1
pcRowFld = FIELD(1)
ELSE
pcRowFld = FIELD(pnRowFld)
ENDIF

** Checking for validity of counts or field names not yet done
IF n < 6 OR VARTYPE(pnColFld) # "N"
pnColFld = 2
pcColFld = FIELD(2)
ELSE
pcColFld = FIELD(pnColFld)
ENDIF

** Checking for validity of counts or field names not yet done
IF n < 7 OR VARTYPE(pnCellFld) # "N"
pnCellFld = 3
pcCellFld = FIELD(3)
ELSE
pcCellFld = FIELD(pnCellFld)
ENDIF

IF n < 8 OR VARTYPE(plTotal) # "L"
plTotal = .f.
ENDIF

IF n < 9 OR VARTYPE(pnSum) # "N"
pnSum = 0
ENDIF

** n=10 Null values Left to default settings.
** Not considered but kept for compatibility

** n=11 or n=12 field checkings not done.

IF n < 11 OR VARTYPE(pcGroup) # "C"
pcGroup = ''
ENDIF
IF EMPTY(pcGroup)
** pcGroup = "A." + pcRowFld
pcGroup = "1"
ENDIF

IF n < 12 OR VARTYPE(pcOrder) # "C"
pcOrder = ''
ENDIF
IF EMPTY(pcOrder)
** pcOrder = "A." + pcRowFld
pcOrder = "1"
ENDIF

IF n < 13 OR VARTYPE(plAvg) # "L"
plAvg = .f.
ENDIF

IF n < 14 OR VARTYPE(plMin) # "L"
plMin = .f.
ENDIF

IF n < 15 OR VARTYPE(plMax) # "L"
plMax = .f.
ENDIF

** If Col Cell is not numeric.. suitably disable maths functions
IF ! VARTYPE(&pcCellFld) $ "BFINY"
STORE .f. TO plTotal, plAvg, plMin, plMax, llTotal
ENDIF
*************************************************
** Create a CrossTab cursor to get the crosstab fields
** Once the crossTab fields are known, output can be generated
**
** Select all distinct pColFlds to identify crosstabs
** The first column will be left for identification of field
** The last column will be modified as the name for xtab column headers
SELECT DISTINCT &pcColFld, " " ;
FROM (lcALias) ORDER BY 1 INTO ARRAY la_CrossTab
*************************************************
** Check if total number of fields do not exceed 255
IF ALEN(la_CrossTab,1) > 255
=MESSAGEBOX("Number of columns exceed 255. Cannot process.",0+16,"Error")
RETURN
ENDIF
*************************************************
** Check for bad characters and prepare for field names
lcField = ''
n = 1
FOR I=1 TO ALEN(la_crossTab,1)
la_CrossTab(i,2)=goodchars(la_CrossTab(i,1))
** Also checking to avoid duplication of such new names
IF la_CrossTab(i,2) == lcField
n = n+1
lcField = LEFT(la_CrossTab(i,2), (9-LEN(ALLTRIM(STR(n))))) ;
+ "_"+ ALLTRIM(STR(n))
la_CrossTab(i,2) = lcField
ELSE
n = 1
lcField = la_CrossTab(i,2)
ENDIF
ENDFOR

** Create the crossTab cursor to create our output file
** and populate the crossTab table with 1's
n1 = LEN(&pcColFld) && Length of Column Field
CREATE CURSOR gsXtemp (&pcColFld C(n1+1))

FOR n= 1 TO ALEN(la_crossTab,1)
ALTER TABLE gsXtemp ADD COLUMN &la_crossTab(n,2) I
INSERT INTO gsXtemp (&pcColFld,(FIELD(n+1))) ;
VALUES (la_crossTab(n,1),1)
ENDFOR
*************************************************
** Prepare the SQL macro to extract output table

n1 = FCOUNT("gsXtemp") && fields count of Cross Tab including the 1st
SELECT (lcAlias)
lcSql = 'SELECT A.*'

FOR n = 2 TO n1 && since 1st field of gsXtemp table is not wanted
IF llTotal
lcSql = lcSql + ", SUM(A. " + pcCellfld + "*B." + ;
FIELD(n,"gsXtemp") + ") AS '" + FIELD(n,"gsXtemp") + "' "
ELSE
SCATTER FIELDS (pcCellFld) MEMVAR BLANK
lcSql = lcSql + ", IIF(B." + FIELD(n,"gsXtemp") + "=1,A." + ;
pcCellfld + ",M." + pcCellfld + ") AS '" ;
+ FIELD(n,"gsXtemp") + "' "
ENDIF
ENDFOR

IF plTotal AND llTotal && Totals of Row Field required
DO CASE
CASE pnSum = 0 && Total type is SUM
lcSql = lcSql + ", SUM( " + pcCellfld + " ) AS 'XTOT' "
CASE pnSum = 1 && Total type is Count
lcSql = lcSql + ", COUNT( " + pcRowFld + " ) AS 'XCNT' "
** CASE pnSum = 2 && not implemented yet
ENDCASE
ENDIF

IF plAvg AND llTotal
lcSql = lcSql + ", AVG( " + pcCellfld + " ) AS 'XAVG' "
ENDIF

IF plMin AND llTotal
lcSql = lcSql + ", MIN( " + pcCellfld + " ) AS 'XMIN' "
ENDIF

IF plMax AND llTotal
lcSql = lcSql + ", MAX( " + pcCellfld + " ) AS 'XMAX' "
ENDIF

** From tables
** lcSql = lcSql + "FROM " + DBF(lcAlias) + "A, gsXtemp B"
lcSql = lcSql + "FROM " + lcAlias + " A, gsXtemp B"

** Where condition
lcSql = lcSql + " WHERE B." + pcColFld + "=" + "A." + pcColFld

** Group by
lcSql = lcSql + " GROUP BY " + pcGroup

** Order by
lcSql = lcSql + " ORDER BY " + pcOrder

** INTO output
IF plOutCursor && Cursor
lcSql = lcSql + " INTO CURSOR " + pcOutFile + " READWRITE"
ELSE && TABLE
lcSql = lcSql + " INTO DBF " + pcOutFile
ENDIF

** My own quick find of what the SQL looks like
* STRTOFILE(lcSql,"gsx.Prg")
* = MESSAGEBOX(lcSql)
*************************************************
** Get the XTAB table
lcVer = LEFT(VERSION(4),2)
lcEngine = ''
IF lcVer > "07"
lcEngine = SET("ENGINEBEHAVIOR")
SET ENGINEBEHAVIOR 70
ENDIF
&lcSql
** Drop the Col field and the cell field columns
ALTER TABLE (pcOutFile) DROP (pcColFld)
ALTER TABLE (pcOutFile) DROP (pcCellFld)
*************************************************
** Close the input database, if required
IF plCloseinput
USE IN (lcAlias)
ENDIF
*************************************************
IF lcVer > "07"
SET ENGINEBEHAVIOR &lcEngine
ENDIF

RETURN
*************************************************
** EOP
*************************************************
** Check for acceptable characters in Field names
** and return first 10 characters for the purpose
**
PROCEDURE goodChars
LPARAMETERS cChars
LOCAL cGoodChars, nCount, x
cGoodChars = ""
nCount = 0
FOR x=1 TO LEN(cChars)
IF UPPER(SUBSTR(cChars,x,1)) $ "0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ"
cGoodChars = cGoodChars + UPPER(SUBSTR(cChars,x,1))
nCount = nCount+1
ENDIF
IF nCount = 10
EXIT
ENDIF
ENDFOR
IF !ISALPHA(SUBSTR(cGoodChars,1))
cGoodChars = "_"+cGoodChars
ENDIF
IF LEN(cGoodChars) > 10
cGoodChars = LEFT(cGoodChars,10)
ENDIF

RETURN cGoodChars
**************************************************
** EOF
**************************************************

_________________
#############################
快樂媽咪系列幸福宅配,喝十全雞湯~原來幸福那麼簡單!!

學會VFP使用者社區的搜尋,Code才會更有趣~
#############################
回頂端
檢視會員個人資料 發送私人訊息
從之前的文章開始顯示:   
發表新主題   回覆主題    VFP 愛用者社區 首頁 -> VFP 討論區 所有的時間均為 台北時間 (GMT + 8 小時)
1頁(共1頁)

 
前往:  
無法 在這個版面發表文章
無法 在這個版面回覆文章
無法 在這個版面編輯文章
無法 在這個版面刪除文章
無法 在這個版面進行投票
無法 在這個版面附加檔案
無法 在這個版面下載檔案


Powered by phpBB © 2001, 2005 phpBB Group
正體中文語系由 phpbb-tw 維護製作