| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 5399 人关注过本帖
标题:在梅子论坛看到的一个Grid转Excl的程序,有点问题。
只看楼主 加入收藏
mywisdom88
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:191
帖 子:3147
专家分:8408
注 册:2015-3-25
结帖率:98.98%
收藏
已结贴  问题点数:20 回复次数:22 
在梅子论坛看到的一个Grid转Excl的程序,有点问题。
在梅子论坛看到的一个Grid转Excl的程序,有点问题。
问题在红色字体那里,哪位能解决?
**====================================
*!*Create By Alan Hung
*!*Create Date 2012-06-15
*!*Modify Date 2016-11-01
**====================================
FUNCTION GridToExcel
   LPARA LoGrid
 LoGrid= thisform.grid1
    IF VARTYPE(oGrid)='O'
        IF  UPPER(oGrid.BASECLASS)<>'GRID'
            oGrid=''
        ENDIF
    ENDIF
    LTable=.f.
    if vartype(oGrid)='C'
        if !used(oGrid)
            oGrid=ALIAS()
        ENDIF
        LTable=.t.
    ENDIF
    &&获取数据源
    LOCAL m.cTableName,FileRate

    m.cTableName=''
    if LTable=.f.
        IF VARTYPE(oGrid)<>'O'
            FOR EACH oGrid IN _screen.ActiveForm.CONTROLS
                IF UPPER(oGrid.BASECLASS)='GRID' AND oGrid.VISIBLE=.T.
                    EXIT
                ELSE
                    LOOP
                ENDIF
            ENDFOR
            IF UPPER(oGrid.BASECLASS)<>'GRID'
                RETURN .F.
            ENDIF
        ENDIF
        m.cTableName=ALLT(oGrid.RECORDSOURCE)
        IF NOT USED(m.cTableName)
            RETURN
        ENDIF
    Else
        m.cTableName=oGrid
    ENDIF

    IF !USED(m.cTableName) OR EMPTY(m.cTableName)
        MESSAGEBOX('Grid數據源為空,不能導出數據。',64,'提示')
        RETURN
    ENDIF

    oExcelApp=CREATEOBJECT('Excel.Application')
    IF NOT TYPE("oExcelApp") = "O"
        =MESSAGEBOX("Excel對象建立失敗,程序將中止!", 16, "Error")
        RETURN
    ENDIF

    LOCAL oColumn,cFields,nFldCount,FieldName,MemoFields,LMemo,MemoOrder
    MemoFields=''
    cFields=''
    MemoOrder=''

    oExcelApp.DisplayAlerts=.F.

    oExcelApp.VISIBLE=.f. &&我发现,当存在分页时,oExcelApp.VISIBLE=.f. 就会报错,当为oExcelApp.VISIBLE=.T.就不报错
**************************************************************************************************************************

    DO WHILE oExcelApp.Workbooks.COUNT<2
        oExcelApp.Workbooks.ADD()
    ENDDO

    oExcelApp.Workbooks(2).ACTIVATE
    oExcelApp.ActiveWindow.WINDOWSTATE=2
    oSheet = oExcelApp.ActiveSheet
   
    LOCAL lTalk,lSafe
    lTalk=SET('talk')
    lSafe=SET('safe')
    SET TALK OFF
    SET SAFE OFF

    &&获取表头,获取非隐藏字段
    LOCAL NewTableName,ii
    NewTableName=SYS(2015)

    if LTable=.f.
        ii = 1
        FOR i0611 = 1 TO oGrid.COLUMNCOUNT
            FOR EACH oColumn IN oGrid.COLUMNS
                IF oColumn.COLUMNORDER=i0611 AND oColumn.VISIBLE=.T. AND oColumn.Width>0 &&列宽等于0的不处理,列隐藏不处理
                    LOCAL aCaption[ii]
                    aCaption[ii]=ALLT(oColumn.Header1.CAPTION)
                    CurFieldName=GETWORDNUM(oColumn.CONTROLSOURCE,2,'.') &&去掉表名,取字段名
                    IF TYPE(CurFieldName)='T' &&把时间类型字段改为字符
                       cFields=cFields+IIF(EMPTY(cFields),'',',PADR(TTOC(')+CurFieldName+'),19,SPACE(1))'+' As '+CurFieldName
                    ELSE
                       cFields=cFields+IIF(EMPTY(cFields),'',',')+CurFieldName
                    ENDIF
                    ii = ii + 1
                ENDIF
            ENDFOR
        ENDFOR
        IF EMPTY(cFields)
            RETURN
        ENDIF
        SELECT &cFields FROM (m.cTableName) INTO CURSOR (NewTableName)
    Else
        SELECT * FROM (m.cTableName) into cursor (NewTableName)
    ENDIF
    SELECT (NewTableName)
    nFldCount=AFIELD(aFldList,NewTableName)


    &&判断是否有备注字段
    lMemo=.F.
    nStartMemoOrder=0
    nEndMemoOrder=0
    FOR ii=1 TO nFldCount
        IF aFldList[ii,2]='M'
            LMemo=.T.
            IF nStartMemoOrder=0
               nStartMemoOrder=ii
            ENDIF
            nEndMemoOrder=ii
        ENDIF
    ENDFOR

    nLine=RECCOUNT(NewTableName)
    cRecc = STR(nLine)
    nMaxCount= oSheet.ROWS.COUNT - 1 &&留下标题栏

    nMaxCount= 4500  &&我在测试时,为了测试分页功能;正常情况使用时,要去掉此行。
