回 帖 发 新 帖 刷新版面

主题:[原创]从当前任意dbf-table 到 xl-table的实现过程

请版主请此贴清理掉!有孽障在哭丧,没法呆了[em20]

回复列表 (共119个回复)

91 楼

proc dbf_to_xls     && 从dbf-table 到 xl-table
*定义常量
#define True .t.
#define False .f.
#define xlWBatWorksheet  -4167
#define xlAutomatic 0
#define xlNone 1
#define xlContinuous 1
#define xlThin 2          && 等于1时为点线,2为细线,3为粗线,4更粗
IF TYPE('XLApp.Workbooks[1]') = 'U'
  PUBLIC XLApp
  XLApp = createobject("Excel.Application")
  XLApp.Workbooks.add[xlWBatWorksheet]
  wsCount = 0
ELSE
  XLApp.visible = True
  wsCount = xlApp.Sheets.count
  XLApp.Worksheets.add(,xlApp.Sheets(wsCount),1)
ENDIF
Sheet = XLApp.Workbooks[1].Worksheets(wsCount+1)
*设定字符型字段所对应的EXCEL列为字符型
FOR i = 1 TO FCOUNT()
  cfieldname = field(i)
  colName = IIF(INT(i/26) = 0,'',CHR(64+INT(i/26))) + CHR(64+MOD(i,26))
  colName = colName+':'+colName
  IF TYPE(cfieldname) = "C"
    sheet.Columns(colName).NumberFormatLocal = "@"   && 设置单元格数据类型为字符型,以避免数字字符变为数值型
  ENDIF
ENDFOR
_vfp.DataToClip(,,3)              && 将当前工作区中数据记录复制到剪切板
sheet.Activate      && 激活工作表
XLApp.ActiveSheet.Paste           && 粘贴剪切板中数据记录到EXCEL表  
XLApp.visible = True
*整理列标题,去掉列名后随的空格
for i = 1 to FCOUNT()
  Sheet.Cells[1,i] = ALLTRIM(sheet.cells[1,i].value)
endfor
*-------------------
Selection=XLApp.Range(XLApp.Cells(1,1),XLApp.Cells(1,FCOUNT()))   && 设定范围为第一行
Selection.font.bold = .t.           && 字体加粗
Selection.horizontalAlignment = 3   && 水平居中排列
Selection=XLApp.Range(XLApp.Cells(1,1),XLApp.Cells(RECCOUNT()+1,FCOUNT()))  && 设定范围为有数据的整个区域
Selection.font.size = 9    && 体字大小为 9 号
XLApp.Workbooks[1].Sheets[1].rows.rowHeight=20   && 行距为20
XLApp.ActiveSheet.PageSetup.PrintTitleRows = "$1:$1"  && 设定第一行为每页必须打印的行
* 设定表格边线
for i=1 to 4
  With Selection.Borders(i)
    .LineStyle = xlContinuous
    .Weight = xlThin
    .ColorIndex = xlAutomatic
  EndWith
ENDFOR
retu
---------------------------

这个版本可以在已建立的EXCEL工作薄中写入多个工作表.

92 楼

其实每个问题都会有不同的办法,
应该看问题的不同需求择优使用,
关于VBA for EXCEL编程其实很简单,
1. 了解EXCEL的对象
2. 了解可提供的属性和操作

网上有很多关于EXCEL编程的教程,
我学习EXCEL是从教程,录制宏,帮助中走过来的,
感觉并不难.技巧是从使用和学习中来的.固步自封不会有进步.

仅仅是数据复制的话,我不明白为什么要一大堆代码,而不用Copy to 
如果是为了避免那个16383的限制的话那也没得说,
(其实如果真有这样的要求分次Copy to就可以了)

如果没有其他要求的话,看看以下代码能否实现同样的效果?
还有的就是那个变量Selection使用得实在不是很明智.
[quote]F1=sys(2023)-"\"-sys(3)-".xls"
SELECT 表1
COPY TO (F1) TYPE xl5
E_x=GETOBJECT(FULLPATH(F1))
WITH E_x.sheets(1) 
  WITH .rows(1)
       .font.bold=.t.
       .horizontalalignment=3
  ENDWITH 
  WITH .cells(1,1).currentregion
       .font.size=9
       .Borders.Linestyle=1
       .columns.autofit
       .rows.autofit
  ENDWITH 
  .PageSetup.PrintTitleRows = "$1:$1"
ENDWITH 
WITH E_x.Application
.Visible= .T.
.Windows(E_x.Name).Visible= .T.
ENDWITH [/quote]
VBA for EXCEL最大的好处就是几乎所有人手操作都可以使用代码来完成.

93 楼

实践中发现,当数据量越大的时候
.columns.autofit 
这一行因为对象范围太大,Excel需要检查完所有数据的宽度来设置列宽,导致耗去很多的时间.
适当的缩小对象范围可以使得设置时间大大缩短.
.....range("1:2").columns.autofit

94 楼

93楼贴子该评30分.
92楼贴子选收藏了,有时间再学习.本贴粗略看了一下,似乎嫌我的代码太冗,但不知你的代码能否解决长字符型数字串转移后变为科学记数问题,以及WZXC先生提出的问题?能否适应任意一个当前工作区中打开的数据表或查询表?如果可以,那你的代码无疑是优秀的,否则,...
  93楼的贴子确实是个不错的补充!
  谢谢MOZ先生!

95 楼

嗯,听得出来,呵呵.

我完全没有和你攀比的意思,别误会,
也完全没有嫌你代码的偏见,
我只是在提一些想法,孰优孰劣,共同研究.
没有实践就没有发言权,所以我认为我还是可以斗胆发言的.

科学计数法,嗯,这是个什么样的问题,为什么会有科学计数法?
为什么人们都制定些不喜欢用的标准? 怎么解决? 回去慢慢研究研究.

至于说这位孔夫子的老乡WZXC的是不是说的这个问题:
[quote]谢谢高老师的回复。本人水平有限,向你学习才是。
您的这段代码,是将一个表转excel一个工作簿中,表名作为sheet名称。
我有四个表,结构完全一样,一个季度使用一次。我想分次结转到excel中,在一个工作簿中,sheet1存放表1,sheet2存放表2,sheet3存放表3,sheet4存放表4。
请较高老师如何实现?[/quote]
1.如果有特定格式,可以学学模板的用法
2.一簿多表,可以学学表对象的移动和复制
如果这两项有不明白的,我可以解释,
我走过的路我会指出来,我没走过的路不会瞎说,瞎说也会说清楚我不懂.(非典型的中国人)

96 楼

经MOZ一说,我反而像小人了!哈哈,没关系,MOZ的才学我是很敬佩的.我喜欢与MOZ交流!
至于这个主题贴里讨论的问题,我过多的是出于通用性考虑的.WZXC提的问题,用我的代码虽然没有中规中矩地解决,但也算是通用性与具体性兼得的一种方案.
    我编的VFP程序虽不算太多,但也很讨厌面对太具体的问题.科学记数,就是像: "2.5678E12"这样的数字,我并不抵触用这样的形式记数,但在dbf到xls的转换中, 总会把我的一些诸如身份证号码一类的数字串给变换成了科学记数的形式,所以,得想办法解决.
    说到模板的使用,也超出了本主题的讨论范围.
    本主题强调的是"通用",能兼顾一点具体的使用当然更好!

97 楼

呵,很惭愧你这么抬举.

当然,在方向问题上可以通用一些,这些都只是一个解决问题的办法而已,
具体问题具体解决.
我在数据表中都会把身份证号码弄成字符串类型,然后在文本框输入时加以数字字母限定.
(这个时候,我突然想到,你那个字母X是怎么输入的?)

在VFP中
数值型: 16位有效数字
货币型: 整数15位有效数字
好像都不能符合身份证号码的使用,

然后我在想,是不是我的理解出了错误,
老高你说的应该是在VFP中是字符串类型,到了EXCEL中就变成了数值型了?
呵呵,其实在Copy to中,你这个类型是不会改变的,依然是字符串类型,不会变成数值型的.

而你的 Sheet.Cells[nRows,i] = 这样的代码的确是会自动转换的,
因为EXCEL当成是你的输入,又没有限定格式,默认就成了数值型了,这正是EXCEL的便利.并不是弱点.

怎样避免? 只好用 _Vfp.DataClip( ) 先复制再按列类型设置格式了.

我这个小人肚子意见多,如果老高坚持一下我可能就不说下去了.
在录制宏的学习过程中,很多人(包括我)都会照搬,
像这样的代码,你能说它不是从录制宏过来的吗?
之前我提过一次,结果被别人狠批,呵呵,没关系,我又不会有损失的.
[quote]for i=1 to 4
  With Selection.Borders(i)
    .LineStyle = xlContinuous
    .Weight = xlThin
    .ColorIndex = xlAutomatic
  EndWith
ENDFOR[/quote]
还有你那个变量 Selection 在EXCEL的VBA中指代已选择的对象.
所以很容易会造成混淆,当然,故意混淆视听刚另当别论.

98 楼

[quote]还有你那个变量 Selection 在EXCEL的VBA中指代已选择的对象.
[/quote]

这个意见提得好,我接受!我改进!

99 楼

谢谢楼上两位老师。你们的探讨很精彩。
正在加紧学习vba。
等学会了,一定会很好地解决问题的。

100 楼

没必要刻意地去学它,都是对象、方法、属性的引用,会用宏录制和宏编辑就行了。

我来回复

您尚未登录,请登录后再回复。点此登录或注册