从Windows Scripting Host操作Excel文件

时间:2009-04-20 05:17:28

标签: excel vbscript ado wsh

是否有一种快速方法可以从Windows Scripting Host操作现有 XLS文件的内容?

我们收到了客户提供的Excel模板。我们的任务是使用从Oracle数据库中提取的数据填充这些模板。

目前的方法是使用Windows Scripting Host和VBScript:

  1. 使用ADODB从Oracle获取数据:

    Set db = CreateObject("ADODB.Connection")
    SQL = "SELECT ..."
    Set rs=db.execute(SQL)
    
  2. 使用VBScript在Windows Scripting Host中创建Excel对象:

    Set objExcel = CreateObject("Excel.Application")  
    Set objWorkbook = objExcel.Workbooks.Open(xls_final)  
    Set objSheet = objWorkBook.Sheets(1)
    
  3. 然后按照以下方式逐个填写模板:

    If rs.EOF = False Then
       rs.MoveFirst
       Do Until rs.EOF
          objSheet.Cells(RowNumber, 1).Value = rs("COLUMN1")
          objSheet.Cells(RowNumber, 2).Value = rs("COLUMN2")
          objSheet.Cells(RowNumber, 3).Value = rs("COLUMN3")
          rs.MoveNext
       Loop
    End If
    objWorkbook.Save 
    rs.Close
    

    问题是这些文件中的一些包含大量数据,并且需要花费数小时来填充它们。 有没有更快的方法呢?

4 个答案:

答案 0 :(得分:5)

我觉得你很高兴在这里:

Set db = CreateObject("ADODB.Connection")
SQL = "SELECT ..."
Set rs=db.execute(SQL)

Set objExcel = CreateObject("Excel.Application")  
Set objWorkbook = objExcel.Workbooks.Open(xls_final)  
Set objSheet = objWorkBook.Sheets(1)

但正如你所发现的,其余部分将会非常缓慢。与工作表的交互具有很高的开销,您需要为每行中的每一列付费。这有一些方法。

最简单的是

objSheet.Cells(1,1).CopyFromRecordset rs

我建议你先试试。

答案 1 :(得分:2)

看看这个。
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=49926
如果使用ADODB连接到Excel,而不是操作Excel,它也可能会有所帮助。如果您需要帮助,请阅读本文 http://support.microsoft.com/kb/257819

答案 2 :(得分:1)

一种可能性是将其分为两个阶段,但这取决于瓶颈在哪里。

如果是Excel,则只需将记录集行转换为CSV类型文件,然后完成后,创建Excel对象并将整个文件导入固定位置。

这可能比逐个细胞操作更快。

如果您无法将CSV导入到工作表上的固定位置(或者单元格不在连续的行或列中),我会将CSV导入新工作表,然后从那里执行批量复制到您的模板片材。

移动范围也应该比逐个细胞操作更快。

批量导入和批量复制应该会给你一些很好的改进。当你使用更复杂的Excel功能时,我已经有了处理单个单元格的工作表,这些单元格加速了10个因子(想想使用= sum(a1..a999)而不是在VBA中添加每个单独的单元格并将该值放在某处)。

至于如何从VBA导入,我总是依靠"Record Macro"功能来获得可以修改的基线(对于那些我不熟悉的基线)。这个导入c:\x.csvC7的当前工作表:

With ActiveSheet.QueryTables.Add(Connection:="TEXT;C:\x.csv", _
    Destination:= Range("C7"))
    .Name = "x"
    .FieldNames = True
    .RowNumbers = False
    .FillAdjacentFormulas = False
    .PreserveFormatting = True
    .RefreshOnFileOpen = False
    .RefreshStyle = xlInsertDeleteCells
    .SavePassword = False
    .SaveData = True
    .AdjustColumnWidth = True
    .RefreshPeriod = 0
    .TextFilePromptOnRefresh = False
    .TextFilePlatform = 850
    .TextFileStartRow = 1
    .TextFileParseType = xlDelimited
    .TextFileTextQualifier = xlTextQualifierDoubleQuote
    .TextFileConsecutiveDelimiter = False
    .TextFileTabDelimiter = True
    .TextFileSemicolonDelimiter = False
    .TextFileCommaDelimiter = True
    .TextFileSpaceDelimiter = False
    .TextFileColumnDataTypes = Array(1, 1, 1)
    .TextFileTrailingMinusNumbers = True
    .Refresh BackgroundQuery:=False
End With

现在我确信那里的大部分垃圾都可以删除,但你明智地一次做一件以确保没有问题出现。

您也可以使用以下内容修改它以使用其他工作表。

dim ws as worksheet
dim savealert as boolean
set ws = Sheets.Add
ws.select
' Put all that other code above in here. '
' Move all that data just loaded into a real sheet. '
savealert = Application.DisplayAlerts
Application.DisplayAlerts = False
ws.delete
Application.DisplayAlerts = savealert

答案 3 :(得分:0)

您可以通过OLEDB连接访问它,并且速度非常快。

以下是我用于将数据从电子表格导入数据库的脚本中的一些代码。显然你会想要改变光标类型和锁类型,但你明白了。

strExcelConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & objFile.Path & ";Extended Properties=""Excel 8.0;HDR=Yes"""
strSQL = "SELECT * FROM [RegistrationList$] ORDER BY DateToRegister DESC"

objExcel.Open strSQL, strExcelConn, adOpenForwardOnly, adLockReadOnly, adCmdText