*************************************************************************************************************************************


    nSheet = CEILING(nLine/nMaxCount) &&获取Sheet数

    FileRate=CHRTRAN(TRANSFORM(DATETIME()),' :-.','')

    LcCaption=ALLT(_screen.ActiveForm.CAPTION)
    cExcelFile=LcCaption+'_'+TRAN(FileRate)+".xls"

    DO WHILE FILE(cExcelFile)
        cExcelFile=LcCaption+'_'+TRAN(FileRate)+".xls"
        FileRate=CHRTRAN(TRANSFORM(DATETIME()),' :-.','')
        IF FILE(cExcelFile)
            LOOP
        ELSE
            EXIT
        ENDIF
    ENDDO

    cExcelFile=PUTFILE('文件保存為(&N):',cExcelFile,'XLS')

    IF EMPTY(cExcelFile)
        RETURN
    ENDIF

    cMessageText ='系統正在導出數據到Excel......'
    WAIT WINDOW cMessageText AT SROW()/2,(SCOLS()-LEN(cMessageText))/2  NOWAIT NOCLEAR

    LOCAL ARRAY TempExcel(nSheet)

    dStartDate=DATETIME()
    IF !DIRECTORY('temp')
        MD ('temp')
    ENDIF

    SELECT (NewTableName)
    GO TOP
    FOR i=1 TO nSheet
        TempExcel(i) ='temp\'+SYS(2015)+'.dbf'
        tname = FULLPATH(TempExcel(i))
        IF FILE(tname)
            DELETE FILE (tname)
        ENDIF
        COPY TO (tname)  NEXT (nMaxCount) TYPE FOX2X
    ENDFOR


    &&添加Sheet
    DO WHILE oExcelApp.Workbooks(2).worksheets.COUNT<nSheet
        oExcelApp.Workbooks(2).worksheets.ADD
    ENDDO

    FOR i=1 TO nSheet

        tname = FULLPATH(TempExcel(i))
        oExcelApp.Workbooks(1).ACTIVATE
        oExcelApp.Workbooks.OPEN(tname)
        oExcelApp.ActiveSheet.UsedRange.COPY
        oExcelApp.Workbooks(2).ACTIVATE
        oExcelApp.Worksheets(i).ACTIVATE  &&出错在这行,OLE 错误码 0x8002000b: Invalid index,但当设置oExcelApp.VISIBLE=.T.就不报错
