标题:关于导出EXCEL问题,继续请教吹版
只看楼主
laowan001
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:54
帖 子:802
专家分:1914
注 册:2015-12-30
结帖率:100%
已结贴  问题点数:20 回复次数:10 
关于导出EXCEL问题,继续请教吹版
吹版好,根据您在我另一个关于导出EXCEL帖子中提供的程序,做了个导出EXCEL函数,请指正
(1)可在一个EXCEL中导出不同sheet
(2)加上了表头行
(3)测试结果:sheet1-7042条,sheet2-473765条,用时277秒
导出的数据有个问题,查了网上没找到相应的方法:导出的字符型字段字符数是按字段宽度在有效字符后面加了空格,如:字符字段长度10,内容为:123,导出的结果是:123<7个空格>,有什么方法统一将字符后面的空格(或非打印字符)去掉?
先行谢过!!!

程序代码:
FUNCTION Dbf2excel(cExcelfilename,cDbfname,cSheetname,cFields,cFilter)
********************************************************
* cExcelfilename:C,带完整路径的EXCEL文件全名,abc.xlsx
* cDbfname: C,数据文件名
* cSheetname: C,工作表名字,可空
* cFields: C,"class 班级,name 姓名,math 数学",可空
* cFilter: C,数据过滤条件,可空
********************************************************
cFields = EVL(cFields,'*')
cSheetname = EVL(cSheetname,'')
cFilter = EVL(cFilter,'1=1')

LOCAL sc,arr[1],vbsCode,aFieldInfo[1],nStep,xnewfile,xtmpfile,i,xfile
xfile = cDbfname

sc = CREATEOBJECT("ScriptControl")
sc.Language = "VBScript"
TEXT TO vbsCode TEXTMERGE NOSHOW PRETEXT 7
    dim oExcel,oRange, nRows, nCols, nCol,cExcelname
    set oExcel = CREATEOBJECT("Excel.Application")

    function Open(cExcelname,cSheetname,nNew)
        if nNew=0 then        ' 新建
            oExcel.Workbooks.Add
            oExcel.ActiveWorkbook.saveas cExcelname
        else                '已有
            oExcel.Workbooks.Open(cExcelname)
            oExcel.ActiveWorkbook.Worksheets.Add
        end if

        if cSheetname<>"" then
            oExcel.Activesheet.name = cSheetname
        end if
    end function
   
    function SetFormat(aFieldInfo, nRows)
        for nCol=1 to UBound(aFieldInfo,1)
            oExcel.Range(oExcel.Cells(1,nCol),oExcel.Cells(nRows,nCol)).Select
            oExcel.Selection.NumberFormatLocal = aFieldInfo(nCol,8)
        next  
    end function

    function Append(vfpArray, nRow)
        nRows = UBound(vfpArray,1)
        nCols = UBound(vfpArray,2)
        oExcel.Range(oExcel.Cells(nRow,1),oExcel.Cells(nRow+nRows-1,nCols)).Value = vfpArray
    end function

    function Close(nRows, nCols)
        oExcel.Range(oExcel.Cells(1,1),oExcel.Cells(nRows,nCols)).Columns.AutoFit
        oExcel.Cells(1,1).select
        oExcel.ActiveWorkbook.save
        oExcel.quit
    end function
   
    function Show(nRows, nCols)
        oExcel.Range(oExcel.Cells(1,1),oExcel.Cells(nRows,nCols)).Columns.AutoFit
        oExcel.Visible = 1   
    end function
ENDTEXT  
sc.AddCode(vbsCode)

* 是否新建EXCEL文件
xnewfile = IIF(file(cExcelfilename),1,0)
sc.Run("Open", cExcelfilename,cSheetname,xnewfile)

* 表头数组
xtmpfile = SYS(2015)
SELECT &cFields FROM &xfile WHERE &cFilter INTO CURSOR &xtmpfile READWRITE
DIMENSION arr[1,fcount(xtmpfile)]

* 字段类型
SELECT &xtmpfile
AFIELDS(aFieldInfo)
FOR i=1 TO ALEN(aFieldInfo,1)
    arr[1,i] = aFieldInfo[i,1]
    aFieldInfo[i,8] = ICASE(;    && 数据格式
        aFieldInfo[i,2]=="I", '##0;[=0]""',;              && 整数格式
        INLIST(aFieldInfo[i,2],"B","N","F"), '#,##0.'+REPLICATE("0",aFieldInfo[i,4])+';[=0]""',; && 小数格式
        INLIST(aFieldInfo[i,2],"C","V","W","M"), '@',;    && 文本格式
        aFieldInfo[i,2]=="D", 'yyyy-m-d',;                && 日期格式
        aFieldInfo[i,2]=="T", 'yyyy-m-d hh:mm:ss',;       && 日期时间格式
        'G/通用格式')
ENDFOR

* 插入表头
sc.Run("Append", @arr, 1)

* 各列格式
sc.Run("SetFormat", @aFieldInfo, RECCOUNT(xtmpfile)+1)

* 表体
nStep = 10000
FOR i=1 TO RECCOUNT(xtmpfile) STEP nStep
    SELECT * FROM &xtmpfile WHERE BETWEEN(RECNO(),i,i+nStep-1) INTO ARRAY arr
    sc.Run("Append", @arr, i+1)
ENDFOR

sc.Run("Close",RECCOUNT(xtmpfile),FCOUNT(xtmpfile))

*sc.Run("Show",RECCOUNT(xfile),FCOUNT(xfile))
* 如果需要当时查看EXCEL表,可执行上面的语句

RELEASE sc
RETURN


[此贴子已经被作者于2021-9-20 20:08编辑过]

搜索更多相关主题的帖子: EXCEL end FUNCTION 导出 格式 
2021-09-20 20:06
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:20 
回复 楼主 laowan001
字符型字段用C型后面可能会有空格,虽然可用TRIM()处理,但有点烦,最好改用V型就没有后面的空格。

[此贴子已经被作者于2021-9-20 20:54编辑过]

2021-09-20 20:52
laowan001
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:54
帖 子:802
专家分:1914
注 册:2015-12-30
得分:0 
回复 2楼 吹水佬
但是,从SQLserver下来的数据,类型就有C型而不是V型,难道只有trim一条路?
2021-09-20 21:26
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
以下是引用laowan001在2021-9-20 21:26:36的发言:

但是,从SQLserver下来的数据,类型就有C型而不是V型,难道只有trim一条路?

如果不能用代码将C修为V,将C的DBF, APPEND FROM 到V的DBF,这样应该可以
2021-09-21 08:46
laowan001
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:54
帖 子:802
专家分:1914
注 册:2015-12-30
得分:0 
回复 4楼 吹水佬
把C字段的值trim了(在数组里),100W条记录导出用时399秒,比之前多了100秒,还可以接受
您说的方法回头我再测试一下
谢吹版!
2021-09-21 09:10
独木星空
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:河北省曲阳县
等 级:版主
威 望:57
帖 子:713
专家分:556
注 册:2016-6-29
得分:0 
回复 楼主 laowan001
有时间,好好读一读,练习运用。

素数问题的解决是我学习编程永恒的动力。
2021-09-21 09:37
laowan001
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:54
帖 子:802
专家分:1914
注 册:2015-12-30
得分:0 
回复 4楼 吹水佬
IF aFieldInfo[i,2]="C"
    aFieldInfo[i,2] = 'V'
ENDIF
CREATE CURSOR 临时表 FROM ARRAY aFieldInfo
SELECT 临时表
APPEND FROM DBF(数据表)
。。。

导出用时比trim数组用时还稍多点,没有本质差异,但由于多了一份临时表,占用内存会多些,所以还是准备用trim数组的方法了
2021-09-21 13:05
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
重建表要创建和读写文件,数据量大时耗时更多,应该直接修改数组较快。
2021-09-21 14:56
laowan001
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:54
帖 子:802
专家分:1914
注 册:2015-12-30
得分:0 
回复 8楼 吹水佬
所言极是

trim数组时是对C型字段(数组对应的列)逐个处理(从头到尾循环处理每个元素),不知有没有更高效的方法

[此贴子已经被作者于2021-9-21 15:34编辑过]

2021-09-21 15:31
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
回复 9楼 laowan001
VFP操作数组也只好这样
先按列判断是C型就再按行处理该列
每行字符串长度也有长短,如果无必要就不要管他,到EXCEL后自展开列显示也是以最长宽度定。

[此贴子已经被作者于2021-9-21 16:16编辑过]

2021-09-21 16:11



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-506927-1-1.html




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

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