不管是使用vb6还是vb.net,处理excel都需要引用office的对象库,遇到所安装的excel版本发生变化,则会遇到令人头痛的兼容问题。
经过摸索,我发现可以先由python实现excel的处理,再用vb6调用,解决了因为安装excel的版本不同导致的兼容问题。
以下以csv和excel文件的互相转换为例,演示vb6操作excel的通用操作过程。
一、使用python实现csv和xls、xlsx的互转
需要安装python的第三方库:xlwt,xlrd,openpyxl,具体代码如下,脚本的逻辑和注意事项见注释:
import sys
import os
import xlrd
import xlwt
import openpyxl
import pathlib
#openpyxl记录excel行列均从1开始,xlrd、xlwt记录excel行列则从0开始
#xlrd、xlwt操作excel完毕,不需要使用close()关闭excel
def csv2xlsx(cn,xn):
#csv转xlsx,遍历csv,转成xlsx
wb=openpyxl.Workbook() #创建workbook对象
worksheet=wb.worksheets[0] #获取第一个sheet
row_num=1
with open(cn) as f:
for eachline in f:
tmplist=eachline.split(',')
for field_num,eachfield in enumerate(tmplist,1):
tmpfield=eachfield.rstrip() #去掉最后一个字段的'\n'
if tmpfield != 'None':
worksheet.cell(row_num,field_num).value=tmpfield
row_num+=1
wb.save(xn)
wb.close() #openpyxl需有此关闭命令,否则对应的文件仍在缓冲区中
def xlsx2csv(xn,cn):
#xlsx转csv,csv文件不必事先存在
workbook=openpyxl.load_workbook(xn)
worksheet=workbook.worksheets[0]
with open(cn,'w') as f:
for i in range(1,worksheet.max_row+1):
tmp=[str(worksheet.cell(i,j).value).strip() for j in range(1,worksheet.max_column+1)] #.cell(行,列)
f.write(','.join(tmp)+"\n") #添加了+"\n"
workbook.close() #openpyxl需有此关闭命令,关闭对应的文件
def csv2xls(cn,xn):
#csv转xls,遍历csv,转成xls
#和openpyxl不同,引用行列序号从0开始
wb=xlwt.Workbook() #创建workbook对象
worksheet=wb.add_sheet('sheet1') #添加第一个sheet
row_num=0
with open(cn) as f:
for eachline in f:
tmplist=eachline.split(',')
for field_num,eachfield in enumerate(tmplist,0):
tmpfield=eachfield.rstrip() #去掉最后一个字段的'\n'
if tmpfield != 'None':
worksheet.write(row_num,field_num,tmpfield)
row_num+=1
wb.save(xn)
#wb.close() #xlwt不需有此关闭命令
def xls2csv(xn,cn):
#xlsx转csv,csv文件不必事先存在
workbook=xlrd.open_workbook(xn)
worksheet=workbook.sheets()[0]
with open(cn,'w') as f:
for i in range(0,worksheet.nrows):
tmp=[str(worksheet.cell(i,j).value).strip() for j in range(0,worksheet.ncols)] #.cell(行,列)
f.write(','.join(tmp)+'\n')
#workbook.close() #xlrd不用关闭对应的excel文件
if __name__=='__main__':
#获取两个文件的名字,根据两个参数名中的文件后缀,调用对应的函数
n1=pathlib.Path(sys.argv[1]) # n1为<class 'pathlib.WindowsPath'>对象,路经分隔符为“/"
n2=pathlib.Path(sys.argv[2])
n1_base=os.path.basename(n1) # Returns the final component of a pathname
n2_base=os.path.basename(n2)
if n1_base.endswith('xlsx'):
xlsx2csv(n1,n2)
if n1_base.endswith('csv') and n2_base.endswith('xlsx'):
csv2xlsx(n1,n2)
if n1_base.endswith('xls'):
xls2csv(n1,n2)
if n1_base.endswith('csv') and n2_base.endswith('xls'):
csv2xls(n1,n2)
使用openpyxl处理xlsx格式的excel文档(其不能处理xls格式的),使用xlwt和xlrd处理xls格式的excel文档(这两者不能处理xlsx格式的),这相当于使用python库解决了excel的版本兼容问题 。
二、将上面的代码使用pyinstaller将其转为exe
将上面代码保存到“f:\pythoncodes\csv与xls及xlsx互转.py”。
pyinstaller.exe是由pyinstall库提供的命令,后者也是python第三方库,需要手工安装。在python安装路径下的scripts目录下执行:
pyinstaller -F f:\pythoncodes\csv与xls及xlsx互转.py
之后,会在scripts目录下的dist目录中(如果第一次运行pyinstaller,则会新建此目录),可以找到生成的“csv与xls及xlsx互转.exe”文件,这是一个exe文件,可以在命令行下正常执行,并且可以脱离python的运行环境,也不需要其运行的机器上安装office。
执行该命令,需要为其提供两个参数,一个为csv文件的完整路径,另一个是xls(或xlsx)文件的完整路径(如果参数文件和命令文件在同一目录下,则只需提供文件名即可)。有一点需要注意,python会将“\”解释为转义符,所以路经的分隔符可以使用“\\”或“/”。
三、在vb6中通过shell调用该命令,执行格式转换
vb6中,使用shell函数调用上面的exe文件,需要消耗数秒钟的时间,然而,默认vb6并不等待shell执行完毕,就会运行其后边的指令,故我们需要告诉vb6等待shell执行完毕,这可以使用api函数来实现。
1、先引用api及相关参数定义:
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function GetExitCodeProcess Lib "kernel32" (ByVal HProcess As Long, lpExitCode As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Const PROCESS_QUERY_INFORMATION = &H400
Const STILL_ALIVE = &H103
2、定义WaitForShell函数,其参数为一个pid,WaitForShell函数会等待该pid对应的进程直至其结束,代码如下:
Public Sub WaitForShell(ByVal Pid As Long)
Dim HProcess, ExitCode As Long
HProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 0, Pid)
Do
Call GetExitCodeProcess(HProcess, ExitCode)
DoEvents
Loop While ExitCode = STILL_ALIVE
Call CloseHandle(HProcess)
End Sub
3、shell函数会启动一个进程,并返回该进程的pid,作为WaitForShell函数的参数,如下:
Dim fntmp As String
fntmp = Strings.Replace(filename, "\", "\\") 'python把"\"解释为转义字符,故需先将其替换为"\\"
WaitForShell Shell(App.Path & "\测试csv和xlsx互转.exe " & fntmp & " tmp.csv", vbHide) '如此调用,可以保证在执行完转换后,才继续向下执行
总结,以上操作利用python,在vb6中实现了csv格式和xls及xlsx格式的相互转换,绕过了office对象库的版本不同时导致的尴尬。这实际上扩展了vb6的功能,未尝不是一种解决问题的思路。另外, xlwt、xlrd、openpyxl提供了丰富功能,还有待探索。

本文介绍了如何使用VB6调用Python脚本来处理Excel文件,避免因Excel版本不同产生的兼容问题。首先,用Python的xlwt、xlrd、openpyxl库实现CSV和Excel的互转,然后通过PyInstaller将Python脚本打包成exe。最后在VB6中使用Shell函数调用这个exe文件,完成转换操作,确保VB6程序等待转换完成。
2097

被折叠的 条评论
为什么被折叠?