***********************************************************************************************************************

        oExcelApp.Worksheets(i).NAME=LcCaption+'_'+ALLT(STR(i))
        oExcelApp.RANGE( "A1:A1 ").SELECT
        oExcelApp.ActiveSheet.Paste

        if !LTable     &&替换Grid Title
            nTitle0209=alen(aCaption)
            for z=1 to nTitle0209
                oExcelApp.ActiveSheet.cells(1,z).value=aCaption[z]
            endfor
        ENDIF

        oExcelApp.ActiveSheet.ROWS(1).FONT.NAME="黑体"
        oExcelApp.ActiveSheet.ROWS(1).FONT.Bold=.T.
        oExcelApp.ActiveSheet.ROWS(1).HorizontalAlignment=3
        oExcelApp.ActiveSheet.UsedRange.SELECT
        &&排版
        oExcelApp.SELECTION.ROWHEIGHT = 15
        oExcelApp.SELECTION.COLUMNS.autofit
        oExcelApp.SELECTION.BORDERS(1).LineStyle=1
        oExcelApp.SELECTION.BORDERS(2).LineStyle=1
        oExcelApp.SELECTION.BORDERS(3).LineStyle=1
        oExcelApp.SELECTION.BORDERS(4).LineStyle=1

        oExcelApp.SELECTION.FONT.SIZE=9
        &&處理備註字段
        IF LMemo
            IF USED('BillyTemp')
                USE IN BillyTemp
            ENDIF
            USE (tname) ALIAS BillyTemp SHARED
            SELECT BillyTemp
            GO TOP
            j=2
            SCAN
                FOR N=nStartMemoOrder TO nEndMemoOrder
                    IF  aFldList[N, 2] = "M"
                        oExcelApp.ActiveSheet.cells(j,N).VALUE=EVAL(aFldList[N, 1])
                    ELSE
                        LOOP
                    ENDIF
                ENDFOR
                j=j+1
            ENDS
            USE IN BillyTemp
        ENDIF
    ENDFOR
    WAIT CLEAR

    oExcelApp.ActiveWorkbook.SAVEAS(cExcelFile)&&保存數據
    oExcelApp.DisplayAlerts=.T.
    oExcelApp.ActiveWorkbook.CLOSE(.F.)
    oExcelApp.Workbooks.CLOSE
    oExcelApp.QUIT
    &&Excel  退出
    Use in (NewTableName) &&關閉臨時表
    STORE NULL TO  oExcelApp,oExcelSheet
    RELEASE oExcelApp,oExcelSheet
    dEndDate=DATETIME()
    MESSAGEBOX('数据成功导出,耗时:'+TRANSFORM(dEndDate-dStartDate)+'秒。合计:'+TRANSFORM(nLine)+'条记录!',64,'导出数据')
    DECLARE INTEGER ShellExecute IN shell32.DLL INTEGER HWND,STRING, ;
        STRING lpszFile, STRING, STRING, INTEGER
    operate= "open"
    ShellExecute(0,operate,cExcelFile,0,0,1)                && EXCEL文件

    SET TALK &lTalk
    SET  SAFE &lSafe

ENDFUNC
收到的鲜花
  • 厨师王德榜2016-11-25 15:14 送鲜花  10朵   附言:好文章
  • yzg05052022-07-04 10:43 送鲜花  1朵  
搜索更多相关主题的帖子: Create 
2016-11-25 08:43
tlliqi
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:204
帖 子:15453
专家分:65956
注 册:2006-4-27
收藏
得分:0 
Grid转Excl?
2016-11-25 11:37
厨师王德榜
Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18
等 级:贵宾
威 望:199
帖 子:995
专家分:4966
注 册:2013-2-16
收藏
得分:10 
1、在我的二台电脑上测试了,没问题。大容量的数据也测试过。
2、功能很不错,前面有很多检测代码,程序容错做得不错。
3、班门弄斧,提一点建议,
A 建立OLE对象成功之后,最好加上代码检测一下用户电脑上EXCEL的版本,这样的好处是确定默认的文件后缀,以及确定Excel所能容纳记录数的上限:
    IF oExcelApp.version>="12.0" THEN
        cExd= "XLSX"  && 默认的文件后缀
        nEXCELIMIT=1040000  && Excel所能容纳记录数的上限
    ELSE
        cExd= "XLS"
        nEXCELIMIT=65536
    ENDIF
这样的话,后面就可以事先检测一下数据源,看看是否在上限以内,如数据源记录数已经超出nEXCELIMIT,给用户提示是否继续。
二来,凡是后面输出文件名的语句,    cExcelFile=LcCaption+'_'+TRAN(FileRate)+ ".XLS"
都可以改成:    cExcelFile=LcCaption+'_'+TRAN(FileRate)+ "." + cExd
这样更灵活一点。
B,在做了很多转换工作之后,需要用户确定输出文件名和位置,原代码为:
程序代码:
    IF EMPTY(cExcelFile)
        RETURN
    ENDIF
