在单元格中写入缓慢的VBA宏

Lau*_*ant 5 excel vba excel-vba ms-project

我有一个VBA宏,它将数据写入清除的工作表,但它真的很慢!

我正在从Project Professional中实例化Excel.

Set xlApp = New Excel.Application
xlApp.ScreenUpdating = False
Dim NewBook As Excel.WorkBook
Dim ws As Excel.Worksheet
Set NewBook = xlApp.Workbooks.Add()
With NewBook
     .Title = "SomeData"
     Set ws = NewBook.Worksheets.Add()
     ws.Name = "SomeData"
End With

xlApp.Calculation = xlCalculationManual 'I am setting this to manual here

RowNumber=2
Some random foreach cycle
    ws.Cells(RowNumber, 1).Value = some value
    ws.Cells(RowNumber, 2).Value = some value
    ws.Cells(RowNumber, 3).Value = some value
             ...............
    ws.Cells(RowNumber, 12).Value = some value
    RowNumber=RowNumber+1
Next
Run Code Online (Sandbox Code Playgroud)

我的问题是,foreach周期有点大.最后,我将获得大约29000行.在漂亮的OK计算机上完成此操作需要超过25分钟.

是否有任何技巧可以加快写入细胞的速度?我做了以下事情:

xlApp.ScreenUpdating = False
xlApp.Calculation = xlCalculationManual
Run Code Online (Sandbox Code Playgroud)

我是以错误的方式引用细胞吗?是否有可能,写一整行,而不是单个单元格?

会更快吗?

我已经测试了我的代码,foreach循环经历了相当快速(我将值写入一些随机变量),所以我知道,写入单元格是一直占用的.

如果您需要更多信息,请告知密码.

感谢您的时间.

Rac*_*ger 8

是否有可能,写一整行,而不是单个单元格?会更快吗?

是的,是的.这正是您可以提高性能的地方.对单元格的读/写非常慢.重要的是你正在读/写多少个单元,而是你要对COM对象进行多少次调用.因此,使用二维数组以块的形式读取和写入数据.

以下是将MS Project任务数据写入Excel的示例过程.我用29,000个任务模拟了一个计划,这个计划在几秒钟内就完成了.

Sub WriteTaskDataToExcel()

Dim xlApp As Excel.Application
Set xlApp = New Excel.Application
xlApp.Visible = True

Dim NewBook As Excel.Workbook
Dim ws As Excel.Worksheet
Set NewBook = xlApp.Workbooks.Add()
With NewBook
     .Title = "SomeData"
     Set ws = NewBook.Worksheets.Add()
     ws.Name = "SomeData"
End With

xlApp.ScreenUpdating = False
Dim OrigCalc As Excel.XlCalculation
OrigCalc = xlApp.Calculation
xlApp.Calculation = xlCalculationManual

Const BlockSize As Long = 1000
Dim Values() As Variant
ReDim Values(BlockSize, 12)
Dim idx As Long
idx = -1
Dim RowNumber As Long
RowNumber = 2
Dim tsk As Task
For Each tsk In ActiveProject.Tasks
    idx = idx + 1
    Values(idx, 0) = tsk.ID
    Values(idx, 1) = tsk.Name
    ' populate the rest of the values
    Values(idx, 11) = tsk.ResourceNames
    If idx = BlockSize - 1 Then
        With ws
            .Range(.Cells(RowNumber, 1), .Cells(RowNumber + BlockSize - 1, 12)).Value = Values
        End With
        idx = -1
        ReDim Values(BlockSize, 12)
        RowNumber = RowNumber + BlockSize
    End If
Next
' write last block
With ws
    .Range(.Cells(RowNumber, 1), .Cells(RowNumber + BlockSize - 1, 12)).Value = Values
End With
xlApp.ScreenUpdating = True
xlApp.Calculation = OrigCalc

End Sub
Run Code Online (Sandbox Code Playgroud)