Hỏi đáp về VBA (các vấn đề căn bản nhất) (2 người xem)

Liên hệ QC

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

havietchuong

Thành viên tiêu biểu
Tham gia
16/6/09
Bài viết
490
Được thích
570
Giới tính
Nam
Nghề nghiệp
Giáo viên tiểu học.
Tôi không biết đặt đặt câu hỏi này nơi nào cho đúng, xin gởi vào đây. Nếu có sai xin thông cảm cho người mới học VBA.
Trong 1 cửa sổ Module có thể ghi nhiều nhiều Macro và mỗi macro có thể ứng với 1 tổ hợp phím nào đó được không?
Tôi thử nhiều lần thì khi được khi không. Không biết nó thế nào? Trong tập tin sau có lỗi gì không trong cách ghi Macro? Cám ơn.
 

File đính kèm

Lần chỉnh sửa cuối:
Xin viết code trong dự toán

Bác chỉnh giùm em
ô E8 thành kiểu dữ liệu như trong ô E9, thay đổi cho cả cột E
 

File đính kèm

Upvote 0
Bác chỉnh giùm em
ô E8 thành kiểu dữ liệu như trong ô E9, thay đổi cho cả cột E

PHP:
Sub them_chuoi()
Dim i, kq(), tam
kq = Range([E8], [E65536].End(3)).Value
   For i = 1 To UBound(kq)
      If kq(i, 1) <> "" Then
         tam = kq(i, 1): tam = Replace(tam, " ", ""): tam = Replace(tam, "=", "")
         kq(i, 1) = Replace(tam, ":", ":" & String(15, Space(1))) & Space(5) & "="
      End If
   Next
[E8].Resize(i - 1) = kq
End Sub
 
Upvote 0
Bác chỉnh giùm em
ô E8 thành kiểu dữ liệu như trong ô E9, thay đổi cho cả cột E

@ thangcola114: bạn nên mô tả dữ liệu một chút và mô tả kết quả phải thế nào. Bạn quá kiệm lời đấy.
Tôi thử miêu tả xem đúng như ý bạn không nhé?

Trong ô tại cột E gõ:

[chuoi1 = chuỗi ký tự kết thúc bằng ký tự ":" đầu tiên (chuỗi có thể có nhiều ":" không? Nếu luôn có 1 và chỉ 1 ":" thì bỏ chữ "đầu tiên")][chuỗi ký tự " " (có thể có TAB không?)][chuoi2 = chuỗi bắt đầu và cũng kết thúc đều bằng chữ số (hay cả chữ cái?) và không chứa ký tự "="][chuỗi ký tự tùy ý (dấu cách, =, chữ cái, chữ số ...)]

Chỉ có "chuoi1" và "chuỗi2" luôn luôn có?

Và kết quả là cả mớ "hổ lốn" đó được thay bằng chuoi1 & " " & chuoi2 & " " đúng không?


Ví dụ tôi gõ "bla : 1*2,2*2,2*0,5*1,22 + 1 + 2 TAB TAB =3 = 4 ========xyz"
thì chuyển thành "bla : 1*2,2*2,2*0,5*1,22 + 1 + 2 "?

Mà bạn giải thích không chính xác đấy.

Móng: 1+2 = 4
tự động chuyển thành:
Móng: 1+2 (xóa phần sau dấu "="

Nếu chỉ còn "Móng: 1+2 " thì có nghĩa là xóa cả dấu "=". Nếu chỉ xóa phần sau dấu "=" thì dĩ nhiên dấu "=" vẫn còn
 
Lần chỉnh sửa cuối:
Upvote 0
@ thangcola114: bạn nên mô tả dữ liệu một chút và mô tả kết quả phải thế nào. Bạn quá kiệm lời đấy.
Tôi thử miêu tả xem đúng như ý bạn không nhé?

Trong ô tại cột E gõ:

[chuoi1 = chuỗi ký tự kết thúc bằng ký tự ":" đầu tiên (chuỗi có thể có nhiều ":" không? Nếu luôn có 1 và chỉ 1 ":" thì bỏ chữ "đầu tiên")][chuỗi ký tự " " (có thể có TAB không?)][chuoi2 = chuỗi bắt đầu và cũng kết thúc đều bằng chữ số (hay cả chữ cái?) và không chứa ký tự "="][chuỗi ký tự tùy ý (dấu cách, =, chữ cái, chữ số ...)]

Chỉ có "chuoi1" và "chuỗi2" luôn luôn có?

Và kết quả là cả mớ "hổ lốn" đó được thay bằng chuoi1 & " " & chuoi2 & " " đúng không?


Ví dụ tôi gõ "bla : 1*2,2*2,2*0,5*1,22 + 1 + 2 TAB TAB =3 = 4 ========xyz"
thì chuyển thành "bla : 1*2,2*2,2*0,5*1,22 + 1 + 2 "?
n
Em cần code đúng như bác miêu tả. Thỏa mãn 2 nguyên tắc:
1. Nguyên tắc để tính giá trị của chuỗi 2 (quan trọng nhất): Giúp em xóa phần bắt đầu từ dấu "=" đầu tiên trở về sau (xóa cả dấu "=")
2. Nguyên tắc về chính tả khi viết: không tồn tại 2 dấu Tab (dấu cách) liền kề nhau trong chuỗi thu được cuối cùng (Giống tác dụng của hàm Trim)
Chuỗi cuối cùng thu được:
chuoi1 & " " & ":" chuoi2 & " " (sau chuỗi 2 cũng như trong toàn văn bản chỉ được phép có <=1 dấu Tab liền kề nhau)
 
Upvote 0
PHP:
Sub them_chuoi()
Dim i, kq(), tam
kq = Range([E8], [E65536].End(3)).Value
   For i = 1 To UBound(kq)
      If kq(i, 1) <> "" Then
         tam = kq(i, 1): tam = Replace(tam, " ", ""): tam = Replace(tam, "=", "")
         kq(i, 1) = Replace(tam, ":", ":" & String(15, Space(1))) & Space(5) & "="
      End If
   Next
[E8].Resize(i - 1) = kq
End Sub
Em nhầm, xóa bắt đầu từ dấu "=" trở về sau (xóa cả dấu "=")
Code này vẫn tồn tại 2 dấu Tab liền kề nhau a à.
Anh xem giúp em 1 code giải quyết 2 yêu cầu:
1. Về giá trị: code bài 198 của anh quanghai đã giải quyết xong (xóa cả dấu "="
2. Về nguyên tắc chính tả: không tồn tại 2 dấu Tab liền kề nhau trong ô
Thank a nhiều
 
Upvote 0
Em cần code đúng như bác miêu tả. Thỏa mãn 2 nguyên tắc:
1. Nguyên tắc để tính giá trị của chuỗi 2 (quan trọng nhất): Giúp em xóa phần bắt đầu từ dấu "=" đầu tiên trở về sau (xóa cả dấu "=")
2. Nguyên tắc về chính tả khi viết: không tồn tại 2 dấu Tab (dấu cách) liền kề nhau trong chuỗi thu được cuối cùng (Giống tác dụng của hàm Trim)
Chuỗi cuối cùng thu được:
chuoi1 & " " & ":" chuoi2 & " " (sau chuỗi 2 cũng như trong toàn văn bản chỉ được phép có <=1 dấu Tab liền kề nhau)

Nói chuyện với bạn khó quá.
Tôi đã miêu tả chuoi1 có cả dấu ":" rồi mà bạn lại viết:

Chuỗi cuối cùng thu được:
chuoi1 & " " & ":" chuoi2

Thế thì kết quả có 2 dấu ":"?
Thôi tôi cứ viết đại. Mà đúng là viết đại thôi vì biết đâu có thể viết pattern khác hay hơn.
code cho sheet "Du toan". Bạn cứ viết đại một cái gì đấy ở cột E (vd. ở ô trống nào đó) rồi xem

Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim i, kq
    If Not Intersect(Target, Range([E8], [E65536].End(3))) Is Nothing Then
        Application.EnableEvents = False
        kq = Range([E8], [E65536].End(3)).Offset(, -1).Resize(, 2).Value
        With CreateObject("vbscript.regexp")
           .Pattern = "(.*:)\s*(\w[^=]*\w*\b).*"
           For i = 1 To UBound(kq)
              If kq(i, 1) = "" Then
                 If kq(i, 2) <> "" Then
                    kq(i, 2) = .Replace(kq(i, 2), "$1 $2 ")
                 End If
              End If
           Next
        End With
        [D8].Resize(i - 1, 2) = kq
        Application.EnableEvents = True
    End If
End Sub

code ở bài #198 của quanghai chưa xóa các dấu cách thừa ở sau ":"
Có thể lấy cách đó để xóa từ "=" đầu tiên cho tới cuối, sau đó xóa tiếp các dấu cách sau ":" nếu nhiều quá. Cách đi 2 bước thì cả 2 pattern đơn giản hơn.
 
Upvote 0
Nói chuyện với bạn khó quá.
Tôi đã miêu tả chuoi1 có cả dấu ":" rồi mà bạn lại viết:



Thế thì kết quả có 2 dấu ":"?
Thôi tôi cứ viết đại. Mà đúng là viết đại thôi vì biết đâu có thể viết pattern khác hay hơn.
code cho sheet "Du toan". Bạn cứ viết đại một cái gì đấy ở cột E (vd. ở ô trống nào đó) rồi xem

Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim i, kq
    If Not Intersect(Target, Range([E8], [E65536].End(3))) Is Nothing Then
        Application.EnableEvents = False
        kq = Range([E8], [E65536].End(3)).Offset(, -1).Resize(, 2).Value
        With CreateObject("vbscript.regexp")
           .Pattern = "(.*:)\s*(\w[^=]*\w*\b).*"
           For i = 1 To UBound(kq)
              If kq(i, 1) = "" Then
                 If kq(i, 2) <> "" Then
                    kq(i, 2) = .Replace(kq(i, 2), "$1 $2 ")
                 End If
              End If
           Next
        End With
        [D8].Resize(i - 1, 2) = kq
        Application.EnableEvents = True
    End If
End Sub

code ở bài #198 của quanghai chưa xóa các dấu cách thừa ở sau ":"
Có thể lấy cách đó để xóa từ "=" đầu tiên cho tới cuối, sau đó xóa tiếp các dấu cách sau ":" nếu nhiều quá. Cách đi 2 bước thì cả 2 pattern đơn giản hơn.
Em giờ mới tìm hiểu về VBA nên mong được các bác giúp.
1. Code trên vẫn chưa giải quyết triệt để nguyên tắc về chính tả là không tồn tại 2 dấu Tab liền kề nhau trong ô.
- Nếu 2 dấu Tab này nằm trong chuỗi 2 thì sẽ làm sai giá trị, ví dụ chuỗi 2 là:
(1+2*3)/10 có giá trị là 0.7
nhưng nếu có lỗi 2 dấu Tab liền kề nhau: (1+2*3)/Tab Tab 10 có giá trị là 10
- 2 dấu Tab này nằm trong chuỗi 1 (không ảnh hưởng đến giá trị, chỉ là chưa được đúng chính tả khi nhập)
2. Em chỉ mới biết dùng Dạng Sub, dạng private Sub muốn áp dụng thì phải làm thế nào, có phải là phải copy vào sheet dutoan mỗi khi mở 1 file
3. Không phải khi nào cũng có chuỗi 1&" "
4. Cells đang có 2 lỗi, giờ cần sửa nên tạo macro (1 macro giải quyết 2 yêu cầu là tốt nhất) (dữ liệu cần sửa nhiều nên ưu tiên tốc độ xử lý và đã có sẵn nên có thể bỏ qua bước sửa lúc nhập sai):
- Macro xoa_chuoi tại bài 198 đã giải quyết xong vấn đề về giá trị
- Cần tiếp macro giải quyết bài toán chính tả: không tồn tại 2 dấu Tab trong Cells thuộc cột E chứa giá trị mà cột D tương ứng rỗng.
- File em đã up ở bài 201
Giúp em, đang cần gấp
 
Lần chỉnh sửa cuối:
Upvote 0
Em giờ mới tìm hiểu về VBA nên mong được các bác giúp.
1. Code trên vẫn chưa giải quyết triệt để nguyên tắc về chính tả là không tồn tại 2 dấu Tab liền kề nhau trong ô.
- Nếu 2 dấu Tab này nằm trong chuỗi 2 thì sẽ làm sai giá trị, ví dụ chuỗi 2 là:
(1+2*3)/10 có giá trị là 0.7
nhưng nếu có lỗi 2 dấu Tab liền kề nhau: (1+2*3)/Tab Tab 10 có giá trị là 10
- 2 dấu Tab này nằm trong chuỗi 1 (không ảnh hưởng đến giá trị, chỉ là chưa được đúng chính tả khi nhập)
2. Em chỉ mới biết dùng Dạng Sub, dạng private Sub muốn áp dụng thì phải làm thế nào, có phải là phải copy vào sheet dutoan mỗi khi mở 1 file
3. Không phải khi nào cũng có chuỗi 1&" "
4. Cells đang có 2 lỗi, giờ cần sửa nên tạo macro (1 macro giải quyết 2 yêu cầu là tốt nhất) (dữ liệu cần sửa nhiều nên ưu tiên tốc độ xử lý và đã có sẵn nên có thể bỏ qua bước sửa lúc nhập sai):
- Macro xoa_chuoi tại bài 198 đã giải quyết xong vấn đề về giá trị
- Cần tiếp macro giải quyết bài toán chính tả: không tồn tại 2 dấu Tab trong Cells thuộc cột E chứa giá trị mà cột D tương ứng rỗng.
- File em đã up ở bài 201
Giúp em, đang cần gấp

Với tôi thì tôi kết thúc tại đây tới khi bạn miêu tả cái mà bạn gõ.
1. Trước dấu ":" có bao nhiêu chuỗi "rời nhau? Chỉ có 1 chuỗi dạng "abc...xyz" + nhiều TAB + dấu cách + ":" hay nhiều chuỗi "rời" kiểu "abc" + Tab, dấu cách + "xyz" + Tab, dấu cách + ":"?
2. Sau ":" có thể có Tab, dấu cách sau đó là "chuỗi". Cái "chuỗi" này bắt đẫu bàng chữ số? Kết thúc bằng chữ số? Còn trong "giữa" là có gì? Chữ số + chữ cái + tab, dấu cách + "+, -, *, /" (4 phép tính số học)?
3. Sau "chuỗi" ở trên là là Tab, dấu cách và "=" và một loạt ký tự tùy ý cho tới cuối?
Miêu tả cho rõ bạn ạ. Bạn kêu là code chưa chuẩn nhưng người ta có biết rõ dữ liệu của bạn thế nào đâu để viết cho chuẩn?
Bạn nói: Macro xoa_chuoi tại bài 198 đã giải quyết xong vấn đề về giá trị
Thế code của tôi chưa giải quyết xong vấn đề về giá trị?
Bạn không miêu tả, chỉ cho ví dụ thì 1000 ví dụ chưa chắc đã nói hết về kiểu dữ liệu. Mất thời gian với bạn quá.
Tôi cũng nói rồi: dùng cách của quanghai thì sau khi đã cắt "đuôi" "=...." thì làm tiếp bỏ các dấu cách và Tab.
Mà bạn miêu tả kết quả phải có nữa nhé. Tôi cho vd. Nếu có phép tính +, -, *, / thì trước và sau mỗi toán tử có phải cho dấu cách không? Vd. 1 + 2 hay phải là 1+2? Bạn cung cấp thông tin nhỏ gọt thì tôi xin rút lui.
 
Upvote 0
Em giờ mới tìm hiểu về VBA nên mong được các bác giúp.
1. Code trên vẫn chưa giải quyết triệt để nguyên tắc về chính tả là không tồn tại 2 dấu Tab liền kề nhau trong ô.
- Nếu 2 dấu Tab này nằm trong chuỗi 2 thì sẽ làm sai giá trị, ví dụ chuỗi 2 là:
(1+2*3)/10 có giá trị là 0.7
nhưng nếu có lỗi 2 dấu Tab liền kề nhau: (1+2*3)/Tab Tab 10 có giá trị là 10
- 2 dấu Tab này nằm trong chuỗi 1 (không ảnh hưởng đến giá trị, chỉ là chưa được đúng chính tả khi nhập)
2. Em chỉ mới biết dùng Dạng Sub, dạng private Sub muốn áp dụng thì phải làm thế nào, có phải là phải copy vào sheet dutoan mỗi khi mở 1 file
3. Không phải khi nào cũng có chuỗi 1&" "
4. Cells đang có 2 lỗi, giờ cần sửa nên tạo macro (1 macro giải quyết 2 yêu cầu là tốt nhất) (dữ liệu cần sửa nhiều nên ưu tiên tốc độ xử lý và đã có sẵn nên có thể bỏ qua bước sửa lúc nhập sai):
- Macro xoa_chuoi tại bài 198 đã giải quyết xong vấn đề về giá trị
- Cần tiếp macro giải quyết bài toán chính tả: không tồn tại 2 dấu Tab trong Cells thuộc cột E chứa giá trị mà cột D tương ứng rỗng.
- File em đã up ở bài 201
Giúp em, đang cần gấp
Mình cũng đã cố hết khả năng để giúp cho bạn nhưng với cách bạn mô tả yêu cầu thì mình xin chào thua. Hãy kiên nhẫn đợi thành viên khác giúp nhé.
 
Upvote 0
Rất cảm ơn các bác Hoàng Trọng Nghĩa, quanghai1969,siwtom đã nhiệt tình giúp đỡ và chỉ bảo cho em.
Hiện tại em có thể sử dụng code ở bài 198 để sử dụng trong khi làm dự toán xây dựng do nhu cầu của em là tốc độ và dễ sử dụng (em không biết sử dụng hàm Private Sub nên các bác thông cảm cho).
Em chỉ thắc mắc về bài toán viết chính tả khi nhập dữ liệu (giống tác dụng của hàm Trim):
Giá trị cần thao tác tại cột E có giá trị, cột D tương ứng rỗng.
Có thể tạo macro: sau khi chạy macro thì chuyển E8 thành Trim(E8) (thao tác tất cả trong ô E8, nếu phải đặt ô phụ thì sẽ xoá đi sau khi macro chạy xong)
 
Upvote 0
Nhờ các bác xem giúp em code chèn nhiều dòng
Sub Themdong()
Dim tongdong, message, title, default
message = "Chuyen con tro len tren dong TONG CONG va nhap so dong muon them:"
title = "Them dong"
default = "10"
tongdong = InputBox(message, title, default)
If tongdong = "" Then
Exit Sub
End If
For sodong = 1 To tongdong
Selection.EntireRow.Insert
Next sodong
End Sub
Code xử lý chậm khi số dòng lớn, ví dụ như 2000 trở lên. Nhờ bác nào viết code tác dụng tương tự tối ưu tốc độ xử lý
 
Upvote 0
Rất cảm ơn các bác Hoàng Trọng Nghĩa, quanghai1969,siwtomđã nhiệt tình giúp đỡ và chỉ bảo cho em.
Hiện tại em có thể sử dụng code ở bài 198 để sử dụng trong khi làm dự toán xây dựng do nhu cầu của em là tốc độ và dễ sử dụng (em không biết sử dụng hàm Private Sub nên các bác thông cảm cho).
Em chỉ thắc mắc về bài toán viết chính tả khi nhập dữ liệu (giống tác dụng của hàm Trim):
Giá trị cần thao tác tại cột E có giá trị, cột D tương ứng rỗng.
Có thể tạo macro: sau khi chạy macro thì chuyển E8 thành Trim(E8) (thao tác tất cả trong ô E8, nếu phải đặt ô phụ thì sẽ xoá đi sau khi macro chạy xong)

Mượn lại code của QuangHai, tôi chỉ chỉnh một tí xíu, bạn xem có đúng ý bạn chưa?

Mã:
Sub xoa_chuoi1()
Dim i, kq()
kq = Range([E8], [E65536].End(3)).Offset(, -1).Resize(, 2).Value
With CreateObject("vbscript.regexp")
   .Global = True
   .Pattern = "=.*"
   For i = 1 To UBound(kq)
      If kq(i, 1) = "" Then
         If kq(i, 2) <> "" Then
            kq(i, 2) = .Replace([COLOR=#ff0000][B]WorksheetFunction.Trim([/B][/COLOR]kq(i, 2)[B][COLOR=#ff0000])[/COLOR][/B], "")
         End If
      End If
   Next
End With
[D8].Resize(i - 1, 2) = kq
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Mình cũng vừa mới tập tành VBA và có cái file nghich ngợm về Tổ tôm không biết cho vào chủ đề nào muốn hỏi các bro mấy vấn đề là:
1. Tại sao khi chạy Sub Chia_bai thì lúc đầu các quân bài hiện ra nhanh, sau đó lại chậm dần.
2. Có thể bỏ mấy Sheet trung gian và hiện thẳng quân bài vào Sheet hinh_anh_cac_bai như thế nào.
3. Có thể gọn các dòng sau các case thế nào, hoặc có cách gì gọn hơn được không.

Case "1sa"
Cells(row_to_check + 1, column_to_check).Select
Sheets("quan_bai").Select
ActiveSheet.Shapes.Range(Array("1sa")).Select
Selection.Copy
Sheets("hinh_anh_cac_bai").Select
ActiveSheet.Paste


File đính kèm View attachment VuiCungToTom.rar
Xin cảm ơn trước.
 
Lần chỉnh sửa cuối:
Upvote 0
Mượn lại code của QuangHai, tôi chỉ chỉnh một tí xíu, bạn xem có đúng ý bạn chưa?

Mã:
Sub xoa_chuoi1()
Dim i, kq()
kq = Range([E8], [E65536].End(3)).Offset(, -1).Resize(, 2).Value
With CreateObject("vbscript.regexp")
   .Global = True
   .Pattern = "=.*"
   For i = 1 To UBound(kq)
      If kq(i, 1) = "" Then
         If kq(i, 2) <> "" Then
            kq(i, 2) = .Replace([COLOR=#ff0000][B]WorksheetFunction.Trim([/B][/COLOR]kq(i, 2)[B][COLOR=#ff0000])[/COLOR][/B], "")
         End If
      End If
   Next
End With
[D8].Resize(i - 1, 2) = kq
End Sub
Bác xem giúp em cái file em gửi lên, chạy macro xong bị lỗi giá trị của ô E21, tăng gấp 1000 lần so với giá trị ban đầu.
Còn lại các dòng khác xử lý rất hay, đúng theo yêu cầu không tồn tại 2 dấu Tab liền kề nhau.
 

File đính kèm

Upvote 0
Bác xem giúp em cái file em gửi lên, chạy macro xong bị lỗi giá trị của ô E21, tăng gấp 1000 lần so với giá trị ban đầu.
Còn lại các dòng khác xử lý rất hay, đúng theo yêu cầu không tồn tại 2 dấu Tab liền kề nhau.

Đọc xong chả hiểu cái gì là cái gì hết! Diễn giải trong Sheet càng khó hiểu hơn, lúc thì ô E21, khi thì ô E23 mà thực sự giá trị ban đầu nó thế nào? Và muốn nó thành như thế nào?
 
Upvote 0
Đọc xong chả hiểu cái gì là cái gì hết! Diễn giải trong Sheet càng khó hiểu hơn, lúc thì ô E21, khi thì ô E23 mà thực sự giá trị ban đầu nó thế nào? Và muốn nó thành như thế nào?
Diễn giải em ghi nhầm,đúng là ô 21.
Em đã tìm ra lỗi tăng gấp 1000 lần là do trong phần mềm aciit mặc định lại dấu "," và dấu "."
Macro của bác Hoàng Trọng Nghĩa ở bài 212 đã giải quyết triệt để 2 yêu cầu em cần. Macro này sẽ rất hữu ích cho ai sử dụng phần mềm dự toán aciitt trong xây dựng.
1 lần nữa cảm ơn các bác rất nhiều.
 
Upvote 0
Diễn giải em ghi nhầm,đúng là ô 21.
Em đã tìm ra lỗi tăng gấp 1000 lần là do trong phần mềm aciit mặc định lại dấu "," và dấu "."
Macro của bác Hoàng Trọng Nghĩa ở bài 212 đã giải quyết triệt để 2 yêu cầu em cần. Macro này sẽ rất hữu ích cho ai sử dụng phần mềm dự toán aciitt trong xây dựng.
1 lần nữa cảm ơn các bác rất nhiều.

Nói rõ hơn, cái Macro này là của quanghai1969 tôi chỉ sửa lại chút xíu thôi. Dù sao nó chạy hiệu quả là tốt rồi!
 
Upvote 0
Hỏi về cách viết code?

Xin chào Thầy Cô và Anh Chị trong GPE!
Em có 1 câu hỏi dưới đây mong mọi người tìm cách giúp Em với ạ!
Em hay viết code kiểu này:
HTML:
…
Sheets("$").Visible = 2
Sheets(1).Visible = 2
Range("F10:F361").AutoFilter Field:=1
Range("F11:F355"). EntireRow.Hidden = False
…
Và đôi khi Em cũng hay phải thêm sheet , xóa sheet và thay đổi tên sheet. Nên code lại phải chỉnh sửa lại.
Hoặc là khi insert dòng cột cũng phải sửa lại vùng v..v..Vì vậy em muốn hỏi có cách viết code nào khác để mỗi lần khi có sự thay đổi như vậy mình không phải thao tác trong cửa sổ lập trình nữa không ạ?
Vì file này nhiều người sử dụng nên Em mới hỏi cho vấn đề này ạ.
Em mới chỉ biết cái Range("F10:F361") này ta có thể đặt name là :kumi= '$'!$F$10:$F$361 chẳng hạn. Sau đó code sẽ viết thành:Range(kumi).
Nhưng còn cách viết code cho Sheets thì Em chịu thôi. Thầy Cô và Anh Chị xem có cách viết nào khác không giúp Em với ạ!
Trân thành cám ơn!
 
Upvote 0
Xin chào Thầy Cô và Anh Chị trong GPE!
Em có 1 câu hỏi dưới đây mong mọi người tìm cách giúp Em với ạ!
Em hay viết code kiểu này:
HTML:
…
Sheets("$").Visible = 2
Sheets(1).Visible = 2
Range("F10:F361").AutoFilter Field:=1
Range("F11:F355"). EntireRow.Hidden = False
…
Và đôi khi Em cũng hay phải thêm sheet , xóa sheet và thay đổi tên sheet. Nên code lại phải chỉnh sửa lại.
Hoặc là khi insert dòng cột cũng phải sửa lại vùng v..v..Vì vậy em muốn hỏi có cách viết code nào khác để mỗi lần khi có sự thay đổi như vậy mình không phải thao tác trong cửa sổ lập trình nữa không ạ?
Vì file này nhiều người sử dụng nên Em mới hỏi cho vấn đề này ạ.
Em mới chỉ biết cái Range("F10:F361") này ta có thể đặt name là :kumi= '$'!$F$10:$F$361 chẳng hạn. Sau đó code sẽ viết thành:Range(kumi).
Nhưng còn cách viết code cho Sheets thì Em chịu thôi. Thầy Cô và Anh Chị xem có cách viết nào khác không giúp Em với ạ!
Trân thành cám ơn!
Xóa sheet thì ăn nhậu gì được nữa?
Thay đổi tên sheet bạn lấy CodeName sheet thì code không thay đổi
VD: Sheet1.Range(..).. chứ khong phải là Sheets("Sheet1").Range(..)...
 
Upvote 0
Hỏi để hiểu thêm về vòng lặp và cấu trúc điều khiển If

Mình tập tành học VBA nhưng vì tự học nên có nhiều khi bí rị. Mình nhờ các bạn chỉ một chút để mình có thể áp dụng vào hiểu thêm về vòng lặp và cấu trúc điều khiển If. Ví dụ như nếu ô C4 là "Giỏi" thì ô D4 được gán giá trị "5", nếu là C4 là "Khá" thì D4 được gán "4" và cứ lặp như thế trong vùng C4:C8 để gán giá trị tương ứng cho D4:D8. Tương tự như vậy là dò tìm giá trị cho E4:E8 để gán giá trị cho F4:F8.
Cách thông thường là dùng hàm If hoặc dùng Vlookup. Nhưng mình muốn hiểu thêm về vòng lặp và cấu trúc điều khiển If trong VBA. Mong các bạn viết đoạn code mẫu để mình học thêm. Cám ơn rất nhiều.
 

File đính kèm

Upvote 0
PHP:
Option Explicit
Sub GPE()
 Dim Cls As Range
 Dim HL As String
 
 For Each Cls In Range([C4], [C4].End(xlDown))
    HL = Left(Cls.Value, 2)
    If HL = "Gi" Then
        Cls.Offset(0, 1).Value = 5
    ElseIf HL = "Kh" Then
        Cls.Offset(0, 1).Value = 4
    ElseIf HL = "TB" Then
        Cls.Offset(0, 1).Value = 3
    ElseIf HL = "Ké" Then
        Cls.Offset(0, 1).Value = 1
    Else
        Cls.Offset(0, 1).Value = 2
    End If
 Next Cls
End Sub
 
Upvote 0
Nhờ sửa giúp đoạn code sau.

Với code trên em chỉ có thể chạy được trên sheet Tong hop N-X. Nếu chuyển qua sheet khác chạy code trên thì báo lỗi dòng With sheet3.range([f8], [F56636].End(xlUp)). Anh chị có thể sửa lại giúp em với.
With Sheet3.Range([f8], [F56636].End(xlUp))
.Offset(1, 0).Value = "=SUMIF('Nhap - Xuat'!$E$7:$E$1020,'Tong hop N-X'!B9,'Nhap - Xuat'!$H$7:$H$1020)"
.Offset(1, 1).Value = "=SUMIF('Nhap - Xuat'!$E$7:$E$1020,'Tong hop N-X'!B9,'Nhap - Xuat'!$j$7:$j$1020)"
.Offset(1, 2).Value = "=SUMIF('Nhap - Xuat'!$E$7:$E$1020,'Tong hop N-X'!B9,'Nhap - Xuat'!$i$7:$i$1020)"
.Offset(1, 3).Value = "=SUMIF('Nhap - Xuat'!$E$7:$E$1020,'Tong hop N-X'!B9,'Nhap - Xuat'!$k$7:$k$1020)"
.Offset(1, 4).Value = "=(d9+F9-H9)"
.Offset(1, 5).Value = "=(e9+g9-i9)"
With .Resize(, 6)
.Value = .Value
On Error Resume Next
End With
End With
 
Upvote 0
Không nói rõ nội dung thông báo lỗi như thế nào nhưng Dòng này : With Sheet3.Range([f8], [F56636].End(xlUp))

bạn thêm thành : With Sheet3.Range(sheet3.[f8], sheet3.[F56636].End(xlUp))

Xem có bị lỗi nữa không nhé - không biết tôi có hiểu nhầm ý bạn không (đứng ở sheet khác chạy code cho sheet3)

Mình đọc lại chỗ này :Nếu chuyển qua sheet khác nghĩa là ta phải thay thằng sheet3 thành thằng sheet khác chính là sheet mà mình muốn chạy code rồi, thế thì bạn phải xem sheet bạn đang chạy code là sheet nào để thay cho chuẩn nhé vì không có file đính kèm nên không biết chỉ cho bạn thay bằng sheet nào, hix
 
Lần chỉnh sửa cuối:
Upvote 0
Cảm ơn mình làm được rồi. Đúng là đổi thành :With Sheet3.Range(sheet3.[f8], sheet3.[F56636].End(xlUp)) mới chạy.
 
Upvote 0
Bạn nên viết như thế này dễ nhìn hơn:

With Sheet3.Range("F8:F" & Sheet3.[F65536].End(3).Row)
 
Upvote 0
Anh cho em hỏi End(3) = End(xlup) hả anh?

Người ta thường viết tắt theo vị trí của phương thức này:

xlToLeft = 1

xlToRight = 2

xlUp = 3

xlDown = 4

Nhưng nếu đúng trong list contants thì nó phải như sau:

xlToLeft = -4159

xlToRight = -4161

xlUp = -4162

xlDown = -4121

Nhưng cá nhân tôi thì thích viết kiểu chuỗi, nó thể hiện một cách tường minh, nhìn vào khỏi cần thắc mắc nó là gì.
 
Upvote 0
Người ta thường viết tắt theo vị trí của phương thức này:

xlToLeft = 1

xlToRight = 2

xlUp = 3

xlDown = 4

Nhưng nếu đúng trong list contants thì nó phải như sau:

xlToLeft = -4159

xlToRight = -4161

xlUp = -4162

xlDown = -4121

Nhưng cá nhân tôi thì thích viết kiểu chuỗi, nó thể hiện một cách tường minh, nhìn vào khỏi cần thắc mắc nó là gì.

Không chỉ là vấn đề chuyên nghiệp mà đúng là phải tường minh. Mình viết sao cho người khác đọc cũng hiểu.
Mà bạn hãy tưởng tượng một code dùng toàn số xem sao. Rồi ai viết trong API cũng thay mọi thông điệp bằng số hết thì chắc là ngày hôm nay bạn tìm kiếm trên google vất vả lắm. Muốn tìm những ví dụ hướng dẫn dùng thông điệp WM_HICHIC thì không tìm thấy vì những tác giả đã viết 2 (3, 5, 1000) thay cho WM_HICHIC rồi. Mà gõ vào google số 2 để tìm? Có mà điên.

Ngay cả khi tự tạo cho mình một thông điệp riêng cũng chả ai lấy nó là xyz cả. Mà phải là

Private/Public "một cái tên gợi ý rất nhiều" = xyz

Dùng toàn số là a ma tơ, là thói quen xấu. Cứ hỏi bất cứ ai có kinh nghiệm lập trình thì người ta cũng sẽ nói như thế. Chấm hết.
 
Upvote 0
Làm thế nào để VBA chỉ có tác dụng cho file chứa code?

Em xin hỏi:
- Tại sao file chứa code VBA của em khi mở lên lại có tác dụng cho cả các file khác?
+ Trong Workbook em viết:
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
Call Callsub
End Sub
+ Trong Module em viết:
Sub Callsub()
Application.OnKey "{ENTER}", "FindPic"
End Sub

Khi em mở các file khác thì đều thực thi code này.
Xin các anh chỉ giáo!
 
Upvote 0
Em xin hỏi:
- Tại sao file chứa code VBA của em khi mở lên lại có tác dụng cho cả các file khác?
+ Trong Workbook em viết:
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
Call Callsub
End Sub
+ Trong Module em viết:
Sub Callsub()
Application.OnKey "{ENTER}", "FindPic"
End Sub

Khi em mở các file khác thì đều thực thi code này.
Xin các anh chỉ giáo!

OnKey là phương thức của object Application mà. Vậy nhấn Enter trong "toàn bộ lãnh thổ" sẽ gây ra việc thực thi FindPic.
Nếu bạn chỉ muốn thực thi FindPic khi nhấn Enter trong tỉnh xyz thôi thì ...


Bạn làm thế này

ThisWorkbook
Mã:
Private Sub Workbook_Activate()
    Callsub True
End Sub

Private Sub Workbook_Deactivate()
    Callsub False
End Sub

module
Mã:
Sub Callsub(ByVal DoSet As Boolean)
    If DoSet Then
        Application.OnKey "{ENTER}", "FindPic"
    Else
        Application.OnKey "{ENTER}", ""
    End If
End Sub

Hoặc

Mã:
Private Sub Workbook_Activate()
    Application.OnKey "{ENTER}", "FindPic"
End Sub

Private Sub Workbook_Deactivate()
    Application.OnKey "{ENTER}", ""
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Cảm ơn anh Nghĩa nhiều lắm ạ! Tại em thấy có 1 số code vẫn dùng if......Endif nên gặp IIF em không hiểu là gì?
Anh Nghĩa và anh Ba Tê có thể suy nghĩ giúp đỡ em 3 hàm còn lại trong File đính kèm ở bài #233 được không ạ. Nếu có thêm chú thích cho em thì càng tốt. Em mới tìm hiểu về VBA nên còn nhiều điều bỡ ngỡ lắm ạ!
P/S: Nhân tiện cho em hỏi ý nghĩa UBound trong lệnh For I = 1 To UBound(Arr, 1) với ạ.

Những cái khác bạn từ từ nghiên cứu, học lập trình thì chớ vội vàng chi! Nhưng với dòng màu đỏ, Ubound là hàm để tính cận trên của một mảng (array).

Cận trên (Ubound), cận dưới (Lbound) là gì? Tạm thời bạn xem ở bài này nhé:

http://www.giaiphapexcel.com/forum/showthread.php?22361-Lbound-và-UBound-là-gì&p=155471#post155471
 
Upvote 0
Những cái khác bạn từ từ nghiên cứu, học lập trình thì chớ vội vàng chi! Nhưng với dòng màu đỏ, Ubound là hàm để tính cận trên của một mảng (array).

Cận trên (Ubound), cận dưới (Lbound) là gì? Tạm thời bạn xem ở bài này nhé:

http://www.giaiphapexcel.com/forum/showthread.php?22361-Lbound-và-UBound-là-gì&p=155471#post155471
Em cảm ơn anh nhiều ạ! Anh Nghĩa cho em hỏi ngoài hàm Ubound có thể thay bằng hàm nào khác không ạ?
 
Lần chỉnh sửa cuối:
Upvote 0
Tôi viết lại theo kiểu tôi làm:
PHP:
Public Function GetMon(Ngay As Date, Thu As Long, Tiet As Long, Rng As Range) As Variant
Dim Arr(), Cll As Range, I As Long, J As Long, Col As Long
With Sheets("tkb")
    Arr = Rng.Value
    For I = 1 To UBound(Arr, 1)
        If Arr(I, 1) = Ngay Then
            Col = ((Thu - 1) * 10 - 9) + (Tiet * 2 - 1)
            GetMon = IIf(Arr(I, Col) = "", "", Arr(I, Col))
            Exit For
        End If
    Next I
End With
End Function
Ví dụ ô C6 thì công thức là:
=GetMon($A$8;$A$7;$B6;Tkb!$B$4:$BJ$41)

Anh Ba Tê có thể giúp em viết tiếp 3 hàm còn lại không ạ?
 
Lần chỉnh sửa cuối:
Upvote 0
Ubound là hàm để tính cận trên của một mảng (array).

Cận trên (Ubound), cận dưới (Lbound) là gì? Tạm thời bạn xem ở bài này nhé:

http://www.giaiphapexcel.com/forum/showthread.php?22361-Lbound-và-UBound-là-gì&p=155471#post155471

Không phải cận trên và cận dưới, mà là chỉ số trên và chỉ số dưới. Trong toán học và lập trình phải phát biểu cho chính xác.

Cận trên của 1 số A trong 1 mảng giá trị là số nhỏ nhất của mảng, và lớn hơn A
Cận dưới của số A trong 1 mảng giá trị là số lớn nhất của mảng, và nhỏ hơn A

Với Base 0 thì LBound = 0, UBound = số phần tử của chiều đang đếm - 1
Với Base 1 và mảng lấy giá trị trực tiếp từ range trên sheet thì LBound = 1, UBound = số phần tử của chiều đang đếm

Nói chiều đang đếm vì mảng có thể có 1 hoặc nhiều chiều. LBound và UBound phải nói rõ tính theo chiều nào, không ghi thì hiểu là chiều thứ nhất.
 
Upvote 0
Không phải cận trên và cận dưới, mà là chỉ số trên và chỉ số dưới. Trong toán học và lập trình phải phát biểu cho chính xác.

Cận trên của 1 số A trong 1 mảng giá trị là số nhỏ nhất của mảng, và lớn hơn A
Cận dưới của số A trong 1 mảng giá trị là số lớn nhất của mảng, và nhỏ hơn A

Với Base 0 thì LBound = 0, UBound = số phần tử của chiều đang đếm - 1
Với Base 1 và mảng lấy giá trị trực tiếp từ range trên sheet thì LBound = 1, UBound = số phần tử của chiều đang đếm

Nói chiều đang đếm vì mảng có thể có 1 hoặc nhiều chiều. LBound và UBound phải nói rõ tính theo chiều nào, không ghi thì hiểu là chiều thứ nhất.
Thầy Mĩ có thể nghiên cứu giúp em các code trong File đính kèm ở #233 và giải thích giúp em được không ạ.
 
Upvote 0
Không phải cận trên và cận dưới, mà là chỉ số trên và chỉ số dưới. Trong toán học và lập trình phải phát biểu cho chính xác.

Nếu Sư phụ giỏi hơn người viết cuốn sách lập trình căn bản này (file pdf) thì hãy sửa lưng người khác Sư phụ nhé!

http://www.giaiphapexcel.com/forum/...ung-kiến-thức-căn-bản-VBA&p=539115#post539115


Trích tại trang 11:

Xác định cận của mảng:
Các hàm Ubound và LBound có thể tìm cận trên và dưới của một mảng.
Cú pháp:
x = UBound(arrayname)
UBound trả lại chỉ số cao nhất của mảng. Số phần tử thật sự của mảng phụ thuộc vào
điểm bắt đầu của mảng. Nếu dùng cận dưới mặc định của mảng là 0, Ubound nhỏ hơn
số phần tử 1.
iArraySize = UBound(array) + 1
Tuy nhiên, công thức chính xác là:
iArraySize = UBound(array) – LBound(array) + 1

Các bạn mới học lập trình cũng nên tải sách này về (tại link trên) để tham khảo một cách cơ bản về lập trình!
 
Lần chỉnh sửa cuối:
Upvote 0
Nếu Sư phụ giỏi hơn người viết cuốn sách lập trình căn bản này (file pdf) thì hãy sửa lưng người khác Sư phụ nhé!

Tôi không giỏi hơn ai, cũng không sửa lưng. Tôi phát biểu vì tôi thấy là sai. Ai thấy tôi sai thì tranh luận.

Cận theo tiếng Hán Việt là "gần". Gần trên và gần dười thường dùng trong việc tìm kiếm không chính xác, cũng như dò tìm trong phép nội suy.
 
Upvote 0
Không phải cận trên và cận dưới, mà là chỉ số trên và chỉ số dưới. Trong toán học và lập trình phải phát biểu cho chính xác.

1) Thật sự mà nói là tôi nói theo sách nói chứ không phải tôi tự chế ra mà nói.

2) Bound theo tôi nghĩ nó là biên giới, vậy theo tôi nói, Hàm Ubound để xác định BIÊN TRÊN và Lbound để xác định BIÊN DƯỚI. Vậy có ai bàn gì về cái tôi nói hay không?
 
Upvote 0
1) Thật sự mà nói là tôi nói theo sách nói chứ không phải tôi tự chế ra mà nói.

2) Bound theo tôi nghĩ nó là biên giới, vậy theo tôi nói, Hàm Ubound để xác định BIÊN TRÊN và Lbound để xác định BIÊN DƯỚI. Vậy có ai bàn gì về cái tôi nói hay không?

Biên trên và biên dưới thì đúng. Chỉ khi dùng cận mới sai. Cận là "gần"

Tôi phải nhắc lại bao nhiêu lần rằng hãy chỉ ra chỗ sai của tôi, chứ đừng cãi ngang mà không đọc?
 
Lần chỉnh sửa cuối:
Upvote 0
Em cảm ơn anh nhiều ạ! Anh Nghĩa cho em hỏi ngoài hàm Ubound có thể thay bằng hàm nào khác không ạ?

Khi bạn thao tác trên một mảng được truyền vào dưới dạng tham số chẳng hạn thì nhiều khi bạn không biết được chỉ số dưới/trên của chiều nhất định là thế nào. Tại sao? Vì người dùng có thể truyền mảng được trả về bởi một hàm nào đó. Thậm chí những hàm có sẵn cũng trả về mảng mà chỉ số dưới không nhất quán: vd. hàm Split trả về mảng mà chỉ số dưới luôn là 0, hàm Array trả về mảng mà chỉ số dưới là 0 nếu không có Option Base hoặc có Option Base 0, còn nếu có Option Base 1 thì mảng trả về có chỉ số dưới là 1. Ngoài ra một hàm tự tạo bất kỳ cũng có thể trả về một mảng. Mà lúc đó thì chả có qui luật gì cả. Vd. người ta có thể trả về mảng mà chỉ số dưới là 5, -3, 10 ...

Bạn có thói quen trả về mảng có chỉ số dưới là 1 (0)? Nhưng không có nghĩa là không có vị nào trả về mảng có chỉ số dưới <> 0, 1.

Ví dụ code
Mã:
Sub he()
Dim a, arr(4 To 8, 3 To 5)
    a = Array(3, 4, 5)
    MsgBox a(0)
    MsgBox LBound(arr, 1)   '   = 4
End Sub

Nếu không có Option Base hoặc có Option Base 0 thì code chạy "ngon". Nhưng nếu có Option Base 1 thì sẽ có lỗi "Subscript out of range" vì mảng trả về bởi hàm Array có chỉ số dưới là 1. Truy cập tới phần tử có chỉ số 0 thì rõ ràng có lỗi rồi.

Trong ví dụ trên thì rõ ràng mảng arr có chỉ số dưới của chiều thứ nhất là 4, không phụ thuộc vào Option Base. Tất nhiên truy cập tới vd. Arr(1, 4) là có lỗi vì chỉ số của chiều thứ nhất chỉ có thể là 4, 5, 6, 7 hoặc 8. Nói nôm na thì mảng có 5 dòng và 3 cột nhưng các dòng có chỉ số là 4, 5, 6, 7 hoặc 8, còn các cột có chỉ số là 3, 4 hoặc 5.

Vì chỉ số dưới và trên có thể bất kỳ - không chắc chắn là 0, 1 hay giá trị nào đó - nên khi thao tác trên mảng thì an toàn nhất là dùng LBound và UBound.
Vd.
Mã:
    For r = LBound(arr) To UBound(arr)
        For c = LBound(arr, 2) To UBound(arr, 2)
            ...
        Next
    Next

Chỉ khi ta biết chắc chắn chỉ số dưới là thế nào thì có thể không dùng LBound.
Vd. nếu ta có
Mã:
Sub he()
Dim arr
    arr = Range("D12:F24")
    ...
End Sub

Thì chỉ số dưới của 2 chiều đều là 1

Theo tôi nghĩ thì trong VBA không có hàm nào ngoài L/UBound. Vì các hàm này là quá đơn giản rồi. Dù có thêm hàm nào chăng nữa thì nó cũng phải có ít nhất 2 đối số: mảng để biết trả về kết quả cho mảng cụ thể nào, và chiều để biết trả về cho chiều nào. Vậy thì tại sao lại phải đẻ thêm 1 hàm khác? Và bạn muốn có hàm khác để làm gì?
 
Upvote 0
Biên trên và biên dưới thì đúng. Chỉ khi dùng cận mới sai. Cận là "gần"

Tôi phải nhắc lại bao nhiêu lần rằng hãy chỉ ra chỗ sai của tôi, chứ đừng cãi ngang mà không đọc?
Vậy phát biểu không chính xác thì Thầy siwtom cũng phát biểu sai hay sao?

Không đúng. Tôi nhìn thấy là các chuỗi được phân cách bởi 2 ký tự là ";" và " ". Đối với bạn có thể " " chả là gì cả nhưng bạn hãy tin rằng ký tự dấu cách " " là ký tự "ngag hàng" với tất cả các ký tự khác.



Một ví dụ

Module
Mã:
Public Sub QuickSort1DArray(Arr, iLo As Long, iHi As Long, ByVal sortAtoZ As Boolean)
'    Arr là mảng cần sắp xếp
'    sortAtoZ xác định cách sắp xếp tăng hay giảm
[COLOR=#ff0000][B]'    iLo là cận dưới của mảng Arr, iHi là cận trên của mảng Arr[/B][/COLOR]

Dim Lo As Long, Hi As Long, iMid, DoChange As Boolean, s

    Do
        Lo = iLo
        Hi = iHi
        
        iMid = Arr((Lo + Hi) \ 2)
        Do
            If sortAtoZ Then
                Do While Arr(Lo) < iMid
                    Lo = Lo + 1
                Loop
                Do While Arr(Hi) > iMid
                    Hi = Hi - 1
                Loop
            Else
                Do While Arr(Lo) > iMid
                    Lo = Lo + 1
                Loop
                Do While Arr(Hi) < iMid
                    Hi = Hi - 1
                Loop
            End If
            
            If Lo <= Hi Then
                If sortAtoZ Then
                    DoChange = (Arr(Lo) > Arr(Hi))
                Else
                    DoChange = (Arr(Lo) < Arr(Hi))
                End If
                If DoChange Then
                    s = Arr(Lo)
                    Arr(Lo) = Arr(Hi)
                    Arr(Hi) = s
                End If
                
                Lo = Lo + 1
                Hi = Hi - 1
            End If
        Loop Until Lo > Hi
        If Hi > iLo Then QuickSort1DArray Arr, iLo, Hi, sortAtoZ
        iLo = Lo
    Loop Until Lo >= iHi
End Sub

Sub Button1_Click()
Dim s As String, k As Long, Arr, result() As String
    ReDim result(1 To [B][COLOR=#ff0000]4[/COLOR][/B], 1 To 1)
    
    For k = 1 To[B][COLOR=#ff0000] 4[/COLOR][/B]
        s = Cells(k, 1).Value
        Arr = Split(s, "; ")
        QuickSort1DArray Arr, LBound(Arr), UBound(Arr), True
        result(k, 1) = Join(Arr, "; ")
    Next
    
    Range("B1").Resize(UBound(result)).Value = result
End Sub

Nếu số dòng khác đi thì sửa chố đỏ đỏ
http://www.giaiphapexcel.com/forum/showthread.php?86365-Hỏi-về-cách-sort-array&p=538522#post538522
 
Upvote 0

Tôi cũng thấy là nên dùng "chỉ số" thay cận. Dùng cận cũng được, do nhiều khi ta dùng cách nói "bình dân", nhưng dùng "chỉ số" là chính xác.
------------
Nếu tôi không lầm thì trong Toán học khái niệm cận cũng có thể hiểu là "giới hạn". Ví dụ ta có tập vô hạn các số tăng dần (chuỗi số) có giới hạn là g. g là số nhỏ nhất trong tập số thực mà > tất cả các số của tập (chuỗi) kia. Nói cách khác thì g không thuộc tập kia. Nhưng L/UBound thì "chắc chắn" thuộc "tập các chỉ số" của mảng. Vậy có thể chấp nhận rằng: dùng cận là không chính xác.
 
Lần chỉnh sửa cuối:
Upvote 0
Tôi cũng thấy là nên dùng "chỉ số" thay cận. Dùng cận cũng được, do nhiều khi ta dùng cách nói "bình dân", nhưng dùng "chỉ số" là chính xác.
Chỉ số là Index, Bound là Biên, vậy dùng đúng là biên chứ không phải là chỉ số, theo em là vậy!

LBound có nghĩa là Low Bound và UBound có nghĩa là Up Bound vậy phải là Biên Dưới và Biên Trên chứ không thể nói là Chỉ số Trên, Chỉ số dưới.
 
Lần chỉnh sửa cuối:
Upvote 0
Nếu tôi không lầm thì trong Toán học khái niệm cận cũng có thể hiểu là "giới hạn". Ví dụ ta có tập vô hạn các số tăng dần (chuỗi số) có giới hạn là g. g là số nhỏ nhất trong tập số thực mà > tất cả các số của tập (chuỗi) kia. Nói cách khác thì g không thuộc tập kia. Nhưng L/UBound thì "chắc chắn" thuộc "tập các chỉ số" của mảng. Vậy có thể chấp nhận rằng: dùng cận là không chính xác.

Ở đây phải phân biệt rõ ràng, nếu nó CẬN là chưa chính xác thì CHỈ SỐ cũng không chính xác, bởi, CHỈ SỐ từ 0 đến 10 thì mỗi giá trị là một chỉ số, còn 0 và 10 mới chính là số biên, không thể thay thế số biên ở giữa được, nhưng nói chỉ số 2 đến chỉ số 9 trong tập 0 đến 10 đều được. Vậy thì dùng CHỈ SỐ LÀ KHÔNG HỢP LÝ.

Cho nên phải gọi LBOUND hay UBOUND là hàm xác định SỐ BIÊN DƯỚI & SỐ BIÊN TRÊN của một mảng là hoàn toàn chính xác.
 
Upvote 0
Chỉ số là Index, Bound là Biên, vậy dùng đúng là biên chứ không phải là chỉ số, theo em là vậy!

LBound có nghĩa là Low Bound và UBound có nghĩa là Up Bound vậy phải là Biên Dưới và Biên Trên chứ không thể nói là Chỉ số Trên, Chỉ số dưới.

Người ta dùng chỉ số vì như anh siwtom nói, LBound và UBound thuộc về 1 tập hợp các chỉ số. Nghĩa là có chỉ số trên, chỉ số dưới, và chỉ số giữa giữa. Còn biên thì chỉ có ở 2 đầu.

Nếu dùng biên thì không sai, nhưng khi truy xuất phần tử thứ n, thì n vẫn sẽ được gọi là chỉ số: Số chỉ ra vị trí của phần tử. Nếu số n chỉ ra vị trí biên dưới thì n là LBound, nếu số n chỉ ra vị trí biên trên, thì n là UBound

Vậy dùng chung "chỉ số" cho khỏe.

Ghi chú: L viết tắt của Lower và U viết tắt của Upper, chứ không phải Low và Up
 
Upvote 0
Chỉ số là Index, Bound là Biên, vậy dùng đúng là biên chứ không phải là chỉ số, theo em là vậy!

LBound có nghĩa là Low Bound và UBound có nghĩa là Up Bound vậy phải là Biên Dưới và Biên Trên chứ không thể nói là Chỉ số Trên, Chỉ số dưới.

Thì cái "biên" đấy nó là một "chỉ số" chứ còn là gì nữa? Những mỗi chiều trong mảng có những chỉ số. Trong tất cả những chỉ số đó thì chỉ số lớn nhất ta gọi là U còn nhỏ nhất ta gọi là L. Thế thôi.

Vậy thì bạn dùng "biên" hay "chỉ số" thì tôi thấy được vì "chỉ số" hay "biên" đó thuộc "tập các chỉ số trong chiều nào đó".

Tôi đã nói rồi. Tôi nói kiểu "bình dân" (tức không phải đang giảng trên giảng đường) là "cận" nhưng bản thân tôi nếu phải chọn chính xác thì tôi sẽ chọn "chỉ số". Cái biên trên/dưới thì nó cũng là chỉ số chứ nó là cái gì khác?
 
Upvote 0
Người ta dùng chỉ số vì như anh siwtom nói, LBound và UBound thuộc về 1 tập hợp các chỉ số. Nghĩa là có chỉ số trên, chỉ số dưới, và chỉ số giữa giữa. Còn biên thì chỉ có ở 2 đầu.

Nếu dùng biên thì không sai, nhưng khi truy xuất phần tử thứ n, thì n vẫn sẽ được gọi là chỉ số: Số chỉ ra vị trí của phần tử. Nếu số n chỉ ra vị trí biên dưới thì n là LBound, nếu số n chỉ ra vị trí biên trên, thì n là UBound

Vậy dùng chung "chỉ số" cho khỏe.

Ghi chú: L viết tắt của Lower và U viết tắt của Upper, chứ không phải Low và Up
Khi đã phát biểu cái gọi là chính xác thì phải triệt để chính xác, chứ bảo người ta phát biểu không chính xác mà lại dùng chung chung như thế thì không nên.

Thì cái "biên" đấy nó là một "chỉ số" chứ còn là gì nữa? Những mỗi chiều trong mảng có những chỉ số. Trong tất cả những chỉ số đó thì chỉ số lớn nhất ta gọi là U còn nhỏ nhất ta gọi là L. Thế thôi.

Vậy thì bạn dùng "biên" hay "chỉ số" thì tôi thấy được vì "chỉ số" hay "biên" đó thuộc "tập các chỉ số trong chiều nào đó".

Tôi đã nói rồi. Tôi nói kiểu "bình dân" (tức không phải đang giảng trên giảng đường) là "cận" nhưng bản thân tôi nếu phải chọn chính xác thì tôi sẽ chọn "chỉ số". Cái biên trên/dưới thì nó cũng là chỉ số chứ nó là cái gì khác?

Cách gọi và thói quen cũng như thông lệ của chúng ta như thế nào thì thôi, cứ để như vậy, còn chỉnh sửa thì phải chỉnh sửa cho chính xác Thầy ạ.

Phải hiểu rõ chữ Anh: Index khác với Bound. Và đã dịch thì phải dịch cho chính xác, còn không thì ta về ta tắm ao ta, miễn sao ta hiểu ta là được.
 
Lần chỉnh sửa cuối:
Upvote 0
Ở đây phải phân biệt rõ ràng, nếu nó CẬN là chưa chính xác thì CHỈ SỐ cũng không chính xác, bởi, CHỈ SỐ từ 0 đến 10 thì mỗi giá trị là một chỉ số, còn 0 và 10 mới chính là số biên, không thể thay thế số biên ở giữa được, nhưng nói chỉ số 2 đến chỉ số 9 trong tập 0 đến 10 đều được. Vậy thì dùng CHỈ SỐ LÀ KHÔNG HỢP LÝ.

Cho nên phải gọi LBOUND hay UBOUND là hàm xác định SỐ BIÊN DƯỚI & SỐ BIÊN TRÊN của một mảng là hoàn toàn chính xác.

Tôi không nói là vd. UBound là "chỉ số". Tôi nói là: UBound là "chỉ số trên"
Bạn có thấy khác không?
------------
Ngoài ra bạn gọi tên tôi trong bài # 254 nên tôi buộc phải trả lời bạn. Chứ tôi không góp ý gì cho bạn cả.
 
Upvote 0
Khi đã phát biểu cái gọi là chính xác thì phải triệt để chính xác, chứ bảo người ta phát biểu không chính xác mà lại dùng chung chung như thế thì không nên.

Chỗ cụ thể này dùng chung là chính xác. Từ 0 đến 10, gọi chung là chỉ số, vì đều chỉ ra vị trí của phần tử trong 1 chiều nào đó của mảng.

Chỉ số nhỏ nhất và chỉ số lớn nhất chỉ là trường hợp đặc biệt (chạm biên) của chỉ số má thôi.

Bắt đầu vặn lại (tranh luận) đây, nhưng vặn chưa đúng chỗ.
 
Upvote 0
Tôi không nói là vd. UBound là "chỉ số". Tôi nói là: UBound là "chỉ số trên"
Bạn có thấy khác không?
------------
Ngoài ra bạn gọi tên tôi trong bài # 254 nên tôi buộc phải trả lời bạn. Chứ tôi không góp ý gì cho bạn cả.
Em có 1 đến 10, vậy chỉ số trên 1 là 2 được không? Nhưng nói Biên số trên 1 là 2 có được không?

Nếu mà được vậy thì ngôn ngữ lập trình người ta đã dùng LIndex và UIndex rồi chứ không ai lại dùng Lbound hay UBound cả!
 
Lần chỉnh sửa cuối:
Upvote 0
Em có 1 đến 10, vậy chỉ số trên 1 là 2 được không? Nhưng nói Biên số trên 1 là 2 có được không?

Nếu mà được vậy thì ngôn ngữ lập trình người ta đã dùng LIndex và UIndex rồi chứ không ai lại dùng Lbound hay UBound cả!

Tôi đã nói rồi. Do bạn gọi tên tôi trong bài # 254 nên tôi buộc phải trả lời bạn, và nói về quan điểm của mình. Chỉ thế thôi. Bạn có quan điểm khác thì bạn cứ trình bầy. Có chỗ nào tôi chỉ trích bạn đâu?

Đơn giản vì tôi không muốn góp ý gì cho bạn cả.
 
Upvote 0
Khi đã phát biểu cái gọi là chính xác thì phải triệt để chính xác, chứ bảo người ta phát biểu không chính xác mà lại dùng chung chung như thế thì không nên.

Đọc bài 262

Và đã dịch thì phải dịch cho chính xác

Đọc câu cuối bài 258:
Ghi chú: L viết tắt của Lower và U viết tắt của Upper, chứ không phải Low và Up
 
Upvote 0
Đọc bài 262



Đọc câu cuối bài 258:
Ghi chú: L viết tắt của Lower và U viết tắt của Upper, chứ không phải Low và Up
Theo Help:

UBound Function: Returns a Long containing the largest available subscript for the indicated dimension of an array.


LBound Function: Returns a Long containing the smallest available subscript for the indicated dimension of an array.

Vậy đi, khi dùng CHỈ SỐ thì phải gọi CHỈ SỐ LỚN NHẤT và CHỈ SỐ NHỎ NHẤT chứ không trên hay dưới.

Khi dùng BIÊN, vì biên là giá trị xác định (giống như mạo từ xác định vậy) ở mỗi 2 đầu kích thước chỉ định của một mảng, vì thế, chỉ cần nói BIÊN TRÊN hoặc BIÊN DƯỚI là OK (vì đã là biên là chỉ số duy nhất ở 2 đầu).
 
Upvote 0
Theo Help:

UBound Function: Returns a Long containing the largest available subscript for the indicated dimension of an array.

LBound Function: Returns a Long containing the smallest available subscript for the indicated dimension of an array.

Vậy đi, khi dùng CHỈ SỐ thì phải gọi CHỈ SỐ LỚN NHẤT và CHỈ SỐ NHỎ NHẤT chứ không trên hay dưới.

Khi dùng BIÊN, vì biên là giá trị xác định (giống như mạo từ xác định vậy) ở mỗi 2 đầu kích thước chỉ định của một mảng, vì thế, chỉ cần nói BIÊN TRÊN hoặc BIÊN DƯỚI là OK (vì đã là biên là chỉ số duy nhất ở 2 đầu).

Ý kiến thôi chứ không có ý tranh luận.

1. Tôi xem từ điển Anh - Ba Lan (sách từ điển) thì thấy nghĩa của subscript là indeks (tiếng Anh là index, tiếng Việt là chỉ số)

2. Tôi xem wiktionary Việt thì thấy nghĩa của subscript là "chỉ số dưới"
http://vi.wiktionary.org/wiki/subscript

3. Tôi xem wiktionary Anh thì thấy nghĩa của subscript (nghĩa thứ hai) là "A numerical index into an array"
http://en.wiktionary.org/wiki/subscript

4. Từ điển Hồ Ngọc Đức tất nhiên sẽ dịch là "chỉ số dưới".
View attachment 115878

Nếu dịch subscript là "chỉ số" là sai thì chả nhẽ có nhiều người sai thế.

Nghĩa của subscript là thế thì phải chấp nhận thôi.

L/UBound chẳng qua cũng là chỉ số (chỉ số "đặc biệt"), hiển nhiên như câu: "Số nguyên tố là số tự nhiên. Số hữu tỷ là số thực".
------------
Ngoài ta nếu bạn đọc kỹ các bài thì thấy không ai "đeo bám" cái "biên" của bạn cả.
Tôi viết:
Vậy thì bạn dùng "biên" hay "chỉ số" thì tôi thấy được

Anh ptm0412 viết
Nếu dùng biên thì không sai

Mà bạn cứ tưởng tượng dimension nó là một cái gì đó có "điểm bắt đầu - điểm dưới" và "điểm kết thúc - điểm cuối - điểm trên" thì bạn thấy thoải mái ngay mà.
 
Lần chỉnh sửa cuối:
Upvote 0
L/UBound chẳng qua cũng là chỉ số (chỉ số "đặc biệt"), hiển nhiên như câu: "Số nguyên tố là số tự nhiên. Số hữu tỷ là số thực".
------------
Anh siwtom ạ, tôi cũng nói như thế: "Chỉ số nhỏ nhất và chỉ số lớn nhất chỉ là trường hợp đặc biệt (chạm biên) của chỉ số mà thôi."

Cơ mà "đối tác" không đọc, hoặc đọc không hiểu, hoặc cố tình không hiểu, hoặc không biết thế nào là tổng quát mí lị chi tiết, thì thôi anh ạ.

Vì nếu phản biện, thì phải chứng minh ngược lại: UBound và LBound không phải chỉ số, nghĩa là chứng minh 2 giá trị đó không dùng để chỉ ra vị trí.
 
Lần chỉnh sửa cuối:
Upvote 0
Nói túm lại, đã bảo người ta chính xác thì phải phải dùng từ chính xác chứ không dùng chung chung.

Khi đã dùng CHỈ SỐ thì phải nói CHỈ SỐ LỚN NHẤT chứ không nói CHỈ SỐ TRÊN hay CHỈ SỐ NHỎ NHẤT chứ không nói CHỈ SỐ DƯỚI. Đó là sự xác định duy nhất, còn trên - dưới thì chỉ số B có thể trên chỉ số A và có thể dưới chỉ số C v.v... là không xác định.

Còn không thì cứ để "muôn sự tự nhiên hương" rồi cùng ngầm hiểu là nó, chứ đừng chỉnh sửa rồi lại chỉnh sửa theo cách chung chung, vậy thôi.

Cuối cùng là tôi không bàn cải về vấn đề này nữa! Thay vì để thời gian giải thích cho mấy bài kia về code mà bạn đó thắc mắc còn hơn!
 
Upvote 0
Thay vì bạn dùng trong Excel với hàm IF thì hàm trong VBA nó thêm một chữ I nữa đó là IIF vậy thôi. Về tính chất nó giống y chang hàm IF của Excel.

Nhưng với câu lệnh đó mà dùng IIF đó thì hơi thừa, bởi:

Thay vì:

GetMon = IIf(Arr(I, Col) = "", "", Arr(I, Col))

Thì nên như vầy:

GetMon = Arr(I, Col)

Xong!

Đằng nào nó rỗng thì GetMon nó cũng bằng rỗng, nếu nó là rỗng mà cần kết quả khác thay thế rỗng thì ta mới sử dụng hàm IIF này thôi, vì thế, tính toán thêm chi cho phức tạp vụ!
Hu hu!
Tại viết vội, thấy kết quả mấy chỗ trống hiện ra con số 0 "dzô dziêng" nên thêm hàm IIF cũng "dzô dziêng" luôn.
Khai báo như vầy thì êm "gồi":
Public Function GetMon(Ngay As Date, Thu As Long, Tiet As Long, Rng As Range) As String
Biến Cll và J khai báo sẵn, không xài cũng không xoá, càng "dzô dziêng".
Híc.
 
Lần chỉnh sửa cuối:
Upvote 0
Khi đã dùng CHỈ SỐ thì phải nói CHỈ SỐ LỚN NHẤT chứ không nói CHỈ SỐ TRÊN hay CHỈ SỐ NHỎ NHẤT chứ không nói CHỈ SỐ DƯỚI. Đó là sự xác định duy nhất, còn trên - dưới thì chỉ số B có thể trên chỉ số A và có thể dưới chỉ số C v.v... là không xác định.
Vặn chữ "chỉ số" không được, bèn vặn qua chữ "trên dưới", ha ha ha
Cuối cùng là tôi không bàn cải về vấn đề này nữa! Thay vì để thời gian giải thích cho mấy bài kia về code mà bạn đó thắc mắc còn hơn!

Nhớ giải thích cho đúng, đừng nhầm lẫn kiểu "sự kiện" và "thủ tục cho sự kiện", Do và For; và muốn dùng biên thì dùng, đừng dùng 'cận". Ha ha ha
 
Upvote 0
mấy hôm trước mình đã tự mày mò và đã làm được một file excel nhập dữ liệu từ form nhưng mình có một vài lỗi
- lúc tạo file từ một pc của mình thì các maco chạy bình thường nhưng không hiểu sao đưa file đó sang một pc khác thì không chạy được nữa mà nó giống một file bình thường

- với maco mình tạo như vậy giờ mình muốn nâng nó lên một tí là chạy nhập dữ liệu từ form mà mình đang tạo dỡ thì nó có được không
đó là những vấn đê mình thắc mắc , rất mong nhân được sự giúp đỡ của cac ban
 
Upvote 0
Mình có đoạn code bên dưới. mình muốn thay đổi lại một chút. Mình sẽ làm thêm 1 hộp combo box để thiết lập cách lựa chọn như sau. Khi combo box này chọn GIÁ SỈ thì cột E (cột số 4) và cột F (cột số 5) trong sheet HD BANHANG này sẽ lấy dữ liệu từ cột G (cột 7- Đơn giá) và cột K(cột 11- lãi) ở sheet MAHANG. Khi combo box này chọn GIÁ SỈ thì cột E (cột số 4) và cột F (cột số 5) trong sheet HD BANHANG này sẽ lấy dữ liệu từ cột Q (cột 18-KH(SL,BB) ) và cột P (cột 17- lai BL) ở sheet MAHANG

http://www.mediafire.com/view/j0cfd55xgv8hhaw/gpec_USE.xlsm


Nhờ các bạn xem qua file gởi kèm và hướng dẫn cho mình cách làm và in đậm phần code nào thay đổi. Xin cảm ơn !


Mã:
Public Check As BooleanOption Explicit
Private Sub Worksheet_Activate()
            additemcombo
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  With Target
    If .Row > 11 And .Column = 3 And .Count = 1 Then
     ComboBox1.Activate
                With ComboBox1
                        .Value = ""
                        .Top = Target.Top
                        .Visible = True
                End With
       Else
       ComboBox1.Visible = False
       End If
  End With
End Sub
Private Sub ComboBox1_Change()
 Dim ws As Worksheet, Found As Range
  If ActiveCell.Row > 11 And Sheet3.ComboBox1 <> "" Then
        For Each ws In ThisWorkbook.Worksheets
            With ws
                If ws.Name = "HD BAN HANG" Then Exit Sub
                        Set Found = .Range("D12:D50000").Find(ComboBox1.Value)
                        If Not Found Is Nothing Then
                                'Sheet HD BAN HANG Cot C12 tro xuong "Chu y offset (,2)"
                                ActiveCell.Offset(, 0).Value = Found.Offset(, 0).Value
                                'Sheet HD BAN HANG Cot H12 tro xuong
                                ActiveCell.Offset(, 5).Value = Found.Offset(, 15).Value
                                'Sheet HD BAN HANG Cot F12 tro xuong
                                ActiveCell.Offset(, 3).Value = Found.Offset(, 7).Value
                                'Sheet HD BAN HANG Cot E12 tro xuong
                                ActiveCell.Offset(, 2).Value = Found.Offset(, 3).Value
                                'Sheet HD BAN HANG Cot D12 tro xuong
                                ActiveCell.Offset(, 1).Value = Found.Offset(, 2).Value
                                'Sheet HD BAN HANG Cot B12 tro xuong
                                ActiveCell.Offset(, -1).Value = Found.Offset(, -1).Value
                                'Sheet HD BAN HANG Cot A12 tro xuong
                                ActiveCell.Offset(, -2).Value = Application.WorksheetFunction.CountA(Range("C12:C" & ActiveCell.Row))
                                Exit For
                        End If
                End With
            Next ws
  End If
 
End Sub
Private Sub ComboBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
 Sheet3.ComboBox1.DropDown
End Sub
Private Sub ComboBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    'Hide combo box and move to next cell on Enter and Tab
    Select Case KeyCode
        Case 9 'tab key
            ActiveCell.Offset(0, 1).Activate
        Case 13 'enter key
            ActiveCell.Offset(1, 0).Activate
        Case 37 'left
            ActiveCell.Offset(0, -1).Activate
        Case 39 'right
            ActiveCell.Offset(0, 1).Activate
        Case 46 ' delete key
          '  Me.ComboBox1.DropDown
       ' Case 38
      '     ActiveCell.Offset(-1).Activate
     '   Case 40
     '      ActiveCell.Offset(1).Activate
    End Select
 
Upvote 0

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

Back
Top Bottom