* 这样的话,万一用户操作不熟练,或误点了鼠标,前面做的那些动作都放弃,直接Return 了,有点可惜,
* 而且这种直接返回,内存里的OLE对象还没有释放。 建议改成:
    IF EMPTY(cExcelFile)
        cExcelFile=ADDBS(JUSTPATH(SUBSTR(SYS(16),AT(":\",SYS(16))-1))) + "GRID2EXCEL" + TTOC(DATETIME(),1) + "." + CEXD
    ENDIF  
* 即:给他一个默认的文件名,先让程序把数据导出来再说。
收到的鲜花
  • 梦幻倩影2016-11-25 14:56 送鲜花  10朵   附言:我很赞同
2016-11-25 13:01
hyswcyh
Rank: 8Rank: 8
等 级:贵宾
威 望:20
帖 子:391
专家分:896
注 册:2004-11-23
收藏
得分:0 
好东东,收藏!以后省事很多!
2016-11-25 16:20
mywisdom88
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:191
帖 子:3147
专家分:8408
注 册:2015-3-25
收藏
得分:0 
以下是引用厨师王德榜在2016-11-25 13:01:31的发言:

1、在我的二台电脑上测试了,没问题。大容量的数据也测试过。
2、功能很不错,前面有很多检测代码,程序容错做得不错。
3、班门弄斧,提一点建议,
A 建立OLE对象成功之后,最好加上代码检测一下用户电脑上EXCEL的版本,这样的好处是确定默认的文件后缀,以及确定Excel所能容纳记录数的上限:
    IF oExcelApp.version>="12.0" THEN
        cExd= "XLSX"  && 默认的文件后缀
        nEXCELIMIT=1040000  && Excel所能容纳记录数的上限
    ELSE
        cExd= "XLS"
        nEXCELIMIT=65536
    ENDIF
这样的话,后面就可以事先检测一下数据源,看看是否在上限以内,如数据源记录数已经超出nEXCELIMIT,给用户提示是否继续。
二来,凡是后面输出文件名的语句,    cExcelFile=LcCaption+'_'+TRAN(FileRate)+ ".XLS"
都可以改成:    cExcelFile=LcCaption+'_'+TRAN(FileRate)+ "." + cExd
这样更灵活一点。
B,在做了很多转换工作之后,需要用户确定输出文件名和位置,原代码为:

    IF EMPTY(cExcelFile)
        RETURN
    ENDIF
* 这样的话,万一用户操作不熟练,或误点了鼠标,前面做的那些动作都放弃,直接Return 了,有点可惜,
* 而且这种直接返回,内存里的OLE对象还没有释放。 建议改成:
    IF EMPTY(cExcelFile)
        cExcelFile=ADDBS(JUSTPATH(SUBSTR(SYS(16),AT(":\",SYS(16))-1))) + "GRID2EXCEL" + TTOC(DATETIME(),1) + "." + CEXD
    ENDIF  
* 即:给他一个默认的文件名,先让程序把数据导出来再说。

难道是我电脑问题?我的是2013,我只要1分页就报错。
2016-11-25 17:08
mywisdom88
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:191
帖 子:3147
专家分:8408
注 册:2015-3-25
收藏
得分:0 
图片附件: 游客没有浏览图片的权限,请 登录注册
图片附件: 游客没有浏览图片的权限,请 登录注册
2016-11-25 17:12
hu9jj
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:红土地
等 级:贵宾
威 望:400
帖 子:11857
专家分:43421
注 册:2006-5-13
收藏
得分:10 
会不会是表变量i超出了当前工作簿的表数量,造成出界?

活到老,学到老!http://www.(该域名已经被ISP盗卖了)E-mail:hu-jj@
2016-11-26 06:45
hu9jj
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:红土地
等 级:贵宾
威 望:400
帖 子:11857
专家分:43421
注 册:2006-5-13
收藏
得分:0 
以下是引用tlliqi在2016-11-25 11:37:31的发言:

Grid转Excl?

grid应该是与table有点相似吧,也就是dbf。

活到老,学到老!http://www.(该域名已经被ISP盗卖了)E-mail:hu-jj@
2016-11-26 06:48
mywisdom88
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:191
帖 子:3147
专家分:8408
注 册:2015-3-25
收藏
得分:0 
以下是引用hu9jj在2016-11-26 06:45:39的发言:

会不会是表变量i超出了当前工作簿的表数量,造成出界?
oExcelApp.VISIBLE=.f.
不显示EXCL界面时即 oExcelApp.VISIBLE=.f.,就报错,但显示EXCL界面时即 oExcelApp.VISIBLE=.t. ,就不报错。

[此贴子已经被作者于2016-11-26 12:40编辑过]

2016-11-26 12:26
mywisdom88
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:191
帖 子:3147
专家分:8408
注 册:2015-3-25
收藏
得分:0 
见鬼,我刚才在家测试,我用的是WPS不报错。。。
难道是我上班电脑2013有问题?但怎么oExcelApp.VISIBLE=.f.报错,oExcelApp.VISIBLE=.T.不报错嫩。
2016-11-26 12:40
快速回复:在梅子论坛看到的一个Grid转Excl的程序,有点问题。
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.036399 second(s), 10 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved