从Windows脚本宿主处理Excel文件

问题描述 投票:2回答:4

是否有一种快速的方法来处理Windows脚本宿主的现有 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脚本宿主中创建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
    

问题是,其中一些文件包含大量数据,这样填充它们需要几个小时。有没有更快的方法呢?

excel vbscript ado wsh
4个回答
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

我建议您先尝试。


2
投票

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


1
投票

一种可能是使其成为两个阶段的过程,但这取决于瓶颈在哪里。

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

这可能比逐个单元的操作要快。

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

移动范围也应该比逐个单元的操作更快。

这是批量导入和批量复制,应该可以给您带来一些改善。我有工作表处理的单个单元格,当您使用更复杂的Excel功能时(考虑使用= sum(a1..a999)而不是在VBA中添加每个单个单元格并将该值放在某个地方,这些单元格的速度提高了10倍)。

关于如何从VBA进行导入,我始终依靠"Record Macro"功能来获得可以修改的基线(对于我不十分熟悉的基线)。这将c:\x.csv导入到当前工作表的C7

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

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
© www.soinside.com 2019 - 2024. All rights reserved.