這是一個園長學習VFP(Visual Foxpro)的Blog歡迎同好一起來參與

星期日, 5月 23, 2010

CSV IMPORT

自己寫的CSV IMPORT
取代FOXPRO 之 Append From xxx.CSV TYPE CSV
原因:使用內建之IMPORT指令,會出現line is too long (列過長)之錯誤

注意:本版本無法辨識由EXCEL轉存之 CSV 檔

可辨識的格式為:

“abc”,”123”,”we”….

所有欄位皆以””包括

*green 2010/05/23
*傳入cvs檔案,轉換存入cAlias,錯誤記錄轉入cCSVErrFile
*傳回轉換筆數
Function CSVTRAN2
    Lparameters cCSVfile,cAlias,cCSVErrFile
    Local handle, lcCommand,esckey,nRecord
    If !File(cCSVfile)
        Return .F.
    Endif
    handle = Fopen(cCSVfile)
    If handle <=0
        Return .F.
    Endif
    *
    Fseek(m.handle,0) && Go Top
    nRecord=0
    nn=0
    rec1pos=0
    rr=0
    Do While !Feof(m.handle)
        *!*            esckey=Inkey()
        *!*            If esckey=27
        *!*                Cancel
        *!*            Endif
        lcCommand = Fread(m.handle, 8192)
        haveRecEnd=Occurs(Chr(10),lcCommand)
        If haveRecEnd>0
            ii=1
            Do While ii<=haveRecEnd
                If ii>1
                    rec1pos=Atc(Chr(10),lcCommand,ii-1)
                Else
                    rec1pos=0
                Endif
                rec2pos=Atc(Chr(10),lcCommand,ii)
                rr=rr+1
                Dimension RecStr[rr]
                RecStr[rr]=Substr(lcCommand,rec1pos+1,rec2pos-rec1pos)
                nn=nn+1
                If nn=1
                    *記錄結尾
                    Wait '匯入中-'+cCSVfile+':'+Str(nRecord) Windows Nowait
                    pstr=''
                    For jj=1 To rr
                        pstr=pstr+RecStr[jj]
                    Next jj
                    *大於最大限制
                    *nRecord=nRecord+1
                    *IF ck_fld(cAlias,pstr,cCSVErrFile,nRecord)    &&填入值
                    IF ck_csvfld(cAlias,pstr,cCSVErrFile,nRecord)    &&填入值
                        nRecord=nRecord+1
                    Endif
                    nn=0
                    rr=0
                Endif
                ii=ii+1
            Enddo
            *
            lastPOS=Ratc(Chr(10),lcCommand,1)
            rr=rr+1
            Dimension RecStr[rr]
            RecStr[rr]=Substr(lcCommand,lastPOS+1) &&取最後段之字串
        Else
            *一定大於8192
            rr=rr+1
            Dimension RecStr[rr]
            RecStr[rr]=lcCommand
        Endif
    Enddo
    Fclose(m.handle)
    Wait Clear
    Return nRecord
ENDFUNC

*Green 2010/5/23
*CSVTRAN的子程式,分解單筆CSV記錄(p_str),存入cAlias
Function ck_fld
    Lparameters cAlias,p_str,cCSVErrFile,nRecord
    is_Debug=.F.
    *IF nRecord>=6568   
    *    SET STEP ON
    *ENDIF    
    op_str=p_str
    *先清空
    p_str='(start)'+ALLTRIM(STRTRAN(p_str,CHR(10),[]))+'(End)'   
    *先替換原內含欄分隔字元[',']為[(NotFldDiv)]   
    p_str=STRTRAN(p_str,[','],[(NotFldDiv)])
*-----------------------------------------------------------樣版替換(注意:有先後順序)
    *1. [,"""] --> [,"(->Inch<-)]
    DO WHILE !Occurs([,""","],p_str)=0
        p_str=STRTRAN(p_str,[,""","],[,(->Inch<-)","])
    ENDDO       
    DO WHILE !Occurs([,"""],p_str)=0
        p_str=STRTRAN(p_str,[,"""],[,"(->Inch<-)])
    ENDDO
    *2. [""",] --> [(->Inch<-)",]
    DO WHILE !Occurs([""",],p_str)=0
        p_str=STRTRAN(p_str,[""",],[(->Inch<-)",])
    ENDDO   
*-----------------------------------------------------------樣版替換(注意:有先後順序)
    *3. [,"",] --> [,'',]
    DO WHILE !Occurs([,"",],p_str)=0
        p_str=STRTRAN(p_str,[,"",],[,'',])
    ENDDO
    *4start and end
    p_str=STRTRAN(p_str,[(start)"",],[(start)'',])
    p_str=STRTRAN(p_str,[,""(End)],[,''(End)])
    p_str=STRTRAN(p_str,[(start)],[])
    p_str=STRTRAN(p_str,[(End)],[])   
    *5. [""] --> [(->Inch<-)]
    DO WHILE !Occurs([""],p_str)=0
        p_str=STRTRAN(p_str,[""],[(->Inch<-)])
    ENDDO   
    *6. ["]--> [']
    p_str=STRTRAN(p_str,["],['])   
    *7. [(->Inch<-)] --> ["]
    p_str=STRTRAN(p_str,[(->Inch<-)],["])
    *8.修正錯誤
    p_str=STRTRAN(p_str,[',',','],[','.','])
    *9. FIND [',']
    Fldnum=Occurs([','],p_str)
    *Fldnum=Occurs('","',p_str)
    *p_str=STRTRAN(p_str,'",",","','",".","')
    *取得各欄
    If Fcount(cAlias)=Fldnum+1
        Select (cAlias)
        Append Blank
        For fnum=1 To Fldnum+1
            If fnum>1
                *fld1pos=Atc('","',p_str,fnum-1)+1
                fld1pos=Atc([','],p_str,fnum-1)+1
            Else
                fld1pos=0
            Endif
            *fld2pos=Atc('","',p_str,fnum)
            fld2pos=Atc([','],p_str,fnum)
            fldna = Fields[fnum]
            Select IMPORT_TMP
            If fld2pos=0
                wfldna = Substr(p_str,fld1pos+2,Len(p_str)-fld1pos-3)
                wfldna = STRTRAN(wfldna,[(NotFldDiv)],[',']) &&還原
            Else
                wfldna = Substr(p_str,fld1pos+2,fld2pos-fld1pos-2)
                wfldna = STRTRAN(wfldna,[(NotFldDiv)],[','])    &&還原
            Endif
            Replace &fldna With wfldna
            *            Fwrite(gnErrFile ,'['+STR(fnum)+']'+wfldna+CHR(10))
        Next
    Else
        *? 'Field Count Error'
        IF !EMPTY(cCSVErrFile)
            If File(cCSVErrFile)  && 檔案是否存在?
                gnErrFile = Fopen(cCSVErrFile,12)     && 如果存在,以讀寫方式開啟
            Else
                gnErrFile = Fcreate(cCSVErrFile)  && 如果不存在,就建立它
            ENDIF
            FSEEK(gnErrFile ,0,2) && 移至檔尾
            If gnErrFile < 0      && 檢查開啟檔案錯誤
                Wait '不能開啟或建立輸出檔案' Window
            ELSE
                *Fwrite(gnErrFile,'['+STR(nRecord)+']'+p_str)
                Fwrite(gnErrFile,op_str)
                IF is_Debug
                    Fwrite(gnErrFile,p_str)
                ENDIF    
                FCLOSE(gnErrFile)
            ENDIF
        ENDIF    
        RETURN .F.
    ENDIF
    RETURN .T.
Endfunc

*Green 2010/05/23
*傳入CSV,計算筆數
Function CSVRECCOUNT
    Lparameters cCSVfile
    Local handle,nRet
    If !File(cCSVfile)
        Return .F.
    Endif
    handle = Fopen(cCSVfile)
    If handle <=0
        Return .F.
    Endif
    *
    Fseek(m.handle,0) && Go Top
    nRet=0
    Do While !Feof(handle)
        nRet=nRet+Occurs(Chr(10),Fread(handle,8192))
    Enddo
    Fclose(handle)
    Return nRet
Endfunc

*Green 2010/05/23
*傳入CSV,計算筆數 (2) 另一方式計算CSV筆數
Function CSVRECCOUNT2
    Lparameters cCSVfile 
    cFile = FILETOSTR(cCSVfile)
    nLines = ALINES(aFile,cFile)
    Return nLines
EndFunc

沒有留言: