Những câu hỏi về code, xin giải thích các code, đề nghị các bạn gửi vào đây (3 người xem)

  • Thread starter Thread starter ST-Lu!
  • Ngày gửi Ngày gửi
Liên hệ QC

Người dùng đang xem chủ đề này

Status
Không mở trả lời sau này.

ST-Lu!

Love Wingchun
Tham gia
19/8/08
Bài viết
730
Được thích
546
Nghề nghiệp
Xích lô một thời
Kể từ hôm nay, tất cả những câu hỏi nhờ giải thích dùm một đoạn code, hay là hỏi những vấn đề linh tinh gì liên quan đến cách viết code, đề nghị các bạn gửi chung vào đây.

Những đề tài mới với tiêu đề: "Nhờ giải thích dùm đoạn code", mà không nói rõ là code gì, code dùng để làm gì, sẽ bị xóa.

BQT

----------------------------------------------------------------------------------------------------------------


Em xin được hỏi 2 đoạn code sau có tương đương nhau ?

Cells(Cells.Rows.Count, 1).End(xlUp).Row có tương đương với [A65000].End(xlup).row

Cám ơn các anh chỉ giáo
 
Chỉnh sửa lần cuối bởi điều hành viên:
True / False

Cái này là quy định của Micorsoft thôi... chắc chắn phải có nguyên nhân, nhưng là nguyên nhân gì thì mọi người vẫn... đang bàn...

Hằng logic False luôn có giá trị 0 ở tất cả các ngôn ngữ lập trình (chưa thấy ở đâu quy định khác). Riêng hằng True được quy định là <> 0, tuy nhiên nó mang giá trị 1 hay -1 là do tính thứ tự của các giá trị True, False khi khai báo kiểu Enum. Trong VB (và VBA), 2 giá trị này có thứ tự là (TRUE, FALSE), do đó true < false, từ đó VB quy định True có giá trị là -1. Trong Excel thì tính có thứ tự của cặp T, F không mang ý nghĩa đặc biệt, và vì Excel đã quy định thứ tự (False, True) từ trước khi có macro cho nên đến giờ nó không thể thay đổi được.


Ngoài ra, trong VBA và Excel còn có sự khác nhau quan trọng giữa hàm làm tròn ROUND.

Round trong (E) đơn thuần làm tròn đến chữ số thập phân theo nguyên tắc >=5 và <5. Nhưng trong VBA, hàm Round làm tròn theo uy ước phân bố thống kê. Chúng ta thấy rằng, từ 0 đến 10 có 11 giá trị, khi đó 5 đứng giữa của khoảng, khi làm tròn nguyên, các giá trị 1.5, 3.5, 5.5, 7.5, 9.5 sẽ được làm tròn len 2, 4, 6, 8, 10. Nhưng các giá trị 0.5, 2.5, 4.5, 6.5, 8.5 sẽ được làm tròn xuống 0, 2, 4, 6, 8 để tạo sự phân bố đều ra 2 phía của khoảng (0..10).

Từ đó, khi dùng hàm làm tròn Round trong VBA để xử lý kết quả trong (E) thì nên dùng hàm sẵn có của (E) thay cho hàm Round của VBA:

WorksheetFunction.Round(...)
 
Upvote 0
Em dùng code còn phát hiện 1 lỗi nữa. Đó là lúc AutoFilter bằng code thì có 1 trường hợp như sau:
Nếu định dạng trong Windows là "d/m/yyyy" và tất nhiên trong Excel vẫn hiểu định dạng này (tức là 31/12/2007 vẫn nằm bên phải, và hàm Month vẫn cho kết quả là 12).
Nhưng nếu ngày nhỏ hơn 12 (1,2,3,...,12) thì khi qua dòng lệnh:
PHP:
Sheet2.Range("B1:M" & HC).AutoFilter Field:=2, Criteria1:=">=" & [G5], Operator:=xlAnd, Criteria2:="<=" & [I5]
Với: [G5]=1/12/2007 và [I5]=10/12/2007
Thì xem lại trong Sheet2 không có dữ liệu. Mặt dù biết rằng vẫn có vùng thời gian này.
Xét đến tận cùng thì phát hiện trong Custom (AutoFilter) nó báo rằng 12/1/2007, 12/10/2007.
Vậy xin hỏi làm sao để có được 1/12/200710/12/2007.
Mọi người có thể tự làm thử. Điều này hình như là luôn đúng nữa rồi.
Thân.
Đây không phải là lỗi đâu Po_Pi ạ. Định dạng ngày tháng trong system không hề ảnh hưởng gì đến VBA. Trong VBA nếu làm việc với kiểu dữ liệu Ngày/Tháng thì nên dùng hàm Date******, còn nếu là kiểu chuỗi thì phải theo định dạng "Tháng/Ngày/Năm" hoặc "Năm/Tháng/Ngày". Tôi vẫn thích dùng theo định dạng "Năm/Tháng/Ngày" hơn.
 
Upvote 0
Em dùng code còn phát hiện 1 lỗi nữa. Đó là lúc AutoFilter bằng code thì có 1 trường hợp như sau:
Nếu định dạng trong Windows là "d/m/yyyy" và tất nhiên trong Excel vẫn hiểu định dạng này (tức là 31/12/2007 vẫn nằm bên phải, và hàm Month vẫn cho kết quả là 12).
Nhưng nếu ngày nhỏ hơn 12 (1,2,3,...,12) thì khi qua dòng lệnh:
PHP:
Sheet2.Range("B1:M" & HC).AutoFilter Field:=2, Criteria1:=">=" & [G5], Operator:=xlAnd, Criteria2:="<=" & [I5]
Với: [G5]=1/12/2007 và [I5]=10/12/2007
Thì xem lại trong Sheet2 không có dữ liệu. Mặt dù biết rằng vẫn có vùng thời gian này.
Xét đến tận cùng thì phát hiện trong Custom (AutoFilter) nó báo rằng 12/1/2007, 12/10/2007.
Vậy xin hỏi làm sao để có được 1/12/200710/12/2007.
Mọi người có thể tự làm thử. Điều này hình như là luôn đúng nữa rồi.
Thân.
Thử sửa lại điều kiện thành:
Criteria1:=">=" & Format([G5], "#")

Criteria2:="<=" & Format([I5], "#")
xem thế nào!
Hoặc:
Criteria1:=">=" & CDbl([G5])
và:
Criteria2:="<=" & CDbl([I5])
 
Lần chỉnh sửa cuối:
Upvote 0
Vâng, em làm được rồi! Cảm ơn hai bác nha.
Thân.
 
Upvote 0
Nhờ các bác viết hộ bài toán đơn giản như sau:
Nếu tại ô H1="Delete" thì xóa toàn bộ dòng đó luôn, áp dụng cho toàn bộ cột H.

Thanks các bác!
 
Upvote 0
Bạn nhấn phải chuột vào tên Sheet -> chọn View Code -> Rồi nạp đoạn code dưới vào trang trắng hiện ra. Rồi bạn thử gõ Delete ở 1 ô nào đó trên cột H xem.
PHP:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
If Target.Column = 8 And Target = "Delete" Then
Target.EntireRow.ClearContents
End If
End Sub
Thân.
 
Upvote 0
Nếu chọn đúng ô có chữ "Delete" thì nó sẽ xóa luôn ô đó và không có gì thay đổi. Nhưng khi Ctrl+Z lại lệnh vừa rồi thì nó lại xóa cả dòng luôn. Còn nếu chọn ô nào khác thì không có gì thay đổi cả.
 
Upvote 0
Vậy thực ra bác muốn như thế nào chứ? Bác toàn viết hiện trạng ra không thì làm sao giải quyết được?
Và yêu cầu cuối là nên đưa file đó lên đi?
Việc xóa dòng đâu nhất thiết phải gõ Delete như vậy? Vì dùng chuột chọn 1 dòng rồi nhấn Delete chẳng phải nhanh hơn không?
Thân.
 
Upvote 0
Mình gửi file đính kèm nhé! Mình muốn xóa bỏ tất cả những dòng bôi hồng đi và sẽ căn cứ theo cột H để xóa (gần như là xóa tiêu đề của mỗi bảng đi vậy). Mình dùng phần mềm để trộn rất nhiều file vào một file vì vậy sẽ có Form rất giống nhau. Nếu mình phải tìm từng dòng một để xóa thì lâu nắm. Bác giữ lại dòng đầu nhé!

Thanks!
 

File đính kèm

Upvote 0
Vậy thì dùng code này đi. Đơn giản là xóa dữ liệu của các dòng đó đi hết là xong chứ gì?
PHP:
Sub xoa()
For i = [H65000].End(xlUp).Row To 1 Step -1
If Cells(i, 8) = "Delete" Then
Rows(i).ClearContents
End If
Next
End Sub
Thân.
 

File đính kèm

Upvote 0
Hi, không phải là xóa dữ liệu mà là xóa cả dòng đó đi luôn. Nhưng bác nhớ để lại dòng đầu tiên lại nhé!
 
Upvote 0
Vầy thì chỉnh lại như vầy ha!
PHP:
Sub xoa()
For i = [H65000].End(xlUp).Row To 2 Step -1
If Cells(i, 8) = "Delete" Then
Rows(i).EntireRow.Delete
End If
Next
End Sub
Thân.
 
Upvote 0
PHP:
Sub xoa()
For i = [H65000].End(xlUp).Row To 2 Step -1
If Cells(i, 8) = "Delete" Then
Rows(i).EntireRow.Delete
End If
Next
End Sub
Macro này còn có thể tăng tốc bằng các cách sau:
* Không cho lay động màn hình; (Phụ :-=)
* Dùng phương thức tìm kiếm, dấu hiệu tìm là từ 'Delete' nêu trên, phạm vi tìm là cột 'H'
Tìm thấy thì gôm vô biến đã khai báo, sau giai đoạn tìm chỉ xóa 1 lần. Riêng chuyện gôm vô rồi xóa 1 lần cũng nhanh hơn là xóa từng hàng như macro trên. (--=0 Chính)
 
Upvote 0
Muốn ngắn hả? Như vầy có ngắn không?
PHP:
Sub xoa()
Range("H1:H" & [H65000].End(xlUp).Row).AutoFilter 1, "Delete"
Range("H2:H" & [H65000].End(xlUp).Row).SpecialCells(12).EntireRow.Delete
End Sub
Thân.
 
Upvote 0
Muốn ngắn hả? Như vầy có ngắn không?
PHP:
Sub xoa()
Range("H1:H" & [H65000].End(xlUp).Row).AutoFilter 1, "Delete"
Range("H2:H" & [H65000].End(xlUp).Row).SpecialCells(12).EntireRow.Delete
End Sub
Thân.
Ngắn hơn nữa:
PHP:
Sub Test()
 Range([H1], [H65536].End(xlUp)).AutoFilter 1, "Delete"
 Range([H1], [H65536].End(xlUp)).SpecialCells(12).EntireRow.Delete
End Sub
Thật ra dùng AutoFilter cho trường hợp này sẽ cho tốc độ rất nhanh ---> Có điều tôi thao tác bằng tay cũng được, cần gì code nhỉ
Này nhé:
- Chọn cell H1, bấm Ctrl + Shift + mũi tên xuống
- Vào menu Data\Filter\AutoFilter
- Bấm mũi tên xổ xuống, chọn chử Delete
- Click phải vào vùng vừa Filter, chọn Delete Row --> OK
Vậy là xong!
Ẹc.. Ẹc...
 
Lần chỉnh sửa cuối:
Upvote 0
Bác test code chưa vậy? Em nghĩ chắc là chưa rồi! hi hihihi
Vì nó xóa luôn dòng đầu tiên mất rồi!
PHP:
Sub Test()
 Range([H1], [H65536].End(xlUp)).AutoFilter 1, "Delete"
 Range([H1], [H65536].End(xlUp)).SpecialCells(12).EntireRow.Delete
End Sub
Sữa lại thành:
PHP:
Sub Test()
 Range([H1], [H65536].End(xlUp)).AutoFilter 1, "Delete"
 Range([H2], [H65536].End(xlUp)).SpecialCells(12).EntireRow.Delete
End Sub
Thân.
 
Upvote 0
Bác test code chưa vậy? Em nghĩ chắc là chưa rồi! hi hihihi
Vì nó xóa luôn dòng đầu tiên mất rồi!
PHP:
Sub Test()
 Range([H1], [H65536].End(xlUp)).AutoFilter 1, "Delete"
 Range([H1], [H65536].End(xlUp)).SpecialCells(12).EntireRow.Delete
End Sub
Sữa lại thành:
PHP:
Sub Test()
 Range([H1], [H65536].End(xlUp)).AutoFilter 1, "Delete"
 Range([H2], [H65536].End(xlUp)).SpecialCells(12).EntireRow.Delete
End Sub
Thân.
Thì dòng đầu cũng có chử Delete ---> Xóa luôn đi chứ để làm gì ---> Nếu H1 không phải là chử Delete thì tính tiếp...
Ẹc...Ẹc...
Ý tôi không phải nói về code (vì lòng vòng vẩn là AutoFilter) ---> Mà tôi muốn nói yêu cầu này quá dể dàng để thao tác bằng tay ---> KHÔNG CẦN CODE
 
Upvote 0
Thì dòng đầu cũng có chử Delete ---> Xóa luôn đi chứ để làm gì ---> Nếu H1 không phải là chử Delete thì tính tiếp...
Ẹc...Ẹc...
Ý tôi không phải nói về code (vì lòng vòng vẩn là AutoFilter) ---> Mà tôi muốn nói yêu cầu này quá dể dàng để thao tác bằng tay ---> KHÔNG CẦN CODE

Theo em nếu là để học code thì ok, nhưng nếu là để phục vụ công việc thì cứ theo nguyên tắc "thơm, ngon, bổ, rẻ" --> sao cho vừa nhanh vừa tiện thôi.
Thực ra làm bằng tay cũng được mà
 
Upvote 0
Xin hỏi trong cửa sổ VBA (Alt+F11) có chế độ nào tự động mở không. Không hiểu sao mỗi lần mở máy (sau khi đã khóa máy) thì cửa sổ của VBA luôn luôn hiên lên mặc dù trước đó không hề mở. Có cách nào để bỏ nó đi không các bác?? (nghĩa là cửa sổ VBA không tự động mở mỗi lần mở máy nữa)
 
Upvote 0
xin hỏi cách tạo code để chống move va copy làm như thế nào, xin hướng dẫn cụ thể vì tôi mới vào nghề excel. thanks...
 
Upvote 0
Xin hỏi về định dạng sau số thập phân

Chào anh, chị
Khi mình thực hiện phép nhân (*) trong VBA. Thì VBA tự đọng làm tròn số đàng sau số thập phân
VD: Giá trị trên sheets.cells(1,1)=0.23
thực hiện trong code:
sheets.cells(1,1) * 1000= 0 ??
Dù format hoặc chuyển dịnh dạng nhưng kết quả vẫn =0
Mong anh chị chỉ dùm lỗi ở đâu?

Chân thành cám ơn
 
Upvote 0
Chào anh, chị
Khi mình thực hiện phép nhân (*) trong VBA. Thì VBA tự đọng làm tròn số đàng sau số thập phân
VD: Giá trị trên sheets.cells(1,1)=0.23
thực hiện trong code:
sheets.cells(1,1) * 1000= 0 ??
Dù format hoặc chuyển dịnh dạng nhưng kết quả vẫn =0
Mong anh chị chỉ dùm lỗi ở đâu?

Chân thành cám ơn
Tôi thí nghiệm thấy đúng mà!
PHP:
Sub Test()
 [B1] = [A1] * 1000
End Sub
</b>
Với A1 = 0.23 thì B1 = 230
Có lẻ dử liệu của bạn đang sai chổ nào ấy chứ ---> Đưa lên xem thử
 
Upvote 0
Chắc có lẽ cách viết code có lỗi gì đó, Bạn xem giùm theo File đính kèm
http://www.zshare.net/download/57316693d8fec3de/
http://myfreefilehosting.com/f/fd51510eee_0.01MB

Cells(i, 3) = DateDiff("m", .Cells(1, 8), .Cells(1, 9))
Cells(1, 8) thì = Cells(1, 9)
==> DateDiff("m", .Cells(1, 8), .Cells(1, 9)) phải luôn =0
==> .Cells(1, 11) = Hsluong * tlBHXH * .Cells(i, 3) * .Cells(i, 4) đương nhiên cũng = 0 là đúng rồi còn gì
--------
Thêm nữa, trong code có nhiều chổ hơi khó hiểu, ví dụ:
1> Thứ nhất
Bạn định nghĩa:
Ma1 = WorksheetFunction.Match(.Cells(1, 8), rng, 1)
Ma2 = WorksheetFunction.Match(.Cells(1, 9), rng, 1)

Mà trong code lại có đoạn
If Ma1 = Ma2 Then
vậy cần gì vòng lập FOR ---> Vì đàng nào cũng chỉ xét có 1 vị trí ---> 2 Mã này bằng nhau khi Cells(1, 8) = Cells(1, 9)
2> Thứ hai:
Hsluong = .Cells(1, 10) = 0.33 ---> Vậy sao bạn lại khai báo biến Hsluong As Integer được chứ ---> Lý ra phải là Hsluong As Double (Integer là số nguyên cơ mà)
--------
Bạn hãy nói rõ bạn đang cần tính cái gì? Tính như thế nào? Chúng ta sẽ sửa lại code đúng ý đồ của bạn
(tôi nghĩ bài toán này không cần khai báo biến nhiều đến thế)
 
Upvote 0
Lần chỉnh sửa cuối:
Upvote 0
Cám ơn bạn

Mình đang tạo thủ tục theo yêu cầu của bài này
hiện đã viết được sub tạm ưng ý nhưng muốn chuyển thanh UDF để tiện sử dụng nhưng không được.
Mong bạn có thể sửa dùm và sửa giúp mình thủ tục tại File đính kèm theo link dưới:

http://myfreefilehosting.com/f/f0fa46e729_0.01MB

Chân thành cám ơn.
Ai dà... file thì tải không được (báo lổi)... còn topic kia tôi có xem qua nhưng quả thật chưa hiểu gì lắm yêu cầu của bạn (có lẻ không phải chuyên ngành)
----> Nhờ các cao thủ khác giúp 1 tay với!
 
Lần chỉnh sửa cuối:
Upvote 0
Chuyển thủ tục sau thành UDF như thế nào?

Mã:
 Tinhnop1()
Dim i As Long, Ma1 As Long, Ma2 As Long
Dim rng As Range
Dim HSL As Double, TL As Double
With Sheets(1)
HSL = .Cells(1, 10) ' 
TL = .Cells(1, 11)
Set rng = .Range("A1:A" & [A65000].End(xlUp).Row) ' Vung luong toi thieu
rng.Offset(, 2).ClearContents
Ma1 = WorksheetFunction.Match(.Cells(1, 8), rng, 1) ' s.cells(1,8) cua Tu thang
Ma2 = WorksheetFunction.Match(.Cells(1, 9), rng, 1) ' S.cells(1,8) den thang
        If Ma1 = Ma2 Then
            .Cells(Ma1, 3) = DateDiff("m", .Cells(1, 8), .Cells(1, 9))
            .Cells(Ma1, 4) = .Cells(Ma1, 3) * HSL * TL * .Cells(Ma1, 2)
        Else
        'Sua Dk dau de cho dung voi thoi gian Tuthang
            .Cells(Ma1, 3) = DateDiff("m", .Cells(1, 8), .Cells(Ma1 + 1, 1))
            .Cells(Ma1, 4) = .Cells(Ma1, 3) * HSL * TL * .Cells(Ma1, 2)
 
        For i = Ma1 + 1 To Ma2
            'Chay vong lap tinh thang cua cac moc trong khoang ma1 - ma2
            .Cells(i, 3) = DateDiff("m", .Cells(i, 1), .Cells(i + 1, 1))
            .Cells(i, 4) = .Cells(i, 3) * HSL * TL * .Cells(i, 2)
        Next
            'Sua Dk cuoi de cho dung voi thoi gian Denthang
            .Cells(Ma2, 3) = DateDiff("m", .Cells(Ma2, 1), .Cells(1, 9))
            .Cells(Ma2, 4) = .Cells(Ma2, 3) * HSL * TL * .Cells(Ma2, 2)
        End If
End With
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Upvote 0
Cám ơn sự nhiệt tình của các bác.
Thực sự là do up trực tiếp lên không được, nhờ các anh chi trên diễn đàn mình đã Upload được File
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Mọi người chỉ giáo giùm cách viết code trong excel và Word có khác nhau nhiều không. Mình có đoạn code tự record như sau:
Sub Macro1()
CommandBars("Stop Recording").Visible = False
Selection.TypeParagraph
Selection.MoveDown Unit:=wdLine, Count:=1
Selection.HomeKey Unit:=wdLine
End Sub

Code này chỉ chạy trên file word hiện hành. Các bác có thể sửa giúp để marco có thể chạy trên tất cả các file word đang mở được không. Thanks nhiều!
 
Upvote 0
Mình muốn bảng tính tự động cố định cột và dòng tại P4 nên đã dùng
PHP:
Private Sub worksheet_selectionchange(ByVal Target As Range)
...
[P4].Select: ActiveWindow.FreezePanes = True
...
end sub
Nhưng ngoài tác dụng cố định cột và dòng thì chẳng còn làm được gì nữa vì con trỏ luôn nhảy về P4. Nhờ các bạn giúp mình sửa lại câu lệnh này. Thank !
 
Upvote 0
Nhưng ngoài tác dụng cố định cột và dòng thì chẳng còn làm được gì nữa vì con trỏ luôn nhảy về P4
Nó cứ nhảy về P4 là đúng rồi.

Cái việc freeze pane chỉ làm 1 lần cho 1 sheet trong 1 lần mở file, thậm chí để nguyên như vậy mà xài mãi mãi đến khi chán mới thôi. Bạn lại cho nó vào sự kiện selection_change (thay đổi ô chọn)! Thử hỏi bạn làm việc gì với excel mà cả ngày không thay đổi ô chọn (selection)?

Cứ mỗi lần bạn thay đổi ô chọn, code chạy 1 lần, trong code lại có câu lệnh [P4].Select thì anh Bill biết làm gì khác hơn là chạy về P4 ngồi?
 
Upvote 0
Vì một lý do là ngay trên đường freezepanes tôi dùng Calendar1 để nhập ngày tháng và dưới đường này có một dòng ẩn vì vậy Calendar1 bị co lại không sử dụng được nếu bỏ freezepanes thì OK.
Vì vậy tôi định dùng giải pháp khi Calendar1 được gọi ra thì cũng đồng thời freezepanes = false và sau khi Click Calendar1 thì freezepanes = True và sau đó di chuyển con trỏ đến ô khác thì freezepanes vẫn luôn = True
PHP:
Private Sub worksheet_selectionchange(ByVal Target As Range)
       With Target
            Calendar1.Visible = (Not Intersect([L2:AU2], Target) Is Nothing)
            Calendar1.Top = .Top: Calendar1.Left = .Offset(5, 1).Left
            Calendar1.Width = 130
            Calendar1.Height = 110
            ActiveWindow.FreezePanes = False
        End With
End sub
Private Sub Calendar1_Click()
        Selection.Value = Calendar1
        Calendar1.Visible = False
        [P4].Select: ActiveWindow.FreezePanes = True
  End With
End Sub
Tôi nghĩ nó luôn nhảy về P4 bởi tại P4.Select tôi đã thử bỏ .Select nhưng không bỏ được. Vì vậy tôi muốn hỏi:

1- Có câu lệnh nào khác [P4].Select: ActiveWindow.FreezePanes = True
(với ý tưởng con trỏ không nhảy về P4 nhưng vẫn thực hiện được freezepanes tại P4)

2- Có cách nào để Calendar1 xuất hiện cách [L2:AU2] khoảng 2 dòng (để nó nằm dưới đường FreezePanes).
Thank !
 
Upvote 0
Xin các bạn chỉ dùm tôi cách tạo phím tắt bằng một đoạn code
vd: Ctrl+Shift+M là "Merge and center"
Ctrl+Alt+F là "Fill color"
Cám ơn nhiều nhé
 
Upvote 0
Tôi chưa tìm ra cách bỏ cái [P4].Select, nhưng cũng chưa tìm ra cách thay thế để calendar không bị che khuất.
Vậy hãy dùng tạm bằng cách nới chiều cao dòng 2 hoặc dòng 3 lên cho đủ chiều cao của cái calendar
 
Upvote 0
Tôi chưa tìm ra cách bỏ cái [P4].Select, nhưng cũng chưa tìm ra cách thay thế để calendar không bị che khuất.
Vậy hãy dùng tạm bằng cách nới chiều cao dòng 2 hoặc dòng 3 lên cho đủ chiều cao của cái calendar

Thanks ptm0412 ! Tôi sẽ dùng tạm cách của bạn cho đến khi có một giải pháp mới. Mong rằng bạn sẽ nhanh chóng quay lại chủ đề này.
 
Upvote 0
Thanks ptm0412 ! Tôi sẽ dùng tạm cách của bạn cho đến khi có một giải pháp mới. Mong rằng bạn sẽ nhanh chóng quay lại chủ đề này.
Tôi nghĩ anh nên cho Freeze Panes mặc định tại P4 luôn (khỏi cho vào code)
Việc còn lại là chỉnh Calendar sao cho đỉnh của nó luôn nằm tại P4, tức nằm dưới đường vạch của Freeze Panes ---> Vậy là không bị che rồi
giờ tôi giã định rằng Freeze Panes đã được thiệt lập sẳn tại cell P4, ta sửa code lại thành:
PHP:
Private Sub worksheet_selectionchange(ByVal Target As Range)
  Dim ScrRng As Range
  With ActiveWindow
    Set ScrRng = ActiveSheet.Cells(.ScrollRow, .ScrollColumn)
  End With
  With Target
    Calendar1.Visible = (Not Intersect([L2:AU2], Target) Is Nothing)
    Calendar1.Top = ScrRng.Top: Calendar1.Left = ScrRng.Left
    Calendar1.Width = 130
    Calendar1.Height = 110
  End With
End Sub
PHP:
Private Sub Calendar1_Click()
  Selection.Value = Calendar1
  Calendar1.Visible = False
End Sub
Lưu ý: Nếu Freeze Panes chưa được thiết lập thì Calendar sẽ "nhảy" đến cell A1
Tham khảo về Freeze Panes tại bài này:
http://www.giaiphapexcel.com/forum/showthread.php?t=19651
 
Upvote 0
Cảm ơn ndu sáng nay mất điện bây giờ mới xem được bài, Tôi đã test thử cách của bạn kết quả OK.

Trước khi bạn giúp tôi phải dùng hạ sách là cho vùng chọn xuống dưới đường vạch của Freeze Panes
(đổi L2:AU2 -> L4:AU4)sau đó selection.offset(-2,0).Value = Calendar1 kết quả cũng được nhưng người khác thì làm sao biết mà dùng.

Tôi cũng đã xem qua các bài theo đường link của bạn, thì ra vấn đề Freeze Panes không đơn giản chút nào.
 
Lần chỉnh sửa cuối:
Upvote 0
Save and Exit

thanhnhanubnd đã viết:
Nhờ bạn viết dùm mình code để liên kết 2 file excel :
- File A có 01 form, có nút để đóng, lưu file A và mở file B.
- File B tương tự.
- Làm sao để bỏ qua mọi masgbox.
Thank.

Có phải ý bạn muốn thế này không? Xem file
rar.gif
MyFolder.rar (16.1 KB)​
 

File đính kèm

Upvote 0
Từ câu lệnh chọn 2 vùng không liên tục: Range("K8:O28,T8:Y28").Select
Tôi muốn thay số dòng cuối 28 trong câu lệnh này thành & [F65536].End(xlUp).Row + 1 thì phải viết như thế nào ?

Nếu viết là Range("K8:O" & [F65536].End(xlUp).Row + 1, "T8:Y" & [F65536].End(xlUp).Row + 1).Select thì máy chấp nhận nhưng nó chọn luôn 2 vùng thành 1. Nhờ các bạn chỉ giúp chỗ sai trong câu lệnh hoặc viết lại giúp câu lệnh, Thanks!
 
Upvote 0
Từ câu lệnh chọn 2 vùng không liên tục: Range("K8:O28,T8:Y28").Select
Tôi muốn thay số dòng cuối 28 trong câu lệnh này thành & [F65536].End(xlUp).Row + 1 thì phải viết như thế nào ?

Nếu viết là Range("K8:O" & [F65536].End(xlUp).Row + 1, "T8:Y" & [F65536].End(xlUp).Row + 1).Select thì máy chấp nhận nhưng nó chọn luôn 2 vùng thành 1. Nhờ các bạn chỉ giúp chỗ sai trong câu lệnh hoặc viết lại giúp câu lệnh, Thanks!
Anh dùng thử cái này xem:
PHP:
Union(Range("K8:O" & [F65536].End(xlUp).Row + 1), Range("T8:Y" & [F65536].End(xlUp).Row + 1)).Select
Hoặc
PHP:
With Range("K8:O" & [F65536].End(xlUp).Row + 1)
    Union(.Cells, .Offset(, 9)).Select
End With
 
Lần chỉnh sửa cuối:
Upvote 0
Anh dùng thử cái này xem:
PHP:
With Range("K8:O" & [F65536].End(xlUp).Row + 1)
    Union(.Cells, .Offset(, 9)).Select
End With

@ ndu: Cái này nó chọn được 2 vùng riêng biệt nhưng số cột vùng 1 luôn bằng số cột vùng 2. Cách khắc phục. Thanks!
 
Upvote 0
@ ndu: Cái này nó chọn được 2 vùng riêng biệt nhưng số cột vùng 1 luôn bằng số cột vùng 2. Cách khắc phục. Thanks!
Vùng 2 là chổ .Offset(,9) ---> Mặc định nó có số cột = số cột vùng 1 ---> Nếu anh muốn thay đổi số cột thì them Resize vào
Ví dụ: .Offset(,9).Resize(,6) ---> Sẽ chỉnh vùng 2 thành 6 cột
 
Upvote 0
Khi làm việc trên sheet hiện hành thì câu lệnh như sau:
PHP:
Sub Macro1()
 Range("F3:F26").Select   
 Selection = "=SUM(RC[-3]:RC[-1])"
 Selection.Value = Selection.Value
End Sub
Nếu muốn làm tương tự cho một sheet khác (không phải sheet hiện hành hoặc có thể là sheet ẩn) thì viết như thế nào ? Mục đích dùng Selection là để xoá công thức

Thanks!
 
Lần chỉnh sửa cuối:
Upvote 0
Khi làm việc trên sheet hiện hành thì câu lệnh như sau:
PHP:
Sub Macro1()
 Range("F3:F26").Select   
 Selection = "=SUM(RC[-3]:RC[-1])"
 Selection.Value = Selection.Value
End Sub
Nếu muốn làm tương tự cho một sheet khác (không phải sheet hiện hành hoặc có thể là sheet ẩn) thì viết như thế nào ? Mục đích dùng Selection là để xoá công thức

Thanks!
Ý anh là sao? Có phải anh đang nói đến trường hợp vùng dử liệu nằm ở sheet khác, còn vùng đặt kết quả lại nằm ở 1 sheet khác?
Vậy thì anh ghi thêm tên sheet vào nữa là được!
Ví dụ: Vùng dử liệu nằm tại sheet 2, C3:E26 .. Cò vùng cần đặt kết quả là Sheet1, F3:F26 ---> Anh viết code như sau:
PHP:
Sub Macro1()
 With Sheet1.Range("F3:F26")
  .Value = "=SUM(Sheet2!RC[-3]:RC[-1])"
  .Value = .Value
 End With
End Sub
Ghi tên sheet rõ ràng để có thể đúng bất cứ nơi đâu gọi macro cũng cho kết quả chính xác...
Thêm nữa: Hạn chế vụ Select, nếu không sẽ bị lổi khi anh đang ở 1 sheet, lại đi select 1 sheet đang ẩn
 
Lần chỉnh sửa cuối:
Upvote 0
Cảm ơn ndu: ý mình hỏi là làm thế nào để từ hiện hành (vd đang ở sheet2) mà vẫn thực hiện được trên sheet khác không mở hoặc ẩn (vd sheet1 đang ẩn) mà ra được kết quả như đoạn code trên và đúng như bạn nhắc nhở: đang ở sheet2 tôi muốn xoá công thức ở sheet1 bằng cách dùng selection thì bị lỗi select.

Với đoạn code của bạn tôi chỉ sửa "=SUM(Sheet2!RC[-3]:RC[-1])" -> "=SUM(Sheet1!RC[-3]:RC[-1])" hoặc bỏ Sheet1! -> "=SUM(RC[-3]:RC[-1])" là OK.

Tôi thấy kiểu viết này code chạy cực nhanh (có thể gọi là siêu tốc), tôi đã thử với 10 cột và 65.536 dòng chỉ mất khoảng 0,4 giây.

Điểm mấu chốt ở đây chính là ta đã thực hiện đồng thời gán công thức vào tất cả các ô trong vùng chọn (thay vì dùng vòng lặp quét để gán công thức cho từng ô như vẫn thường làm).

PHP:
Sub Macro1()
    startTime = Timer
        With Sheet1.Range("L3:L65536")
        .Value = "=SUM(RC[-10]:RC[-1])" 
        .Value = .Value
        End With
    EndTime = Timer
    MsgBox "Total Time: " & (EndTime - startTime)
End Sub
 
Upvote 0
Tôi xem bài này http://www.giaiphapexcel.com/forum/showthread.php?t=13005
thấy có nhiều câu từ rất lạ (không thấy trong Macro bao giờ) Tôi muốn nhờ các bạn dịch nôm theo từng dòng xen kẽ (nôm na dòng code đó nói gì). Đặc biệt những từ tôi không hiểu là những từ được tô đậm, màu đỏ. Thanks !

Mã:
Option Explicit
Sub SelectExpandSelectionToLastUsedRow() 
 Dim lRow As Long, Rng As Range    
 If WorksheetFunction.CountA(Cells) > 0 Then 
    Set Rng = Selection 
    lRow = Cells.Find([B][COLOR=Red]What[/COLOR][/B]:="*", [B][COLOR=Red]After[/COLOR][/B]:=Cells(1, 1), Search[COLOR=Red][B]Order[/B][/COLOR]:=[COLOR=Red][B]xlByRows[/B][/COLOR], _ 
        Search[COLOR=Red][B]Direction[/B][/COLOR]:=[B][COLOR=Red]xlPrevious[/COLOR][/B]).Row 
    Set Rng = Rng.Resize(lRow, Rng.Columns.Count)             
    lRow = Rng.Find(What:="*", After:=Rng.Cells(1, 1), SearchOrder:=xlByRows, _ 
        SearchDirection:=xlPrevious).Row 
    Rng.Resize(lRow - Rng.Cells(1, 1).Row + 1, Rng.Columns.Count).Select 
 End If 
End Sub
 
Upvote 0
http://giaiphapexcel.com/forum/showthread.php?t=15116

Tôi xem bài này http://www.giaiphapexcel.com/forum/showthread.php?t=13005
thấy có nhiều câu từ rất lạ (không thấy trong Macro bao giờ) Tôi không hiểu là những từ được tô đậm, màu đỏ. Thanks !
Mã:
    lRow = Cells.Find([B][COLOR=Red]What[/COLOR][/B]:="*", [B][COLOR=Red]After[/COLOR][/B]:=Cells(1, 1), Search[COLOR=Red][B]Order[/B][/COLOR]:=[COLOR=Red][B]xlByRows[/B][/COLOR], _ 
        Search[COLOR=Red][B]Direction[/B][/COLOR]:=[B][COLOR=Red]xlPrevious[/COLOR][/B]).Row

Bạn đến đây & nghiền ngẫn tự ên nha!
 
Upvote 0
Tôi xem bài này http://www.giaiphapexcel.com/forum/showthread.php?t=13005
thấy có nhiều câu từ rất lạ (không thấy trong Macro bao giờ) Tôi muốn nhờ các bạn dịch nôm theo từng dòng xen kẽ (nôm na dòng code đó nói gì). Đặc biệt những từ tôi không hiểu là những từ được tô đậm, màu đỏ. Thanks !

Mã:
Option Explicit
Sub SelectExpandSelectionToLastUsedRow() 
 Dim lRow As Long, Rng As Range    
 If WorksheetFunction.CountA(Cells) > 0 Then 
    Set Rng = Selection 
    lRow = Cells.Find([B][COLOR=Red]What[/COLOR][/B]:="*", [B][COLOR=Red]After[/COLOR][/B]:=Cells(1, 1), Search[COLOR=Red][B]Order[/B][/COLOR]:=[COLOR=Red][B]xlByRows[/B][/COLOR], _ 
        Search[COLOR=Red][B]Direction[/B][/COLOR]:=[B][COLOR=Red]xlPrevious[/COLOR][/B]).Row 
    Set Rng = Rng.Resize(lRow, Rng.Columns.Count)             
    lRow = Rng.Find(What:="*", After:=Rng.Cells(1, 1), SearchOrder:=xlByRows, _ 
        SearchDirection:=xlPrevious).Row 
    Rng.Resize(lRow - Rng.Cells(1, 1).Row + 1, Rng.Columns.Count).Select 
 End If 
End Sub
Cái đó là chức năng Find (trong menu Edit) của Excel thôi anh à!
Anh Record macro quá trình tìm kiếm (bằng Ctrl + F) sẽ thấy
 
Upvote 0
Mình mới học VBA nên còn nhiều chỗ chưa hiểu được. Nhờ các bạn kiểm tra giúp minh cái code này, mình chạy thử cứ đến dòng "đánh đấu" là lỗi.

ActiveSheet.Calculate
n = Range("b4").Value
Sec1:
For i = 8 To n + 7
If Range("H" & i).Value = "C" Then heso = 0.013 Else If Range("H" & i).Value = "CI" Then heso = 0.012 Else heso = 0.011
qdv = Range("K3").Value / Range("D4").Value
q1 = qdv * Range("F" & i).Value
Next
GoTo Congtron

Congtron:
flag = 0
Dk = Range("K" & i) / 10
doday = 0.95
step = 0.05
Slope = Range("O" & i)
Suite3:
X = 2 * doday - 1
X = Atn(X / Sqr(-X * X + 1))
alpha = (X + 3.1416 / 2) * 180 / 3.1416
Pr = alpha * 3.1416 * Dk / 100 / 180
a = (alpha * 3.1416 * 2 / 180 - Sin(2 * 3.1416 * alpha / 180)) / 8 * Dk ^ 2 / 100 ^ 2
Rh = a / Pr
lamda = 2.5 * heso ^ 0.5 - 0.13 - 0.75 * Rh ^ 0.5 * (heso ^ 0.5 - 0.1)
V2 = Sqr(Rh * Slope / 1000) * Rh ^ lamda / heso
q2 = a * V2
If flag = 1 Then GoTo Suite1
If q1 > q2 Then GoTo modif
GoTo Suite2
Suite1:
If q1 < q2 Then GoTo Suite2
doday = doday + step
step = step / 10
Suite2:
flag = 1
doday = doday - step
If step > 0.0001 Then GoTo Suite3
Range("Q" & i) = doday
GoTo Sec2
modif:
Range("K" & i).Select
UserForm1.Show
Sec2:
For i = 8 To n + 7
Range("I" & i).Value = qdv
Range("J" & i).Value = q1
Range("M" & i).Value = doday * Range("K" & i)
Range("N" & i).Value = V2
Range("P" & i).Value = (Range("O" & i).Value * Range("D" & i).Value) / 1000
Next
GoTo Fin
Fin:
End Sub
 
Upvote 0
Mình mới học VBA nên còn nhiều chỗ chưa hiểu được. Nhờ các bạn kiểm tra giúp minh cái code này, mình chạy thử cứ đến dòng "đánh đấu" là lỗi.

ActiveSheet.Calculate
n = Range("b4").Value
Sec1:
For i = 8 To n + 7
If Range("H" & i).Value = "C" Then heso = 0.013 Else If Range("H" & i).Value = "CI" Then heso = 0.012 Else heso = 0.011
qdv = Range("K3").Value / Range("D4").Value
q1 = qdv * Range("F" & i).Value
Next
GoTo Congtron

Congtron:
flag = 0
Dk = Range("K" & i) / 10
doday = 0.95
step = 0.05
Slope = Range("O" & i)
Suite3:
X = 2 * doday - 1
X = Atn(X / Sqr(-X * X + 1))
alpha = (X + 3.1416 / 2) * 180 / 3.1416
Pr = alpha * 3.1416 * Dk / 100 / 180
a = (alpha * 3.1416 * 2 / 180 - Sin(2 * 3.1416 * alpha / 180)) / 8 * Dk ^ 2 / 100 ^ 2
Rh = a / Pr
lamda = 2.5 * heso ^ 0.5 - 0.13 - 0.75 * Rh ^ 0.5 * (heso ^ 0.5 - 0.1)
V2 = Sqr(Rh * Slope / 1000) * Rh ^ lamda / heso
q2 = a * V2
If flag = 1 Then GoTo Suite1
If q1 > q2 Then GoTo modif
GoTo Suite2
Suite1:
If q1 < q2 Then GoTo Suite2
doday = doday + step
step = step / 10
Suite2:
flag = 1
doday = doday - step
If step > 0.0001 Then GoTo Suite3
Range("Q" & i) = doday
GoTo Sec2
modif:
Range("K" & i).Select
UserForm1.Show
Sec2:
For i = 8 To n + 7
Range("I" & i).Value = qdv
Range("J" & i).Value = q1
Range("M" & i).Value = doday * Range("K" & i)
Range("N" & i).Value = V2
Range("P" & i).Value = (Range("O" & i).Value * Range("D" & i).Value) / 1000
Next
GoTo Fin
Fin:
End Sub
 
Upvote 0
Cảm ơn Bác HYen: đọc mãi mới hiểu là Bác chỉ bài theo đường link này http://giaiphapexcel.com/forum/showthread.php?t=15116

Loạt bài này em đã xem qua khi mới đăng nhưng không nhớ ra, em sẽ nghiên cứu tiếp nếu có gì chưa hiểu Bác lại giúp em nha.
 
Upvote 0
Em có viết đoạn code tra bảng nội suy bảng 2 chiều nhưng không hiểu sao nó không chạy nữa. Cái bảng này của e nó lại khác kiểu so với các ví dụ đã có ở diến đàn. Mong các bác kiểm tra giúp em. Em xin chân thành cảm ơn. Chúc các bác và gia đình luôn mạnh khỏe.
Đoạn Code như sau:

Function CalE(vungtra As Range, R As Double, V As Double) As Double
'Ham noi suy gia tri e tu R va V cho truoc
Dim ktra As Boolean
Dim i As Integer
Dim r1 As Double, r2 As Double, e1 As Double, e2 As Double
For i = 1 To vungtra.Cells.Count
kiemtra = False
Select Case V
Case V = 20
If vungtra.Cells(i, 2) >= R And vungtra.Cells(i + 1, 2) <= R Then
r1 = vungtra.Cells(i, 2): r2 = vungtra.Cells(i + 1, 2)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 30
If vungtra.Cells(i, 3) >= R And vungtra.Cells(i + 1, 3) <= R Then
r1 = vungtra.Cells(i, 3): r2 = vungtra.Cells(i + 1, 3)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 40
If vungtra.Cells(i, 4) >= R And vungtra.Cells(i + 1, 4) <= R Then
r1 = vungtra.Cells(i, 4): r2 = vungtra.Cells(i + 1, 4)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 50
If vungtra.Cells(i, 5) >= R And vungtra.Cells(i + 1, 5) <= R Then
r1 = vungtra.Cells(i, 5): r2 = vungtra.Cells(i + 1, 5)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 60
If vungtra.Cells(i, 6) >= R And vungtra.Cells(i + 1, 6) <= R Then
r1 = vungtra.Cells(i, 6): r2 = vungtra.Cells(i + 1, 6)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 70
If vungtra.Cells(i, 7) >= R And vungtra.Cells(i + 1, 7) <= R Then
r1 = vungtra.Cells(i, 7): r2 = vungtra.Cells(i + 1, 7)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 80
If vungtra.Cells(i, 8) >= R And vungtra.Cells(i + 1, 8) <= R Then
r1 = vungtra.Cells(i, 8): r2 = vungtra.Cells(i + 1, 8)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 90
If vungtra.Cells(i, 9) >= R And vungtra.Cells(i + 1, 9) <= R Then
r1 = vungtra.Cells(i, 9): r2 = vungtra.Cells(i + 1, 9)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 100
If vungtra.Cells(i, 10) >= R And vungtra.Cells(i + 1, 10) <= R Then
r1 = vungtra.Cells(i, 10): r2 = vungtra.Cells(i + 1, 10)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 110
If vungtra.Cells(i, 11) >= R And vungtra.Cells(i + 1, 11) <= R Then
r1 = vungtra.Cells(i, 11): r2 = vungtra.Cells(i + 1, 11)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 120
If vungtra.Cells(i, 12) >= R And vungtra.Cells(i + 1, 12) <= R Then
r1 = vungtra.Cells(i, 12): r2 = vungtra.Cells(i + 1, 12)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 130
If vungtra.Cells(i, 13) >= R And vungtra.Cells(i + 1, 13) <= R Then
r1 = vungtra.Cells(i, 13): r2 = vungtra.Cells(i + 1, 13)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
End Select
End Function
 

File đính kèm

Upvote 0
Các bác ơi
Em xin hỏi là khi nào mình dùng đến Set
ví dụ
Dim Rng As Range
Set Rng = Application.InputBox _

nếu dùng thế cuối đoạn code có cần set lại = nothing không?

-----
Em đã search lại nhưng ko thấy, mạn phép hỏi lại

Thanks các bác
 
Upvote 0
Các bác ơi
Em xin hỏi là khi nào mình dùng đến Set
ví dụ


nếu dùng thế cuối đoạn code có cần set lại = nothing không?

-----
Em đã search lại nhưng ko thấy, mạn phép hỏi lại

Thanks các bác
Theo chổ tôi biết thì Set thường dùng để khai báo 1 vùng hoặc 1 Object (gần giống Define name ấy)
Còn chuyện Set... = nothing thì... tùy thói quen... Tôi thấy cũng chẳng cần, sau khi chạy xong code, biến sẽ tự giải phóng khỏi bộ nhớ (Nếu biến nằm dưới tên Sub)
Bạn xem bài này:
http://www.giaiphapexcel.com/forum/showpost.php?p=94013&postcount=12
 
Upvote 0
Em có viết đoạn code tra bảng nội suy bảng 2 chiều nhưng không hiểu sao nó không chạy nữa. Cái bảng này của e nó lại khác kiểu so với các ví dụ đã có ở diến đàn. Mong các bác kiểm tra giúp em. Em xin chân thành cảm ơn. Chúc các bác và gia đình luôn mạnh khỏe.
Đoạn Code như sau:

Function CalE(vungtra As Range, R As Double, V As Double) As Double
'Ham noi suy gia tri e tu R va V cho truoc
Dim ktra As Boolean
Dim i As Integer
Dim r1 As Double, r2 As Double, e1 As Double, e2 As Double
For i = 1 To vungtra.Cells.Count
kiemtra = False
Select Case V
Case V = 20
If vungtra.Cells(i, 2) >= R And vungtra.Cells(i + 1, 2) <= R Then
r1 = vungtra.Cells(i, 2): r2 = vungtra.Cells(i + 1, 2)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 30
If vungtra.Cells(i, 3) >= R And vungtra.Cells(i + 1, 3) <= R Then
r1 = vungtra.Cells(i, 3): r2 = vungtra.Cells(i + 1, 3)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 40
If vungtra.Cells(i, 4) >= R And vungtra.Cells(i + 1, 4) <= R Then
r1 = vungtra.Cells(i, 4): r2 = vungtra.Cells(i + 1, 4)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 50
If vungtra.Cells(i, 5) >= R And vungtra.Cells(i + 1, 5) <= R Then
r1 = vungtra.Cells(i, 5): r2 = vungtra.Cells(i + 1, 5)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 60
If vungtra.Cells(i, 6) >= R And vungtra.Cells(i + 1, 6) <= R Then
r1 = vungtra.Cells(i, 6): r2 = vungtra.Cells(i + 1, 6)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 70
If vungtra.Cells(i, 7) >= R And vungtra.Cells(i + 1, 7) <= R Then
r1 = vungtra.Cells(i, 7): r2 = vungtra.Cells(i + 1, 7)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 80
If vungtra.Cells(i, 8) >= R And vungtra.Cells(i + 1, 8) <= R Then
r1 = vungtra.Cells(i, 8): r2 = vungtra.Cells(i + 1, 8)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 90
If vungtra.Cells(i, 9) >= R And vungtra.Cells(i + 1, 9) <= R Then
r1 = vungtra.Cells(i, 9): r2 = vungtra.Cells(i + 1, 9)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 100
If vungtra.Cells(i, 10) >= R And vungtra.Cells(i + 1, 10) <= R Then
r1 = vungtra.Cells(i, 10): r2 = vungtra.Cells(i + 1, 10)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 110
If vungtra.Cells(i, 11) >= R And vungtra.Cells(i + 1, 11) <= R Then
r1 = vungtra.Cells(i, 11): r2 = vungtra.Cells(i + 1, 11)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 120
If vungtra.Cells(i, 12) >= R And vungtra.Cells(i + 1, 12) <= R Then
r1 = vungtra.Cells(i, 12): r2 = vungtra.Cells(i + 1, 12)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
Case V = 130
If vungtra.Cells(i, 13) >= R And vungtra.Cells(i + 1, 13) <= R Then
r1 = vungtra.Cells(i, 13): r2 = vungtra.Cells(i + 1, 13)
e1 = vungtra.Cells(i, 1): e2 = vungtra.Cells(i + 1, 1)
CalE = (e2 - e1) * (r1 - R) / (r1 - r2) + e1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
End Select
End Function

Ôi không bác nào giúp em sao?
 
Upvote 0
Các bác ơi Em xin hỏi là khi nào mình dùng đến Set
ví dụ

nếu dùng thế cuối đoạn code có cần set lại = nothing không?
-----

Có khi đến giữa chừng của chương trình, nhưng muốn xài biến đối tượng đó vô việc khác thì ta cũng nên Set nó thành Nothing Với ví dụ sau:
PHP:
 Dim Rng As Range, sRng As Range
 Set Rng= Range([A2, [B3].End(xlDown))
 Set sRng= Rng.FIND("GPE", , , xlPart)
' . . . . . . . . '
' Để xài việc nữa, ta nên '
 
Set Rng = Nothing
' Sau đó lại '
 Set Rng= Union(sRng, cRng) ' . . . . ' 
 
' . . . . . . . . '
End Sub

Bạn xem ví dụ cụ thể sau:
PHP:
Sub ColorAndCopy()
 Dim Sh As Worksheet:                     Dim MyAdd As String
 Dim Rng As Range, sRng As Range, cRng As Range
 Dim jJ As Long, eRw As Long
 
1 ' Add Font Color Or Interior Color '
 Set Sh = Sheets("SP")
 Set Rng = Sh.Range(Sh.[c10], Sh.[c65500].End(xlUp))
 Sheets("PM").Select:         eRw = [d65500].End(xlUp).Row
 For jJ = 2 To eRw
   With Cells(jJ, "G")
      If .Value <> "" Then
         Set sRng = Rng.Find(.Value, , xlFormulas, xlWhole)
         If Not sRng Is Nothing Then
            MyAdd = sRng.Address
            Do
               sRng.Font.ColorIndex = 3
               .Interior.ColorIndex = 35
               Set sRng = Rng.FindNext(sRng)
            Loop While Not sRng Is Nothing And sRng.Address <> MyAdd
         End If
      End If
   End With
 Next jJ
2 ' Copy From None Color "SP" '
 Sheets("KQ").Select:            Cells.Clear
 [a1].Resize(, 9).Value = Sheets("PM").[a1].Resize(, 9).Value
 eRw = Sh.[A65500].End(xlUp).Row
 Set Rng = Sh.Range(Sh.[c11], Sh.Cells(eRw, "C"))
 For Each sRng In Rng
   With sRng
      If .Value <> "" And .Font.ColorIndex <> 3 Then
         Set cRng = Cells(65500, "C").End(xlUp)
         cRng.Offset(1).Value = .Offset(, -1).Value
         cRng.Offset(1, 5).Value = .Value
         cRng.Offset(1, 6).Value = .Offset(, 2).Value
      End If
   End With
 Next sRng
3 ' Copy From "PM" '
 Set Rng = Nothing
 Set Sh = Sheets("PM"):          eRw = Sh.[d65500].End(xlUp).Row
 For jJ = 2 To eRw
   With Sh.Cells(jJ, "G")
      If .Value <> "" And .Interior.ColorIndex <> 35 Then
         If Rng Is Nothing Then
            Set Rng = .Offset(, -6).Resize(, 9)
         Else
            Set Rng = Union(Rng, .Offset(, -6).Resize(, 9))
         End If
      End If
   End With
 Next jJ
 Rng.Copy Destination:=[c65500].End(xlUp).Offset(1, -2)
End Sub


Chúc vui.
 
Lần chỉnh sửa cuối:
Upvote 0
Theo chổ tôi biết thì Set thường dùng để khai báo 1 vùng hoặc 1 Object (gần giống Define name ấy)
Còn chuyện Set... = nothing thì... tùy thói quen... Tôi thấy cũng chẳng cần, sau khi chạy xong code, biến sẽ tự giải phóng khỏi bộ nhớ (Nếu biến nằm dưới tên Sub)
Bạn xem bài này:
http://www.giaiphapexcel.com/forum/showpost.php?p=94013&postcount=12

Cái define name này ăn tiền đây...
Em đã được giải thích một lần nhưng rồi quên...he he nhưng lần này bác nói là giống Define name thì vụ này nhớ là cái chắc rồi

Cám ơn đại ân nhân
 
Upvote 0
Offset(1) có phải bằng offset(1,0)??

Rng.Offset(1).SpecialCells(12).EntireRow.Delete

Em xin được hỏi là Offset(1) ở đây có nghĩa trượt một row ạh? nếu ghi tắt như vậy có phải là offset(1,0) ko?

Xin cám ơn
 
Upvote 0
Em xin được hỏi là Offset(1) ở đây có nghĩa trượt một row ạh? nếu ghi tắt như vậy có phải là offset(1,0) ko?

Xin cám ơn
Cả OFFSETRESIZE đều có cú pháp giống nhau:
Ref.Offset(dòng, cột)
Ref.Resize(số dòng, số cột)

Trong 2 tham số này nếu ta bỏ đi 1 thì xem như là... KHÔNG LÀM GÌ (với tham số đó)
Cú pháp để bỏ bớt cột
Ref.Offset(x) <===> Ref.Offset(x, 0)
Ref.Resize(x)
<===>Ref.Resize(x, Ref.Columns.Count)

Cú pháp để bỏ bớt dòng
Ref.Offset(, y) <===>Ref.Offset(0, y)
Ref.Resize(, y) <===>Ref.Resize(Ref.Rows.Count, y)

(chú ý dấu phẩy màu đỏ)
 
Upvote 0
Currentregion?

Em học mãi mà vẫn ngu VBA...hic
Em xin hỏi thêm vụ này vì chưa biết phải làm thí nghiệm thế nào
Nếu
PHP:
Dim Rng As Range
 Set Rng = [A1].CurrentRegion

Giả sử cột dữ liệu không liên tục (cột A,B,C có dữ liệu;cột D trống; sau đó đến cột E có dữ liệu
Thì sau khi set như trên Rng có bao gồm cả cột E không?

Cám ơn bác
 
Upvote 0
Em học mãi mà vẫn ngu VBA...hic
Em xin hỏi thêm vụ này vì chưa biết phải làm thí nghiệm thế nào
Nếu
PHP:
Dim Rng As Range
 Set Rng = [A1].CurrentRegion
Giả sử cột dữ liệu không liên tục (cột A,B,C có dữ liệu;cột D trống; sau đó đến cột E có dữ liệu
Thì sau khi set như trên Rng có bao gồm cả cột E không?

Cám ơn bác
Ref.CurrentRegion dùng để set 1 vùng dử liệu có liên quan đến Ref
Vì cột D rổng nên đương nhiên E sẽ không được tính
Bạn thí nghiệm bằng cách:
- Chọn A1
- Bấm tổ hợp phím Ctrl + Shift + * (dấu * ở dưới số 8)
 
Upvote 0
PHP:
Option Explicit
Sub ConvertToText()
  Dim TempRng As Range, Original As Range
  Application.ScreenUpdating = False
  Set Original = ActiveCell
  With Sheet1.[A1].CurrentRegion
    Set TempRng = .Offset(, .Columns.Count).Resize(.Rows.Count, .Columns.Count)
    .NumberFormat = "@"
    TempRng.FormulaArray = "=TEXT(" & .Address & ",""@"")"
    TempRng.Copy
    TempRng.PasteSpecial 3
    .PasteSpecial 3
    TempRng.Clear
  End With
  Application.ScreenUpdating = True
  Original.Select
End Sub
Trên đây là đoạn code của Bác NDU, em chưa hiểu đoạn sau
1. Set Original = ActiveCell ' mình set như này để làm gì
Em xoá nó đi (cả đoạn duới Original.select ) em thấy code vẫn chạy

2. Set TempRng = .Offset(, .Columns.Count).Resize(.Rows.Count, .Columns.Count)
Có phải đoạn code này tạo ra một vùng "tạm thời --> như kiểu note pad ko?"
+ sẽ trượt đi .columns cột, resize đúng bằng kích thước dữ liệu ban đầu?
3. NumberFormat = "@" --> @ có nghĩa là chuyển về định dạng Text?

4. Và em chưa hiểu cả đoạn này nữa
TempRng.FormulaArray = "=TEXT(" & .Address & ",""@"")"

đoạn này sao ko phải là Formula mà thêm Array đằng sau ạh?
em khó hiểu nhất đoạn này
Các cao thủ chỉ dạy cho em.
 
Lần chỉnh sửa cuối:
Upvote 0
PHP:
Option Explicit
Sub ConvertToText()
  Dim TempRng As Range, Original As Range
  Application.ScreenUpdating = False
  Set Original = ActiveCell
  With Sheet1.[A1].CurrentRegion
    Set TempRng = .Offset(, .Columns.Count).Resize(.Rows.Count, .Columns.Count)
    .NumberFormat = "@"
    TempRng.FormulaArray = "=TEXT(" & .Address & ",""@"")"
    TempRng.Copy
    TempRng.PasteSpecial 3
    .PasteSpecial 3
    TempRng.Clear
  End With
  Application.ScreenUpdating = True
  Original.Select
End Sub
Trên đây là đoạn code của Bác NDU, em chưa hiểu đoạn sau
1. Set Original = ActiveCell ' mình set như này để làm gì
Em xoá nó đi (cả đoạn duới Original.select ) em thấy code vẫn chạy

2. Set TempRng = .Offset(, .Columns.Count).Resize(.Rows.Count, .Columns.Count)
Có phải đoạn code này tạo ra một vùng "tạm thời --> như kiểu note pad ko?"
+ sẽ trượt đi .columns cột, resize đúng bằng kích thước dữ liệu ban đầu?
3. NumberFormat = "@" --> @ có nghĩa là chuyển về định dạng Text?

4. Và em chưa hiểu cả đoạn này nữa
TempRng.FormulaArray = "=TEXT(" & .Address & ",""@"")"

đoạn này sao ko phải là Formula mà thêm Array đằng sau ạh?
em khó hiểu nhất đoạn này
Các cao thủ chỉ dạy cho em.
1> Set Original = ActiveCell chẳng qua là để nhớ lại ActiveCell... để sau khi chạy code xong, nó sẽ Select ngay cell củ (bạn thấy dưới cùng có Original.Select không?)
2> Gần giống như bạn nói... Nó sẽ tạo 1 vùng tạm nằm cạnh vùng gốc (về bên phải)
3> Chính xác
4> Như bạn gõ công thức thường thôi
Giả sử câu lệnh Sheet1.[A1].CurrentRegion xác định được 1 vùng = A1:C10 thì vùng TempRng sẽ = D1:F10 ---> Khi ấy ta quét chọn D1:F10 rồi gõ công thức:
=TEXT(A1:C10,"@") ---> Đơn giản thế thôi!
Bạn cứ record macro quá trình gõ công thức sẽ thấy ---> Chỉ có điều do ta chưa xác định được vùng dử liệu gốc từ đâu đến đâu nên phải ghi... & .Address &... (tức thằng Sheet1.[A1].CurrentRegion có địa chỉ là gì thì điền vào đây)
 
Upvote 0
Cám ơn Anh NDU chỉ dạy nhiệt tình
Set TempRng = .Offset(, .Columns.Count).Resize(.Rows.Count, .Columns.Count)
.NumberFormat = "@"
TempRng.FormulaArray = "=TEXT(" & .Address & ",""@"")"
TempRng.Copy
TempRng.PasteSpecial 3
.PasteSpecial 3
TempRng.Clear
Trong đoạn code trên chỉ thấy
-set vùng tạm thời " nằm bên phải"
- chuyển về text
- Copy
- Dán
- Xoá vùng tạm thời
---
Sao em ko thấy dán vào vào vùng (cần chuyển đổi nhỉ?) mà dán ngay tại TemRng (mà range này đã set là nằm bên phải "ảo" cơ mà?
.PasteSpecial 3 --> dòng này em thấy (.) lơ lửng nằm một mình vậy?

Em còn rất rất...ngốc trong VBA và excel.
Xin ANh nhẫn nại chỉ thêm?
 
Lần chỉnh sửa cuối:
Upvote 0
Cám ơn Anh NDU chỉ dạy nhiệt tình

Trong đoạn code trên chỉ thấy
-set vùng tạm thời " nằm bên phải"
- chuyển về text
- Copy
- Dán
- Xoá vùng tạm thời
---
Sao em ko thấy dán vào vào vùng (cần chuyển đổi nhỉ?) mà dán ngay tại TemRng (mà range này đã set là nằm bên phải "ảo" cơ mà?
.PasteSpecial 3 --> dòng này em thấy (.) lơ lửng nằm một mình vậy?

Em còn rất rất...ngốc trong VBA và excel.
Xin ANh nhẫn nại chỉ thêm?
Uh... có lẽ khi viết bị dư thôi ----> thì cừ xóa TempRng.PasteSpecial 3 vậy! Chừa lại thằng PasteSpecial 3 ---> tức dán trực tiếp vào vùng gốc luôn
Ẹc.. Ẹc...
 
Upvote 0
Cám ơn Anh NDU chỉ dạy nhiệt tình

Đó là kiểu cầm tay chỉ việc, bước đầu & 1 lần thôi;
Nhưng sau này cứ mãi vậy, bạn sẽ ỉ lại đó;

Mình chỉ cách này sẽ hay hơn xíu nè:

Dùng MsgBox để tìm hiểu thông tin từ máy khi nào bạn muốn

Tôi ví dụ:

PHP:
Dim Rng As Range
 
Set Rng = Cells.UsedRange.Offset(1)
' Bạn thêm câu lệnh sau để biết Rng sẽ là gì trong đó'
 MsgBox Rng.Address, , Rng.Resize( 3, 5)
' . . . . . '

Macro sẽ không hẹp hòi gì khi bạn hỏi nó; Nó không phải như chúng ta điểm này, có gì nó nói ngay!

Không tin bạn cứ thử bất cứ lúc nào

Tất nhiên cách này là cách chuối nhất; Chứ còn cách hiện đại hơn nữa kia!
Nhưng tạm thời vậy đã là hay với chúng ta rồi - những người tự học í mà!

Chớ phật lòng nha!
 
Lần chỉnh sửa cuối:
Upvote 0
Đó là kiểu cầm tay chỉ việc, bước đầu & 1 lần thôi;
Nhưng sau này cứ mãi vậy, bạn sẽ ỉ lại đó;

Mình chỉ cách này sẽ hay hơn xíu nè:

Dùng MsgBox để tìm hiểu thông tin từ máy khi nào bạn muốn

Tôi ví dụ:

PHP:
Dim Rng As Range
 
Set Rng = Cells.UsedRange.Offset(1)
' Bạn thêm câu lệnh sau để biết Rng sẽ là gì trong đó'
 MsgBox Rng.Address, , Rng.Resize( 3, 5)
' . . . . . '
Macro sẽ không hẹp hòi gì khi bạn hỏi nó; Nó không phải như chúng ta điểm này, có gì nó nói ngay!

Không tin bạn cứ thử bất cứ lúc nào

Tất nhiên cách này là cách chuối nhất; Chứ còn cách hiện đại hơn nữa kia!
Nhưng tạm thời vậy đã là hay với chúng ta rồi - những người tự học í mà!

Chớ phật lòng nha!
Em cũng hay làm theo cách này... Ngoài ra em còn dùng Select để biết thực sự vùng mà em đang cần là vùng nào (có đúng như em suy luận không)
Ví dụ
PHP:
Sub Test()
  With Range("A1").CurrentRegion
     .Select
     MsgBox "Dang chon vung 1, chuyen sang vung 2 nha"
     .Offset(, .Columns.Count).Select
  End With
End Sub
Ẹc... Ẹc...
 
Upvote 0
Em được hỏi khai báo biến ở đầu Sub và sau sub có gì khác nhau?

Các Huynh chỉ giúp
 
Upvote 0
Tôi làm 1 cái đồng hồ nằm trên cell A1, dựa vào code sau:
PHP:
Private Check As Boolean
Private Sub CommandButton1_Click()
  Check = (CommandButton1.Caption = "Start")
  CommandButton1.Caption = Choose(1 - Check, "Start", "Stop")
  Do While Check
    Range("A1").Value = Format(Now, "hh:mm:ss")
    DoEvents
  Loop
End Sub
- Bấm nút ---> Đồng hồ chạy
- Bâm nút lần nữa ---> Đồng hồ dừng
Code chạy không có vấn đề, chỉ có 1 trục trặc là: Khi đồng hồ chạy, chỉ cần ta nhập liệu vào 1 cell nào đó thì lập tức đồng hồ dừng ngay
Nhờ các cao thủ giúp cách khắc phục, sao cho đồng hồ vẫn chạy trong khi nhập liệu (nó chỉ dừng khi ta bấm nút)
 

File đính kèm

Upvote 0
Worksheet_Change & Worksheet_SelectionChange là mấy thứ?

Cho tôi hỏi tí:
Worksheet_Change & Worksheet_SelectionChange khác nhau và giống nhau chỗ nào vậy?
 
Upvote 0
Cho tôi hỏi tí:
Worksheet_Change & Worksheet_SelectionChange khác nhau và giống nhau chỗ nào vậy?
- Hai cái này giống ở chổ đều là sự kiện CHANGE (tức thay đổi.. gì đó)
- Worksheet_Change dựa vào việc thay đổi dử liệu tại 1 cell hoặc 1 vùng nào đó mà chạy code
-Worksheet_SelectionChange dựa vào việc thay đổi con trỏ chuột (từ cell này sang cell khác) mà chạy code
 
Upvote 0
- Hai cái này giống ở chổ đều là sự kiện CHANGE (tức thay đổi.. gì đó)
- Worksheet_Change dựa vào việc thay đổi dử liệu tại 1 cell hoặc 1 vùng nào đó mà chạy code
-Worksheet_SelectionChange dựa vào việc thay đổi con trỏ chuột (từ cell này sang cell khác) mà chạy code
Khó hỉu quá. Vậy có phải là... Ví dụ em lập trình cho ô A1:
Nếu em gõ cái gì đó vào trong ô A1 thì chọn Worksheet_Change?
Còn khi em đang đứng ở A1 mà nhảy xuống A2 (hoặc đi đâu đó) thì chọn Worsheet_SelectionChange ?

Em chỉ hiểu đơn giản rằng:
- Change = Thay đổi
- SelectionChange = Thay đổi cái đang chọn

Thấy nó y chang nhau... Rắc rối thiệt.
 
Upvote 0
Em chỉ hiểu đơn giản rằng:
- Change = Thay đổi
- SelectionChange = Thay đổi cái đang chọn

Thấy nó y chang nhau... Rắc rối thiệt.

Bạn nhập 2 cái ni vô 1 sheet nào đó

PHP:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
 If Not Intersect(Target, Columns("A:A")) Is Nothing Then _
      MsgBox "Change only"
End Sub
Mã:
[B]Private Sub Worksheet_SelectionChange(ByVal Target As Range)[/B]
 If Not Intersect(Target, Columns("A:A")) Is Nothing Then _
   MsgBox "SelectionChange"
[B]End Sub [/B]

Sau đó lần lượt thử các hành động sau:

(1) Di chuyển bằng chuột giữa các ô trong cột 'A'
Di chuyển bằng bàn phím như trên

(2) Thử nhập dữ liệu vô 1 trong các ô của cột nớ. sau đó {ENTER} chú ý từng hộp thoại xuất hiện
Sau đó có thể bấm chuột lên thanh công thức để đổi dữ liệu khác vô ô hiện hành xem sao?

(3) Chọn vài hàng & thêm dòng xem sao?

(4) Copy dữ liệu từ nơi khác vô 1 & sau đó là vài ô trong cột 'A' để xem các macro làm việc theo trình tự nào;

. . . . .

(n) Chọn vài ô trong 'A' nhập lên thanh công thức 'GPE', sau đó giữ fím {CTRL} & thực hiện {ENTER} coi chúng ra răng!

Chúc vui! :-=
 
Lần chỉnh sửa cuối:
Upvote 0
Sư phụ ơi, nhân tiện xem giúp em bài #275 ở trên với
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Sư phụ ơi, nhân tiện xem giúp em bài #275 ở trên với
Thú thực cái này mình chưa đủ công lực & cũng iếu hứng thú luôn!
Hay mượn cái "Thụy sỹ" đâu đó trên xa lộ ai để quên về xài đi, "Đồ Nội" mau hư lắm!
Chúc đứa con tinh thần của bạn khỏe mạnh & an lành!
--=0
 
Upvote 0
Thú thực cái này mình chưa đủ công lực & cũng iếu hứng thú luôn!
Hay mượn cái "Thụy sỹ" đâu đó trên xa lộ ai để quên về xài đi, "Đồ Nội" mau hư lắm!
Chúc đứa con tinh thần của bạn khỏe mạnh & an lành!
--=0
Àh... không phải em cần xài cái đồng hồ ấy... chỉ là thí nghiệm để học hỏi code thôi
Em cảm thấy ngạc nhiên, không biết nguyên nhân do đâu mà khi ta nhập liệu vào bất kỳ cell nào thì đồng hồ lập tức dừng ngay ---> điều gì làm cho nó dừng lại? Em nào có bấm nút dừng đâu?
Hay nói đúng hơn, điều em muốn hỏi ở đây là: Vòng lập Do While đang chạy ngon lành, sao tự nhiên không chạy tiếp?
 
Upvote 0
Àh... không phải em cần xài cái đồng hồ ấy... chỉ là thí nghiệm để học hỏi code thôi
Em cảm thấy ngạc nhiên, không biết nguyên nhân do đâu mà khi ta nhập liệu vào bất kỳ cell nào thì đồng hồ lập tức dừng ngay ---> điều gì làm cho nó dừng lại? Em nào có bấm nút dừng đâu?
Hay nói đúng hơn, điều em muốn hỏi ở đây là: Vòng lập Do While đang chạy ngon lành, sao tự nhiên không chạy tiếp?
Cái này cũng bị vậy... Di chuyển chuột thì không sao, nhưng hễ nhập liệu vào 1 ô là cái đồng hồ chết máy liền hà... Hỏng hiểu tại sao...

Nhưng khá hơn cái anh ndu96081631 chút... Nhập liệu xong (Enter) thì đồng hồ lại chạy tiếp, giống như nó đứng lại để xem mình làm gì vậy, rồi hỏng thấy có gì liên quan đến nó nên... thôi, việc ta ta làm.

Còn cái của anh ndu96081631 thì nhập liệu xong, Enter, cái đồng hồ vẫn đứng dòm, không chịu chạy tiếp.

Bài này, cảm ơn bác SA_DQ, em đã biết vận dụng cái WorkSheet_SelectionChange để làm cái ô Pause và Continue cho cái đồng hồ, khỏi cần vẽ cái nút.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Cái này cũng bị vậy... Di chuyển chuột thì không sao, nhưng hễ nhập liệu vào 1 ô là cái đồng hồ chết máy liền hà... Hỏng hiểu tại sao...

Nhưng khá hơn cái anh ndu96081631 chút... Nhập liệu xong (Enter) thì đồng hồ lại chạy tiếp, giống như nó đứng lại để xem mình làm gì vậy, rồi hỏng thấy có gì liên quan đến nó nên... thôi, việc ta ta làm.

Còn cái của anh ndu96081631 thì nhập liệu xong, Enter, cái đồng hồ vẫn đứng dòm, không chịu chạy tiếp.

Bài này, cảm ơn bác SA_DQ, em đã biết vận dụng cái WorkSheet_SelectionChange để làm cái ô Pause và Continue cho cái đồng hồ, khỏi cần vẽ cái nút.
Cái đồng hồ này chạy thế là ngon rồi còn gì! Có điều ý tôi không phải hỏi về cái đồng hồ (thuật toán 2 file khác nhau mà)
Ý tôi chỉ hỏi vòng lập trong file của tôi sao tự nhiên bị "đơ" không chạy tiếp
(chỉ mượn cái đồng hồ làm mẫu thôi)
--------
Riêng về code của BNTT, nếu chỉ chọn có 1 cell thì ta dùng Address gọn hơn Intersect
Ví dụ:
PHP:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    If Target.Address = "$B$1" Then StopRunClock
    If Target.Address = "$B$2" Then RunClock
End Sub
hoặc:
PHP:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    If Target.Address(0,0) = "B1" Then StopRunClock
    If Target.Address(0,0)= "B2" Then RunClock
End Sub
Nếu chọn 1 dòng thì dùng Target.Row = ???
Nếu chọn 1 cột thì dùng Target.Column = ???
vân vân...
Intersect bạn chỉ nên xài trong trường hợp bạn muốn con trỏ chuột nằm trong 1 vùng xác định nào đó
Ví dụ:
PHP:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    If Not Intersect(Target, Range("B1:D1")) Is Nothing Then StopRunClock
    If Not Intersect(Target, Range("B2:D2")) Is Nothing Then RunClock
End Sub
Khi này, vùng hoạt động của con trỏ chuột là B1:D1B2:D2
 
Upvote 0
Hic hic, anh ndu96081631 à, em đâu có biết... Thầy SA_DQ dạy cái gì thì em xài cái đó, thấy nó không báo lỗi, và chạy ngon, thì em cứ để yên à... Cảm ơn anh, lại thêm một chiêu nữa... Mấy thứ này hỏng có trong Help của VBE, mà nếu có thì đọc cũng chả hiểu nổi.

À, sẵn cho em hỏi tí:
PHP:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    If Target.Address = "$B$1" Then StopRunClock
    If Target.Address = "$B$2" Then RunClock
End Sub
Có cách nào mà khi nhấn (hay chọn) ô B1 thì nó Pause, rồi hễ thoát ra khỏi ô B1, hoặc là nhấn vào ô B1 một cái nữa, thì nó chạy tiếp hông? Nghĩa là chỉ "lập trình" cho mỗi cái ô B1 thôi.
 
Lần chỉnh sửa cuối:
Upvote 0
Hic hic, anh ndu96081631 à, em đâu có biết... Thầy SA_DQ dạy cái gì thì em xài cái đó, thấy nó không báo lỗi, và chạy ngon, thì em cứ để yên à... Cảm ơn anh, lại thêm một chiêu nữa... Mấy thứ này hỏng có trong Help của VBE, mà nếu có thì đọc cũng chả hiểu nổi.

À, sẵn cho em hỏi tí:
PHP:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    If Target.Address = "$B$1" Then StopRunClock
    If Target.Address = "$B$2" Then RunClock
End Sub
Có cách nào mà khi nhấn (hay chọn) ô B1 thì nó Pause, rồi hễ thoát ra khỏi ô B1, hoặc là nhấn vào ô B1 một cái nữa, thì nó chạy tiếp hông? Nghĩa là chỉ "lập trình" cho mỗi cái ô B1 thôi.
Được chứ... như code này đây
PHP:
Private Check As Byte
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  If Target.Address = "$B$1" Then
    Check = Check Xor -(Not Target)
    If Check Then
      RunClock
    Else
      StopRunClock
    End If
  End If
End Sub
Nhưng trong trường hợp này ta dùng Button sẽ hay và "an toàn" hơn!
 

File đính kèm

Upvote 0
Em sửa lại như vầy cho ngắn hơn được hông:
PHP:
Private Check As Byte
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
     If Target.Address = "$B$1" Then
          Check = Check Xor -(Not Target)
          If Check Then RunClock Else StopRunClock
     End If
End Sub

Và cho em hỏi: Xor nghĩa là gì vậy anh ?

Và cái này:
If Check Then RunClock Else StopRunClock​
Có thể viết như vầy không:
IIf(Check, RunClock, StopRunClock)​
 
Upvote 0
Tôi sửa lại code 1 tí, Bạn BNTT xài file mới này "an toàn" hơn (hàm Xor có vẻ không được ổn định)
PHP:
Option Explicit
Private Check As Byte
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  If Target.Address = "$B$1" Then
    Check = IIf(Check = 1, 0, 1)
    Range("B1") = Choose(Check + 1, "Start", "Stop")
    Run Choose(Check + 1, "StopRunClock", "RunClock")
  End If
End Sub
Em sửa lại như vầy cho ngắn hơn được hông:
PHP:
Private Check As Byte
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
     If Target.Address = "$B$1" Then
          Check = Check Xor -(Not Target)
          If Check Then RunClock Else StopRunClock
     End If
End Sub
Và cho em hỏi: Xor nghĩa là gì vậy anh ?

Và cái này:
If Check Then RunClock Else StopRunClock​
Có thể viết như vầy không:
IIf(Check, RunClock, StopRunClock)
Không được, phải thế này:
Run IIf(Check, "RunClock", "StopRunClock")
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Anh Ndu ơi...
Sửa lại giống anh nói, nó ra như thế này mỗi khi nhấn vào B1:
000-1077.jpg
Và nhấn vào Debug thì nó la làng như vầy:
001-65.jpg
 
Upvote 0
Anh Ndu ơi...
Sửa lại giống anh nói, nó ra như thế này mỗi khi nhấn vào B1:
000-1077.jpg
Và nhấn vào Debug thì nó la làng như vầy:
001-65.jpg
Thì ở trên tôi nói rồi đó: Hàm Xor có vẻ không ổn định (khi được khi không) ---> Chắc hiểu nguyên nhân nữa, nên đã sửa lại rồi!
(Xem file phía trên nhé)
 
Upvote 0
Tôi sửa lại code 1 tí, Bạn BNTT xài file mới này "an toàn" hơn (hàm Xor có vẻ không được ổn định)
PHP:
Option Explicit
Private Check As Byte
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  If Target.Address = "$B$1" Then
    Check = IIf(Check = 1, 0, 1)
    Range("B1") = Choose(Check + 1, "Start", "Stop")
    Run Choose(Check + 1, "StopRunClock", "RunClock")
  End If
End Sub

Không được, phải thế này:
Run IIf(Check, "RunClock", "StopRunClock")
Anh ơi, cái file này thì chạy được rồi... nhưng không giống ý đồ của em muốn (cũng có thể là cái em muốn nó trời ơi quá)...
Cái ô B1... Nếu dùng chuột, thì nhấn vào nó 1 cái, nó Pause (OK). Nhấn tiếp nó một cái nữa, nothing! Phải nhấn một ô khác, rồi quay lại nhấn nó, thì nó mới Play.
Còn nếu dùng bàn phím, chọn nó, nó Pause (OK)... nhưng muốn nó chạy tiếp thì phải chạy ra ngoài lấy đà rồi quay lại tông nó một cái, nó mới chịu chạy tiếp...

Em muốn là, với ô B1:
  • Nếu dùng chuột, nhấn một cái: Pause, nhấn tiếp một cái: Play, nhấn tiếp cái nữa: Pause, v.v...
  • Nếu dùng bàn phím: chọn nó: Pause, bỏ nó đi chỗ khác: Play, quay lại: Pause, đi ra: Play, v.v...
Liệu ý muốn này có trời ơi quá hông anh?
 
Upvote 0
Em muốn là, với ô B1:
  • Nếu dùng chuột, nhấn một cái: Pause, nhấn tiếp một cái: Play, nhấn tiếp cái nữa: Pause, v.v...
  • Nếu dùng bàn phím: chọn nó: Pause, bỏ nó đi chỗ khác: Play, quay lại: Pause, đi ra: Play, v.v...
Liệu ý muốn này có trời ơi quá hông anh?
Thế thì... ăn chắc không được... vì nếu ta không di chuột sang cell khác thì code không "cảm nhận" được có cái gì là SELECTIONCHANGE cả ---> Vì thế mà trong trường hợp này người ta sẽ xài nút nhấn
Thí nghiệm đơn giản đây:
PHP:
Private Check As Byte
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  If Target.Address = "$A$1" Then
    Check = IIf(Check, 0, 1)
    MsgBox Check
  End If
End Sub
Bấm vào A1, 1 MsgBox xuất hiện
Nếu không dời chuột ra nơi khác mà cứ bấm tiếp thì chả có gì xuất hiện cả
Còn như bạn vẫn cố tình muốn thế thì ta chơi... tà đạo ---> sau khi chọn xong B1, cho con trỏ chuột chuyển sang cell bên cạnh luôn --> Target.Offset(1).Select chẳng hạn
Ẹc... Ẹc...
 
Lần chỉnh sửa cuối:
Upvote 0
Có thêm cách này

Có cách nào mà khi nhấn (hay chọn) ô B1 thì nó Pause, rồi hễ thoát ra khỏi ô B1, hoặc là nhấn vào ô B1 một cái nữa, thì nó chạy tiếp hông? Nghĩa là chỉ "lập trình" cho mỗi cái ô B1 thôi.

Khai báo 1 biến toàn cục kiểu Jes/No
Sau đó bấm ô nào đó (VD 'B1') & ra lệnh
1 Xoay chiều Jes=> No hay No => Jes
2 Nếu Jes thì làm thêm việc gì đó, như bửa cũi chẳng hạn. khà . . . :-= khà. . . :-= :-= :-=
 
Upvote 0
Khai báo 1 biến toàn cục kiểu Jes/No
Sau đó bấm ô nào đó (VD 'B1') & ra lệnh
1 Xoay chiều Jes=> No hay No => Jes
2 Nếu Jes thì làm thêm việc gì đó, như bửa cũi chẳng hạn. khà . . . :-= khà. . . :-= :-= :-=
"Khai báo 1 biến toàn cục kiểu Jes/No" có phải là: Private Biến as Boolean ?
Nhưng rồi... cái 1, 2 gì đó, cụ thể hơn được không, sư phụ ơi ?
 
Upvote 0
Khai báo 1 biến toàn cục kiểu Jes/No
Sau đó bấm ô nào đó (VD 'B1') & ra lệnh
1 Xoay chiều Jes=> No hay No => Jes
2 Nếu Jes thì làm thêm việc gì đó, như bửa cũi chẳng hạn. khà . . . :-= khà. . . :-= :-= :-=
Sau khi xoay chiều Yes, No xong, bạn hỏng chuyển chuột rồi bấm tiếp thì lấy gì Yes --> NoNo ---> Yes được ---> Code cũng chả bao giờ chạy
Điểm quan trọng: Code chạy được chủ yếu nhờ bấm chuột mà ra... Không có CHANGE sẽ không có CHẠY
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
công thức sort tự động

Mình đang cố gắng học các tuyệt chiêu của các bậc đàn anh, trong đó có Chiêu thứ 30: "Sort thứ tự dựa trên nhiều hơn 3 cột"
Code:
Sub SortByX( )
Dim i As Long
For i = Selection.Columns.Count To 1 Step -1
Selection.Sort Key1:=Selection.Cells(2, i), _
Order1:=xlAscending, Header:=xlGuess, Orientation:=xlTopToBottom
Next i
End Sub


Mình muốn Sort ưu tiên theo cột A (giảm dần) và các cột B,C,D,E (tăng dần), các bạn giúp mình sửa code sao cho thỏa yêu cầu trên

Chiêu trên mình học của tác giả ptm 0412, mình không biết vế VBA nên không hiểu - giúp mình với - cảm ơn các bạn nhiều lắm !
 
Upvote 0
Mình đang cố gắng học các tuyệt chiêu của các bậc đàn anh, trong đó có Chiêu thứ 30: "Sort thứ tự dựa trên nhiều hơn 3 cột"
Code:
Sub SortByX( )
Dim i As Long
For i = Selection.Columns.Count To 1 Step -1
Selection.Sort Key1:=Selection.Cells(2, i), _
Order1:=xlAscending, Header:=xlGuess, Orientation:=xlTopToBottom
Next i
End Sub


Mình muốn Sort ưu tiên theo cột A (giảm dần) và các cột B,C,D,E (tăng dần), các bạn giúp mình sửa code sao cho thỏa yêu cầu trên

Chiêu trên mình học của tác giả ptm 0412, mình không biết vế VBA nên không hiểu - giúp mình với - cảm ơn các bạn nhiều lắm !
Yêu cầu của bạn đâu cần dùng VBA đâu.
Bạn cứ sort lần lượt các cột theo thứ tự mức độ ưu tiên tăng dần (cái nào mức ưu tiên thấp thì sort trước, mức ưu tiên cao thì sort sau).
VBA cũng làm trên cở sở này thôi.
 
Upvote 0
Mình làm thử theo cách Sort thông thường thì khi dữ kiệu thay đổi, nó không luôn luôn sort theo ý mình, ví dụ ưu tiên cột A (luôn sorrt theo cách giảm dần), còn các cột còn lại thì luôn sorrt theo cách tăng dần - mỗi lần thay đổ dữ liệu thì mình phải sort lại - các bạn giúp mình với
 
Upvote 0
Mình làm thử theo cách Sort thông thường thì khi dữ kiệu thay đổi, nó không luôn luôn sort theo ý mình, ví dụ ưu tiên cột A (luôn sorrt theo cách giảm dần), còn các cột còn lại thì luôn sorrt theo cách tăng dần - mỗi lần thay đổ dữ liệu thì mình phải sort lại - các bạn giúp mình với
Không biết tại sao bạn làm sai. Có thể là do dữ liệu của bạn không liên tục. Tốt nhất là quét hết bảng dữ liệu (chừa cột tiêu đề ra). Sort cột nào thì Active cell trong cột đó. Làm lần lượt theo thứ tự ưu tiên giảm dần.
 
Upvote 0
Mình có thử nhiều lần nhưng không ổn, còn áp dụng đoạn code đã học ở chiêu thứ 30 thì luôn sort theo kiểu Ascending, có cách nào sửa code sao cho cột đầu tiên (theo thứ tự ưu tiên) thì descending, còn các cột còn lại thì Ascending - giúp mình với
Bằng cách sửa đoạn code sau:

Sub SortByX( )
Dim i As Long
For i = Selection.Columns.Count To 1 Step -1
Selection.Sort Key1:=Selection.Cells(2, i), _
Order1:=xlAscending, Header:=xlGuess, Orientation:=xlTopToBottom
Next i
End Sub
 
Upvote 0
Status
Không mở trả lời sau này.

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

Back
Top Bottom