Ghi Dữ Liệu Vào File Đóng Bằng ADO
Mình có viết một chương trình Bán hàng…sử dụng VBA để ghi dữ liệu từ file chuơngTrinh.xlsb vào File Data.xlsb hiện tại sử dụng tốt …
Nhưng khi dữ liệu File Data càng lớn thì thấy nó hơi chậm lại…vì vậy mình muốn chuyển qua sử dụng ADO với code có chức năng tương tự nhưng kẹt chưa làm được …Vậy úp lên nhờ các Bạn trợ giúp1/ vùng dữ liệu cần ghi từ File chuongTrinh là
2/ điều kiện ghi là từ nếu Cells nào có dữ liệu thì lọc ghi theo dòng đó (khó khúc này ADO là mình Tịt…Nếu ghi nguyên vùng thì OK)
3/ Ghi vào Sheets("Data_Ban")File Data.xlsb nối tiếp xuống dưới tương tự như Code VBA mình viết….sau khi ghi xong thì chay Sub Auto_Open trong File Data.xlsb
Xin cảm ơn các Bạn đã trợ giúp…
Code VBAPublic Sub LuuData_Ban()
Application.ScreenUpdating = False
Dim Nguon(), Kq(), i&, j&, k&
Nguon = ActiveSheet.Range("A6:J82").Value
ReDim Kq(1 To UBound(Nguon, 1), 1 To UBound(Nguon, 2))
For i = 1 To UBound(Nguon, 1)
If Nguon(i, 3) <> "" Then
k = k + 1
For j = 1 To UBound(Nguon, 2)
Kq(k, j) = Nguon(i, j)
Next
End If
Next
With Workbooks.Open(ThisWorkbook.Path & "Data.xlsb", 0)
.Sheets("Data_Ban").Range("A65536").End(3)(2).Resize(k, UBound(Nguon, 2)) = Kq
.RunAutoMacros (xlAutoOpen) ''Chay Sub Auto_Open Trong File Data
.Close True
End With
Application.ScreenUpdating = True
End Sub
theo hiểu biết của tôi mà muốn dùng ADO để gọi SUB của file đang đóng e là chuyện động trời .
nhưng mà có cần thiết phải gọi sub Auto_open , chạy code tương tự các dòng trong Sub Auto_open là được chứ gì ?
Phải chạy Sub Auto_Open Trong File Data Vì khi Mình nhập hàng hay xuất hàng thì nó tổng hợp Nhập Xuất Tồn Luôn và trả kết quả về File chương Trình tức thì để mình Kiểm hàng….vì vậy không Thể bỏ được…
Và còn kèm thêm Một sub khác chạy theo nữa ….mình chưa viết trong đó thôi
vậy tôi cập nhật dữ liệu từ sheet Data_ban vào thẳng cột M:N luôn ngay sau khi ghi dữ liệu lên sheet Data_ban được không ?
Vậy cũng được mình lại viết thêm Sub khác lấy lên cũng Ok….
Nhưng Sub Auto_Open Phải chạy vì còn liên quan mấy sub khác nữa…..
Vụ này Làm Sao mà làm Khó bạn hiền được chứ
hay chơi kiểu sau … Sau khi ADO ghi xong thì chạy Sub này kể ra thì nó cũng không đẹp lắmSub Open_CloseFile()
Application.ScreenUpdating = False
Dim Openfile
Openfile = "data.xlsb"
Workbooks.Open ThisWorkbook.Path & "" & Openfile
Workbooks(Openfile).RunAutoMacros (xlAutoOpen)
Workbooks(Openfile).Close True
Application.ScreenUpdating = True
End Sub
Thay vì viết code trong file đóng đó ta viết trong file mở rồi ghi dữ liệu file đóng đó thử.
đây là code ghi dữ liệu lên sheet Data_ban rồi cập nhật ngược lại vào vùng M:N chứ không đụng chạm gì tới sheet TongHop
Public Sub hell()
Dim cn As Object, rs As Object
Set cn = CreateObject("ADODB.Connection")
cn.Open ("provider=Microsoft.ACE.OLEDB.12.0; data source=" & _
ThisWorkbook.Path & "data.xlsb" & _
";extended properties=""Excel 12.0;hdr=no"";")
cn.Execute ("insert into [Data_Ban$A2:J] " & _
"select * from [" & ThisWorkbook.FullName & ";hdr=no].[BanHang$A6:J] where f3 is not null")
Set rs = cn.Execute("select f1,sum(f2) as f2 from [Data_Ban$B2:C] where f1 is not null group by f1")
Sheet1.Range("M6").CopyFromRecordset rs
rs.Close
cn.Close
End Sub
anh cho xem cái sub auto_open rốt cục chứa cái gì đã rồi mới tính tiếp được
Mô tả Sub Auto_Open()
1/ Khi mình nhập hàng thì từ File ChuongTrinh Sẽ nhập Ghi vào File Data và Bán hàng Cũng vậy2/ khi nhập hay bán xong thì sub Auto_Open() nó sẽ tổng hợp lại Xuất Nhập Tồn Xuất qua Sheet TongHop Từ Sheet TongHop nó sẽ báo cho mình biết tồn kho còn bao nhiêu và xuất kết quả ngược lại File ChuongTrinh như Cột đó mình biết xử lý hàng tồn kho luôn tức thì
Chỉ cần Từ File ChuongTrinh Ghi xong Chạy Sub Auto_Open là ok rồiNó chạy dòng dòng vậy đó….VBA thì mình xử lý OK ….Còn ADO thì tịt……….–=0
như thế là muốn tổng hợp tồn kho thì phải có sheet Data_mua trong file Data.xlsb nữa mới tính được tồn kho . vậy mà file Data anh gửi lên không có sheet này sao tôi tổng hợp ? => có dấu hiệu gian dối
nếu Sub Auto_open chỉ để đi làm ba cái việc tính tồn kho ,cập nhật sheet TongHop, rồi gán kết quả vào cột M:N thì tôi không thấy lý do nào để phải mở file Data lên cả . file Data đóng cũng làm được
bây giờ tôi phải xem cái sheet Data_mua trong file Data.xlsb nó thế nào đã rồi tính tiếp
File Data Đây Bạn …Mình Tổng hợp xong Từ File ChuongTrinh dùng ADO lấy Sheets("NXT"). gán Vào là vậy đó….Bạn nghiên cứu Giúp Mình
Có thể tham gia của mình không đúng với yêu cầu của bạn, bạn nên xem lại và thay đổi cách làm cho nó phù hợp hơn:
-Thằng nào làm kho thì nên phân công nó chuyên làm kho đi, miễn là nó bố trí khoa học, chính xác nhập xuất theo yêu cầu. Nghiêm ngặt qui chế nhập xuất kho theo quy tắc.
-Thằng nào muốn nhập vào thì phải lo thủ tục cho "hàng" của mình vào được kho.
-Thằng nào muốn thông tin thì tự chế biến từ nguyên liệu của kho.
Vậy là file data chứa dữ liệu không phải lo những việc bạn không kiểm soát được. Ví dụ: Đúng lúc bạn chạy cái Sub Auto… có người nhạp sửa dữ liệu là lỗi rồi, file dùng chung thì khó tránh dạng này. Kể cả dùng ADO đi chăng nữa bạn cũng đừng nghĩ là file đó đang đóng im ỉm đâu .
Bạn nên tham kham khảo cách chia file front end – back end của Access ấy. Nó có tiện ích này thật hay, sau khi hoàn thanh file nó giúp tách thành 2 file: 1 file dùng chung và 1 file cho người dùng.
Access thì mình không rành lắm….
Còn File Data có bao Giờ Mình mở lên đâu mà lo lỗi….mình thiết kế sử dụng cho một một máy và khi sử dụng chỉ chạy mỗi File chương trình thôi …
khi cần cái gì thì sử dụng ADO lấy lên xem…
file data.xlsb anh có dùng chung với ai ko ???
anh mà share cùng lúc nhiều người xài thì quên luôn cái ADO đi nhé . nếu chỉ mình anh xài mới dùng được.
code dưới đây thực hiện các nhiệm vụ
chèn dữ liệu vào sheet Data_Ban
cập nhật lại sheet NGUON
Cập nhật toàn bộ bảng Sheet XNT
gán ngược lại kết quả cho vùng M:N
muốn xài được code này cần phải :
Xóa hết code đang có trong file Data.xlsb
Xóa hết công thức hàng 1 của sheet XNT
Tuyệt đối đóng file Data.xlsb khi chạy code
Public Sub GotoHell()
Dim Cn As Object, rs As Object, arrNHAP As Variant, arrBAN As Variant
Dim r As Long, c As Integer, arrSUM(1 To 9) As Double, arrView As Variant
Set Cn = CreateObject("ADODB.Connection")
Cn.Open ("provider=Microsoft.ACE.OLEDB.12.0; data source=" & _
ThisWorkbook.Path & "data.xlsb" & _
";extended properties=""Excel 12.0;hdr=no"";")
Cn.Execute ("insert into [Data_Ban$A2:J] " & _
"select * from [" & ThisWorkbook.FullName & ";hdr=no].[BanHang$A6:J] where f3 is not null")
Cn.Execute ("insert into [NGUON$B3:B] select a.f1 from " & _
"(select distinct f1 from [Data_Nhap$B2:B] where f1 is not null) a left join " & _
"(select f1 from [NGUON$B3:B] where f1 is not null) b on a.f1 = b.f1 where b.f1 is null")
Set rs = Cn.Execute("select b.f1,a.sf2,a.sf5 from " & _
"(select f1,sum(f2) as sf2,sum(f5) as sf5 from [Data_Nhap$B2:F] " & _
"where f1 is not null group by f1 ) a " & _
"right join (select f1 from [NGUON$B3:B] where f1 is not null) b " & _
"on a.f1 = b.f1 order by b.f1")
arrNHAP = rs.GetRows
rs.Close
Set rs = Cn.Execute("select b.f1,a.sf2,a.sf5 from " & _
"(select f1,sum(f2) as sf2,sum(f5) as sf5 from [Data_Ban$B2:F] " & _
"where f1 is not null group by f1 ) a " & _
"right join (select f1 from [NGUON$B3:B] where f1 is not null) b " & _
"on a.f1 = b.f1 order by b.f1")
arrBAN = rs.GetRows
rs.Close
rs.Open "select * from [XNT$B1:K" & UBound(arrBAN, 2) + 3 & "]", Cn, , 3
rs.MoveNext
rs.MoveNext
ReDim arrView(1 To UBound(arrBAN, 2) + 1, 1 To 2)
For r = 0 To UBound(arrBAN, 2) Step 1
arrView(r + 1, 1) = arrNHAP(0, r)
rs("f1") = arrNHAP(0, r)
rs("f2") = arrNHAP(1, r)
rs("f3") = arrNHAP(2, r)
rs("f4") = arrBAN(0, r)
rs("f5") = arrBAN(1, r)
rs("f6") = arrBAN(2, r)
rs("f7") = arrBAN(0, r)
If IsNumeric(arrNHAP(1, r)) And IsNumeric(arrNHAP(2, r)) And _
IsNumeric(arrBAN(1, r)) And IsNumeric(arrBAN(2, r)) Then
rs("f8") = arrNHAP(1, r) - arrBAN(1, r)
rs("f9") = (arrBAN(2, r) / arrBAN(1, r) - arrNHAP(2, r) / arrNHAP(1, r)) * arrBAN(1, r)
rs("f10") = arrNHAP(2, r) - arrBAN(2, r) + rs("f9")
Else
rs("f8") = 0
rs("f9") = 0
rs("f10") = 0
End If
arrView(r + 1, 2) = rs("f8")
For c = 2 To 10 Step 1
If IsNumeric(rs("f" & c)) Then arrSUM(c - 1) = arrSUM(c - 1) + rs("f" & c)
Next
rs.MoveNext
Next
rs.MoveFirst
For c = 2 To 10 Step 1
If arrSUM(c - 1) > 0 Then rs("f" & c) = arrSUM(c - 1)
Next
rs.MoveLast
rs.Close
Cn.Close
Sheet1.Range("M6:N1000").ClearContents
Sheet1.Range("M6").Resize(UBound(arrView), 2).Value = arrView
End Sub
Bạn hiền Mình chạy Thấy lỗi….Khiếp …Code viết dữ quá nhìn thấy sợ luôn
Hay bạn sửa lại Code sau (Của Bạn) cho Mình chỉ cần Ghi dữ liệu Vùng theo điều Kiện Cột vào File Data Là Ok rồi Còn lại mình Tự Xử ĐượcPublic Sub hell()
Dim Cn As Object, rs As Object
Set Cn = CreateObject("ADODB.Connection")
Cn.Open ("provider=Microsoft.ACE.OLEDB.12.0; data source=" & _
ThisWorkbook.Path & "data.xlsb" & _
";extended properties=""Excel 12.0;hdr=no"";")
Cn.Execute ("insert into [Data_Ban$A2:J] " & _
"select * from .[BanHang$A6:J] where f3 is not null")
Set rs = Cn.Execute("select f1,sum(f2) as f2 from [Data_Ban$B2:C] where f1 is not null group by f1")
Sheet1.Range("M6").CopyFromRecordset rs '''Bo khong su dung
rs.Close
Cn.Close
Call Open_CloseFile
End SubXong Mình Chạy Sub sau cũng được vậy
Sub Open_CloseFile()
Application.ScreenUpdating = False
Dim Openfile As String
Openfile = "data.xlsb"
Workbooks.Open ThisWorkbook.Path & "" & Openfile
Workbooks(Openfile).RunAutoMacros (xlAutoOpen)
Workbooks(Openfile).Close True
Application.ScreenUpdating = True
End Sub
nếu chỉ làm đúng cái nhiệm vụ ghi vào file Data thì thôi khỏi xài ADO luôn cho khỏe .
nếu đã xài ADO thì chơi tới bến , không thì khỏi xài chứ làm nữa vời chả ra cái gì
Bạn hiền Mình chạy Thấy lỗi….Khiếp …Code viết dữ quá nhìn thấy sợ luôn
www.youtube.com/watch?t=17&v=A5y_Wtr4ji0
Khâm phục ….Mới Làm lại chạy Tốt….
www.giaiphapexcel.com/diendan/threads/ghi-d%E1%BB%AF-li%E1%BB%87u-v%C3%A0o-file-%C4%90%C3%B3ng-b%E1%BA%B1ng-ado.107950/
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
Sắp xếp lại CSDL, file data thì chỉ để lưu trữ dữ liệu, muốn cần tồn kho thì lấy thẳng ra file báo cáo. Ai lại ghi ngược lại Data cái tồn kho đó làm chi cho tốn bộ nhớ.
Thì chỉ việc ghi data nhập hoặc xuất vào file data để lưu trữ, sau khi nhập hoặc xuất = 1 file khác vào data thì tính toán số tồn kho thực tế đưa vào bên phải hay ở đâu đó tuỳ bạn. Sao phải nhất thiết là ghi số tồn kho đó vào file data rồi lấy ngược ra lại?
Tôi đã diễn đạt ở trên mà bạn không đọc kỹ, có nghĩa là:
File data chỉ dùng để lưu nhập và xuất. Ta ở 1 file khác (file chuongtrinh) truy vấn vào file data, tính toán số nhập và xuất để lấy kết quả ra file chuongtrinh. Đâu cần tính tồn kho ở file data đâu bạn. Không ai làm thế đâu. Như vậy trong file data chỉ có lưu 1 sheet là sheet nhập + xuất, hoặc bạn có thể tách làm 2, tuy nhiên theo tôi thì nên gom 2 sheet nhập và xuất vào 1 sheet. Trong file chương trình sẽ là file xử lý dữ liệu.
Nếu dữ liệu lớn và nhiều người dùng thì nên đi theo hướng này anh à, để sau này dể chuyển đổi từ excel data sang những csdl khác nếu có nhu cầu.
Nếu mọi cái làm ở Data thì chắc chắn 1 điều là CSDL sẽ bị phìn to, code sẽ bị ì ịch. Tôi chỉ góp ý thế còn việc bạn vận dụng theo cách nào thì tùy bạn thôi.
Tôi chỉ làm ví dụ để chứng minh việc tôi gợi ý cho bạn ở trên.
Tạo chuổi kết nối khi mở file chuongtrinh:
Trong file chương trình tôi tạo 1 module mới như sau:
Bạn xem ví dụ nhé.
Theo tôi được biết thì ADO sẽ không làm được việc đó, nó chỉ sort dữ liệu theo dạng chuẩn. Nếu như theo ý bạn thì tôi nghĩ chỉ có cách là dùng update kết quả sang thôi.
Chỉnh lại code khi mở workbook
Trong module
Xem thêm file đính kèm.
Sau này bạn có thể tự tìm được câu trả lời này, với trình độ cùi bắp của tôi không chắc giải thích được.
Tôi gửi bạn ví dụ về cập nhật trên range để phần nào bạn hiểu được cách thức, bạn tự nghiên cứu và tìm giải pháp tốt hơn nhé.
anh nặng lời rồi . giúp người khác theo cách nào đó là tùy vào tính tình mỗi người
tôi không có thói quen tham gia ý kiến về cách người dùng xây dựng CSDL của họ
tôi dễ lắm . thích xôi cho ăn xôi . còn khi nào cảm thấy code không được tôi bỏ chạy trước
đoạn code ở trên có gì đáng để gọi là công lao ? đối với tôi viết những đoạn như thế quá dễ
@Kiều Mạnh : góp ý của anh Hai Lúa Miền Tây làm cho công việc gọn hơn nhiều đấy . anh nên cân nhắc
thay Sub Lay_TonKho() cũ bằng Sub này xem mèo nào cắn miu nào ?
cách trên của mình vẫn chưa đạt vì còn sử dụng mấy cái ngoài ADO . sub này sửa lại sử dụng ADO 100 %
anh làm mẫu luôn đi để em học tập với . sức em có vậy à
ủa vậy là sao anh ? cột M Kiều Mạnh định nghĩa là cột làm mẫu về thứ tự và được copy từ cột B sang . như thế câu hỏi nếu như cột M không có dữ liệu là sao ? Kiều Mạnh đâu có ý định xóa cột M ?
không cho right join đến [BanHang$M6:M] thì right join đến [BanHang$B6:B] . nhưng chắc đây không phải ý anh . anh có thể nói rõ hơn không ?
có phải ý anh là dùng lệnh Update bảng chăng ?
thì nãy giờ em nêu 2 cách rồi mà
phải làm sao mới xí dụ được anh cho học hỏi 1 đoạn code đây . hức . khó quá /-*+//-*+//-*+/
Theo mình thì:
1. Khai báo kiểu Early Binding (tức là check vào mục Reference) cho code chạy nhanh hơn. Khai báo cũng gọn hơn, khỏi mắc công set này set nọ.
2. Nếu muốn dùng VBA xử lý thì sao không dùng phương thức Getrows lấy tất tần tật lên mảng rồi xử lý, mắc chi phải dùng câu lệnh SQL phức tạp kia làm gì. Chú ý cái mảng sau khi lấy bằng GetRows là mảng ngược nhé.
3. Mình chỉ đoán vậy thôi, nên nếu có trật thì mọi người bỏ qua nhé.
Tham gia 1 code cho vui, chứ thật sự không dám ho hen với ADO. Chú ý là phải dùng Early Binding nha. Không check vào running time hoặc không check vào data object* gì đó thì code nó ngu nhá.
*** Lâu rồi không tung chưởng nào hết. Bận quá rồi code cũng biến đi mất. Có chỗ nào không hay thì mọi người góp ý nhé.
Sub Main()
Dim SQL As String, MySheet(), Tmp(), i As Long, j As Long, Arr()
Dim ObjRst As New ADODB.Recordset, ObjConn As New ADODB.Connection, Dic As New dictionary
MySheet = Array("[Data_Nhap$B2:C65536]", "[Data_Ban$B2:C65536]")
Set ObjConn = GetConnection(ThisWorkbook.Path & "Data.xlsb")
For j = 0 To UBound(MySheet)
SQL = "select * from " & MySheet(j)
ObjRst.Open SQL, ObjConn, 3, 1
Tmp = ObjRst.GetRows
ObjRst.Close
GetData Tmp, Dic, j
Next
With Sheets("BanHang")
Arr = .Range("M6", ..End(3)).Resize(, 2).Value
End With
For i = 1 To UBound(Arr)
If Dic.Exists(Arr(i, 1)) Then
Arr(i, 2) = Dic.Item(Arr(i, 1))
Else
Arr(i, 2) = Empty
End If
Next
Sheets("BanHang")..Resize(i – 1, 2) = Arr
End Sub
Sub GetData(Arr, Dic, j)
Dim i As Long
For i = 0 To UBound(Arr, 2)
If j = 0 Then
Dic(Arr(0, i)) = Dic(Arr(0, i)) + Arr(1, i)
Else
Dic(Arr(0, i)) = Dic(Arr(0, i)) – Arr(1, i)
End If
Next
End Sub
Function GetConnection(ByVal Path As String)
Dim StrConn As String, ObjConn As New ADODB.Connection
StrConn = "Provider=Microsoft.ACE.OLEDB.12.0;" & "Data Source=" _
& Path & ";Extended Properties=""Excel 8.0;HDR=No;IMEX=1"";"
ObjConn.Open StrConn
Set GetConnection = ObjConn
End Function
Bài 71 có nói rõ mà. Nếu không check vào 2 mục đó thì code nó sẽ ngu ngu.
Sửa lại vầy xem coi có dễ hiểu hơn không.
Sub Main()
Dim SQL As String, MySheet(), Tmp(), i As Long, j As Long, Arr()
Dim ObjRst As New ADODB.Recordset, ObjConn As New ADODB.Connection, Dic As New dictionary
MySheet = Array("Data_Nhap$", "Data_Ban$")
Set ObjConn = GetConnection(ThisWorkbook.Path & "Data.xlsb")
For j = 0 To UBound(MySheet)
SQL = "select * from [" & MySheet(j) & "B2:C65536]"
ObjRst.Open SQL, ObjConn, 3, 1
Tmp = ObjRst.GetRows
ObjRst.Close
GetData Tmp, Dic, j
Next
With Sheets("BanHang")
Arr = .Range("M6", ..End(3)).Resize(, 2).Value
End With
Final Arr, Dic
Sheets("BanHang")..Resize(UBound(Arr), 2) = Arr
End Sub
Sub GetData(Arr, Dic, j)
Dim i As Long, n As Long
For i = 0 To UBound(Arr, 2)
n = IIf(j = 0, 1, -1)
Dic(Arr(0, i)) = Dic(Arr(0, i)) + (Arr(1, i) * n)
Next
End Sub
Sub Final(Arr, Dic)
Dim i As Long
For i = 1 To UBound(Arr)
If Dic.Exists(Arr(i, 1)) Then
Arr(i, 2) = Dic.Item(Arr(i, 1))
Else
Arr(i, 2) = Empty
End If
Next
End Sub
Function GetConnection(ByVal Path As String)
Dim StrConn As String, ObjConn As New ADODB.Connection
StrConn = "Provider=Microsoft.ACE.OLEDB.12.0;" & "Data Source=" _
& Path & ";Extended Properties=""Excel 8.0;HDR=No;IMEX=1"";"
ObjConn.Open StrConn
Set GetConnection = ObjConn
End Function
Góp vui (Chỉ góp vui thôi nha, ngoài ra không có đóng góp gì khác cả) –=0
Câu "nhân tài kiệt xuất như lá mùa thu" nghe.. buồn cười sao ấy
Vẫn chưa khắc phục như bài [URL="https://www.giaiphapexcel.com/forum/showthread.php?107950-Ghi-D%E1%BB%AF-Li%E1%BB%87u-V%C3%A0o-File-%C4%90%C3%B3ng-B%E1%BA%B1ng-ADO&p=673161#post673161"%5D#57
tôi đã đề cập.
Tôi chuyển những câu truy vấn ra ngoài sheet (Sheet3). Vẫn chưa vừa ý lắm, còn nhiều chổ cần phải cải tiến.
Code khi mở file:
Code trong module
Vậy phải coi dữ liệu của bạn thế nào đã, thường thì ta dùng hàm Val
đã cố gắng suy nghĩ nhưng vẫn không hiểu Kiều Mạnh muốn làm gì . hic
Hoàn toàn có thể được bạn à.
Nên chuyển sang database là access.