Hoàng Nhật Phương
Thành viên gắn bó



- Tham gia
- 5/11/15
- Bài viết
- 1,895
- Được thích
- 1,219
Xin chào tất cả các bạn,chúc các bạn cuối tuần vui vẻ!
Như tiêu đề tôi đã đề cập,cụ thể hơn nữa tôi cũng đã trình bày trong file đính kèm.
Rất mong các bạn dành thời gian để tìm hiểu và giúp đỡ ạ.
Xin cảm ơn các bạn rất nhiều.
Mình không biết code nên khó giúp bạn được,tuy điều kiện có hơi khác nhưng nếu bạn mà hiểu được ít nhiều thì bạn tham khảo thêm bài này xem có giúp gì được cho bạn không nhé:
http://www.giaiphapexcel.com/forum/...-dòng-theo-một-điều-kiện!&p=431089#post431089
Hoặc là:
http://www.giaiphapexcel.com/forum/showthread.php?65374-Khoá-dòng-theo-điều-kiện
GoodLuck!
Về cơ bản thì code thế này:Xin chào tất cả các bạn,chúc các bạn cuối tuần vui vẻ!
Như tiêu đề tôi đã đề cập,cụ thể hơn nữa tôi cũng đã trình bày trong file đính kèm.
Rất mong các bạn dành thời gian để tìm hiểu và giúp đỡ ạ.
Xin cảm ơn các bạn rất nhiều.
Về cơ bản thì code thế này:
[GPECODE=vb]Const Pass = "GPE"
Sub LockCells()
Dim Cll As Range
ActiveSheet.Unprotect Pass
[G5:O26].Locked = False
For Each Cll In [G5:G26]
If Cll + [D6].Offset(Cll.Offset(, 1)) < Now Then Cll.Resize(, 9).Locked = True
Next
ActiveSheet.Protect Pass
End Sub[/GPECODE]
Vấn đề nằm ở chỗ việc kiểm tra thời gian và khóa ô cần phải được thực hiện trước mỗi lúc nhập dữ liệu. Do đó sub LockCells ở trên phải được gọi thường xuyên. Trước mắt thì tôi gắn nó vào sự kiện Worksheet_SelectionChange như sau:
[GPECODE=vb]Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Intersect(Target, [I5:O26]) Is Nothing Then Exit Sub
With Application
.ScreenUpdating = False: .EnableEvents = False: .Calculation = xlCalculationManual
End With
LockCells
With Application
.ScreenUpdating = True: .EnableEvents = True: .Calculation = xlCalculationAutomatic
End With
End Sub[/GPECODE]
Cách này thì code sẽ chạy khá ì ạch vì mỗi khi chọn ô trong vùng I5:O26, sub LockCells đều bị gọi. Tuy nhiên tôi cũng chưa nghĩ ra cách nào khác hay hơn.
Bạn tham khảo trong file nhé. Lưu ý là trong file, ô D9 có giá trị bằng 5/4, hay 1+1/4, tức là "6 giờ sáng hôm sau".
có liên quan gì đến vùng dữ liệu cơ sở trong khung màu đỏ trong hình ảnh không vậy bạn?... [D6].Offset(Cll.Offset(, 1))...
Nhìn trong hình, bạn thấy: Tính từ ô D6, các ca 1, 2, 3 sẽ có giờ kết thúc lần lượt tính xuống phía dưới 1, 2, 3 ô (chính là các ô D7, D8, D9). Và trong bảng màu vàng thì thông tin ca nằm ở bên phải cột Ngày tháng 1 cột. Do đó để lấy giờ kết thúc của từng ca chỉ cần lấy [D6].Offset(Cll.Offset(, 1)) thôi, trong đó Cll chính là thông tin Ngày tháng ở cột G. Cụ thể: Cll.Offset(, 1) sẽ cho biết hàng hiện tại (ứng với Cll) là ca mấy. Nếu là ca mấy thì dịch chuyển bấy nhiêu ô xuống phía dưới so với ô D6 là biết giờ kết thúc. Đem lấy thời điểm kết thúc đó (bằng Ngày ở cột G cộng với Giờ kết thúc) so sánh với thời điểm hiện tại (Now) là biết nên khóa hay chưa. Cũng chính vì cái chỗ lấy Ngày cộng với Giờ này mà ở ca 3 (ô D9), phải lấy 6h cộng với 1 ngày nữa nó mới ra 6h sáng hôm sau đấy. Con số 1+1/4 chính là bằng 1 ngày cộng với 6 giờ.Thật tuyệt vời, bài giải đúng với mong muốn của tôi rồi.Cảm ơn bạn nhiều nghiaphuc rất nhiều ạ.
Nhưng có một chỗ này tôi không hiểu,Mục này:
có liên quan gì đến vùng dữ liệu cơ sở trong khung màu đỏ trong hình ảnh không vậy bạn?
View attachment 155463
Bạn cũng có nhắc đến ô D9 nhưng tôi không thấy có chỗ nào liên quan đến ô D9 trong code cả.
Một lần nữa làm phiền nghiaphuc dành chút thời gian chỉ rõ thêm cho ạ.
Cảm ơn bạn rất nhiều.
Nhìn trong hình, bạn thấy: Tính từ ô D6, các ca 1, 2, 3 sẽ có giờ kết thúc lần lượt tính xuống phía dưới 1, 2, 3 ô (chính là các ô D7, D8, D9). Và trong bảng màu vàng thì thông tin ca nằm ở bên phải cột Ngày tháng 1 cột. Do đó để lấy giờ kết thúc của từng ca chỉ cần lấy [D6].Offset(Cll.Offset(, 1)) thôi, trong đó Cll chính là thông tin Ngày tháng ở cột G. Cụ thể: Cll.Offset(, 1) sẽ cho biết hàng hiện tại (ứng với Cll) là ca mấy. Nếu là ca mấy thì dịch chuyển bấy nhiêu ô xuống phía dưới so với ô D6 là biết giờ kết thúc. Đem lấy thời điểm kết thúc đó (bằng Ngày ở cột G cộng với Giờ kết thúc) so sánh với thời điểm hiện tại (Now) là biết nên khóa hay chưa. Cũng chính vì cái chỗ lấy Ngày cộng với Giờ này mà ở ca 3 (ô D9), phải lấy 6h cộng với 1 ngày nữa nó mới ra 6h sáng hôm sau đấy. Con số 1+1/4 chính là bằng 1 ngày cộng với 6 giờ.
Nếu chỉ để ngăn chặn việc nhập liệu sai thì có thể áp dụng được chứ nếu đã cho phép mở file mà muốn khóa dữ liệu là một điều không tưởng. Việc khóa cứng còn không an toàn chứ đừng nói đến chuyện khóa, mở bằng macro.Xin chào tất cả các bạn,chúc các bạn cuối tuần vui vẻ!
Như tiêu đề tôi đã đề cập,cụ thể hơn nữa tôi cũng đã trình bày trong file đính kèm.
Rất mong các bạn dành thời gian để tìm hiểu và giúp đỡ ạ.
Xin cảm ơn các bạn rất nhiều.
Nếu chỉ để ngăn chặn việc nhập liệu sai thì có thể áp dụng được chứ nếu đã cho phép mở file mà muốn khóa dữ liệu là một điều không tưởng. Việc khóa cứng còn không an toàn chứ đừng nói đến chuyện khóa, mở bằng macro.
Nếu để ngăn chặn việc nhập liệu sai thì tôi nghĩ dùng Validation là phù hợp.
Tôi đã nói ở bài trước là tôi dùng Validation, bạn có thể vào đó để tham khảo công thức.huuthang_bd thân mến!
Xin cảm ơn bạn rất nhiều vì đã hỗ trợ cho tôi ạ.
Tôi xin lỗi bạn nhé do tôi chưa nêu rõ cụ thể mục đích của tôi nên có thể khiến bạn hiểu khác một chút.
không phải mục đích là để ngăn chặn dữ liệu sai đậu ạ.
Thực tế những dòng có dữ liệu ngày và ca (trong quá khứ) thì dữ liệu các cột data1 đếm data7 cũng có hết rồi huuthang_bd à. Mục đích của tôi là chỉ muốn quá hạn thì khóa những dữ liệu này lại để tránh xóa sửa bạn ạ.
Với lại làm phiền bạn có thể xem lại giúp tôi trường hợp này được không ạ:
View attachment 155470
đáng ra những ngày chưa đến hạn thì vẫn có thể nhập dữ liệu bình thường được chứ đúng không ạ. Hi, bạn làm thế nào thế nào mà hay vậy tôi kiểm tra trong file không thấy có một chút macro nào cả.
Tôi đã nói ở bài trước là tôi dùng Validation, bạn có thể vào đó để tham khảo công thức.
Vì mục đích là để ngăn chặn việc nhập liệu nhầm nên trong file đó chỉ cho nhập liệu ở vùng tương ứng với ca hiện tại, các vùng khác (cả quá khứ và tương lai) đều không được nhập. Ví dụ bây giờ là 01/03/2016 08:45 thì chỉ được nhập liệu vào ca 1 ngày 01/03/2016 mà thôi.
Nếu bạn muốn khóa thì không thể dùng cách này. Nhưng như tôi đã nói, nếu đã cho mở file thì rất khó (có thể nói là không thể) cấm người khác sửa dữ liệu. Như file ở bài #4, cho dù tôi không biết cách bẻ khóa, tôi chỉ cần sửa ngày hệ thống về 01/01/2016 là có thể sửa tất cả các dữ liệu trong bảng rồi.
Trời ơi! Đúng rồi bạn chỉ tôi mới thử và thấy đúng như vậy...huhu làm thế nào bây giờ nhỉ!tôi chỉ cần sửa ngày hệ thống về 01/01/2016 là có thể sửa tất cả các dữ liệu trong bảng rồi
Không hẳn là như vậy đâu bạn. Một người bình thường không có ý định sửa dữ liệu của bạn có thể không nghĩ ra cách này nhưng nếu một người đang tìm cách sửa dữ liệu thì họ có thể dễ dàng tìm ra cách qua mặt code.Trời ơi! Đúng rồi bạn chỉ tôi mới thử và thấy đúng như vậy...huhu làm thế nào bây giờ nhỉ!
Nhưng chắc ít ai biết được những điều này phải không bạn,tất nhiên là các bạn trên diễn đàn này có thể bạn không nói nhưng ai cũng có thể biết được rồi.
Bạn vào Data/Validation và ngâm cứu trong thẻ Settings và Error Alert là biết.
Không hẳn là như vậy đâu bạn. Một người bình thường không có ý định sửa dữ liệu của bạn có thể không nghĩ ra cách này nhưng nếu một người đang tìm cách sửa dữ liệu thì họ có thể dễ dàng tìm ra cách qua mặt code.
Về cơ bản thì code thế này:
[GPECODE=vb]Const Pass = "GPE"
Sub LockCells()
Dim Cll As Range
ActiveSheet.Unprotect Pass
[G5:O26].Locked = False
For Each Cll In [G5:G26]
If Cll + [D6].Offset(Cll.Offset(, 1)) < Now Then Cll.Resize(, 9).Locked = True
Next
ActiveSheet.Protect Pass
End Sub[/GPECODE]
Vấn đề nằm ở chỗ việc kiểm tra thời gian và khóa ô cần phải được thực hiện trước mỗi lúc nhập dữ liệu. Do đó sub LockCells ở trên phải được gọi thường xuyên. Trước mắt thì tôi gắn nó vào sự kiện Worksheet_SelectionChange như sau:
[GPECODE=vb]Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Intersect(Target, [I5:O26]) Is Nothing Then Exit Sub
With Application
.ScreenUpdating = False: .EnableEvents = False: .Calculation = xlCalculationManual
End With
LockCells
With Application
.ScreenUpdating = True: .EnableEvents = True: .Calculation = xlCalculationAutomatic
End With
End Sub[/GPECODE]
Cách này thì code sẽ chạy khá ì ạch vì mỗi khi chọn ô trong vùng I5:O26, sub LockCells đều bị gọi. Tuy nhiên tôi cũng chưa nghĩ ra cách nào khác hay hơn.
Bạn tham khảo trong file nhé. Lưu ý là trong file, ô D9 có giá trị bằng 5/4, hay 1+1/4, tức là "6 giờ sáng hôm sau".
Nói thật là tôi không hứng thú với đề tài này (vì cách mở khóa protect sheet dù không biết password có đầy trên internet) nhưng thấy bạn vẫn muốn làm theo cách này nên tôi giúp bạn hạn chế việc sửa ngày giờ hệ thống để sửa dữ liệu quá khứ.nghiaphuc ơi, các bạn ơi!! tôi lại làm phiền mọi người nữa đây ^^!
Các bạn cho hỏi là nếu tôi muốn tách riêng ra một sheets data một sheets điều kiện thì code phải sửa lại thế nào cho phù hợp ạ ?
Các bạn xem file đính kèm và hỗ trợ cho tôi với nhé!
Xin cảm ơn các bạn rất nhiều.