Thiết lập file excel lưu trữ lịch sử

Liên hệ QC

CaoNgan99

Thành viên mới
Tham gia
19/12/21
Bài viết
28
Được thích
1
Giới tính
Nữ
Em chào các anh chị !
hiện em có một file em đang xây dựng để lưu trữ lịch sử các đơn hàng.
Tại sheet historys
khi nhấn vào nút "refresh All" sẽ lấy toàn bộ dữ liệu ở sheet summary đổ sang sheet historys từ A2 đến Y, mỗi khi có dữ liệu mới từ sheet summary thì sẽ được thêm nối tiếp vào sheet historys.

từ cột Z đến AQ là cập nhật từ các sheet khác,
Điều cập nhật là nếu tìm thấy dữ liệu tại cột A sheet Historys ở các sheet còn lại (MATER_ITEM, SHIPOUT, ORDER_SCAN, BY_DATE, KITTING, MATERIAL_SHORTAGE, PRINT_STAGE, CUT_STAGE, BCNK, SOL_CANCEL) thì trả về các vùng tương ứng, mỗi lần các sheet khác thay đổi nội dung thì các vùng bên sheet History cũng được cập nhật theo
và nếu dữ liệu ở các sheet summary hay các sheet khác bị mất thì dữ liệu trong sheet historys không bị mất đi

code thì hiện tại em đã nhặt nhạnh khắp nơi để lắp ghép chỉ còn duy nhất một sheet MATER_ITEM là em không thể nào lắp ghép được vì tham số nằm ở cột L chứ không phải cột A nữa, em đã thử rất nhiều lần nó báo lỗi,

Mã:
For t = 1 To UBound(Sarr_Item)
  Tmp_Item = Sarr_Item(t, 1)
  Dic.Add (Tmp_Item), t
  'If DR(i, 19) <> "AWAITING_SHIPPING" Or DR(i, 19) <> "AWAITING_FULFILLMENT" Then 'co the tuy chinh
    Dic95.Add (Tmp_Item), t
    If DR_Item(t, 8) = "AWAITING_FULFILLMENT" Or DR_Item(t, 8) = "AWAITING_SHIPPING" Or DR_Item(t, 8) = "PRODUCTION_OPEN" Or DR_Item(i, 8) = "EXTERNAL_REQ_OPEN" Or DR_Item(t, 8) = "PO_PARTIAL" Or DR_Item(t, 8) = "PO_OPEN" Or DR_Item(t, 8) = "BOOKED" Or DR_Item(t, 8) = "SUPPLY_ELIGIBLE" Or DR_Item(t, 8) = "ENTERED" Then Dic35.Add (Tmp_Item), t
  'End If
Next t

nên em đã đặt công thức vlookup tại cột AM đến AO sheet historys để anh chị xem và sửa giúp em với, vì bình thường em có thể vlookup nhưng dữ liệu có lúc lên đến 60000 dòng chạy rất chậm.

em cám ơn trước ạ
 

File đính kèm

  • History.xlsb
    2.9 MB · Đọc: 26
Lần chỉnh sửa cuối:
Chúc mừng bạn.

Nhưng bạn đã mô tả cách làm sai hoàn toàn. Từ cách mô tả đại loại là: "nếu dữ liệu SUMMARY đã tồn tại thì làm mới các cột B,C,D,E và S của sheet historys. Còn nếu là dữ liệu mới thì copy toàn bộ dòng A:Y sang HISTORYS". Từ mô tả trên có 2 kết luận:

1. Nếu có khái niệm "dữ liệu của dòng nào đó của SUMMARY ĐÃ TỒN TẠI bên HISTORYS" thì có nghĩa là trước khi chạy code thì HISTORYS có thể đã có dữ liệu rồi. Trong khi đó tập tin HISTIRYS(Thu) trắng tinh.

2. Code đơn giản chỉ copy SUMMARY!A2:Y... sang HISTORYS!A2:Y... chứ có bận tâm gì tới cái gọi là "dữ liệu mới", "dữ liệu cũ" đâu nhỉ. Có bận tâm làm mới các cột B,C,D,E và S của sheet historys đâu nhỉ. Có phải bận tâm ... đâu nhỉ. Hay là tôi sơ ý không nhìn thấy?

Tôi không hiểu ý nên hỏi ở bài 4 và các bài tiếp theo. Nếu cách làm như ở trên thì chỉ cần mô tả 1 câu: "Khi duyệt SUMMARY thì bê hết dữ liệu của nó, cột từ A đến Y rồi ghi đè lên HISTORYS bắt đầu từ A2". Đơn giản thế thôi chứ "dữ liệu mới", "dữ liệu cũ" từ A đến Y, làm mới các cột B,C,D,E và S của sheet historys ... để làm gì. Mất bao nhiêu thời gian
Dạ vì sheet summary sẽ mất đi dữ liệu theo thời gian nên mới cần cập nhật sang hisyorys để bảo toàn anh ạ, nếu ghi đè lên thì mất hết dữ liệu cũ, hàng ngày trong sheet summary sẽ có dữ liệu mới từ A đến Y được sinh ra và đồng thời dữ liệu cũ cũng sẽ bị mất đi cho nên em diễn tả làm anh khó hiểu chút ạ
 
Lần chỉnh sửa cuối:
Upvote 0
Dạ vì sheet summary sẽ mất đi dữ liệu theo thời gian nên mới cần cập nhật sang hisyorys để bảo toàn anh ạ, nếu ghi đè lên thì mất hết dữ liệu cũ,
Thế bạn đã kiểm tra chưa? Theo tôi thì code (code mà bạn khoe là đã chạy được ấy) đang ghi đè, nhưng tôi chỉ là người nên có thể không nhìn thấy.

Bạn mô tả một đường nhưng code làm một nẻo. Nhưng bạn hài lòng nên tôi hơi ngạc nhiên thôi. Còn nếu cuối cùng bạn muốn thế thì đó là quyền của bạn.
 
Upvote 0
Thế bạn đã kiểm tra chưa? Theo tôi thì code (code mà bạn khoe là đã chạy được ấy) đang ghi đè, nhưng tôi chỉ là người nên có thể không nhìn thấy.

Bạn mô tả một đường nhưng code làm một nẻo. Nhưng bạn hài lòng nên tôi hơi ngạc nhiên thôi. Còn nếu cuối cùng bạn muốn thế thì đó là quyền của bạn.
Em đang hiểu ý anh là đè lên tất cả historys nên em mới bảo là ghi đè vậy sẽ mất cả dữ liệu cũ, còn file em gửi là ghi đè dữ liệu cũ và lấy dữ liệu mới sau đó cập nhật cho các vùng, code mà a đưa em đã chạy đúng như em đang cần mà,
chỉ còn thời gian từ C D E thôi ạ, giờ em không biết chuyển đổi làm sao để nó được như file ban đầu.
 
Upvote 0
Em đang hiểu ý anh là đè lên tất cả historys nên em mới bảo là ghi đè vậy sẽ mất cả dữ liệu cũ, còn file em gửi là ghi đè dữ liệu cũ và lấy dữ liệu mới sau đó cập nhật cho các vùng, code mà a đưa em đã chạy đúng như em đang cần mà,
chỉ còn thời gian từ C D E thôi ạ, giờ em không biết chuyển đổi làm sao để nó được như file ban đầu.
Bạn nên theo dõi xem người ta trích gì, trích ai để biết người ta đang nói tới bài nào, tới ai.

Tôi trích bài chính xác mà.

Trong bài 19 tôi viết

Chúc mừng bạn.

sau khi trích bài 18 của bạn
Dạ em vừa chạy được a nhé, vậy sau này phải chạy module napdic trước phải không anh

Trong bài 18 bạn trích bài và trả lời bài 16. Tác giả bài 16 đính kèm tập tin ở bài 9.

Tóm lại bạn khoe là đã chạy được code bài 9. Tôi chúc mừng và phân tích bài 9 nhưng bạn cố tình không hiểu. Vậy tôi dẫn chứng.
Sub RefershAll()

Application.ScreenUpdating = False
...
If Dic Is Nothing Then Call AddDic
Sheets("HISTORYS(Thu)").Cells(2, 1).Resize(65500, 43).ClearContents
Sheets("HISTORYS(Thu)").Cells(2, 1).Resize(R, 25) = Arr
...

Trong code RefershAll có gọi sub AddDic
Sub AddDic()
Dim MATER()
...
Lr = Sheets("SUMMARY").Range("A65500").End(xlUp).Row
Arr = Sheets("SUMMARY").Range("A2:Y" & Lr).Value
...

Tức lấy vùng A2:Y..., tức toàn bộ các dòng dữ liệu, từ SUMMARY vào mảng Arr.

Sau đó trong RefershAll ở dòng

Sheets("HISTORYS(Thu)").Cells(2, 1).Resize(R, 25) = Arr

mảng Arr kia được đập vào HISTORYS bắt đầu từ A2. Thế không là ghi đè thì là gì hả bạn?

Tôi kết thúc ở đây.
 
Upvote 0
Bạn nên theo dõi xem người ta trích gì, trích ai để biết người ta đang nói tới bài nào, tới ai.

Tôi trích bài chính xác mà.

Trong bài 19 tôi viết

Chúc mừng bạn.

sau khi trích bài 18 của bạn


Trong bài 18 bạn trích bài và trả lời bài 16. Tác giả bài 16 đính kèm tập tin ở bài 9.

Tóm lại bạn khoe là đã chạy được code bài 9. Tôi chúc mừng và phân tích bài 9 nhưng bạn cố tình không hiểu. Vậy tôi dẫn chứng.


Trong code RefershAll có gọi sub AddDic


Tức lấy vùng A2:Y..., tức toàn bộ các dòng dữ liệu, từ SUMMARY vào mảng Arr.

Sau đó trong RefershAll ở dòng

Sheets("HISTORYS(Thu)").Cells(2, 1).Resize(R, 25) = Arr

mảng Arr kia được đập vào HISTORYS bắt đầu từ A2. Thế không là ghi đè thì là gì hả bạn?

Tôi kết thúc ở đây.
vâng em cám ơn anh.
 
Upvote 0
Thông qua là cái khỉ gì. Tôi đang nói tới:
a. hoặc mới là A & B & ... & Z mới
b. hoặc mới là A mới

Vd. Bên HISTORYS có A = 12345, B = "blala, C = "hic hic", Bên SUMMARY có A = 12345, B = "blala, C = "he he". Vậy đó có là DỮ LIỆU MỚI không? Theo a. thì là DỮ LIỆU MỚI do "12345blalahe he" <> "12345blalahic hic", còn theo b. thì không là dữ liệu mới vì 12345 (SUMMARY) = 12345 (HISTORYS).

Hoặc mới là khi ít nhất 1 cột trong A:Z là mới, hoặc mới là khi có A mới. Làm gì có kiểu: mới khi ít nhất 1 cột trong A:Z là mới THÔNG QUA cột A.

Thôi tôi không đọc tiếp nữa. Tôi sẽ làm theo một giả thiết nhất định.

1. Trước hết duyệt SUMMARY. kiểm tra từng SOL có trong cột A của HISTORYS không. Nếu có rồi thì cập nhật B,C,D,E và S của sheet historys. Nếu chưa có SOL đang xét trong HISTORYS!A thì toàn bộ dòng có SOL đó từ A tới Y được nhập vào dòng cuối bên HISTORYS.

2. Sau khi duyệt SUMMARY thì duyệt các sheet khác theo mô tả ở bài #3.

3. Tôi không dò code của bạn, mệt lắm. Tôi thử đập đi xây mới. Tôi viết lại Sub History

4. Có nhiều cái bạn phải kiểm tra lại.

1. Trong SUMMARY dạng dữ liệu X572:X573, Y572:Y573 (đều là các số) không ăn nhập gì với dạng của cột X và Y (dạng text). Tương tự Y2470, M174:M185, và nhiều khoảng nữa trong cột M. Vì thế sang HISTORYS cũng kỳ cục - X566:Y567 và Y2464, và M173:M184 và nhiều khoảng nữa trong cột M

2. Trong SUMMARY chắc chắn cột C, D và E không có ngày tháng chuẩn, và chúng được coi là có dạng MM/dd/yyyy. Vì thế khi chạy trên máy bạn thì có thể sẽ có vd. HISTORYS!C2 = 06 tháng 10 năm 2021, nhưng khi chạy code ở máy tôi sẽ có HISTORYS!C2 = 10 tháng 06 năm 2021. Nguyên nhân là do SUMMARY!C2 không là ngày tháng chuẩn - khi mở trên máy tôi C2 được căn trái. Trên máy tôi thì sau khi chạy code trong HISTORYS!C, D, E hoặc sẽ có ngày tháng chuẩn nhưng ngày tháng sẽ bị đổi chỗ (bên SUMMARY có số đầu < 13), hoặc ngày tháng "nhái" (bên SUMMARY số đầu > 12), chúng được bê y nguyên từ SUMMARY sang HISTORYS .

Tóm lại nếu nói về dữ liệu nguồn trong SUMMARY thì phải kiểm tra lại cột C, D, E (ngày tháng không chuẩn), và cột M, X, Y - định dạng ô không phù hợp, dạng dữ liệu không ăn nhập gì với dạng của cột, tức khác với dạng của các dữ liệu khác trong cùng cột.

Tất nhiên phải kiểm tra xem kết quả code có đúng ý không.
Anh ơi, trong trường hợp em muốn thêm sheet thì em sửa code thế nào vậy anh, em có chỉnh thêm trong này rồi nhưng không biết phải chỉnh ở đâu nữa.
ZAQ_historys = .Range("AA2:AS" & lastRow).Value

Mã:
 thong_tin = Array( _
        Array("SHIPOUT", "ORDER_SCAN", "BY_DATE", "KITTING", "MATERIAL_SHORTAGE", "PRINT_STAGE", "CUT_STAGE", "BCNK", "SOL_CANCEL", "MATER_ITEM", "BALANCE_LOCATION"), _
        Array("A", "A", "A", "A", "B", "A", "A", "B", "A", "A", "A"), _
        Array("B", "C", "B", "B", "N", "B", "B", "C", "B", "E", "E"), _
        Array(2, 1, 1, 1, 1, 3, 3, 2, 1, 3, 1), _
        Array(1, 3, 17, 4, 5, 6, 9, 12, 18, 14, 19))
 
Upvote 0
Anh ơi, trong trường hợp em muốn thêm sheet thì em sửa code thế nào vậy anh, em có chỉnh thêm trong này rồi nhưng không biết phải chỉnh ở đâu nữa.
ZAQ_historys = .Range("AA2:AS" & lastRow).Value

Mã:
 thong_tin = Array( _
        Array("SHIPOUT", "ORDER_SCAN", "BY_DATE", "KITTING", "MATERIAL_SHORTAGE", "PRINT_STAGE", "CUT_STAGE", "BCNK", "SOL_CANCEL", "MATER_ITEM", "BALANCE_LOCATION"), _
        Array("A", "A", "A", "A", "B", "A", "A", "B", "A", "A", "A"), _
        Array("B", "C", "B", "B", "N", "B", "B", "C", "B", "E", "E"), _
        Array(2, 1, 1, 1, 1, 3, 3, 2, 1, 3, 1), _
        Array(1, 3, 17, 4, 5, 6, 9, 12, 18, 14, 19))
Về đoạn mà bạn hỏi trong đoạn trích ở trên thì ...
Bạn cần hiểu là ZAQ_historys có nghĩa là lấy vùng từ cột Z tới cột AQ của HISTORYS vào mảng ZAQ_historys. Vì thế không có chuyện ZAQ_historys = .Range("AA2:AS" & lastRow).Value - tức không có chuyện lấy từ cột AA tới AS vào mảng ZAQ_historys đâu.

Bạn để ý là trong mảng thong_tin sheet MATER_ITEM được đặt cuối cùng. Vì sao? Vì khi duyệt các sheet khác thì đều lấy SOL ở cột A của HISTOSYS để tìm trong cột A của sheet đang duyệt. Chỉ tới khi duyệt MATER_ITEM mới lấy ITEM từ cột L của HISTORYS để tìm trong cột A của MATER_ITEM. Vì thế khi duyệt các sheet khác thì ta luôn dùng chung 1 dic, chỉ khi duyệt tới giá trị cuối cùng của vòng FOR ta mới tạo dic mới để làm bảng dò cho MATER_ITEM. Chính vì thế khi thêm sheet thì không thể đặt sau MATER_ITEM được. Và nữa: hiện tại ta chỉ tìm cột A hoặc L của HISTORYS trong các sheet. Thế với sheet thêm thì tìm cột nào của HISTORYS trong sheet thêm? Nếu không là A mà cũng không là L thì còn sửa nữa, vì bảng dò (dic) cũng phải tạo khi duyệt sheet thêm. Tóm lại phải mô tả về sheet thêm này (cách duyệt, khi tìm thấy thì lấy những cột nào để làm mới HISTORYS ...) thì mới nói chuyện được.
--------------

Lẽ ra bạn nên hỏi HUONGHCKT. Theo tôi thì bạn mô tả một đằng còn HUONGHCKT làm một nẻo. Nhưng nếu bạn đổi ý và hài lòng với code đó thì đó là quyền của bạn.

Bạn phải tự test kỹ vì nếu không thì không có gì đảm bảo là code của bất kỳ ai đó cũng làm làm đúng yêu cầu của bạn.
Nếu bạn cuối cùng cho là code của HUONGHCKT chưa làm đúng yêu cầu của bạn thì bạn phải nói rõ ra và nhờ HUONGHCKT sửa lại. Cho tới tận giờ bạn không nói ra và nhờ sửa thì HUONGHCKT có quyền cho là code đã làm đúng yêu cầu của bạn.

Bạn nên nhờ tiếp HUONGHCKT vì code của tôi nếu có đúng thì cũng chỉ là code cho refresh All. Bây giờ đọc kỹ lại bài #1 tôi mới thấy

mỗi lần các sheet khác thay đổi nội dung thì các vùng bên sheet History cũng được cập nhật theo
Cái phần này tôi chưa làm, nhưng tôi thấy HUONGHCKT đã làm cho bạn. Tôi không dám phán là đã đúng ý bạn vì thực ra tôi cũng chưa rõ yêu cầu này. Nhưng HUONGHCKT đã làm thì chỉ cần sửa thôi.

Về phần mình thì nếu thêm cả phần nói ở trên thì có lẽ tôi sẽ viết hơi khác một chút code để sao cho có thể dùng cho refresh All và cả cho cho phần trên. Nhưng tôi chưa hiểu yêu cầu. Tôi trích lại:
mỗi lần các sheet khác thay đổi nội dung thì các vùng bên sheet History cũng được cập nhật theo

Giả sử MỘT DÒNG NÀO ĐÓ của MATER_ITEM thay đổi thì cách làm nào sau đây là đúng yêu cầu (có thể 2 cách đều cho kết quả như nhau ***):

a. tìm từng dữ liệu trong cột L của HISTORYS trong cột A của dòng THAY ĐỔI của MATER_ITEM (chỉ của MATER_ITEM vì không duyệt các sheet không có thay đổi? Đúng là thế hay thế nào?). Nếu không tìm thấy thì không làm gì. Nếu tìm thấy thì lấy dữ liệu tương ứng từ MATER_ITEM sang HISTORYS.

b. tìm từng dữ liệu trong cột L của HISTORYS trong TOÀN BỘ cột A của MATER_ITEM (chỉ của MATER_ITEM vì không duyệt các sheet không có thay đổi? Đúng là thế hay thế nào?). Nếu không tìm thấy thì không làm gì. Nếu tìm thấy thì lấy dữ liệu tương ứng từ MATER_ITEM sang HISTORYS.

Tương tự với các sheet khác. Bạn phải cho biết cách thao tác là theo a. hay b. Nếu thao tác theo b. luôn có thể chấp nhận được thì cũng nói rõ.

***: do tôi không biết dữ liệu trong các sheet xuất hiện và biến mất theo cách nào, qui luật nào nên tôi cho ví dụ khi cách duyệt a. và b. cho hậu quả khác nhau. Vd. hiện tại trong HISTORYS ở ô nào đó của cột L có giá trị 123456789. Trong MATER_ITEM đang có ở cột A giá trị 123456789, và E, F, G = "ngày mai cũ", "em đi cũ", "biển nhớ cũ". Khi nhấn nút refresh All thì E, F, G = "ngày mai cũ", "em đi cũ", "biển nhớ cũ" được lấy sang HISTORYS sang AM, AN, AO và cùng dòng với 123456789. Bây giờ trong sheet MATER_ITEM ngoài 123456789 đã có ta chèn thêm 1 dòng khác TRƯỚC NÓ có các dữ liệu khác nhau ở các cột khác nhưng ở cột A cũng có 123456789, và E,F, G = "ngày mai mới", "em đi mới", "biển nhớ mới". Nếu bây giờ tìm 123456789 lấy từ cột L của HISTORYS trong cột A của MATER_ITEM thì:

- nếu tìm theo cách a. thì kết quả là E,F, G = "ngày mai mới", "em đi mới", "biển nhớ mới" được nhập vào AM, AN, AO của HISTORYS và ghi đè lên "ngày mai cũ", "em đi cũ", "biển nhớ cũ".

- nếu tìm theo cách b. thì kết quả là: đầu tiên E,F, G = "ngày mai mới", "em đi mới", "biển nhớ mới" được nhập vào AM, AN, AO của HISTORYS (tìm thấy 123456789 ở dòng mới) và ghi đè lên E, F, G = "ngày mai cũ", "em đi cũ", "biển nhớ cũ" đang có. Tiếp theo E, F, G = "ngày mai cũ", "em đi cũ", "biển nhớ cũ" được nhập vào AM, AN, AO của HISTORYS (tìm thấy 123456789 ở dòng cũ) và ghi đè lên E,F, G = "ngày mai mới", "em đi mới", "biển nhớ mới" đang có ở thời điểm này. Kết quả có E, F, G = "ngày mai cũ", "em đi cũ", "biển nhớ cũ"

Cách a. và b. cho kết quả khác nhau. Vì tôi không biết dữ liệu trong các sheet thoắt xuất hiện thoắt biến mất như thế nào, theo cách nào, qui luật nào nên tôi buộc phải có những phân tích như trên.

Nhiều người cứ viết theo như họ hiểu nhưng không lưu ý. Nếu họ hiểu sai thì kệ bạn. Bạn không mô tả chính xác cho họ hiểu thì bạn tự lĩnh hậu quả. Nhưng tôi khi không hiểu thì tôi không thể viết được code. Nếu tôi cho là mình hiểu nhưng chưa dám chắc chắn thì tôi luôn lưu ý là code tôi đưa ra được viết cho giả thiết nào.
 
Lần chỉnh sửa cuối:
Upvote 0
Về đoạn mà bạn hỏi trong đoạn trích ở trên thì ...
Bạn cần hiểu là ZAQ_historys có nghĩa là lấy vùng từ cột Z tới cột AQ của HISTORYS vào mảng ZAQ_historys. Vì thế không có chuyện ZAQ_historys = .Range("AA2:AS" & lastRow).Value - tức không có chuyện lấy từ cột AA tới AS vào mảng ZAQ_historys đâu.

Bạn để ý là trong mảng thong_tin sheet MATER_ITEM được đặt cuối cùng. Vì sao? Vì khi duyệt các sheet khác thì đều lấy SOL ở cột A của HISTOSYS để tìm trong cột A của sheet đang duyệt. Chỉ tới khi duyệt MATER_ITEM mới lấy ITEM từ cột L của HISTORYS để tìm trong cột A của MATER_ITEM. Vì thế khi duyệt các sheet khác thì ta luôn dùng chung 1 dic, chỉ khi duyệt tới giá trị cuối cùng của vòng FOR ta mới tạo dic mới để làm bảng dò cho MATER_ITEM. Chính vì thế khi thêm sheet thì không thể đặt sau MATER_ITEM được. Và nữa: hiện tại ta chỉ tìm cột A hoặc L của HISTORYS trong các sheet. Thế với sheet thêm thì tìm cột nào của HISTORYS trong sheet thêm? Nếu không là A mà cũng không là L thì còn sửa nữa, vì bảng dò (dic) cũng phải tạo khi duyệt sheet thêm. Tóm lại phải mô tả về sheet thêm này (cách duyệt, khi tìm thấy thì lấy những cột nào để làm mới HISTORYS ...) thì mới nói chuyện được.
--------------

Lẽ ra bạn nên hỏi HUONGHCKT. Theo tôi thì bạn mô tả một đằng còn HUONGHCKT làm một nẻo. Nhưng nếu bạn đổi ý và hài lòng với code đó thì đó là quyền của bạn.

Bạn phải tự test kỹ vì nếu không thì không có gì đảm bảo là code của bất kỳ ai đó cũng làm làm đúng yêu cầu của bạn.
Nếu bạn cuối cùng cho là code của HUONGHCKT chưa làm đúng yêu cầu của bạn thì bạn phải nói rõ ra và nhờ HUONGHCKT sửa lại. Cho tới tận giờ bạn không nói ra và nhờ sửa thì HUONGHCKT có quyền cho là code đã làm đúng yêu cầu của bạn.

Bạn nên nhờ tiếp HUONGHCKT vì code của tôi nếu có đúng thì cũng chỉ là code cho refresh All. Bây giờ đọc kỹ lại bài #1 tôi mới thấy


Cái phần này tôi chưa làm, nhưng tôi thấy HUONGHCKT đã làm cho bạn. Tôi không dám phán là đã đúng ý bạn vì thực ra tôi cũng chưa rõ yêu cầu này. Nhưng HUONGHCKT đã làm thì chỉ cần sửa thôi.

Về phần mình thì nếu thêm cả phần nói ở trên thì có lẽ tôi sẽ viết hơi khác một chút code để sao cho có thể dùng cho refresh All và cả cho cho phần trên. Nhưng tôi chưa hiểu yêu cầu. Tôi trích lại:


Giả sử MỘT DÒNG NÀO ĐÓ của MATER_ITEM thay đổi thì cách làm nào sau đây là đúng yêu cầu (có thể 2 cách đều cho kết quả như nhau ***):

a. tìm từng dữ liệu trong cột L của HISTORYS trong cột A của dòng THAY ĐỔI của MATER_ITEM (chỉ của MATER_ITEM vì không duyệt các sheet không có thay đổi? Đúng là thế hay thế nào?). Nếu không tìm thấy thì không làm gì. Nếu tìm thấy thì lấy dữ liệu tương ứng từ MATER_ITEM sang HISTORYS.

b. tìm từng dữ liệu trong cột L của HISTORYS trong TOÀN BỘ cột A của MATER_ITEM (chỉ của MATER_ITEM vì không duyệt các sheet không có thay đổi? Đúng là thế hay thế nào?). Nếu không tìm thấy thì không làm gì. Nếu tìm thấy thì lấy dữ liệu tương ứng từ MATER_ITEM sang HISTORYS.

Tương tự với các sheet khác. Bạn phải cho biết cách thao tác là theo a. hay b.

***: do tôi không biết dữ liệu trong các sheet xuất hiện và biến mất theo cách nào, qui luật nào nên tôi cho ví dụ khi cách duyệt a. và b. cho hậu quả khác nhau. Vd. hiện tại trong HISTORYS ở ô nào đó của cột L có giá trị 123456789. Trong MATER_ITEM đang có ở cột A giá trị 123456789, và E, F, G = "ngày mai cũ", "em đi cũ", "biển nhớ cũ". Khi nhấn nút refresh All thì E, F, G = "ngày mai cũ", "em đi cũ", "biển nhớ cũ" được lấy sang HISTORYS sang AM, AN, AO và cùng dòng với 123456789. Bây giờ trong sheet MATER_ITEM ngoài 123456789 đã có ta chèn thêm 1 dòng khác TRƯỚC NÓ có các dữ liệu khác nhau ở các cột khác nhưng ở cột A cũng có 123456789, và E,F, G = "ngày mai mới", "em đi mới", "biển nhớ mới". Nếu bây giờ tìm 123456789 lấy từ cột L của HISTORYS trong cột A của MATER_ITEM thì:

- nếu tìm theo cách a. thì kết quả là E,F, G = "ngày mai mới", "em đi mới", "biển nhớ mới" được nhập vào AM, AN, AO của HISTORYS và ghi đè lên "ngày mai cũ", "em đi cũ", "biển nhớ cũ".

- nếu tìm theo cách b. thì kết quả là: đầu tiên E,F, G = "ngày mai mới", "em đi mới", "biển nhớ mới" được nhập vào AM, AN, AO của HISTORYS (tìm thấy 123456789 ở dòng mới) và ghi đè lên E, F, G = "ngày mai cũ", "em đi cũ", "biển nhớ cũ" đang có. Tiếp theo E, F, G = "ngày mai cũ", "em đi cũ", "biển nhớ cũ" được nhập vào AM, AN, AO của HISTORYS (tìm thấy 123456789 ở dòng cũ) và ghi đè lên E,F, G = "ngày mai mới", "em đi mới", "biển nhớ mới" đang có ở thời điểm này. Kết quả có E, F, G = "ngày mai cũ", "em đi cũ", "biển nhớ cũ"

Cách a. và b. cho kết quả khác nhau. Vì tôi không biết dữ liệu trong các sheet thoắt xuất hiện thoắt biến mất như thế nào, theo cách nào, qui luật nào nên tôi buộc phải có những phân tích như trên.

Nhiều người cứ viết theo như họ hiểu nhưng không lưu ý. Nếu họ hiểu sai thì kệ bạn. Bạn không mô tả chính xác cho họ hiểu thì bạn tự lĩnh hậu quả. Nhưng tôi khi không hiểu thì tôi không thể viết được code. Nếu tôi cho là mình hiểu nhưng chưa dám chắc chắn thì tôi luôn lưu ý là code tôi đưa ra được viết cho giả thiết nào.
Cảm ơn Anh @batman1 đã xem code nhé.
Tôi thấy bạn ấy ghi là " ....sẽ lấy toàn bộ dữ liệu ở sheet summary đổ sang sheet historys từ A2 đến Y...." Do vậy tôi mới Dùng cách ghi lại (đổ sang) mảng Arr của Sh SUMMARY lên Sh History thế thôi. Cũng chẳng có công để đoán ý của bạn đó nữa.
Còn cái đoạn yêu cầu thay đổi thêm bớt dữ liệu của Sh SUMMARY và các sh khác mà không làm mất đi dữ liệu của Sh History đã được Refersh thì thực tình tôi cũng chỉ viết theo ý hiểu của mình và cũng đã test thử những không test kỹ được.

Người nhờ hỗ trợ phải mô tả chính xác yêu cầu mà họ mong muốn và khi đã được hỗ trợ thì phải test kỹ các kết quả theo từng yêu cầu rồi mới phản hồi là đã đáp ứng được nhu cầu của mình.
Anh viết "....Nhiều người cứ viết theo như họ hiểu nhưng không lưu ý. Nếu họ hiểu sai thì kệ bạn. Bạn không mô tả chính xác cho họ hiểu thì bạn tự lĩnh hậu quả. ....". Đúng thế, rất nhiều trường hợp người viết code theo ý đoán mò ý của người cần hỗ trợ. Tôi khi trả bài thường có lưu ý là phải thêm bớt dữ liệu và test thật kỹ, còn người ta test kỹ hay không kỹ (cũng như không mô ta chính xác yêu cầu) thì ....
 
Upvote 0
Cảm ơn Anh @batman1 đã xem code nhé.
Tôi thấy bạn ấy ghi là " ....sẽ lấy toàn bộ dữ liệu ở sheet summary đổ sang sheet historys từ A2 đến Y...." Do vậy tôi mới Dùng cách ghi lại (đổ sang) mảng Arr của Sh SUMMARY lên Sh History thế thôi. Cũng chẳng có công để đoán ý của bạn đó nữa.
Còn cái đoạn yêu cầu thay đổi thêm bớt dữ liệu của Sh SUMMARY và các sh khác mà không làm mất đi dữ liệu của Sh History đã được Refersh thì thực tình tôi cũng chỉ viết theo ý hiểu của mình và cũng đã test thử những không test kỹ được.

Người nhờ hỗ trợ phải mô tả chính xác yêu cầu mà họ mong muốn và khi đã được hỗ trợ thì phải test kỹ các kết quả theo từng yêu cầu rồi mới phản hồi là đã đáp ứng được nhu cầu của mình.
Anh viết "....Nhiều người cứ viết theo như họ hiểu nhưng không lưu ý. Nếu họ hiểu sai thì kệ bạn. Bạn không mô tả chính xác cho họ hiểu thì bạn tự lĩnh hậu quả. ....". Đúng thế, rất nhiều trường hợp người viết code theo ý đoán mò ý của người cần hỗ trợ. Tôi khi trả bài thường có lưu ý là phải thêm bớt dữ liệu và test thật kỹ, còn người ta test kỹ hay không kỹ (cũng như không mô ta chính xác yêu cầu) thì ....
Dạ em xin lỗi anh, đúng là do em chạy code vội vàng trả lời a ngay, trong khi a đã bỏ rất nhiều thời gian để giúp em, một phần em sợ nói sai hoặc nói làm a không hiểu lại bị mắng nên em cũng không biết diễn đạt sao nữa, lúc a bảo kết thúc em biết a đang không hài lòng, em cũng có nhiều điều muốn hỏi lại không dám hỏi nữa, em xin lỗi a nhé.
Bài đã được tự động gộp:

Về đoạn mà bạn hỏi trong đoạn trích ở trên thì ...
Bạn cần hiểu là ZAQ_historys có nghĩa là lấy vùng từ cột Z tới cột AQ của HISTORYS vào mảng ZAQ_historys. Vì thế không có chuyện ZAQ_historys = .Range("AA2:AS" & lastRow).Value - tức không có chuyện lấy từ cột AA tới AS vào mảng ZAQ_historys đâu.

Bạn để ý là trong mảng thong_tin sheet MATER_ITEM được đặt cuối cùng. Vì sao? Vì khi duyệt các sheet khác thì đều lấy SOL ở cột A của HISTOSYS để tìm trong cột A của sheet đang duyệt. Chỉ tới khi duyệt MATER_ITEM mới lấy ITEM từ cột L của HISTORYS để tìm trong cột A của MATER_ITEM. Vì thế khi duyệt các sheet khác thì ta luôn dùng chung 1 dic, chỉ khi duyệt tới giá trị cuối cùng của vòng FOR ta mới tạo dic mới để làm bảng dò cho MATER_ITEM. Chính vì thế khi thêm sheet thì không thể đặt sau MATER_ITEM được. Và nữa: hiện tại ta chỉ tìm cột A hoặc L của HISTORYS trong các sheet. Thế với sheet thêm thì tìm cột nào của HISTORYS trong sheet thêm? Nếu không là A mà cũng không là L thì còn sửa nữa, vì bảng dò (dic) cũng phải tạo khi duyệt sheet thêm. Tóm lại phải mô tả về sheet thêm này (cách duyệt, khi tìm thấy thì lấy những cột nào để làm mới HISTORYS ...) thì mới nói chuyện được.
--------------

Lẽ ra bạn nên hỏi HUONGHCKT. Theo tôi thì bạn mô tả một đằng còn HUONGHCKT làm một nẻo. Nhưng nếu bạn đổi ý và hài lòng với code đó thì đó là quyền của bạn.

Bạn phải tự test kỹ vì nếu không thì không có gì đảm bảo là code của bất kỳ ai đó cũng làm làm đúng yêu cầu của bạn.
Nếu bạn cuối cùng cho là code của HUONGHCKT chưa làm đúng yêu cầu của bạn thì bạn phải nói rõ ra và nhờ HUONGHCKT sửa lại. Cho tới tận giờ bạn không nói ra và nhờ sửa thì HUONGHCKT có quyền cho là code đã làm đúng yêu cầu của bạn.

Bạn nên nhờ tiếp HUONGHCKT vì code của tôi nếu có đúng thì cũng chỉ là code cho refresh All. Bây giờ đọc kỹ lại bài #1 tôi mới thấy


Cái phần này tôi chưa làm, nhưng tôi thấy HUONGHCKT đã làm cho bạn. Tôi không dám phán là đã đúng ý bạn vì thực ra tôi cũng chưa rõ yêu cầu này. Nhưng HUONGHCKT đã làm thì chỉ cần sửa thôi.

Về phần mình thì nếu thêm cả phần nói ở trên thì có lẽ tôi sẽ viết hơi khác một chút code để sao cho có thể dùng cho refresh All và cả cho cho phần trên. Nhưng tôi chưa hiểu yêu cầu. Tôi trích lại:


Giả sử MỘT DÒNG NÀO ĐÓ của MATER_ITEM thay đổi thì cách làm nào sau đây là đúng yêu cầu (có thể 2 cách đều cho kết quả như nhau ***):

a. tìm từng dữ liệu trong cột L của HISTORYS trong cột A của dòng THAY ĐỔI của MATER_ITEM (chỉ của MATER_ITEM vì không duyệt các sheet không có thay đổi? Đúng là thế hay thế nào?). Nếu không tìm thấy thì không làm gì. Nếu tìm thấy thì lấy dữ liệu tương ứng từ MATER_ITEM sang HISTORYS.

b. tìm từng dữ liệu trong cột L của HISTORYS trong TOÀN BỘ cột A của MATER_ITEM (chỉ của MATER_ITEM vì không duyệt các sheet không có thay đổi? Đúng là thế hay thế nào?). Nếu không tìm thấy thì không làm gì. Nếu tìm thấy thì lấy dữ liệu tương ứng từ MATER_ITEM sang HISTORYS.

Tương tự với các sheet khác. Bạn phải cho biết cách thao tác là theo a. hay b. Nếu thao tác theo b. luôn có thể chấp nhận được thì cũng nói rõ.

***: do tôi không biết dữ liệu trong các sheet xuất hiện và biến mất theo cách nào, qui luật nào nên tôi cho ví dụ khi cách duyệt a. và b. cho hậu quả khác nhau. Vd. hiện tại trong HISTORYS ở ô nào đó của cột L có giá trị 123456789. Trong MATER_ITEM đang có ở cột A giá trị 123456789, và E, F, G = "ngày mai cũ", "em đi cũ", "biển nhớ cũ". Khi nhấn nút refresh All thì E, F, G = "ngày mai cũ", "em đi cũ", "biển nhớ cũ" được lấy sang HISTORYS sang AM, AN, AO và cùng dòng với 123456789. Bây giờ trong sheet MATER_ITEM ngoài 123456789 đã có ta chèn thêm 1 dòng khác TRƯỚC NÓ có các dữ liệu khác nhau ở các cột khác nhưng ở cột A cũng có 123456789, và E,F, G = "ngày mai mới", "em đi mới", "biển nhớ mới". Nếu bây giờ tìm 123456789 lấy từ cột L của HISTORYS trong cột A của MATER_ITEM thì:

- nếu tìm theo cách a. thì kết quả là E,F, G = "ngày mai mới", "em đi mới", "biển nhớ mới" được nhập vào AM, AN, AO của HISTORYS và ghi đè lên "ngày mai cũ", "em đi cũ", "biển nhớ cũ".

- nếu tìm theo cách b. thì kết quả là: đầu tiên E,F, G = "ngày mai mới", "em đi mới", "biển nhớ mới" được nhập vào AM, AN, AO của HISTORYS (tìm thấy 123456789 ở dòng mới) và ghi đè lên E, F, G = "ngày mai cũ", "em đi cũ", "biển nhớ cũ" đang có. Tiếp theo E, F, G = "ngày mai cũ", "em đi cũ", "biển nhớ cũ" được nhập vào AM, AN, AO của HISTORYS (tìm thấy 123456789 ở dòng cũ) và ghi đè lên E,F, G = "ngày mai mới", "em đi mới", "biển nhớ mới" đang có ở thời điểm này. Kết quả có E, F, G = "ngày mai cũ", "em đi cũ", "biển nhớ cũ"

Cách a. và b. cho kết quả khác nhau. Vì tôi không biết dữ liệu trong các sheet thoắt xuất hiện thoắt biến mất như thế nào, theo cách nào, qui luật nào nên tôi buộc phải có những phân tích như trên.

Nhiều người cứ viết theo như họ hiểu nhưng không lưu ý. Nếu họ hiểu sai thì kệ bạn. Bạn không mô tả chính xác cho họ hiểu thì bạn tự lĩnh hậu quả. Nhưng tôi khi không hiểu thì tôi không thể viết được code. Nếu tôi cho là mình hiểu nhưng chưa dám chắc chắn thì tôi luôn lưu ý là code tôi đưa ra được viết cho giả thiết nào.
Dạ, em sẽ sẽ đọc chi tiết tất cả nhưng gì a viết để hiểu cốt lõi vấn đề, sau đó em sẽ điều chỉnh lại code để thêm thử các sheet khác, có gì không hiểu em hỏi a giúp em nhé.
 
Upvote 0
Bạn hãy trích chính xác nhé. Muốn trả lời ai thì trích bài của người ấy. Trích bừa bãi thì khó đoán bạn định trả lời ai

Nhìn câu trả lời

lúc a bảo kết thúc em biết a đang không hài lòng,
thì có vẻ bạn đang viết cho tôi vì chỉ có tôi mới tuyên bố là "kết thúc". Thế thì tại sao lại trích bài của bạn HUONGHCKT? Mà đã trích thì trích đoạn mà mình định bình luận thôi chứ không phải trích cả bài.
Dạ, em sẽ sẽ đọc chi tiết tất cả nhưng gì a viết để hiểu cốt lõi vấn đề, sau đó em sẽ điều chỉnh lại code để thêm thử các sheet khác, có gì không hiểu em hỏi a giúp em nhé.
Hãy đọc kỹ bài #27 và trả lời những câu hỏi của tôi trong bài đó. Nếu tôi hiểu được thì tôi sẽ viết lại toàn bộ code cho bạn.
 
Upvote 0
Dạ em xin lỗi anh, đúng là do em chạy code vội vàng trả lời a ngay, trong khi a đã bỏ rất nhiều thời gian để giúp em, một phần em sợ nói sai hoặc nói làm a không hiểu lại bị mắng nên em cũng không biết diễn đạt sao nữa, lúc a bảo kết thúc em biết a đang không hài lòng, em cũng có nhiều điều muốn hỏi lại không dám hỏi nữa, em xin lỗi a nhé.
Bài đã được tự động gộp:


Dạ, em sẽ sẽ đọc chi tiết tất cả nhưng gì a viết để hiểu cốt lõi vấn đề, sau đó em sẽ điều chỉnh lại code để thêm thử các sheet khác, có gì không hiểu em hỏi a giúp em nhé.
Mà tôi có nói là kết thúc đâu nhỉ? Tôi tin là không ai mắng bạn đâu. Họ chỉ phật ý khi người cần trợ giúp có những biểu hiện thái độ thiếu tôn trọng (sắc màu văn hóa, văn minh thấp) mà thôi. Họ đã bỏ công ra giúp bạn nếu không vì cái đã nói trên thì hà cớ gì họ không giúp bạn tới cùng.
Bạn cứ hỏi cứ đăng lên, tôi tin là có rất nhiều người cũng quan tâm đến vấn đề bạn nêu, qua đó họ cũng đã có được chút ít nào đó vấn đề mà họ quan tâm.
 
Upvote 0
- nếu tìm theo cách a. thì kết quả là E,F, G = "ngày mai mới", "em đi mới", "biển nhớ mới" được nhập vào AM, AN, AO của HISTORYS và ghi đè lên "ngày mai cũ", "em đi cũ", "biển nhớ cũ".

- nếu tìm theo cách b. thì kết quả là: đầu tiên E,F, G = "ngày mai mới", "em đi mới", "biển nhớ mới" được nhập vào AM, AN, AO của HISTORYS (tìm thấy 123456789 ở dòng mới) và ghi đè lên E, F, G = "ngày mai cũ", "em đi cũ", "biển nhớ cũ" đang có. Tiếp theo E, F, G = "ngày mai cũ", "em đi cũ", "biển nhớ cũ" được nhập vào AM, AN, AO của HISTORYS (tìm thấy 123456789 ở dòng cũ) và ghi đè lên E,F, G = "ngày mai mới", "em đi mới", "biển nhớ mới" đang có ở thời điểm này. Kết quả có E, F, G = "ngày mai cũ", "em đi cũ", "biển nhớ cũ"
A batman1 ơi em đọc xong 2 ý này có thể hiểu được 2 ý a, b
em nói lại không biết đã đúng chưa, nghĩa là nếu sheet MASTER_ITEM có 2 dòng cột

A1 = 123456789, E1 = "ngày mai cũ" , F1 = "em đi cũ" , G1 = "biển nhớ cũ"
A2 = 123456789, E2 = "ngày mai mới" , F2 = "em đi mới" , G2 = "biển nhớ mới"

thì khi duyệt MASTER_ITEM sẽ lấy dòng nào đúng không anh? thực ra sheet MASTER_ITEM em sẽ chỉ để 1 dòng duy nhất thôi ạ, nếu có 2 dòng trở lên thì là do em copy bị trùng chưa loại đi, a có thể code theo ý a và b đều được ạ, áp dụng tương tự đối với các sheet khác có thể theo a hoặc b đều được.

Bạn cần hiểu là ZAQ_historys có nghĩa là lấy vùng từ cột Z tới cột AQ của HISTORYS vào mảng ZAQ_historys. Vì thế không có chuyện ZAQ_historys = .Range("AA2:AS" & lastRow).Value - tức không có chuyện lấy từ cột AA tới AS vào mảng ZAQ_historys đâu.

Bạn để ý là trong mảng thong_tin sheet MATER_ITEM được đặt cuối cùng. Vì sao? Vì khi duyệt các sheet khác thì đều lấy SOL ở cột A của HISTOSYS để tìm trong cột A của sheet đang duyệt. Chỉ tới khi duyệt MATER_ITEM mới lấy ITEM từ cột L của HISTORYS để tìm trong cột A của MATER_ITEM. Vì thế khi duyệt các sheet khác thì ta luôn dùng chung 1 dic, chỉ khi duyệt tới giá trị cuối cùng của vòng FOR ta mới tạo dic mới để làm bảng dò cho MATER_ITEM. Chính vì thế khi thêm sheet thì không thể đặt sau MATER_ITEM được. Và nữa: hiện tại ta chỉ tìm cột A hoặc L của HISTORYS trong các sheet. Thế với sheet thêm thì tìm cột nào của HISTORYS trong sheet thêm? Nếu không là A mà cũng không là L thì còn sửa nữa, vì bảng dò (dic) cũng phải tạo khi duyệt sheet thêm. Tóm lại phải mô tả về sheet thêm này (cách duyệt, khi tìm thấy thì lấy những cột nào để làm mới HISTORYS ...) thì mới nói chuyện được.

-> Dạ đúng như a nói phần sheet thêm mới cột dò tìm của sheet historys là A thì em dựa vào phần a ghi chú em đã thêm được một số sheet, nhưng đối với sheet thêm cần cột L để dò tìm thì em đang gặp rắc rối,
em đã thêm 1 sheet SPEED_MACHINE, điều kiện lấy là nếu tìm thấy cột L của historys bên cột B sheet SPEED_MACHINE thì lấy các cột E F G H I trả về vùng AV, AW, AX, AY, AZ sheet HISTORYS, nếu không tìm thấy thì không làm gì cả.
a có thể để code giúp em sao cho khi em cần thêm sheet tham chiều từ cột L em có thể tùy chỉnh để thêm được không ạ?

Trước a có nói cho em phần ngày tháng các cột C D E dữ liệu gốc nó không đúng em nghĩ mãi mới tìm ra giải pháp chuyển đổi bằng cách thêm cột chuyển đổi thành ngày tháng xịn, và đặt công thức trong bảng FRU nó sẽ tự động chạy, dữ liệu trong sheet historys sẽ lấy từ sheet FRU từ A->AB thay vì A-Y từ sheet summary như trước đó, summary cũng lấy từ FRU nên em chuyển qua lấy trực tiếp từ FRU luôn.
vì vậy khi a xem file đính kèm sẽ hơi khác một chút.

-> Đối với sheet summary cái này trước em đi nhặt nhạnh code để sửa nhưng đến giờ khi cần thêm sheet SPEED_MACHINE Lấy cột L của summary để dò tìm thì cũng không còn chạy được nữa, em có lấy toàn bộ code của historys sang chạy thử, sheet summary cách hoạt động giống hệt nhưng sheets historys chỉ khác là không lưu trữ lịch sử, em thử đưa dòng này vào Sheets("SUMMARY").Range("A2:AZ20000").ClearContents, nhưng code báo lỗi
trên dòng này
ThisWorkbook.Worksheets("SUMMARY").Range("A2").Resize(UBound(AY_historys, 1), UBound(AY_historys, 2)).Value = AY_historys
em đang hiểu lỗi này là do không có dòng nào được thêm trước vào summary nên gây ra lỗi, nên a xem giúp em với
sheet summary sẽ lấy dữ liệu từ A-AB bên sheet FRU, sau đó cập nhật thông tin từ các sheet khác hoạt động giống hệt như historys chỉ khác là không lưu lịch sử.

-> Em còn 2 thỉnh cầu nữa thôi
mặc dù nó không có trong mô tả lúc đầu vì khi làm mới phát sinh nên em rất cần a hỗ trợ, lúc a nói
***: do tôi không biết dữ liệu trong các sheet xuất hiện và biến mất theo cách nào, qui luật nào
em mới nhớ ra dữ liệu bên sheet summary và FRU em sẽ mất đi khi cột S chuyển trạng thái AWAITING_SHIPPING và AWAITING_FULFILLMENT sẽ biến mất trong vòng 24 đến 48 giờ vì vậy a có thể thêm giúp em tại cột BC của sheet HISTORYS sẽ ghi lại thời gian mỗi khi cột S chuyển trạng thái AWAITING_SHIPPING và WAITING_FULFILLMENT,

ví dụ khi nhấn vào refresh all, hôm nay 25 tháng 12 có 5 SOL ở cột A có 2 trạng thái ở cột S là AWAITING_SHIPPING và AWAITING_FULFILLMENT thì lấy ngày 25 tháng 12 điền vào dòng tương ứng của cột BC,
ngày mai 26-DEC có thêm 10 SOL ở cột A có 2 trạng thái ở cột S là AWAITING_SHIPPING và AWAITING_FULFILLMENT thì lấy ngày 26 tháng 12 điền vào dòng tương ứng của cột BC, như vậy em sẽ biết được mỗi ngày có thêm bao nhiêu SOL ở cột A chuyển trạng thái AWAITING_SHIPPING và AWAITING_FULFILLMENT.

- công thức ở cột BA và BB của 2 sheet summary, em thường phải kéo thủ công và rất hay bị loạn chồng chéo ô với nhau khiến kết quả bị sai lệch, ví dụ em kéo khoảng 10000 dòng thì không sao, em kéo đến 30000 dòng là excel báo Notresponding và tự đóng file, sau khi mở lại công thức không còn đúng với các ô đã được định như lúc đầu nữa mà nó nhảy loạn xạ, vì 2 cột BA và BB luôn luôn sẽ có thay đổi về giá trị trả về nên em ko copy value được
a có thể có cách nào giải quyết giúp em không ạ, liệu có code nào thay thế được công thức không a, hoặc mỗi lần sheet có số dòng đến đâu công thức sẽ tự động chạy tương ứng đến dòng đó.
 

File đính kèm

  • bHistory.xlsb
    3.4 MB · Đọc: 4
Upvote 0
Mà tôi có nói là kết thúc đâu nhỉ? Tôi tin là không ai mắng bạn đâu. Họ chỉ phật ý khi người cần trợ giúp có những biểu hiện thái độ thiếu tôn trọng (sắc màu văn hóa, văn minh thấp) mà thôi. Họ đã bỏ công ra giúp bạn nếu không vì cái đã nói trên thì hà cớ gì họ không giúp bạn tới cùng.
Bạn cứ hỏi cứ đăng lên, tôi tin là có rất nhiều người cũng quan tâm đến vấn đề bạn nêu, qua đó họ cũng đã có được chút ít nào đó vấn đề mà họ quan tâm.
Dạ em đã chạy thử rồi em thấy có một số vấn đề

em chạy phần NapDic trước nhưng không lấy được dữ liệu mới từ A đến Y, từ sheet summary vào sheet historys, chỉ chạy đúng lần nhấn nút refresh đầu tiên thôi, còn sau khi em thử thêm mới vào cột A vào sheet summary thì historys cũng không lấy được, phần cập nhật thay đổi từ B, C, D, E cũng chưa thấy có dữ liệu
dữ liệu sheet historys không được bảo toàn khi summary mất đi.

- phần cập nhật từ sheet master_item cũng không chạy,
- Nếu em muốn thêm sheet mới sử dụng cột L sheet historys tìm kiếm giá trợ tương ứng ở cột B SPEED lấy các cột E,F,G,H,I trả về các vùng AR, AS, AT, AU, AV em mở code em không biết sửa

a xem giúp em nhé, xong em sẽ chạy thử và kiểm tra tiếp ạ
 

File đính kèm

  • History1.xlsb
    2.4 MB · Đọc: 2
Upvote 0
Tôi đã viết cho bạn rồi. Các sheet khác SUMMARY ngoài việc duyệt trong refresh all thì mỗi sheet đó còn được duyệt khi có sự thay đổi trong chúng. Vì thế tôi sẽ viết lại hoàn toàn code, bạn không nên trích code cũ làm gì.

Có một điều bạn phải nói rõ khi những thống nhất tới thời điểm này lại bị thay đổi. Tới thời điểm này ta thống nhất là khi nhấn refresh all thì: duyệt SUMMARY và một số sheet khác. Bây giờ hình như là không duyệt SUMMARY nữa mà duyệt FRU. Nếu là thế thì phải khẳng định thật rõ, phải nhấn thật mạnh để tôi biết. Tôi xem qua thì ngoài việc duyệt FRU thay cho duyệt SUMMARY thì chi tiết cũng có thay đổi. Tức khi gặp dữ liệu đã có thì ngoài làm mới B:E và S còn làm mới mới K, Y và Z. Ngoài ra khi có dữ liệu mới thì không bê A:Y sang HISTORYS mà bê A:AB sang HISTORYS. Nếu đúng thế thì phải nói ra, nói thật to để người khác biết. Còn vấn đề nữa là code vẫn coi "dữ liệu mới" là khi CHỈ A mới (SOL mới). Có nghĩa là bạn không cho là dữ liệu mới khi A & B & C & ... & Y mới nữa à? Hay vẫn là CẢ DÒNG mới? À mà CẢ DÒNG bây giờ vẫn là A:Y hay bây giờ là A:AB hay A:AZ? A:AZ có lẽ là không vì tôi nhìn FRU chỉ có dữ liệu tới AE.

Khi mọi thứ lại thay đổi so với những gì đã thống nhất với nhau thì bạn phải nói ra, và nói thật rõ thật to. Nếu tôi không hiểu thì tôi không giúp bạn đâu.

ThisWorkbook.Worksheets("SUMMARY").Range("A2").Resize(UBound(AY_historys, 1), UBound(AY_historys, 2)).Value = AY_historys
em đang hiểu lỗi này là do không có dòng nào được thêm trước vào summary nên gây ra lỗi, nên a xem giúp em với
sheet summary sẽ lấy dữ liệu từ A-AB bên sheet FRU, sau đó cập nhật thông tin từ các sheet khác hoạt động giống hệt như historys chỉ khác là không lưu lịch sử.
không lưu lịch sử có nghĩa là gì? Bạn làm chuyên môn của mình thì bạn biết "lịch sử" nó là gì chứ tôi làm gì biết. Cũng như bạn nói "lấy nợ cũ" đối chiếu với ... thì tôi không làm chuyên môn kế toán làm sao tôi biết nợ cũ nó là cái gì. Nói với người ngoài thì phải nó: "lấy giá trị ở cột E" hoặc "lấy giá trị ở E7" chứ "nợ cũ", "lịch sử" thì đứa ít học như tôi biết nó là cái gì. Khi dùng khái niệm không phổ biến thì phải định nghĩa để người khác biết nó là gì.

tại cột BC của sheet HISTORYS sẽ ghi lại thời gian mỗi khi cột S chuyển trạng thái AWAITING_SHIPPING và WAITING_FULFILLMENT,
Tôi không hiểu.
Bạn viết là "khi cột S chuyển trạng thái AWAITING_SHIPPING và WAITING_FULFILLMENT". Với tôi thì phải viết:
- hoặc "khi cột S chuyển TỪ trạng thái ... SANG trạng thái ..."
- hoặc "khi cột S chuyển SANG trạng thái ...", đồng nghĩa với "khi cột S chuyển TỪ trạng thái BẤT KỲ SANG trạng thái ..."

Với tôi "khi cột S chuyển trạng thái AWAITING_SHIPPING và WAITING_FULFILLMENT" là không rõ ràng. Vì nó có nghĩa là "TỪ AWAITING_SHIPPING hoặc WAITING_FULFILLMENT" (SANG bất kỳ) hay là "SANG AWAITING_SHIPPING hoặc WAITING_FULFILLMENT" (TỪ bất kỳ)?

Liệu có phải bạn định viết: "khi cột S chuyển SANG trạng thái AWAITING_SHIPPING hoặc WAITING_FULFILLMENT"? Có nghĩa là không quan trọng từ trạng thái nào, miễn SANG trạng thái AWAITING_SHIPPING hoặc WAITING_FULFILLMENT thì đều ghi chú?

ví dụ khi nhấn vào refresh all, hôm nay 25 tháng 12 có 5 SOL ở cột A có 2 trạng thái ở cột S là AWAITING_SHIPPING và AWAITING_FULFILLMENT thì lấy ngày 25 tháng 12 điền vào dòng tương ứng của cột BC,
Nếu bạn đã lấy ví dụ thì nên giúp người ta khỏi dò tìm mất công. Thay vì
ví dụ khi nhấn vào refresh all, hôm nay 25 tháng 12 có 5 SOL ở cột A có 2 trạng thái ở cột S là AWAITING_SHIPPING và AWAITING_FULFILLMENT thì lấy ...
Thì nên viết
ví dụ khi nhấn vào refresh all, hôm nay 25 tháng 12 có 5 SOL ở cột A là 61520066-24, 61520066-25, 61520066-26, 61520066-27, 61520066-28 có ở cột S trạng thái ... TRƯỚC KHI NHẤN Referesh All và trạng thái SAU KHI NHẤN Refresh All là AWAITING_SHIPPING và AWAITING_FULFILLMENT thì lấy ...
 
Upvote 0
Tôi đã viết cho bạn rồi. Các sheet khác SUMMARY ngoài việc duyệt trong refresh all thì mỗi sheet đó còn được duyệt khi có sự thay đổi trong chúng. Vì thế tôi sẽ viết lại hoàn toàn code, bạn không nên trích code cũ làm gì.

Có một điều bạn phải nói rõ khi những thống nhất tới thời điểm này lại bị thay đổi. Tới thời điểm này ta thống nhất là khi nhấn refresh all thì: duyệt SUMMARY và một số sheet khác. Bây giờ hình như là không duyệt SUMMARY nữa mà duyệt FRU. Nếu là thế thì phải khẳng định thật rõ, phải nhấn thật mạnh để tôi biết. Tôi xem qua thì ngoài việc duyệt FRU thay cho duyệt SUMMARY thì chi tiết cũng có thay đổi. Tức khi gặp dữ liệu đã có thì ngoài làm mới B:E và S còn làm mới mới K, Y và Z. Ngoài ra khi có dữ liệu mới thì không bê A:Y sang HISTORYS mà bê A:AB sang HISTORYS. Nếu đúng thế thì phải nói ra, nói thật to để người khác biết. Còn vấn đề nữa là code vẫn coi "dữ liệu mới" là khi CHỈ A mới (SOL mới). Có nghĩa là bạn không cho là dữ liệu mới khi A & B & C & ... & Y mới nữa à? Hay vẫn là CẢ DÒNG mới? À mà CẢ DÒNG bây giờ vẫn là A:Y hay bây giờ là A:AB hay A:AZ? A:AZ có lẽ là không vì tôi nhìn FRU chỉ có dữ liệu tới AE.

Khi mọi thứ lại thay đổi so với những gì đã thống nhất với nhau thì bạn phải nói ra, và nói thật rõ thật to. Nếu tôi không hiểu thì tôi không giúp bạn đâu.


không lưu lịch sử có nghĩa là gì? Bạn làm chuyên môn của mình thì bạn biết "lịch sử" nó là gì chứ tôi làm gì biết. Cũng như bạn nói "lấy nợ cũ" đối chiếu với ... thì tôi không làm chuyên môn kế toán làm sao tôi biết nợ cũ nó là cái gì. Nói với người ngoài thì phải nó: "lấy giá trị ở cột E" hoặc "lấy giá trị ở E7" chứ "nợ cũ", "lịch sử" thì đứa ít học như tôi biết nó là cái gì. Khi dùng khái niệm không phổ biến thì phải định nghĩa để người khác biết nó là gì.


Tôi không hiểu.
Bạn viết là "khi cột S chuyển trạng thái AWAITING_SHIPPING và WAITING_FULFILLMENT". Với tôi thì phải viết:
- hoặc "khi cột S chuyển TỪ trạng thái ... SANG trạng thái ..."
- hoặc "khi cột S chuyển SANG trạng thái ...", đồng nghĩa với "khi cột S chuyển TỪ trạng thái BẤT KỲ SANG trạng thái ..."

Với tôi "khi cột S chuyển trạng thái AWAITING_SHIPPING và WAITING_FULFILLMENT" là không rõ ràng. Vì nó có nghĩa là "TỪ AWAITING_SHIPPING hoặc WAITING_FULFILLMENT" (SANG bất kỳ) hay là "SANG AWAITING_SHIPPING hoặc WAITING_FULFILLMENT" (TỪ bất kỳ)?

Liệu có phải bạn định viết: "khi cột S chuyển SANG trạng thái AWAITING_SHIPPING hoặc WAITING_FULFILLMENT"? Có nghĩa là không quan trọng từ trạng thái nào, miễn SANG trạng thái AWAITING_SHIPPING hoặc WAITING_FULFILLMENT thì đều ghi chú?


Nếu bạn đã lấy ví dụ thì nên giúp người ta khỏi dò tìm mất công. Thay vì

Thì nên viết
-Bây giờ hình như là không duyệt SUMMARY nữa mà duyệt FRU. Nếu là thế thì phải khẳng định thật rõ, phải nhấn thật mạnh để tôi biết -> chỗ này em chưa nhấn mạnh rõ ràng-> em xác nhận là lấy từ sheet FRU a nhé

-Tôi xem qua thì ngoài việc duyệt FRU thay cho duyệt SUMMARY thì chi tiết cũng có thay đổi. Tức khi gặp dữ liệu đã có thì ngoài làm mới B:E và S còn làm mới mới K, Y và Z-> chính xác ạ

-Ngoài ra khi có dữ liệu mới thì không bê A:Y sang HISTORYS mà bê A:AB sang HISTORYS -> chính xác ạ

-dữ liệu mới" là khi CHỈ A mới (SOL mới). Có nghĩa là bạn không cho là dữ liệu mới khi A & B & C & ... & Y mới nữa à? Hay vẫn là CẢ DÒNG mới? -> cả dòng mới ạ
À mà CẢ DÒNG bây giờ vẫn là A:Y hay bây giờ là A:AB hay A:AZ? A:AZ có lẽ là không vì tôi nhìn FRU chỉ có dữ liệu tới AE. -> cả dòng mới là A:AB, vì từ AC đến AE ngày cột ngày tháng định dạng không chuẩn nên không cần lấy thêm AC-AE nữa

- không lưu lịch sử có nghĩa là gì? Bạn làm chuyên môn của mình thì bạn biết "lịch sử" nó là gì chứ tôi làm gì biết.-> không lưu trữ lịch sử ở đây nghĩa là sheet FRU sẽ mất dữ liệu theo thời gian thì sheet summary cũng sẽ mất theo
ví dụ hôm nay 25 tháng 12 SOL 57038842-1 ở A2 kèm theo các giá trị khác nằm ở B2,C2 cho đến AB2 đang nằm ở sheet FRU khi nhấn refresh all sẽ cập nhật sang sheet summary từ A2 đến AB2 và lấy thêm dữ liệu từ các sheet khác bắt đầu từ cột AC2 đến AZ2 dựa trên cột cần dò tìm là cột A và cột L, sang ngày 26 hoặc 27 SOL 57038842-1 ở cột A2 kèm theo các giá trị khác nằm ở B2,C2 cho đến AB2 không còn tồn tại ở sheet FRU nữa, thì sheet summary cũng sẽ bị mất đi dòng A2 đến AZ2.

nó khác so với sheet historys ví dụ

hôm nay 25 tháng 12 SOL 57038842-1 ở A2 kèm theo các giá trị khác nằm ở B2,C2 cho đến AB2 đang nằm ở sheet FRU khi nhấn refresh all sẽ cập nhật sang sheet historys từ A2 đến AB2 và lấy thêm dữ liệu từ các sheet khác bắt đầu từ cột AC2 đến AZ2 dựa trên cột cần dò tìm là cột A và cột L, sang ngày 26 hoặc 27 SOL 57038842-1 ở cột A2 kèm theo các giá trị khác nằm ở B2,C2 cho đến AB2 không còn tồn tại ở sheet FRU nữa thì sheet historys sẽ không bị mất đi dòng A2 đến AZ2.



Nếu bạn đã lấy ví dụ thì nên giúp người ta khỏi dò tìm mất công. Thay vì
ví dụ khi nhấn vào refresh all, hôm nay 25 tháng 12 có 5 SOL ở cột A có 2 trạng thái ở cột S là AWAITING_SHIPPING và AWAITING_FULFILLMENT thì lấy ...
Thì nên viết
ví dụ khi nhấn vào refresh all, hôm nay 25 tháng 12 có 5 SOL ở cột A là 61520066-24, 61520066-25, 61520066-26, 61520066-27, 61520066-28 có ở cột S trạng thái
PRODUCTION_OPEN
EXTERNAL_REQ_OPEN
SUPPLY_ELIGIBLE
ENTERED
PO_OPEN
BOOKED
TRƯỚC KHI NHẤN Referesh All và trạng thái SAU KHI NHẤN Refresh All là AWAITING_SHIPPING và AWAITING_FULFILLMENT thì lấy ngày 25 tháng 12 điền vào cột BC,

Liệu có phải bạn định viết: "khi cột S chuyển SANG trạng thái AWAITING_SHIPPING hoặc WAITING_FULFILLMENT"? Có nghĩa là không quan trọng từ trạng thái nào, miễn SANG trạng thái AWAITING_SHIPPING hoặc WAITING_FULFILLMENT thì đều ghi chú? -> chính xác anh nhé

em xin lỗi đã để a phải đoán nhiều phần em giải thích chưa rõ ràng, cũng may mắn cho em là a đoán đều chính xác thậm chí phân tích rất chi tiết các tình huống có thể gây sai dữ liệu.
 
Upvote 0
- không lưu lịch sử có nghĩa là gì? Bạn làm chuyên môn của mình thì bạn biết "lịch sử" nó là gì chứ tôi làm gì biết.-> không lưu trữ lịch sử ở đây nghĩa là sheet FRU sẽ mất dữ liệu theo thời gian thì sheet summary cũng sẽ mất theo
ví dụ hôm nay 25 tháng 12 SOL 57038842-1 ở A2 kèm theo các giá trị khác nằm ở B2,C2 cho đến AB2 đang nằm ở sheet FRU khi nhấn refresh all sẽ cập nhật sang sheet summary từ A2 đến AB2 và lấy thêm dữ liệu từ các sheet khác bắt đầu từ cột AC2 đến AZ2 dựa trên cột cần dò tìm là cột A và cột L, sang ngày 26 hoặc 27 SOL 57038842-1 ở cột A2 kèm theo các giá trị khác nằm ở B2,C2 cho đến AB2 không còn tồn tại ở sheet FRU nữa, thì sheet summary cũng sẽ bị mất đi dòng A2 đến AZ2.

nó khác so với sheet historys ví dụ

hôm nay 25 tháng 12 SOL 57038842-1 ở A2 kèm theo các giá trị khác nằm ở B2,C2 cho đến AB2 đang nằm ở sheet FRU khi nhấn refresh all sẽ cập nhật sang sheet historys từ A2 đến AB2 và lấy thêm dữ liệu từ các sheet khác bắt đầu từ cột AC2 đến AZ2 dựa trên cột cần dò tìm là cột A và cột L, sang ngày 26 hoặc 27 SOL 57038842-1 ở cột A2 kèm theo các giá trị khác nằm ở B2,C2 cho đến AB2 không còn tồn tại ở sheet FRU nữa thì sheet historys sẽ không bị mất đi dòng A2 đến AZ2.
Tóm lại là khi nhấn Refresh All:

1. Duyệt FRU cho HISTORYS
a. kiểm tra từng dòng (A & B & ... & AB) của FRU có xuất hiện trong HISTORYS hay không. Nếu đã có thì làm mới B:E, S, K, Y và Z. Nếu chưa có thì thêm dòng đó vào cuối HISTORYS.
b. duyệt các sheet SHIPOUT, MATER_ITEM, ...

2. Duyệt FRU cho SUMMARY
a. kiểm tra từng dòng (A & B & ... & AB) của FRU có xuất hiện trong SUMMARY hay không. Nếu đã có thì làm mới B:E, S, K, Y và Z. Nếu chưa có thì thêm dòng đó vào cuối SUMMARY.
b. duyệt các sheet SHIPOUT, MATER_ITEM, ...
c. nếu có dòng nào đó trong SUMMARY mà không xuất hiện trong FRU thì xóa dòng đó khỏi SUMMARY.

Tức duyệt 2 sheet HISTORYS và SUMMARY khác nhau ở chỗ khi duyệt SUMMARY thì làm thêm thao tác c.? Nếu thế thì xóa là xóa dữ liệu và để dòng trống hay xóa nghĩa là DELETE dòng và các dòng ở dưới dồn lên?

Nếu có thời gian thì hôm nay tôi sẽ thử viết, ngược lại thì phải ngày mai.

À còn một ý nữa là ngoài chạy code khi nhấn Refresh All thì cũng chạy một code khác khi một trong các sheet SHIPOUT, MATER_ITEM, ... thay đổi, tức khi đó cũng duyệt nó cho HISTORYS. Vậy khi đó có duyệt nó cho cả SUMMARY hay không?
 
Lần chỉnh sửa cuối:
Upvote 0
Tóm lại là khi nhấn Refresh All:

1. Duyệt FRU cho HISTORYS
a. kiểm tra từng dòng (A & B & ... & AB) của FRU có xuất hiện trong HISTORYS hay không. Nếu đã có thì làm mới B:E, S, K, Y và Z. Nếu chưa có thì thêm dòng đó vào cuối HISTORYS.
b. duyệt các sheet SHIPOUT, MATER_ITEM, ...

2. Duyệt FRU cho SUMMARY
a. kiểm tra từng dòng (A & B & ... & AB) của FRU có xuất hiện trong SUMMARY hay không. Nếu đã có thì làm mới B:E, S, K, Y và Z. Nếu chưa có thì thêm dòng đó vào cuối SUMMARY.
b. duyệt các sheet SHIPOUT, MATER_ITEM, ...
c. nếu có dòng nào đó trong SUMMARY mà không xuất hiện trong FRU thì xóa dòng đó khỏi SUMMARY.

Tức duyệt 2 sheet HISTORYS và SUMMARY khác nhau ở chỗ khi duyệt SUMMARY thì làm thêm thao tác c.? Nếu thế thì xóa là xóa dữ liệu và để dòng trống hay xóa nghĩa là DELETE dòng và các dòng ở dưới dồn lên?

Nếu có thời gian thì hôm nay tôi sẽ thử viết, ngược lại thì phải ngày mai.

À còn một ý nữa là ngoài chạy code khi nhấn Refresh All thì cũng chạy một code khác khi một trong các sheet SHIPOUT, MATER_ITEM, ... thay đổi, tức khi đó cũng duyệt nó cho HISTORYS. Vậy khi đó có duyệt nó cho cả SUMMARY hay không?
phần tóm tắt 1 và 2 a vừa liệt kê là chính xác a nhé.

Tức duyệt 2 sheet HISTORYS và SUMMARY khác nhau ở chỗ khi duyệt SUMMARY thì làm thêm thao tác c.? Nếu thế thì xóa là xóa dữ liệu và để dòng trống hay xóa nghĩa là DELETE dòng và các dòng ở dưới dồn lên? -> dạ xóa hẳn dòng và dồn các dòng ở dưới lên ạ

À còn một ý nữa là ngoài chạy code khi nhấn Refresh All thì cũng chạy một code khác khi một trong các sheet SHIPOUT, MATER_ITEM, ... thay đổi, tức khi đó cũng duyệt nó cho HISTORYS. Vậy khi đó có duyệt nó cho cả SUMMARY hay không?-> duyệt luôn cả sheet summary ạ, hoặc a để giúp em 2 nút ở 2 sheet summary và historys khi cần cập nhật sheet nào em nhấn sheet đó cũng được, vì em sợ gộp một lúc code sẽ chạy lâu anh ạ.

Nếu có thời gian thì hôm nay tôi sẽ thử viết, ngược lại thì phải ngày mai.-> vâng hôm nay hoặc mai a viết giúp em cũng được
 
Upvote 0
Dạ em đã chạy thử rồi em thấy có một số vấn đề

em chạy phần NapDic trước nhưng không lấy được dữ liệu mới từ A đến Y, từ sheet summary vào sheet historys, chỉ chạy đúng lần nhấn nút refresh đầu tiên thôi, còn sau khi em thử thêm mới vào cột A vào sheet summary thì historys cũng không lấy được, phần cập nhật thay đổi từ B, C, D, E cũng chưa thấy có dữ liệu
dữ liệu sheet historys không được bảo toàn khi summary mất đi.

- phần cập nhật từ sheet master_item cũng không chạy,
- Nếu em muốn thêm sheet mới sử dụng cột L sheet historys tìm kiếm giá trợ tương ứng ở cột B SPEED lấy các cột E,F,G,H,I trả về các vùng AR, AS, AT, AU, AV em mở code em không biết sửa

a xem giúp em nhé, xong em sẽ chạy thử và kiểm tra tiếp ạ
Tôi vẫn làm trên ý tưởng ban đầu.
1/Và chỉ giải quyết:
1.1 Bạn không cần phải chạy NapDic nữa vì khi mở Workbook ra là đã chạy NapDic rồi( sự kiện Workbook_Open ở ThisWorkbook).
1.2 code NapDic chỉ nạp dic cho các lần cập nhật sau (ví dụ cập nhật thêm ở Sh SUMMARY và các Sh khác). Do vậy nó sẽ không Đổ Từ Sh SUMMARY sang Sh History (từ A2: Y&dòng cuối= mảng Arr)
Code RefershAll sẽ có phần:
+ Đổ Từ Sh SUMMARY sang Sh History (từ A2: Y&dòng cuối= mảng Arr) - theo như ý ban đầu của bài #1
+ dò tìm cột A (SOL) hay Arr(i,1) của các Sh bạn muốn tham chiếu vào (như bài 2# đã giải thích) nếu thấy có trong Dic thì lấy các dữ liệu tương ứng và Gán vào Sh History theo đúng dòng và cột tương ứng. (Code History2 trong modul Import_Sh)
2/ Tất nhiên khi bạn làm thì có lẽ chỉ chạy modul Refersh All một lần đầu còn từ đó về sau cứ khi Sh SUMMARY có sự biến động (ở đây biến động là thêm dữ liệu-Bản ghi cuối cùng của Sh SUMMARY) thì Sh History sẽ được cập nhật thêm sự biến động ấy. Do khi bạn nhập liệu thì thông thường sẽ nhập từ cột A, B, C,... cho đến cuối cùng (cột Y), Do vậy, để ghi lại sự biến động của dòng cuối Sh SUM tôi sử dụng code bắt sự kiện ở Sh SUM.
Còn sự biến động của các Sh có thế ở bất kỳ bản ghi nào. Khi có sự biến động ấy code ở Sh ấy sẽ kích hoạt Sub History2 chạy để cho kết quả ở Sh History.
Riêng Sh Master _Item thì khi có biến động sẽ kích hoạt code NapDic hoạt động, và sau đó là kích hoạt Code History2 (modul Import_Sh) hoạt động.
Trong trường hợp bạn muốn thêm dữ liệu cho Sh History từ một Sh nào đó (ngoài những Sh được kể tên ở bài 2 ) thì phải sửa lại code

Sau khi đã chạy modul Refersh All rồi, bạn có thể Sửa lại, hoặc xóa các bản ghi của Sh SUMMARY thì Sh History cũng không bị sửa hoặc xóa.

Quy trình Test file của tôi làm như sau:
a/ Thủ xem Napdic có nạp sau khi mở file không và code History có hoạt động đúng không.?
Mở file lên. Vào Sh History(Thu). xóa sạch dữ liệu. Ghi lại và thoát file.
Mở lại file lên. vào Sh History(thu). nhấn nút Refersh All và xem kết quả. Kiểm tra dữ liệu được lấy ở các Sh khác vào xem có đúng không?-Kiểm tra thật kỹ nhé.
Ghi nhớ dòng cuối của Sh History(thu), sau đó thử vào sh SUM Copy một dòng bất kỳ (copy từ A đến X) sau đó gõ một vài ký tự bất kỳ vào Ô Y cùng dòng, và Enter. Chuyến sang Sh History(thu) và xem dữ liệu mới - Kể cả dữ liệu được lấy từ các Sh khác đã được thêm vào dòng cuối của Sh History(thu) chưa.

b/ Kiểm tra sự biến động của các Sh khác( các Sh được lấy dữ liệu cho Sh History(thu)-trừ Sh Master_Item))
Vào một Sh và thử thay đổi(Thêm bớt ký tự, hoặc xóa..) và enter. sau đó quay về Sh History(thu) để kiểm tra. (để đỡ mất công tìm kiếm- bạn nên chọn dòng có SOL trùng với SOL ở dòng 2-5 của sh Histor(thu).

c/ Kiểm tra sự biến động của các Sh Master_Item.
Vào một Sh và thử thay đổi(Thêm bớt ký tự, hoặc xóa, hoặc thêm Item mới...)ở bất kỳ dòng nào có số cột <5 và enter. sau đó quay về Sh History(thu) để kiểm tra.

Đây là cách tôi làm theo đúng ý tưởng của bạn trình bày ở bài 1 và bài 2. Cũng nói thật là dữ liệu của bạn nhiều( trên 5000 bản ghi), các trường (tên cột) lại là tiếng Tây, nên tôi cũng ngại kiểm tra kỹ. nhưng vẫn tin tưởng và thấy rằng chạy code không vấp lỗi và cho ra kết quả đúng như ý định viết code. Còn các ý tưởng của bạn phát sinh sau này, hoặc code của tôi cho ra kết quả chưa đúng ý, thì thực tình khuyên bạn nên trình bày thật kỹ với Anh @batman1, anh ấy sẽ nhiệt tình giúp bạn đến tận gốc vấn đề. Code anh ấy viết thì khỏi phải lo lắng gì về độ chính xác và tốc độ xử lý, kể cả các trường hợp phát sinh mà chính bạn cũng không lường hết được.

Cũng rất mong là bạn đọc hết và đọc kỹ bài viết này.

Bạn xem file đính kèm và chạy thử như cách tôi đã trình bày ở trên nhé.
Ngóng chờ hồi âm.
 

File đính kèm

  • History1.xlsb
    2.4 MB · Đọc: 9
Upvote 0
Code được viết với giả thiết sau đây:
1. Khi nhấn RefreshAll thì thực hiện code sub RefreshAll

a. Duyệt FRU để cập nhật HISTORYS và SUMMARY. Sub RefreshAll sẽ gọi sub duyet_FRU 2 lần để cập nhật HISTORYS và SUMMARY.
- kiểm tra từng dòng (A & B & ... & AB) của FRU có xuất hiện trong HISTORYS hoặc SUMMARY hay không. Nếu đã có thì làm mới B:E, S, K, Y và Z. Nếu chưa có thì thêm dòng đó vào cuối HISTORYS hoặc SUMMARY

- nếu dòng (A & B & ... & AB) nào đó của SUMMARY không có trong FRU thì xóa khỏi SUMMARY

b. Sub RefreshAll cũng gọi sub duyet_KHAC nhiều lần, mỗi lần để duyệt từng sheet SHIPOUT, MATER_ITEM, ... để cập nhật HISTORYS và SUMMARY

2. Trong sub duyet_KHAC do muốn rút gọn code nên tôi có đoạn
Mã:
'    cot_historys
    Select Case sheet_can_duyet_name
        Case "SHIPOUT", "ORDER_SCAN", "BY_DATE", "KITTING", "PRINT_STAGE", "CUT_STAGE", "SOL_CANCEL", "MATERIAL_SHORTAGE", "BCNK": cot_historys = "A"
        Case "MATER_ITEM": cot_historys = "L"
    End Select
'    cot_do
    Select Case sheet_can_duyet_name
        Case "SHIPOUT", "ORDER_SCAN", "BY_DATE", "KITTING", "PRINT_STAGE", "CUT_STAGE", "SOL_CANCEL", "MATER_ITEM": cot_do = "A"
        Case "MATERIAL_SHORTAGE", "BCNK": cot_do = "B"
    End Select
'    kq_tu_cot
    Select Case sheet_can_duyet_name
        Case "SHIPOUT", "BY_DATE", "KITTING", "PRINT_STAGE", "CUT_STAGE", "SOL_CANCEL": kq_tu_cot = "B"
        Case "ORDER_SCAN", "BCNK": kq_tu_cot = "C"
        Case "MATERIAL_SHORTAGE": kq_tu_cot = "N"
        Case "MATER_ITEM": kq_tu_cot = "E"
    End Select
'    socot_kq
    Select Case sheet_can_duyet_name
        Case "SHIPOUT", "BCNK": socot_kq = 2
        Case "ORDER_SCAN", "BY_DATE", "KITTING", "MATERIAL_SHORTAGE", "SOL_CANCEL": socot_kq = 1
        Case "PRINT_STAGE", "CUT_STAGE", "MATER_ITEM": socot_kq = 3
    End Select
'    kq_den_cot
    Select Case sheet_can_duyet_name
        Case "SHIPOUT": kq_den_cot = 1
        Case "ORDER_SCAN": kq_den_cot = 3
        Case "BY_DATE": kq_den_cot = 17
        Case "KITTING": kq_den_cot = 4
        Case "MATERIAL_SHORTAGE": kq_den_cot = 5
        Case "PRINT_STAGE": kq_den_cot = 6
        Case "CUT_STAGE": kq_den_cot = 9
        Case "BCNK": kq_den_cot = 12
        Case "SOL_CANCEL": kq_den_cot = 18
        Case "MATER_ITEM": kq_den_cot = 14
    End Select

Nếu bạn cảm thấy khó hiểu thì thay toàn bộ đoạn trên bằng
Mã:
Select Case sheet_can_duyet_name
    Case "SHIPOUT":
        cot_historys = "A"
        cot_do = "A"
        kq_tu_cot = "B"
        socot_kq = 2
        kq_den_cot = 1
    Case "BY_DATE":
        cot_historys = "A"
        cot_do = "A"
        kq_tu_cot = "B"
        socot_kq = 1
        kq_den_cot = 17
    Case "KITTING":
        cot_historys = "A"
        cot_do = "A"
        kq_tu_cot = "B"
        socot_kq = 1
        kq_den_cot = 4
    Case "PRINT_STAGE":
        cot_historys = "A"
        cot_do = "A"
        kq_tu_cot = "B"
        socot_kq = 3
        kq_den_cot = 6
    Case "CUT_STAGE":
        cot_historys = "A"
        cot_do = "A"
        kq_tu_cot = "B"
        socot_kq = 3
        kq_den_cot = 9
    Case "SOL_CANCEL":
        cot_historys = "A"
        cot_do = "A"
        kq_tu_cot = "B"
        socot_kq = 1
        kq_den_cot = 18
    Case "ORDER_SCAN":
        cot_historys = "A"
        cot_do = "A"
        kq_tu_cot = "C"
        socot_kq = 1
        kq_den_cot = 3
    Case "BCNK":
        cot_historys = "A"
        cot_do = "B"
        kq_tu_cot = "C"
        socot_kq = 2
        kq_den_cot = 12
    Case "MATERIAL_SHORTAGE":
        cot_historys = "A"
        cot_do = "B"
        kq_tu_cot = "N"
        socot_kq = 1
        kq_den_cot = 5
    Case "MATER_ITEM":
        cot_historys = "L"
        cot_do = "A"
        kq_tu_cot = "E"
        socot_kq = 3
        kq_den_cot = 14
End Select

Tức bạn phải nhập cot_historys, cot_do, kq_tu_cot, socot_kq, kq_den_cot cho từng sheet. Khi thêm sheet mới thì thêm cot_historys, cot_do, kq_tu_cot, socot_kq, kq_den_cot cho sheet mới.

Vd.
"thêm 1 sheet SPEED_MACHINE, điều kiện lấy là nếu tìm thấy cột L của historys bên cột B sheet SPEED_MACHINE thì lấy các cột E F G H I trả về vùng AV, AW, AX, AY, AZ sheet HISTORYS, nếu không tìm thấy thì không làm gì cả."

thì
cot_historys = "L" <- lấy giá trị ở cột "L" của HISTORYS hoặc SUMMARY để tìm kiếm
cot_do = "B" <- dò tìm ở cột "B" của sheet thêm là SPEED_MACHINE
kq_tu_cot = "E" <- cột đầu tiên lấy kết quả từ SPEED_MACHINE là cột "E"
socot_kq = 5 <- tính từ cột "E" lấy tổng cộng 5 cột
kq_den_cot = 23 <- mảng Z_AQ sẽ được nhập xuống HISTORYS hoặc SUMMARY vào các cột của Z:AQ. Cột AV sẽ tương ứng với cột 23 trong mảng Z_AQ. Vì thế kq_den_cot = 23.

Tóm lại nếu bạn dùng phiên bản dài dòng hơn như ở trên thì phải thêm 1 CASE
Case "SPEED_MACHINE":
cot_historys = "L"
cot_do = "B"
kq_tu_cot = "E"
socot_kq = 5
kq_den_cot = 23


3. Trong module ThisWorkbook có code trong Sub Workbook_SheetChange. Mỗi khi có sự thay đổi trong sheet nào đó của tập tin mà không phải là HISTORYS và SUMMARY thì code trong Workbook_SheetChange sẽ NGAY LẬP TỨC gọi sub duyet_KHAC, nhưng code trong sub duyet_KHAC chỉ được thực hiện khi tên sheet được liệt kê trong Select ... Case ... End Select. Hiện tại danh sách mới chỉ có: "SHIPOUT", "ORDER_SCAN", "BY_DATE", "KITTING", "PRINT_STAGE", "CUT_STAGE", "SOL_CANCEL", "MATERIAL_SHORTAGE", "BCNK", "MATER_ITEM".

4. Trong module SUMMARY có sub Worksheet_Change. Khi có bất cứ sự thay đổi nào trong SUMMARY, từ cột E tới cột AS, thì code sẽ tính giá trị cho cột BA. Nếu có sự thay đổi trong A:AU thì tính giá trị cho cột BB.

5. Bạn tự test thật kỹ vì con người ai cũng có thể nhầm lẫn. Việc của bạn, chỉ bạn hiểu rõ dữ liệu, nên cách test bạn phải biết, không ai giúp được phần test. Tôi ghi chú rất nhiều. Cần đọc kỹ để hiểu ý nghĩa các biến, những việc mà từng dòng code thực hiện.

Hình như bạn có nói là các sheet như SHIPOUT có ít dòng mà sao tôi thấy thực tế khác xa.
SHIPOUT = 18331 dòng
ORDER_SCAN = 17455 dòng
BY_DATE = 32978 dòng
KITTING = 31209 dòng
 

File đính kèm

  • History(1).xlsb
    2.8 MB · Đọc: 19
Upvote 0
Code được viết với giả thiết sau đây:
1. Khi nhấn RefreshAll thì thực hiện code sub RefreshAll

a. Duyệt FRU để cập nhật HISTORYS và SUMMARY. Sub RefreshAll sẽ gọi sub duyet_FRU 2 lần để cập nhật HISTORYS và SUMMARY.
- kiểm tra từng dòng (A & B & ... & AB) của FRU có xuất hiện trong HISTORYS hoặc SUMMARY hay không. Nếu đã có thì làm mới B:E, S, K, Y và Z. Nếu chưa có thì thêm dòng đó vào cuối HISTORYS hoặc SUMMARY

- nếu dòng (A & B & ... & AB) nào đó của SUMMARY không có trong FRU thì xóa khỏi SUMMARY

b. Sub RefreshAll cũng gọi sub duyet_KHAC nhiều lần, mỗi lần để duyệt từng sheet SHIPOUT, MATER_ITEM, ... để cập nhật HISTORYS và SUMMARY

2. Trong sub duyet_KHAC do muốn rút gọn code nên tôi có đoạn
Mã:
'    cot_historys
    Select Case sheet_can_duyet_name
        Case "SHIPOUT", "ORDER_SCAN", "BY_DATE", "KITTING", "PRINT_STAGE", "CUT_STAGE", "SOL_CANCEL", "MATERIAL_SHORTAGE", "BCNK": cot_historys = "A"
        Case "MATER_ITEM": cot_historys = "L"
    End Select
'    cot_do
    Select Case sheet_can_duyet_name
        Case "SHIPOUT", "ORDER_SCAN", "BY_DATE", "KITTING", "PRINT_STAGE", "CUT_STAGE", "SOL_CANCEL", "MATER_ITEM": cot_do = "A"
        Case "MATERIAL_SHORTAGE", "BCNK": cot_do = "B"
    End Select
'    kq_tu_cot
    Select Case sheet_can_duyet_name
        Case "SHIPOUT", "BY_DATE", "KITTING", "PRINT_STAGE", "CUT_STAGE", "SOL_CANCEL": kq_tu_cot = "B"
        Case "ORDER_SCAN", "BCNK": kq_tu_cot = "C"
        Case "MATERIAL_SHORTAGE": kq_tu_cot = "N"
        Case "MATER_ITEM": kq_tu_cot = "E"
    End Select
'    socot_kq
    Select Case sheet_can_duyet_name
        Case "SHIPOUT", "BCNK": socot_kq = 2
        Case "ORDER_SCAN", "BY_DATE", "KITTING", "MATERIAL_SHORTAGE", "SOL_CANCEL": socot_kq = 1
        Case "PRINT_STAGE", "CUT_STAGE", "MATER_ITEM": socot_kq = 3
    End Select
'    kq_den_cot
    Select Case sheet_can_duyet_name
        Case "SHIPOUT": kq_den_cot = 1
        Case "ORDER_SCAN": kq_den_cot = 3
        Case "BY_DATE": kq_den_cot = 17
        Case "KITTING": kq_den_cot = 4
        Case "MATERIAL_SHORTAGE": kq_den_cot = 5
        Case "PRINT_STAGE": kq_den_cot = 6
        Case "CUT_STAGE": kq_den_cot = 9
        Case "BCNK": kq_den_cot = 12
        Case "SOL_CANCEL": kq_den_cot = 18
        Case "MATER_ITEM": kq_den_cot = 14
    End Select

Nếu bạn cảm thấy khó hiểu thì thay toàn bộ đoạn trên bằng
Mã:
Select Case sheet_can_duyet_name
    Case "SHIPOUT":
        cot_historys = "A"
        cot_do = "A"
        kq_tu_cot = "B"
        socot_kq = 2
        kq_den_cot = 1
    Case "BY_DATE":
        cot_historys = "A"
        cot_do = "A"
        kq_tu_cot = "B"
        socot_kq = 1
        kq_den_cot = 17
    Case "KITTING":
        cot_historys = "A"
        cot_do = "A"
        kq_tu_cot = "B"
        socot_kq = 1
        kq_den_cot = 4
    Case "PRINT_STAGE":
        cot_historys = "A"
        cot_do = "A"
        kq_tu_cot = "B"
        socot_kq = 3
        kq_den_cot = 6
    Case "CUT_STAGE":
        cot_historys = "A"
        cot_do = "A"
        kq_tu_cot = "B"
        socot_kq = 3
        kq_den_cot = 9
    Case "SOL_CANCEL":
        cot_historys = "A"
        cot_do = "A"
        kq_tu_cot = "B"
        socot_kq = 1
        kq_den_cot = 18
    Case "ORDER_SCAN":
        cot_historys = "A"
        cot_do = "A"
        kq_tu_cot = "C"
        socot_kq = 1
        kq_den_cot = 3
    Case "BCNK":
        cot_historys = "A"
        cot_do = "B"
        kq_tu_cot = "C"
        socot_kq = 2
        kq_den_cot = 12
    Case "MATERIAL_SHORTAGE":
        cot_historys = "A"
        cot_do = "B"
        kq_tu_cot = "N"
        socot_kq = 1
        kq_den_cot = 5
    Case "MATER_ITEM":
        cot_historys = "L"
        cot_do = "A"
        kq_tu_cot = "E"
        socot_kq = 3
        kq_den_cot = 14
End Select

Tức bạn phải nhập cot_historys, cot_do, kq_tu_cot, socot_kq, kq_den_cot cho từng sheet. Khi thêm sheet mới thì thêm cot_historys, cot_do, kq_tu_cot, socot_kq, kq_den_cot cho sheet mới.

Vd.
"thêm 1 sheet SPEED_MACHINE, điều kiện lấy là nếu tìm thấy cột L của historys bên cột B sheet SPEED_MACHINE thì lấy các cột E F G H I trả về vùng AV, AW, AX, AY, AZ sheet HISTORYS, nếu không tìm thấy thì không làm gì cả."

thì
cot_historys = "L" <- lấy giá trị ở cột "L" của HISTORYS hoặc SUMMARY để tìm kiếm
cot_do = "B" <- dò tìm ở cột "B" của sheet thêm là SPEED_MACHINE
kq_tu_cot = "E" <- cột đầu tiên lấy kết quả từ SPEED_MACHINE là cột "E"
socot_kq = 5 <- tính từ cột "E" lấy tổng cộng 5 cột
kq_den_cot = 23 <- mảng Z_AQ sẽ được nhập xuống HISTORYS hoặc SUMMARY vào các cột của Z:AQ. Cột AV sẽ tương ứng với cột 23 trong mảng Z_AQ. Vì thế kq_den_cot = 23.

Tóm lại nếu bạn dùng phiên bản dài dòng hơn như ở trên thì phải thêm 1 CASE
Case "SPEED_MACHINE":
cot_historys = "L"
cot_do = "B"
kq_tu_cot = "E"
socot_kq = 5
kq_den_cot = 23


3. Trong module ThisWorkbook có code trong Sub Workbook_SheetChange. Mỗi khi có sự thay đổi trong sheet nào đó của tập tin mà không phải là HISTORYS và SUMMARY thì code trong Workbook_SheetChange sẽ NGAY LẬP TỨC gọi sub duyet_KHAC, nhưng code trong sub duyet_KHAC chỉ được thực hiện khi tên sheet được liệt kê trong Select ... Case ... End Select. Hiện tại danh sách mới chỉ có: "SHIPOUT", "ORDER_SCAN", "BY_DATE", "KITTING", "PRINT_STAGE", "CUT_STAGE", "SOL_CANCEL", "MATERIAL_SHORTAGE", "BCNK", "MATER_ITEM".

4. Trong module SUMMARY có sub Worksheet_Change. Khi có bất cứ sự thay đổi nào trong SUMMARY, từ cột E tới cột AS, thì code sẽ tính giá trị cho cột BA. Nếu có sự thay đổi trong A:AU thì tính giá trị cho cột BB.

5. Bạn tự test thật kỹ vì con người ai cũng có thể nhầm lẫn. Việc của bạn, chỉ bạn hiểu rõ dữ liệu, nên cách test bạn phải biết, không ai giúp được phần test. Tôi ghi chú rất nhiều. Cần đọc kỹ để hiểu ý nghĩa các biến, những việc mà từng dòng code thực hiện.

Hình như bạn có nói là các sheet như SHIPOUT có ít dòng mà sao tôi thấy thực tế khác xa.
SHIPOUT = 18331 dòng
ORDER_SCAN = 17455 dòng
BY_DATE = 32978 dòng
KITTING = 31209 dòng
A batman1 ơi em đang xem lại bài của a huonghckt và bài a vừa hướng dẫn nhưng em vẫn chưa hiểu hết được, em đang mò mẫm từng chút một nhưng thật sự em đang mong chờ a viết lại theo bài 36 37 vừa được a tóm tắt sau đó em sẽ đọc lại tiếp bài 39, hiện tại em không có khả năng code được sẽ mất rất nhiều thời gian để em tự học nữa ạ, em rất mong a giúp em
 
Upvote 0
Web KT

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

Back
Top Bottom