Cập nhật theo lô – Batch update
Trong một số ứng dụng, việc khởi tạo và import dữ liệu bên ngoài vào sau khi bạn hoàn thành là một công việc không dễ dàng chút nào. Làm sao để kiểm tra việc cập nhật có thành công hay không? Nếu không thành công thì hủy bỏ tất cả…
Việc cập nhật theo lô sẽ giúp bạn điều này.
Xin giới thiệu một thủ tục để các bạn tham khảo:
Option Explicit
Const DBTable As String = "TB_Bom"
Const DBPath As String = "\Sun-ServerProductionQuanLyKho.mdb"
Sub BatchUpdate()
Dim iLastrow As Long, i As Long, j As Long
Dim conn As ADODB.Connection
Dim ADOrst As ADODB.Recordset
Dim arrFieldnames As Variant
Dim arrValues As Variant
Dim arrRecordvals As Variant
On Error GoTo ErrorHandler
arrFieldnames = Array("sBomHeader", "sBomDes", _
"sMaNo", "sMaDes", "sMaUoM", "nMaQty") 'change as needed
'Speed up execution by disabling screen updating
Application.ScreenUpdating = False
'Make a connection to your database file
Set conn = New ADODB.Connection
With conn
.Provider = "Microsoft.Jet.OLEDB.4.0"
.ConnectionString = "data source=" & DBPath
.Open
End With
'Create a *new* recordset here because we overwrite the ones in the existing table
Set ADOrst = New ADODB.Recordset
'Use a client cursor and adLockBatchOptimistic to do batch updates
ADOrst.CursorLocation = adUseClient
ADOrst.Open DBTable, conn, adOpenStatic, adLockBatchOptimistic
'Find the last row(number) with data in Sheet1
With ThisWorkbook.Worksheets("BOM_09092008")
iLastrow = .Range("A" & .Rows.Count).End(xlUp).Row
End With
'Clear the table
ClearTable (DBTable)
'Assign your worksheet values in one statement to the variable arrValues (type Variant)
arrValues = ThisWorkbook.Worksheets("BOM_09092008").Range("A2:M" & iLastrow).Value
'Stuff the worksheet values into the recordset
For i = 1 To UBound(arrValues, 1)
If Len(arrValues(i, 9)) > 0 Then
arrRecordvals = Array(arrValues(i, 1), arrValues(i, 2), _
arrValues(i, 9), arrValues(i, 10), _
arrValues(i, 13), arrValues(i, 12))
ADOrst.AddNew arrFieldnames, arrRecordvals
Application.StatusBar = "Update to record " & i & "/" & iLastrow - 1
End If
Next i
Application.StatusBar = "Batch updating...Please wait."
'(Batch)Update the table with the just created recordset
[B]ADOrst.UpdateBatch
[/B]
'Close the recordset
ADOrst.Close
'Close database connection
conn.Close
'Inform the user
MsgBox "Updating is successful.", vbOKOnly + vbInformation, "Inf"
ErrorExit:
'Clean up
Set ADOrst = Nothing
Set arrValues = Nothing
Set arrRecordvals = Nothing
Set arrFieldnames = Nothing
'Re-enable screen updating
Application.ScreenUpdating = True
Application.StatusBar = False
Exit Sub
ErrorHandler:
MsgBox "Error is " & Err.Number & "; Error description: " & Err.Description
Resume ErrorExit
End Sub
Sub ClearTable(sTable As String)
'Thủ tục này nhằm xóa dữ liệu trong bảng
With New ADODB.Connection
.Provider = "Microsoft.Jet.OLEDB.4.0"
.Open DBPath
.Execute "DELETE FROM " & sTable
.Close
End With
End Sub
Tôi đã test thủ tục trên với hơn 70,000 records và có vài nhận xét như sau:
1. Bằng việc dùng mảng từ đối tượng Range code của các bạn sẽ nhanh hơn.
arrValues = ThisWorkbook.Worksheets("BOM_09092008").Range("A2:M" & iLastrow).Value
2. Đối với dữ liệu quá lớn, các thao tác thêm vào trước khi gọi phương thức UpdateBatch thực hiện rất nhanh. Nhưng khi các bạn gọi phương thức này thì chương trình của bạn sẽ "bị treo" một thời gian, mới thực hiện xong. Vậy nên, cách tốt nhất là chúng ta chia dữ liệu thành nhiều phần nhỏ (giả sử chia thành nhiều sheets chẳng hạn), rồi cập nhật theo từng phần là tốt nhất.
Lê Văn Duyệt
www.giaiphapexcel.com/diendan/threads/c%E1%BA%ADp-nh%E1%BA%ADt-theo-l%C3%B4-batch-update.13797/
Khóa học Power PI – Ứng dung trong Nhân sự
TỔNG QUAN KHÓA HỌC: POWER BI CHO NGÀNH NHÂN SỰ Khóa học Power BI cho Nhân sự được thiết kế dành riêng cho các...
Xem khóa học
Tôi thấy một so sánh cũng hay, xin chia sẽ cùng các bạn:
What is the fastest way to scan a large range in Excel? Cách nhanh nhất để duyệt qua một vùng lớn trong Excel?
Problem description-Vấn đề:
You have a large range in Excel with data. Let's say it contains 100,000 rows and 50 columns for each row (Yes you are using Excel 2007 of course). So altogether you have 5,000,000 cells. Columns A to F have some alphanumeric data that you need analyze and based on the combination of values for each row you need to use the numeric values in G to H to do some calculations and store the results in columns I and J. You could place 200,000 formulas in I and J but you see that a spreadsheet with such a volume of formulas gets very sow and consumes huge amounts of memory.
You decide to try and solve it in a piece of VBA code. The question is how to implement such a task in the most efficient way?
What are your options
How can you scan a range in Excel, read the values in some cells, and change some others?
Use a range object
Let's assume that the range you want to read starts at A1
The code looks something like this:
Use the selection and move it using offset
Many VBA developers learned VBA techniques from macro recording.
When using relative reference the generated VBA code creates statements like:
As a consequence many developers adopt this technique and use the ActiveCell or selection ranges to move from cell to cell in code and read or write the cell values. The code will look like this:
Use a variant type variable
This technique copies the values from all cells in the range into a variable in memory, manipulates the values inside this variable and if needed moves the values back to the range after manipulation.
Here is the code this time:
Another difference is that this method is blazing fast compared to the two others.
Performance Summary
I compared the three methods on relatively large ranges and here are the results:
Method|Operation|Cells/Sec
Variant|Read|1,225,490
|Write|714,286
|Read/Write|263,158
Range|Read|250,000
|Write|1818
|Read/Write|1,852
Offset|Read|206
|Write|200
|Read/Write|203
As you can see using a variant variable is much faster especially when changing cells. Even if the calculation can be done with Excel formulas, in some cases this method is the only one acceptable because using a very large number of formulas can become very slow.
Obviously the one method to avoid is moving the ActiveCell using Offset.
blogs.msdn.com/excel/archive/2008/10/03/what-is-the-fastest-way-to-scan-a-large-range-in-excel.aspx
Một ví dụ tương tự
Dùng Offset
Dùng array
Với hai cách trên nếu chúng ta viết 100,000 giá trị thì cách Offset sẽ mất 9.73 giây còn cách dùng array mất 0.16 giây. Tức là khoảng 60 lần nhanh hơn.
http://www.dailydoseofexcel.com/archives/2006/12/04/writing-to-a-range-using-vba/
Lê Văn Duyệt