2

有没有一种快速的方法可以从 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

4 回答 4

6

我认为你在这里很好:

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

我建议你先试试。

于 2009-04-20T08:09:09.480 回答
2

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

于 2009-04-20T17:34:53.847 回答
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
于 2009-04-20T05:22:22.080 回答
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
于 2009-04-22T22:04:41.937 回答