Copy dữ liêụ vào sheets Tương ứng

Liên hệ QC

lmtuyen

Thành viên chính thức
Tham gia
14/3/09
Bài viết
71
Được thích
12
Thân Chào Các Bạn
Mình đang làm file theo dõi năng lượng tiêu thụ của các thiết bị chính trong nhà máy thủ công:
1. Các bạn ghi nhận điện năng tiêu thụ hàng ngày qua chỉ số công tơ bằng smartphone dùng App "barcode to sheet"
2. Gửi File về cho bạn nhập liệu copy số liệu các thiết bi vào từng sheet.
3. Mong muốn giờ mình, dùng code VBA để copy số liệu này vào từng sheet tương ứng chỉ bằng 1 click chuột.
Mình sưu tầm vài đoạn code và kết hợp lại thử nó chỉ copy có 1 dòng đầu tiên.

Sub findsheet()
Dim strWSName As String
Dim i As Byte, n As Integer
For i = 6 To 17
strWSName = Cells(i, 2).Value
If SheetExists(strWSName) Then
Worksheets(strWSName).Activate
n = Range("c2000").End(xlUp).Offset(1, 0).Row
Range("A" & n, "C" & n).Value = Sheets("DATA_DAILY").Range("A" & i, "C" & i).Value
End If
Next i
End Sub
'-------------------------------
Function SheetExists(strWSName As String) As Boolean
Dim ws As Worksheet
On Error Resume Next
Set ws = Worksheets(strWSName)
If Not ws Is Nothing Then SheetExists = True
End Function
 

File đính kèm

  • Capture.PNG
    Capture.PNG
    165.4 KB · Đọc: 10
  • Energy_update.xlsm
    34 KB · Đọc: 10
Code findsheet() sai.

For i = 6 To 17
strWSName = Cells(i, 2).Value
If SheetExists(strWSName) Then
Worksheets(strWSName).Activate

Khi chạy lượt đầu (i = 6) thì cái chỗ tô đậm nó lấy Value từ ActiveSheet, tức là sheet chứa cái nút bấm.
Nhưng qua lượt thứ hai (i = 7) thì AciveSheet là cái chỗ tô đỏ, tức là sheet khác rồi. Cái chỗ tô đậm lấy dữ liệu sai !!!

Sửa lại:

Sub findsheet()
Dim strWSName As String
Dim i As Long, n As Long
Dim wsA As WorkSheet, wsB As WorkSheet
Set wsA = WorkSheets("DATA_DAILY")
For i = 6 To 17
strWSName = wsA.Cells(i, 2).Value
If SheetExists(strWSName) Then
Set wsB = Worksheets(strWSName)
n = wsB.Range("c2000").End(xlUp).Offset(1, 0).Row
wsB.Range("A" & n, "C" & n).Value = wsA.Range("A" & i, "C" & i).Value
End If
Next i
End Sub
'-------------------------------
Function SheetExists(strWSName As String) As Boolean
On Error Resume Next
SheetExists = Sheets(strWSName).Index > 0
End Function

Lưu ý là code sửa lại chỉ là theo đúng yêu cầu giải thuật của bạn là chép dữ liệu vào từng sheet tương ứng.
Giả thuật đúng đắn còn phải thêm phần tránh bấm nút 2 lần copy 2 lần.
 
Upvote 0
Bác thêm nốt phần tránh nhấn nút copy 2 lần liên tiếp này cho bạn ấy đi,đằng nào tí nữa bạn ấy cũng hỏi mà :D
Anh ơi, em cũng chưa biết làm phần này nên chưa muốn gửi lên. Anh hướng dẫn cho em nhé, xin cảm ơn anh.
.
Nó còn tuỳ theo quy trình của thớt:
Thế nào là copy 2 lần? Nói cách khác, làm thế nào để biết là dữ liệu đã cập nhật rồi?
Tôi chỉ có thể đoán là dựa vào ngày. Trước khi copy thì xét dòng dữ liệu trước đó. Nếu dòng dữ liệu trước trùng ngày hoặc có ngày lớn hơn là đã cập nhật.
Tuy nhiên, trước khi các bạn viết code, cần hỏi lại thớt là nếu dòng dữ liệu trước có ngày lớn hơn thì có phải là cập nhật bị sót? Và có cần chèn dòng vào đúng chỗ?

Cái câu kinh điển mà tôi vẫn phải lập lại như cái đĩa hát hỏng: "Thớt chỉ có ý tưởng chứ chưa hề thực hiện cho nên chưa lường hết các phức tạp của đề tài"
 
Upvote 0
.Nó còn tuỳ theo quy trình của thớt:
Thế nào là copy 2 lần? Nói cách khác, làm thế nào để biết là dữ liệu đã cập nhật rồi?
Tôi chỉ có thể đoán là dựa vào ngày. Trước khi copy thì xét dòng dữ liệu trước đó. Nếu dòng dữ liệu trước trùng ngày hoặc có ngày lớn hơn là đã cập nhật.
Tuy nhiên, trước khi các bạn viết code, cần hỏi lại thớt là nếu dòng dữ liệu trước có ngày lớn hơn thì có phải là cập nhật bị sót? Và có cần chèn dòng vào đúng chỗ?
Cái câu kinh điển mà tôi vẫn phải lập lại như cái đĩa hát hỏng: "Thớt chỉ có ý tưởng chứ chưa hề thực hiện cho nên chưa lường hết các phức tạp của đề tài"
Vậy là còn tùy trường hợp mả đưa ra cách xử lý anh nhỉ, xin cảm ơn anh.
 
Upvote 0
Vậy là còn tùy trường hợp mả đưa ra cách xử lý
Đúng là vậy chứ ý bác ấy không phải là dùng dòng lệnh nhấn 1 lần thì lần thứ hai không nhấn được nữa.Bạn thử đi,đằng nào code trên bài của bạn cũng lấy dòng cuối các sheets mà ,săn tiện lấy nội dụng ô cuối cột A là so sánh được, trong code của bạn Mảng ở sheets DATA_DAILY chỉ cần khai báo một mảng là được rồi
 
Upvote 0
Đúng là vậy chứ ý bác ấy không phải là dùng dòng lệnh nhấn 1 lần thì lần thứ hai không nhấn được nữa.Bạn thử đi,đằng nào code trên bài của bạn cũng lấy dòng cuối các sheets mà ,săn tiện lấy nội dụng ô cuối cột A là so sánh được, trong code của bạn Mảng ở sheets DATA_DAILY chỉ cần khai báo một mảng là được rồi
Xin cảm ơn bạn, mình cũng đang lọ mọ nên chắc còn phải học hỏi bạn và các thành viên khác nhiều, để mình thử tiếp xem sao, có gì sai lại sửa nhỉ.
 
Upvote 0
Thân Chào Các Bạn
Mình đang làm file theo dõi năng lượng tiêu thụ của các thiết bị chính trong nhà máy thủ công:
1. Các bạn ghi nhận điện năng tiêu thụ hàng ngày qua chỉ số công tơ bằng smartphone dùng App "barcode to sheet"
2. Gửi File về cho bạn nhập liệu copy số liệu các thiết bi vào từng sheet.
3. Mong muốn giờ mình, dùng code VBA để copy số liệu này vào từng sheet tương ứng chỉ bằng 1 click chuột.
Mình sưu tầm vài đoạn code và kết hợp lại thử nó chỉ copy có 1 dòng đầu tiên.
Góp ý cho bạn:
1/ Bạn nên thiết kế 1 File mẫu vói cột B có Validation (để chọn cho chuẩn). Khi người báo cáo gửi File cho bạn thì bạn lưu File vào 1 Folder theo dõi.
2/ Trong File gốc tạo 1 sheet theo dõi, khi chạy Macro cho phép bạn lựa chọn File cần lấy dữ liệu vào sheet theo dõi của từng ngày.
3/ Khi cần in để báo cáo thì dựa vào cột B của sheet theo dõi để chạy Macro và tách sheet.
Với cách làm này thì sẽ thuận tiện trong việc tổng hợp báo cáo và File của bạn sẽ đỡ cồng kềnh khi nó không chứa quá nhiều sheet.
 
Upvote 0
Nhờ bạn giúp mình, nếu chỉ khai báo một mảng thì cần sửa lại như thế nào nhỉ? Xin cảm ơn bạn.
Đại khái như vầy:
Sub findsheet()
Dim strWSName As String
Dim i As Long, n As Long
Dim rgA As Range
Set rgA = WorkSheets("DATA_DAILY").Range("A6:C17")
For i = 1 To rgA.Columns.Count
strWSName = rgA.Cells(i, 2).Value
If SheetExists(strWSName) Then
With Worksheets(strWSName)
n = .Range("c2000").End(xlUp).Offset(1, 0).Row
.Range("A" & n, "C" & n).Value = rgA.Offset(i-1,0).Resize(1, ).Value
End With
End If
Next i
End Sub

Hoặc là theo sát "truyền thống GPE" hơn:
Sub findsheet()
Dim i As Long, j As Long, n As Long
Dim a As Variant
a = WorkSheets("DATA_DAILY").Range("A6:C17").Value
For i = 1 To UBound(a)
If SheetExists(a(i, 2)) Then
With WorkSheet(a(i, 2))
n = .Range("c2000").End(xlUp).Offset(1, 0).Row
For j = 1 To 3
.Cells(n, j).Value = a(i, j)
Next j
End With
End If
Next i
End Sub

Tuy nhiên, bản thân tôi thì coi cái chuyện "mảng" này nọ là chuyện phụ, không phải là chỗ đáng lưu tâm.
Code bài bày có một điểm rất đáng lưu tâm. Nhưng đối với "truyền thống GPE" thì rất hiếm khi được xem tới.
 
Upvote 0
Đại khái như vầy:
Sub findsheet()
Dim strWSName As String
Dim i As Long, n As Long
Dim rgA As Range
Set rgA = WorkSheets("DATA_DAILY").Range("A6:C17")
For i = 1 To rgA.Columns.Count
strWSName = rgA.Cells(i, 2).Value
If SheetExists(strWSName) Then
With Worksheets(strWSName)
n = .Range("c2000").End(xlUp).Offset(1, 0).Row
.Range("A" & n, "C" & n).Value = rgA.Offset(i-1,0).Resize(1, ).Value
End With
End If
Next i
End Sub

Hoặc là theo sát "truyền thống GPE" hơn:
Sub findsheet()
Dim i As Long, j As Long, n As Long
Dim a As Variant
a = WorkSheets("DATA_DAILY").Range("A6:C17").Value
For i = 1 To UBound(a)
If SheetExists(a(i, 2)) Then
With WorkSheet(a(i, 2))
n = .Range("c2000").End(xlUp).Offset(1, 0).Row
For j = 1 To 3
.Cells(n, j).Value = a(i, j)
Next j
End With
End If
Next i
End Sub

Tuy nhiên, bản thân tôi thì coi cái chuyện "mảng" này nọ là chuyện phụ, không phải là chỗ đáng lưu tâm.
Code bài bày có một điểm rất đáng lưu tâm. Nhưng đối với "truyền thống GPE" thì rất hiếm khi được xem tới.
Thử 2 code đều không chạy :rolleyes:
 
Upvote 0
Thử 2 code đều không chạy :rolleyes:
Cảm ơn đã thử giùm.
Ở bài ấy tôi có nói là "đại khái". Đại khái đối với tôi có nghĩa là cái ý niệm, code "đại khái" chỉ viết theo "ý niệm", không được xem lại hay chạy thử. :confused::confused::confused:

Chỉnh: bây giờ mới có thì giờ xem code.
Lỗi compile error.

Code 1 sửa như sau:
Dòng: For i = 1 To rgA.Columns.Count
Sửa: For i = 1 To rgA.Rows.Count ' nhầm rows ra columns
Dòng: .Range("A" & n, "C" & n).Value = rgA.Offset(i - 1, 0).Resize(1, ).Value
Sửa: .Range("A" & n, "C" & n).Value = rgA.Offset(i - 1, 0).Resize(1).Value ' hàm Resize không chấp nhận để trống tham số

Code 2 sửa như sau:
If SheetExists(a(i, 2)) Then
With WorkSheet(a(i, 2))
Sửa:
If SheetExists(CStr(a(i, 2))) Then ' tham số không tự ép kiểu variant thành string được
With WorkSheets(CStr(a(i, 2)))
 
Lần chỉnh sửa cuối:
Upvote 0
Cảm ơn đã thử giùm.
Ở bài ấy tôi có nói là "đại khái". Đại khái đối với tôi có nghĩa là cái ý niệm, code "đại khái" chỉ viết theo "ý niệm", không được xem lại hay chạy thử. :confused::confused::confused:

Chỉnh: bây giờ mới có thì giờ xem code.
Lỗi compile error.

Code 1 sửa như sau:
Dòng: For i = 1 To rgA.Columns.Count
Sửa: For i = 1 To rgA.Rows.Count ' nhầm rows ra columns
Dòng: .Range("A" & n, "C" & n).Value = rgA.Offset(i - 1, 0).Resize(1, ).Value
Sửa: .Range("A" & n, "C" & n).Value = rgA.Offset(i - 1, 0).Resize(1).Value ' hàm Resize không chấp nhận để trống tham số

Code 2 sửa như sau:
If SheetExists(a(i, 2)) Then
With WorkSheet(a(i, 2))
Sửa:
If SheetExists(CStr(a(i, 2))) Then ' tham số không tự ép kiểu variant thành string được
With WorkSheets(CStr(a(i, 2)))
Em cảm ơn anh ạ.
 
Upvote 0
Tuy nhiên, bản thân tôi thì coi cái chuyện "mảng" này nọ là chuyện phụ, không phải là chỗ đáng lưu tâm.
Code bài này có một điểm rất đáng lưu tâm. Nhưng đối với "truyền thống GPE" thì rất hiếm khi được xem tới.
Anh ơi, anh cho em hỏi điểm rất đáng lưu tâm của code này là điểm nào ạ, vì em cũng đang học hỏi nên nhờ anh hướng dẫn để em được biết thêm. Xin cảm ơn anh.
 
Lần chỉnh sửa cuối:
Upvote 0
Anh ơi, anh cho em hỏi điểm rất đáng lưu tâm của code này là điểm nào ạ, vì em cũng đang học hỏi nên nhờ anh hướng dẫn để em được biết thêm. Xin cảm ơn anh.
.
Cũng theo đúng sì-tin GPE, code bẫy lỗi nhưng không báo lỗi.
If SheetExists(strWSName) Then
...
End If
---> nếu không tìm được sheet với tên ấy thì bỏ qua?

Một lập trình viên có kinh nghiệm hầu như luôn luôn thêm phần Else
Else
(làm cái gì đó, ví dụ ghi lại danh sách những trị strWSName không đúng tên sheet)
End If
Thường thường tôi cũng thêm một msg báo cho biết con số sheets được cập nhật. Ví dụ tôi dự định 10 sheets, chạy xong thấy báo 8 thì tôi kiểm soát ngay.

Chuyển đổi, cập nhật dữ liệu là công việc rất dễ bị sai sót.
Vì vậy, trên GPE rất nhiều bạn thích "[dùng ADO] ghi vào file đang đóng" chứ tôi thìn hầu như không bao giờ dùng cách này. Bởi vì đây là cách "bút sa gà chết" và không kiểm soát được lỗi.
 
Upvote 0
Cũng theo đúng sì-tin GPE, code bẫy lỗi nhưng không báo lỗi.
If SheetExists(strWSName) Then
...
End If
---> nếu không tìm được sheet với tên ấy thì bỏ qua?
Một lập trình viên có kinh nghiệm hầu như luôn luôn thêm phần Else
Else
(làm cái gì đó, ví dụ ghi lại danh sách những trị strWSName không đúng tên sheet)
End If
Thường thường tôi cũng thêm một msg báo cho biết con số sheets được cập nhật. Ví dụ tôi dự định 10 sheets, chạy xong thấy báo 8 thì tôi kiểm soát ngay.
Anh ơi, em cũng nghĩ rồi, nhưng chưa biết nếu muốn như vậy thì nên thực hiện thế nào, cụ thể là ở bài #4, anh có thể hướng dẫn giúp em trong trường hợp này được không ạ, xin cảm ơn anh.
 
Upvote 0
Anh ơi, em cũng nghĩ rồi, nhưng chưa biết nếu muốn như vậy thì nên thực hiện thế nào, cụ thể là ở bài #4, anh có thể hướng dẫn giúp em trong trường hợp này được không ạ, xin cảm ơn anh.
Để tránh copy 2 lần, ta có thể làm sau đây cho mỗi sheet tương ứng:
- Search ngày trong vùng dữ liệu, có thể dùng Find hay Match gì cũng được.
- Nếu tìm được ngày tức là đã có dữ liệu ngày này. Vào đúng dòng này và cập nhật "CHỈ SỐ MỚI"
- Nếu không tìm được tức là chưa cập nhật. Thêm vào. Vì cách thức thêm thớt không hề trả lời nên bạn có thể chọn giữa hai điều:
1. thêm đại vào dòng cuối.
2. tìm dòng ngày trước và ngày sau, chèn dòng cập nhật vào giữa. (nếu bạn chọn phương pháp này thì phải nắm chắc là dữ liệu mỗi sheet được sắp xếp theo ngày. Và vì dữ liệu sắp xếp cho nên hàm Match hiệu quả hơn Find)
 
Upvote 0
Để tránh copy 2 lần, ta có thể làm sau đây cho mỗi sheet tương ứng:
- Search ngày trong vùng dữ liệu, có thể dùng Find hay Match gì cũng được.
- Nếu tìm được ngày tức là đã có dữ liệu ngày này. Vào đúng dòng này và cập nhật "CHỈ SỐ MỚI"
- Nếu không tìm được tức là chưa cập nhật. Thêm vào. Vì cách thức thêm thớt không hề trả lời nên bạn có thể chọn giữa hai điều:
1. thêm đại vào dòng cuối.
2. tìm dòng ngày trước và ngày sau, chèn dòng cập nhật vào giữa. (nếu bạn chọn phương pháp này thì phải nắm chắc là dữ liệu mỗi sheet được sắp xếp theo ngày. Và vì dữ liệu sắp xếp cho nên hàm Match hiệu quả hơn Find)
Vâng ạ, em xin cảm ơn anh.
 
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom