Chuyên đề giải đáp những thắc mắc về code VBA (1 người xem)

Liên hệ QC

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

maytinhvp01

Thành viên thường trực
Tham gia
27/7/13
Bài viết
390
Được thích
179
Mình muốn nhờ giải thich câu lệnh " If Ran.Cells(d, c) > max Then max = Ran.Cells(d, c) "
trong ví du:
Public Function LonNhat(Ran As Range)
Dim max As Double, v As Integer, d As Integer, c As Integer
max = Ran.Cells(1, 1)
For d = 1 To Ran.Rows.Count
For c = 1 To Ran.Columns.Count
If Ran.Cells(d, c) > max Then max = Ran.Cells(d, c)
Next c
Next d
v = Tim(max, Ran)
LonNhat = max
End Function
-------------------------------------------------------
[INFO1]Thông báo:
Vì topic này:
http://www.giaiphapexcel.com/forum/...ải-thích-các-code-đề-nghị-các-bạn-gửi-vào-đây
đã quá dài nên BQT đóng lại.
Nay tôi mở topic mới với cùng chủ đề: GIẢI THÍCH NHỮNG THẮC MẮC VỀ CODE
Các bạn nếu có nhu cầu giải thích code, vui lòng post tại đây nhé
NDU96081631

[/INFO1]
 
Chỉnh sửa lần cuối bởi điều hành viên:
Không biết các địa chỉ khác có Tổ, Phường hay không nhưng chưa chắc có Quận, Thành phố. Một cô thôn nữ thì ở Quận nào, Thành phố nào? Mà đã chắc gì tiểu thư Sài gòn ở Thành phố? Có thể ở TP cũng nên. Tung 1 địa chỉ lên coi như là có qui luật?
 
Upvote 0
Cho em hỏi với, đoạn code sau:
Sub ..
For q = 1 To 10
For Each tr In doc1.Tables(q).Rows
tr.HeightRule = wdRowHeightAtLeast
tr.Height = 0.5
tr.Cells.VerticalAlignment = wdCellAlignVerticalCenter
tr.LeftIndent = CentimetersToPoints(-0.1)
tr.RightIndent = CentimetersToPoints(-0.1)

Next tr

....
End Sub()
LeftIndent, RightIndent có dùng được cho biến Rows không mà nó báo lỗi Method or data member not found (Error 461) Thế ạ
Em đang chuyển dữ liệu từ Excel sang Word, đến đoạn trình bày bảng biểu
 
Upvote 0
tr.LeftIndent = CentimetersToPoints(-0.1)
tr.RightIndent = CentimetersToPoints(-0.1)

...
LeftIndent, RightIndent có dùng được cho biến Rows không mà nó báo lỗi Method or data member not found (Error 461) Thế ạ
Em đang chuyển dữ liệu từ Excel sang Word, đến đoạn trình bày bảng biểu

Trước đó chắc bạn có đại loại
Mã:
Set WordApp = CreateObject(...)
Vậy thì bây giờ viết
Mã:
tr.LeftIndent = WordApp.CentimetersToPoints(-0.1)
tr.RightIndent = WordApp.CentimetersToPoints(-0.1)

Nhưng tr (Row) bên Word cũng không có thuộc tính RightIndent. Ít ra là ở Word 2010 của tôi. Có thể phiên bản Word mới hơn của bạn có chăng?

Excel VBA cũng không biết wdRowHeightAtLeast và wdCellAlignVerticalCenter là gì (Word hiểu được vì chúng là hằng số của Word) nên sẽ cho chúng là tên 2 biến không được khai báo tường minh. Và dĩ nhiên 2 biến đó có giá trị ban đầu là 0. Lúc đó kết quả r.HeightRule và tr.Cells.VerticalAlignment đều là 0, khác với mong đợi.

Vì thế dòng đầu nên là
Mã:
Const wdRowHeightAtLeast = ...
Const wdCellAlignVerticalCenter = ...
Kiểm tra bên Word hai hằng số này có giá trị bao nhiêu rồi điền vào chỗ ...
 
Lần chỉnh sửa cuối:
Upvote 0
Cho mình hỏi là có cái công thức chuyển từ sheet này sang sheet khác hoạt động OK rồi nhưng mà nó chuyển cả hàm trong ô bên sheet kia nên ai có cách nào nó xóa đi giúp mình với vì mình không rành nên chỉ nhặt về thôi. Thanks. Dưới là công thức
Private Sub CommandButton1_Click()
Dim Lr As Integer, Dc As Integer
Lr = Sheet5.Range("A10000").End(xlUp).Row
Dc = Sheet2.Range("A10000").End(xlUp).Row
Sheet2.Range("A2:A100" & Dc, "AG2:AG101" & Dc).Copy
Sheet5.Range ("A" & Lr + 1)
Range("a2", "c101").ClearContents
Range("e2", "h101").ClearContents
Range("j2", "m101").ClearContents
End Sub
 
Upvote 0
Cho mình hỏi là có cái công thức chuyển từ sheet này sang sheet khác hoạt động OK rồi nhưng mà nó chuyển cả hàm trong ô bên sheet kia nên ai có cách nào nó xóa đi giúp mình với vì mình không rành nên chỉ nhặt về thôi. Cảm ơn. Dưới là công thức
Private Sub CommandButton1_Click()
Dim Lr As Integer, Dc As Integer
Lr = Sheet5.Range("A10000").End(xlUp).Row
Dc = Sheet2.Range("A10000").End(xlUp).Row
Sheet2.Range("A2:A100" & Dc, "AG2:AG101" & Dc).Copy
Range("a2", "c101").ClearContents
Range("e2", "h101").ClearContents
Range("j2", "m101").ClearContents
End Sub
Thay dòng trên bằng dòng dưới xem sao.
Mã:
'Sheet5.Range ("A" & Lr + 1)
Sheet5.Range("A" & Lr + 1).PasteSpecial xlPasteValues
 
Upvote 0
Nhưng tr (Row) bên Word cũng không có thuộc tính RightIndent. Ít ra là ở Word 2010 của tôi. Có thể phiên bản Word mới hơn của bạn có chăng?

Excel VBA cũng không biết wdRowHeightAtLeast và wdCellAlignVerticalCenter là gì (Word hiểu được vì chúng là hằng số của Word) nên sẽ cho chúng là tên 2 biến không được khai báo tường minh. Và dĩ nhiên 2 biến đó có giá trị ban đầu là 0. Lúc đó kết quả r.HeightRule và tr.Cells.VerticalAlignment đều là 0, khác với mong đợi.

Vì thế dòng đầu nên là
Mã:
Const wdRowHeightAtLeast = ...
Const wdCellAlignVerticalCenter = ...
Kiểm tra bên Word hai hằng số này có giá trị bao nhiêu rồi điền vào chỗ ...
Thankiu bạn, thực tế mình chỉ không hiểu LeftIndent có vận dụng được cho biến Row trong table hay không thui, các code kia mình vẫn chạy bình thường mà.
Đúng là phần trên mình đang dùng With CreateObject("Word.Application")
Tiện đây, có bác nào có bài viết chuyên sâu về điều khiển Word bằng VBa bên excel không cho mình xin với ạ
 
Upvote 0
Chào cả nhà,
Mình đang làm một số công việc cần trích xuất dữ liệu excel rất nhiều ra các biểu mẫu word.
Tôi đã đọc hết các trả lời cho bài này. Chắc chủ thớt vừa ý.
Tôi chỉ nêu ý tưởng khác để giải quyết bài này. Đó là chuyển dữ liệu của 1 dòng đến vùng khác trên cùng sheet hoặc trên sheet khác. Tất cả đều dùng công thức và cần một chút code rất đơn giản để dễ thao tác. Cũng dễ đối chiếu dữ liệu vô có "trúng" không. Giờ muộn rồi. Có lẽ ngày mai sẽ gửi file demo.

À, bỏ lâu nên không nhớ cách tìm lại bài đã viết. Chỉ biết nếu có ai chọn bài của mình và trả lời thì GPE có thông báo cho tôi thì tìm lại được.
 
Lần chỉnh sửa cuối:
Upvote 0
Cho em hỏi câu lệnh này có gì sai?
PHP:
For i = 3 To UBound(sArr, 1)
            For j = 4 To UBound(sArr, 2)
                If sArr(i, 1) > 30000 Then
                    If Weekday(sArr(1, j)) <> 1 Then
                        If IsEmpty(sArr(i, j)) Then
                            Tem = sArr(i, 1) & "-" & sArr(1, j)
                            If Dic.exists(Tem) Then
                                GoTo ErrorHandler
                            Else:
                                k = k + 1
                                Result(k, 1) = sArr(2, j)
                                Result(k, 2) = sArr(i, 1)
                                Result(k, 7) = 17
                            End If
                        End If
                    End If
                End If
            Next j
ErrorHandler: Next i
Next i
Mục đích của em là nếu như tồn tại Key thì nó sẽ bỏ qua và chuyển sang Next i luôn.
 
Upvote 0
Bạn đang dư dòng lệnh
Next I
 
Upvote 0
Thay cho ELSE + Exit For hoặc ELSE + GOTO thì có lẽ tốt hơn là
Mã:
If Not Dic.exists(Tem) Then
    k = k + 1
    Result(k, 1) = sArr(2, j)
    Result(k, 2) = sArr(i, 1)
    Result(k, 7) = 17
End If
 
Upvote 0
Thay cho ELSE + Exit For hoặc ELSE + GOTO thì có lẽ tốt hơn là
Mã:
If Not Dic.exists(Tem) Then
    k = k + 1
    Result(k, 1) = sArr(2, j)
    Result(k, 2) = sArr(i, 1)
    Result(k, 7) = 17
End If
Cũng tại em không nói rõ nghĩa lắm. Nếu theo câu lệnh này thì vòng lặp j của em vẫn tồn tại. Mục đích của em là khi gặp Key thì không tiếp tục xét các cột ở dòng đó nữa mà xét dòng tiếp theo ạ.
Bài đã được tự động gộp:

Bạn đang dư dòng lệnh
Next I
Em cũng thấy nó báo lỗi ở Next i. Em cứ hiểu đơn giản là nếu gặp Key thì không xét vòng lặp j nữa mà chuyển sang dòng khác.
 
Lần chỉnh sửa cuối:
Upvote 0
Upvote 0
Cũng tại em không nói rõ nghĩa lắm. Nếu theo câu lệnh này thì vòng lặp j của em vẫn tồn tại. Mục đích của em là khi gặp Key thì không tiếp tục xét các cột ở dòng đó nữa mà xét dòng tiếp theo ạ
Xin lỗi. Tôi nhìn nhầm. Bạn viết liền ErrorHandler: Next i nên tôi tưởng ErrorHandler ở dòng cuối của vòng lặp hiện hành i. Hóa ra vòng lặp hiện hành là j, và ErrorHandler nằm ngoài vòng lặp này nên phải là Exit For (hoặc Goto ErrorHandler) như phuocam đã chỉ ra.
 
Upvote 0
Chào các thầy cô ạ. em có 1 file gồm 104 sheet lần lượt có tên "Table 1" tới "Table 104"
bây giờ em muốn xóa những sheets có số chẵn đi thì code viết như nào ạ.
 
Upvote 0
Chào các thầy cô ạ. em có 1 file gồm 104 sheet lần lượt có tên "Table 1" tới "Table 104"
bây giờ em muốn xóa những sheets có số chẵn đi thì code viết như nào ạ.
Thử:
Mã:
Public Sub DelSheet()
Dim ws As Worksheet
Dim i
Application.DisplayAlerts = False
    For Each ws In Worksheets
        i = Right(ws.Name, 1)
        If IsNumeric(i) Then
            If i Mod 2 = 0 Then
                ws.Delete
            End If
        End If
    Next ws
Application.DisplayAlerts = True
End Sub
 
Upvote 0
Thử:
Mã:
Public Sub DelSheet()
Dim ws As Worksheet
Dim i
Application.DisplayAlerts = False
    For Each ws In Worksheets
        i = Right(ws.Name, 1)
        If IsNumeric(i) Then
            If i Mod 2 = 0 Then
                ws.Delete
            End If
        End If
    Next ws
Application.DisplayAlerts = True
End Sub
Cám ơn thầy ạ
 
Upvote 0
Mọi người giúp em tí : Sau khi em sử dụng phương thức
Mã:
oFolder=Fso.GetFolder(thisworkbook.path)
bây giờ mình làm sao để liệt kê tên folder trong oFolder ạ.
Em cám ơn !
 
Upvote 0
Mọi người giúp em tí : Sau khi em sử dụng phương thức
Mã:
oFolder=Fso.GetFolder(thisworkbook.path)
bây giờ mình làm sao để liệt kê tên folder trong oFolder ạ.
Em cám ơn !
Dùng thử thế này xem sao.
Mã:
For Each objFolder In oFolder.SubFolders
    MsgBox objFolder
Next
 
Upvote 0
Chào các anh chị em,

Em xin nhờ các anh chị một chút ạ: Hiện tại em đang muốn lập VBA dạng Sub để hiện outline chỉ một số dòng cụ thể (ví dụ chỉ các mục 2.1, 3.1, 4.1...) nhưng khi em thử ghi macro thì không hiện dòng mã. Em cũng thử tìm trên help nhưng chưa tìm đc dòng lệnh để điều khiển ẩn hiện outline từng dòng mà chỉ ẩn hiện chung theo level đã group.

Có anh chị nào biết chỉ em với ạ.
Em cảm ơn ace.
 
Upvote 0
Anh/Chị trên diễn đàn cho e hỏi : Có cách nào để lấy một giá trị trên 1 Cell bằng hàm iputbox hoặc hàm gì khác không ạ.?
E sử dụng hàm iputbox thì nó chỉ cho phép nhập bằng tay chứ không cho chọn giá trị trên Cell.
Cám ơn!
 
Upvote 0
Thì bạn nhập chỉ số dòng (hàng) & chỉ số cột vô InputBox, như ví dụ sau:
PHP:
Sub LayDuLieu1OBangInputBox()
 Dim TriCanLay, Hang_Cot As String
 Dim Dg As Long, Cot As Integer, VTr As Byte
 Hang_Cot = InputBox("Nhâp Theo Kiêu 'Number(Hàng)|Numbrt(Côt)'", "GPE.COM", "5|9")
 If Len(Hang_Cot) > 2 Then
    VTr = InStr(Hang_Cot, "|")
    Dg = CLng(Left(Hang_Cot, VTr - 1))
    Cot = CInt(Mid(Hang_Cot, VTr + 1, Len(Hang_Cot)))
    TriCanLay = Cells(Dg, Cot).Value
    MsgBox TriCanLay
 End If
End Sub
 
Upvote 0
Thì bạn nhập chỉ số dòng (hàng) & chỉ số cột vô InputBox, như ví dụ sau:
PHP:
Sub LayDuLieu1OBangInputBox()
Dim TriCanLay, Hang_Cot As String
Dim Dg As Long, Cot As Integer, VTr As Byte
Hang_Cot = InputBox("Nhâp Theo Kiêu 'Number(Hàng)|Numbrt(Côt)'", "GPE.COM", "5|9")
If Len(Hang_Cot) > 2 Then
    VTr = InStr(Hang_Cot, "|")
    Dg = CLng(Left(Hang_Cot, VTr - 1))
    Cot = CInt(Mid(Hang_Cot, VTr + 1, Len(Hang_Cot)))
    TriCanLay = Cells(Dg, Cot).Value
    MsgBox TriCanLay
End If
End Sub
Em cám ơn.
Thực ra là e muốn viết một sub xóa dòng trống bằng việc lựa chọn cột điều kiện tùy ý bằng iputbox mà không chọn lên Cell được.
Thôi thì đành nhập bằng tay lên iputbox vậy.
 
Upvote 0
Có phải thế này là bạn muốn không:
Giả dụ cột F có dự liệu từ F5 cho đến F99; Nhưng trong nớ có vài ô trống (trắng) như [F35] & [F40:F41] mà bạn muốn xóa nguyên những dòng đó?
 
Upvote 0
Có phải thế này là bạn muốn không:
Giả dụ cột F có dự liệu từ F5 cho đến F99; Nhưng trong nớ có vài ô trống (trắng) như [F35] & [F40:F41] mà bạn muốn xóa nguyên những dòng đó?
Vâng đúng rồi ạ.
Nên e tính sử dụng inputbox chọn đại 1 ô trên cột F. Sau đó dùng lệnh .row để xác định cột cần xóa dữ liệu ạ
 
Upvote 0
Bạn khai báo 1 biến kiểu Range
Tạo vòng lặp duyệt theo cột f:f mà mình ví dụ
Gạp ô nào trống thì nạp nó vô biến (đã khai báo)
Sau khi duyệt hết cột F:F thì nếu tham biến không phải là Nothing thì xóa . . .
 
Upvote 0
Bạn khai báo 1 biến kiểu Range
Tạo vòng lặp duyệt theo cột f:f mà mình ví dụ
Gạp ô nào trống thì nạp nó vô biến (đã khai báo)
Sau khi duyệt hết cột F:F thì nếu tham biến không phải là Nothing thì xóa . . .
Nếu vậy hình như nó không được linh động cho lắm ạ. Em muốn là mình muốn lựa chọn cột trước khi duyệt for. Bởi đâu cố định vd là cột F mãi được
 
Upvote 0
Càng linh động thì càng sai sót thêm thôi.
Mà 1 CSDL chỉ 1 sai sót nhỏ là thành đống rác.
 
Upvote 0
Nếu vậy hình như nó không được linh động cho lắm ạ. Em muốn là mình muốn lựa chọn cột trước khi duyệt for. Bởi đâu cố định vd là cột F mãi được
Yêu cầu của bạn chỉ áp dụng đối với tiêu đề cột là dòng 1, vì nếu chọn Cell rổng và Delete và xóa dòng thì nó sẽ dịch chuyển dữ liệu lên trên.
 
Upvote 0
Dạ xin chào các bác,

Chả là em mới tập tành học VBA nên trình độ còn kém quá, có bài toán như ở file đính kèm nghĩ mãi mà vẫn chưa ra cách giải. Nhờ các bác chỉ giáo giúp em với ạ. Em cảm ơn nhiều.
 

File đính kèm

Upvote 0
Dạ xin chào các bác,

Chả là em mới tập tành học VBA nên trình độ còn kém quá, có bài toán như ở file đính kèm nghĩ mãi mà vẫn chưa ra cách giải. Nhờ các bác chỉ giáo giúp em với ạ. Em cảm ơn nhiều.
Bạn chạy thử code này xem sao
Mã:
Dim Dem As Long
Sub Xuat()
Dim DL
Dim i, j, k
With Sheet1
    DL = .Range("a2", .Range("a1000000").End(xlUp))
    For i = 1 To UBound(DL)
        If DL(i, 1) <> "" Then
            j = j + 1
        End If
    Next i
    Dem = Dem + 1
    Dem = (Dem - 1) Mod j + 1
    
    For i = 1 To UBound(DL)
        If DL(i, 1) <> "" Then
            k = k + 1
            If k = Dem Then
                .Range("h1") = DL(i, 1)
                Exit For
            End If
        End If
    Next i
End With
End Sub
 
Upvote 0
Bạn chạy thử code này xem sao
Mã:
Dim Dem As Long
Sub Xuat()
Dim DL
Dim i, j, k
With Sheet1
    DL = .Range("a2", .Range("a1000000").End(xlUp))
    For i = 1 To UBound(DL)
        If DL(i, 1) <> "" Then
            j = j + 1
        End If
    Next i
    Dem = Dem + 1
    Dem = (Dem - 1) Mod j + 1
   
    For i = 1 To UBound(DL)
        If DL(i, 1) <> "" Then
            k = k + 1
            If k = Dem Then
                .Range("h1") = DL(i, 1)
                Exit For
            End If
        End If
    Next i
End With
End Sub
Chuẩn luôn rồi bác ạ. Mỗi tội em đọc code của bác không hiểu gì cả :( chắc tại em thiếu kiến thức quá, để em mày mò học thêm vậy :(
Tks bác nhiều nhé.
 
Upvote 0
Chào các anh chị,

Em cũng mới tập viết VBA, đoạn code sau em check đi check lại không bị lỗi gì nhưng không hiểu sao lại không chạy. Nhờ các anh chị kiểm tra giúp em với ạ. Mục tiêu của đoạn code là khi gõ mã vào cột 1 của Sheet 1 thì Excel sẽ tìm kiếm dòng công thức từ thư viện "Lib" để copy vào dòng vừa gõ mã. Em cảm ơn các anh chị.

Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim var As Variant
    Dim Add As String
    If Target.Cells.Count > 1 Then
        Exit Sub
    End If
    On Error GoTo ErrHandler:
    
    If Not Application.Intersect(Target, Range("A:A")) Is Nothing Then
        Add = Intersect(Target, Range("A:A")).Address
        var = Application.Match(Range(Add).Value, Worksheets("Lib").Columns(1), 0)
        Worksheets("Lib").Rows(var).Copy
        Worksheets("Sheet1").Range(Add).Paste
        
    End If
ErrHandler:
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Chào mọi người, mọi người giúp em về code VBA cho việc tính các thông số rij (thời gian sẵn sàng), dij (thời gian tới hạn) của các công việc trên sơ đồ mạng ạ.
Cụ thể như hình đính kèm214307
Ví dụ có 3 công việc được gia công trên 4 máy như hình (ô 2,1 thì 2 là máy 2, 1 là công việc 1 ạ). Em sử dụng giải thuật shifting bottleneck để điều độ các công việc. Đầu tiên, em tính rij, dij cho tungwg ô như vậy, sau đó sẽ tìm được máy nghẽn rồi chọn thứ tự điều độ trên đó (trên hình là máy 1). Sau đó em sẽ tiến hành tính lại rij, dij của sơ đồ mạng mới (có thêm các đường nối giữa các công việc trên máy 1). Sau đó lại tìm máy nghẽn, rồi lặp lại cho tới khi hết máy nghẽn.
Em tính được rij, dij của lần đầu tiên, nhưng sau khi lặp, có thêm có đường liên kết mới, em không biết viết code để tính thế nào. Mọi người giúp em với ạ. Em cảm ơn
 
Upvote 0
Các anh chị trong diễn đàn có ai biết tài liệu về VBA để vẽ biểu đồ và tinh chỉnh biểu đồ không? Cho em xin với. Xin cám ơn !
 
Upvote 0
các thầy cho em hỏi 1 xíu ạ. ví dụ em nghĩ như này:
nếu tên sheet = "a" hoặc "b" thì....
sẽ phải viết code như nào ạ
 
Upvote 0
Chẳng hạn workbook của em nó có nhiều sheets chẳng hạn. Thì có Phải khai bao biến hay như thế nào không ạ
Vậy dùng thế này.
Mã:
Sub GPE()
Dim sh As Worksheet
For Each sh In ThisWorkbook.Worksheets
    If sh.Name = "a" Or sh.Name = "b" Then MsgBox "lam dai cong viec gi do"
Next sh
End Sub
 
Upvote 0
Vậy dùng thế này.
Mã:
Sub GPE()
Dim sh As Worksheet
For Each sh In ThisWorkbook.Worksheets
    If sh.Name = "a" Or sh.Name = "b" Then MsgBox "lam dai cong viec gi do"
Next sh
End Sub
Nếu như mà em muốn làm gì đó trên cả 2 sheet a và b. Chẳng hạn a1 của cả 2 sheet cùng 1 kiểu thì viết đường dẫn vào từng sheet 1 ạ
 
Upvote 0
Mã:
Sub Boimau()
  Dim ws As Worksheet, LastRow As Long
  For Each ws In Worksheets
    If ws.Name = "Makikaeshi" Or ws.Name = "Yokomaki" Or ws.Name = "Tsunagi" Then
      With ws.Activate
        LastRow = .Cells(.Rows.Count, "H").End(xlUp).Row
      ws.Range("N7:O" & LastRown).Interior
        .Pattern = xlSolid
        .PatternColorIndex = xlAutomatic
        .ThemeColor = xlThemeColorLight2
        .TintAndShade = 0.799981688894314
        .PatternTintAndShade = 0
      End With

    End If
  Next ws
End Sub
Nhờ các thầy xem giúp em. đoạn code tren em đang sai ở chỗ nào với ạ, mà không thấy nó chạy
 
Upvote 0
Mã:
Sub Boimau()
  Dim ws As Worksheet, LastRow As Long
  For Each ws In Worksheets
    If ws.Name = "Makikaeshi" Or ws.Name = "Yokomaki" Or ws.Name = "Tsunagi" Then
      With ws.Activate
        LastRow = .Cells(.Rows.Count, "H").End(xlUp).Row
      ws.Range("N7:O" & LastRown).Interior
        .Pattern = xlSolid
        .PatternColorIndex = xlAutomatic
        .ThemeColor = xlThemeColorLight2
        .TintAndShade = 0.799981688894314
        .PatternTintAndShade = 0
      End With

    End If
  Next ws
End Sub
Nhờ các thầy xem giúp em. đoạn code tren em đang sai ở chỗ nào với ạ, mà không thấy nó chạy
Bạn xem thử code dưới đây
Các dòng có dấu ' là lệnh cũ, dưới liền kề là mới
Mã:
Sub Boimau()
  Dim ws As Worksheet, LastRow As Long
  For Each ws In Worksheets
    If ws.Name = "Makikaeshi" Or ws.Name = "Yokomaki" Or ws.Name = "Tsunagi" Then
      'With ws.Activate
      ws.Activate
        'LastRow = .Cells(.Rows.Count, "H").End(xlUp).Row
        LastRow = Range("H" & Rows.Count).End(xlUp).Row
      'ws.Range("N7:O" & LastRown).Interior
      With ws.Range("N7:O" & LastRow).Interior '<-- LastRown sua thanh LastRow
        .Pattern = xlSolid
        .PatternColorIndex = xlAutomatic
        .ThemeColor = xlThemeColorLight2
        .TintAndShade = 0.799981688894314
        .PatternTintAndShade = 0
      End With

    End If
  Next ws
End Sub
 
Upvote 0
Nhờ các anh chị giúp CODE ạ. Tôi muốn viết 1 macro lấy tên đối tượng mình click vào mà chưa làm được. Xin cám ơn trước ạ!
 

File đính kèm

Upvote 0
chào các thầy cô. cho em hỏi 1 chút à. có code nào khi mà em mở 1 file excell A lên. thì đồng thời file excell B ở thư mục khác sẽ cũng được mở lên cùng không ạ.
 
Upvote 0
chào các thầy cô. cho em hỏi 1 chút à. có code nào khi mà em mở 1 file excell A lên. thì đồng thời file excell B ở thư mục khác sẽ cũng được mở lên cùng không ạ.
Có bạn viết code mở file B rồi vứt nó vào sự kiện mở file trong excel A là được nhé.
 
Upvote 0
Nhờ các Bạn chỉ giúp mình gộp code bên dưới:
Mã:
If sArr(I, 23) <> Empty Then
        If Month(sArr(I, 23)) < 10 Then
            dArr(I, 3) = Right(sArr(I, 23), 2)
        ElseIf Month(sArr(I, 23)) > 9 Then
            dArr(I, 3) = Right(sArr(I, 23), 2) + 1
    End If
End If

    If sArr(I, 23) = Empty Then
            dArr(I, 3) = "kg"
        End If
Xin cảm ơn.
 
Upvote 0
Nhờ các Bạn chỉ giúp mình gộp code bên dưới:
Mã:
Xin cảm ơn.
[/QUOTE]
Bạn gộp vậy xem sao.
[CODE]If sArr(I, 23) <> Empty Then
        If Month(sArr(I, 23)) < 10 Then
            dArr(I, 3) = Right(sArr(I, 23), 2)
        ElseIf Month(sArr(I, 23)) > 9 Then
            dArr(I, 3) = Right(sArr(I, 23), 2) + 1
    End If
Else
   dArr(I, 3) = "kg"
End If
 
Upvote 0
Dear A/c có cách nào giúp tốc độ code phia dưới nhanh hơn dc ko , nhờ a/c giúp
Code dưới là ghi dữ liệu từ textbox trên userform vào sheet

Mã:
Private Sub CommandButton5_Click()

Dim lastrow As Long
Dim i As Long
With Sheets("Pak_in")
For i = 1 To 115 Step 6
lastrow = Sheets("Pak_in").Cells(Rows.Count, "D").End(xlUp).Row + 1
If Controls("TextBox" & i) = "" Then Exit Sub
.Range("D" & lastrow) = Controls("TextBox" & i)
.Range("E" & lastrow) = Controls("TextBox" & i + 1)
.Range("F" & lastrow) = Controls("TextBox" & i + 2)
.Range("G" & lastrow) = Controls("TextBox" & i + 3)
.Range("H" & lastrow) = Controls("TextBox" & i + 4).Value
.Range("I" & lastrow) = Controls("TextBox" & i + 5)

 Controls("TextBox" & i) = ""
 Controls("TextBox" & i + 1) = ""
 Controls("TextBox" & i + 2) = ""
 Controls("TextBox" & i + 3) = ""
 Controls("TextBox" & i + 4) = ""
 Controls("TextBox" & i + 5) = ""
Next i
End With
End Sub
 
Upvote 0
Dear A/c có cách nào giúp tốc độ code phia dưới nhanh hơn dc ko , nhờ a/c giúp
Code dưới là ghi dữ liệu từ textbox trên userform vào sheet

Mã:
Private Sub CommandButton5_Click()

Dim lastrow As Long
Dim i As Long
With Sheets("Pak_in")
For i = 1 To 115 Step 6
lastrow = Sheets("Pak_in").Cells(Rows.Count, "D").End(xlUp).Row + 1
If Controls("TextBox" & i) = "" Then Exit Sub
.Range("D" & lastrow) = Controls("TextBox" & i)
.Range("E" & lastrow) = Controls("TextBox" & i + 1)
.Range("F" & lastrow) = Controls("TextBox" & i + 2)
.Range("G" & lastrow) = Controls("TextBox" & i + 3)
.Range("H" & lastrow) = Controls("TextBox" & i + 4).Value
.Range("I" & lastrow) = Controls("TextBox" & i + 5)

Controls("TextBox" & i) = ""
Controls("TextBox" & i + 1) = ""
Controls("TextBox" & i + 2) = ""
Controls("TextBox" & i + 3) = ""
Controls("TextBox" & i + 4) = ""
Controls("TextBox" & i + 5) = ""
Next i
End With
End Sub
Cách thì có nhưng nhìn thấy file mới viết được code.
 
Upvote 0
Code bên dưới mình khai báo thêm Dic1 nhưng bị lỗi
Mã:
Dim Dic As Object, Dic1 As Object, Ma()
Dim sArr(), sArr1(), dArr(), tArr(), TieuDe(), DK As Boolean
Dim I As Long, J As Long, K As Long, N As Long, R As Long
    Set Dic = CreateObject("Scripting.Dictionary")
    Set Dic1 = CreateObject("Scripting.Dictionary")
    sArr = Sheets("Ma").Range("A2:B14").Value
    sArr1 = Sheets("Ma").Range("D2:E9").Value

    For I = 1 To 13
        Dic.Item(sArr(I, 1)) = sArr(I, 2)
        Dic1.Item(sArr1(I, 1)) = sArr1(I, 2)
    Next I
Các Bạn chỉ giúp cách sửa lại để không bị lỗi.
Xin cảm ơn.
 
Upvote 0
Code bên dưới mình khai báo thêm Dic1 nhưng bị lỗi
Mã:
Dim Dic As Object, Dic1 As Object, Ma()
Dim sArr(), sArr1(), dArr(), tArr(), TieuDe(), DK As Boolean
Dim I As Long, J As Long, K As Long, N As Long, R As Long
    Set Dic = CreateObject("Scripting.Dictionary")
    Set Dic1 = CreateObject("Scripting.Dictionary")
    sArr = Sheets("Ma").Range("A2:B14").Value
    [CODE]sArr1 = Sheets("Ma").Range("D2:E14").Value

For I = 1 To 13
Dic.Item(sArr(I, 1)) = sArr(I, 2)
Dic1.Item(sArr1(I, 1)) = sArr1(I, 2)
Next I[/CODE]
Các Bạn chỉ giúp cách sửa lại để không bị lỗi.
Xin cảm ơn.
Lỗi dòng lệnh này.
Mã:
   Dic1.Item(sArr1(I, 1)) = sArr1(I, 2)
Không liên quan gì đến DIC1 cả.Cái này gặp phải vấn đề là mảng nó không tồn tại.
Bạn sửa dòng này thành
Mã:
sArr1 = Sheets("Ma").Range("D2:E14").Value
 
Upvote 0
Lỗi dòng lệnh này.
Mã:
   Dic1.Item(sArr1(I, 1)) = sArr1(I, 2)
Không liên quan gì đến DIC1 cả.Cái này gặp phải vấn đề là mảng nó không tồn tại.
Bạn sửa dòng này thành
Mã:
sArr1 = Sheets("Ma").Range("D2:E14").Value
Vậy mình phải sửa lại như thế nào vậy Bạn.
Bài đã được tự động gộp:

Lỗi dòng lệnh này.
Mã:
   Dic1.Item(sArr1(I, 1)) = sArr1(I, 2)
Không liên quan gì đến DIC1 cả.Cái này gặp phải vấn đề là mảng nó không tồn tại.
Bạn sửa dòng này thành
Mã:
sArr1 = Sheets("Ma").Range("D2:E14").Value
Nhờ các Bạn xem giúp. Mình muốn kết quả như cột N trong sheet DN5. Xin cảm ơn
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Vậy mình phải sửa lại như thế nào vậy Bạn.
Bài đã được tự động gộp:


Nhờ các Bạn xem giúp. Mình muốn kết quả như cột N trong sheet DN5. Xin cảm ơn
Bạn xem nhé.Sửa chút it code của bạn.
Mã:
Public Sub GPE_LoC()
Dim Dic As Object, Dic1 As Object, Ma()
Dim sArr(), sArr1(), dArr(), tArr(), TieuDe(), DK As Boolean
Dim I As Long, J As Long, K As Long, N As Long, R As Long
    Set Dic = CreateObject("Scripting.Dictionary")
    sArr = Sheets("Ma").Range("A2:B14").Value
    sArr1 = Sheets("Ma").Range("D2:E9").Value
    For I = 1 To 13
        Dic.Item(sArr(I, 1) & "D") = sArr(I, 2)
    Next I
    For I = 1 To 8
        Dic.Item(sArr1(I, 1) & "T") = sArr1(I, 2)
    Next I
With Sheets("Data")
    sArr = .Range("A2", .Range("A60000").End(xlUp)).Resize(, 44).Value
    R = UBound(sArr)
End With
ReDim dArr(1 To R, 1 To 18)
With Sheets("DN5")
    TieuDe = .Range("AA1:AF3").Value
    tArr = .Range("A10:R10").Value
    For I = 1 To R
        DK = True
        For J = 1 To UBound(TieuDe, 2)
            If TieuDe(3, J) <> Empty Then
                If sArr(I, TieuDe(1, J)) <> TieuDe(3, J) Then
                    DK = False
                    Exit For
                End If
            End If
        Next J
        If DK = True Then
            K = K + 1
            dArr(K, 1) = K
            For J = 2 To UBound(tArr, 2)
                If tArr(1, J) <> Empty Then dArr(K, J) = sArr(I, tArr(1, J))
            Next J
            dArr(K, 10) = Dic.Item(sArr(I, 24) & "D")
            dArr(K, 14) = Dic.Item(sArr(I, 25) & "T")
        End If
    Next I
    .Rows("12:450").Hidden = False
    .Range("A12:R450").ClearContents
    If K Then
        .Range("A12:R12").Resize(K) = dArr
        .Rows(K + 12 & ":450").Hidden = True
    End If
End With
Set Dic = Nothing
End Sub
 
Upvote 0
Rất cảm ơn Bạn đã nhiệt tình giúp đỡ.
Bài đã được tự động gộp:
 
Lần chỉnh sửa cuối:
Upvote 0
Ai có thể giúp tôi sửa lại cái code này với, hay chơi cái trò này nhưng kg biết viết nó như thế nào, xin chân thành cảm ơn và hậu tạ!
 

File đính kèm

Upvote 0
Xin chào các bạn,
OT nhập 3 sử 3 dòng sau trong cửa sổ Immediate để lấy dòng cuối,
Mã:
?Sheet1.Cells(Sheet1.Rows.Count, "E").End(xlUp).Row
?Sheet1.Range("E" & Sheet1.Rows.Count).End(xlUp).Row
?Sheet1.Range("E1048576").End(xlUp).Row

cách viết có hơi khác một chút nhưng đều trả về giá trị giống nhau.
Các bạn chỉ giúp OT - 3 cách viết này khác nhau ở điểm nào được không ạ?
Cảm ơn
 
Upvote 0
3 cái trên: (với ex khác 2003)
- Khác nhau: Cách viết lệnh
- Giống nhau: Đều tìm được ô cuối cùng của 1 cột có chứa dữ và lấy số thứ tự hàng của nó
 
Upvote 0
Xin chào các bạn,
OT nhập 3 sử 3 dòng sau trong cửa sổ Immediate để lấy dòng cuối,
Mã:
?Sheet1.Cells(Sheet1.Rows.Count, "E").End(xlUp).Row
?Sheet1.Range("E" & Sheet1.Rows.Count).End(xlUp).Row
?Sheet1.Range("E1048576").End(xlUp).Row

cách viết có hơi khác một chút nhưng đều trả về giá trị giống nhau.
Các bạn chỉ giúp OT - 3 cách viết này khác nhau ở điểm nào được không ạ?
Cảm ơn
Bạn cứ gõ ?Sheet1.Rows.Count là hiểu
 
Upvote 0
Bạn cứ gõ ?Sheet1.Rows.Count là hiểu
Àh thì ra là vậy:
?Sheet1.Rows.Count
là dùng cho mọi phiên bản office

còn nếu sử dụng Sheet1.Range("E1048576").End(xlUp).Row thì chắc phiên bảo nào có số dòng nhỏ hơn thì sẽ bị lỗi..
hihi OT hiểu là vậy, cảm ơn các bạn!
 
Upvote 0
Àh thì ra là vậy:
?Sheet1.Rows.Count
là dùng cho mọi phiên bản office

còn nếu sử dụng Sheet1.Range("E1048576").End(xlUp).Row thì chắc phiên bảo nào có số dòng nhỏ hơn thì sẽ bị lỗi..
hihi OT hiểu là vậy, cảm ơn các bạn!
Bạn hiểu mỗi cái này là xong.
Mã:
End(xlUp)
 
Upvote 0
Xin chào các bạn,

OT có một thắc mắc nhờ bạn chỉ giúp,tại sao:
Dim arr()
arr = .Range("N8:AG10").Value ---> thì phần tử đầu tiên trong mảng là 1
Còn: ReDim arr1(UBound(arr, 1), 6) ---> thì phần tử đầu tiên trong mảng là 0
mà phải sử dụng: ReDim arr1(1 To UBound(arr, 1), 1 To 6) để phần tử bắt đầu từ 1

Hihi
 
Upvote 0
Đây làm một hàm để so sánh số lớn nhất trong một vùng dữ liệu (Range) nào đó.

Nó căn cứ từ ô đầu tiên của vùng [ Ran.Cells(1, 1) ] làm chuẩn để so sánh với các ô trong vùng đó.

Với câu lệnh này:


If Ran.Cells(d, c) > max Then max = Ran.Cells(d, c)

Với d đại diện cho hàng và c đại diện cho cột, khi vòng lặp chạy lần lượt đến mỗi ô trong Vùng tham chiếu, nếu gặp ô có giá trị lớn hơn giá trị ban đầu max = Ran.Cells(1, 1) thì max sẽ nhận giá trị tại ô đó rồi tiếp tục so sánh sang ô khác, còn không thì nó vẫn giữ giá trị lớn nhất.

=============================
Cái mà tôi không hiểu gì trong hàm đó là cái này:


v = Tim(max, Ran)

Chả biết nó dùng để làm gì nữa!
V= Tim(max,ran)
Theo mình nghĩ function Tim(max,Ran) là 1 hàm riêng biệt được gọi đến
tim(int a,int b)
a>b: max=a
b>a: max=b
return max
Nhưng hàm bên trên mình thấy ko cần thiết phải viết thêm function tim() vì đã gọi đệ quy.
 
Upvote 0
Xin chào các bạn,

OT có một thắc mắc nhờ bạn chỉ giúp,tại sao:
Dim arr()
arr = .Range("N8:AG10").Value ---> thì phần tử đầu tiên trong mảng là 1
Còn: ReDim arr1(UBound(arr, 1), 6) ---> thì phần tử đầu tiên trong mảng là 0
mà phải sử dụng: ReDim arr1(1 To UBound(arr, 1), 1 To 6) để phần tử bắt đầu từ 1

Hihi
Chỗ đỏ đỏ tôi đã từng nói cho bạn.

Tôi đã nhiều lần nói là mọi người ai cũng có một kho kiến thức trong tầm tay nhưng cứ đi tìm ở đâu đâu, không chịu đọc mà cứ đi hỏi.
Trong VBA ở trên góc trên bên phải có 1 trường. Nếu không biết nhập gì thì cứ nhập Array rồi sau khi có môt danh sách thì click vd. vào "Using Arrays". Sẽ có như trong hình. Đọc 3 chỗ tôi đánh dấu thì sẽ không phải hỏi ai nữa.array.JPG
 
Upvote 0
Chỗ đỏ đỏ tôi đã từng nói cho bạn.

Tôi đã nhiều lần nói là mọi người ai cũng có một kho kiến thức trong tầm tay nhưng cứ đi tìm ở đâu đâu, không chịu đọc mà cứ đi hỏi.
Trong VBA ở trên góc trên bên phải có 1 trường. Nếu không biết nhập gì thì cứ nhập Array rồi sau khi có môt danh sách thì click vd. vào "Using Arrays". Sẽ có như trong hình. Đọc 3 chỗ tôi đánh dấu thì sẽ không phải hỏi ai nữa.View attachment 216095
Dạ con chào Bác!
Hình như cái Help của con ở phiên bản office2016 nó hơi khác ạ :
https://docs.microsoft.com/en-us/of...nce/user-interface-help/array-function#syntax

Con sẽ tìm hiểu hiểu thêm ạ, cảm ơn Bác đã chỉ dẫn.
 
Upvote 0
Xin chào các bạn,

OT có một thắc mắc nhờ bạn chỉ giúp,tại sao:
Dim arr()
arr = .Range("N8:AG10").Value ---> thì phần tử đầu tiên trong mảng là 1
Còn: ReDim arr1(UBound(arr, 1), 6) ---> thì phần tử đầu tiên trong mảng là 0
mà phải sử dụng: ReDim arr1(1 To UBound(arr, 1), 1 To 6) để phần tử bắt đầu từ 1

Hihi
Nói cho thật đúng ngôn ngữ mảng thì "phần tử đầu tiên" chả phải là 0 mà cũng chả phải là 1.
0 và 1 là chỉ số để truy phần tử mảng.
Nếu mảng bắt đầu từ 0 thì chỉ số phần tử đầu tiên là 0. Nếu bắt đầu từ 1 thì chỉ số phần tử đầu tiên là 1.
arr(i, j) là biểu thức truy ra phần tử ở chỉ số dòng i và chỉ số cột j của mảng arr.

Dim arr() là lệnh khai báo mảng động, chưa định trước số chiều và độ lớn (phạm vi chỉ số). Lưu ý rằng tôi nói mảng động. Mảng tĩnh nó khác.

ReDim arr(....) là lệnh xác định chiều và phạm vi chỉ số của mảng động. Khi sử dụng ReDim mà không xác định chỉ số dưới (trị của LBound) thì lệnh này mặc định chúng là 0. Mặc định này có thể đổi thành 1 nếu ngay đầu Module có lệnh dẫn trình dịch Option Base 1
Ở đầu mõi Module, trước khi có code khai báo biến và sub, function thì người code có thể nhét một số lệnh dẫn trình dịch. Và Option Base là một trong những lệnh dẫn này (Option Explicit là lệnh dẫn thứ hai)

arr = .Range("N8:AG10").Value là lệnh gán trị của Range vào mảng. Lệnh gán này gọi một hàm kín của đối tượng Range. Hàm này lấy trị Range và tự động xác định chiều cùng phạm vi chỉ số của mảng (có thể coi như nó gọi lệnh Redim), và mặc định chỉ số dưới, tức trị LBound là (1,1)

Chú: khi làm việc với mảng thì phải tìm hiểu cho rõ mỗi hàm của VBA mặc định chỉ số dưới ra sao.
 
Upvote 0
Nói cho thật đúng ngôn ngữ mảng thì "phần tử đầu tiên" chả phải là 0 mà cũng chả phải là 1.
0 và 1 là chỉ số để truy phần tử mảng.
Nếu mảng bắt đầu từ 0 thì chỉ số phần tử đầu tiên là 0. Nếu bắt đầu từ 1 thì chỉ số phần tử đầu tiên là 1.
arr(i, j) là biểu thức truy ra phần tử ở chỉ số dòng i và chỉ số cột j của mảng arr.

Dim arr() là lệnh khai báo mảng động, chưa định trước số chiều và độ lớn (phạm vi chỉ số). Lưu ý rằng tôi nói mảng động. Mảng tĩnh nó khác.

ReDim arr(....) là lệnh xác định chiều và phạm vi chỉ số của mảng động. Khi sử dụng ReDim mà không xác định chỉ số dưới (trị của LBound) thì lệnh này mặc định chúng là 0. Mặc định này có thể đổi thành 1 nếu ngay đầu Module có lệnh dẫn trình dịch Option Base 1
Ở đầu mõi Module, trước khi có code khai báo biến và sub, function thì người code có thể nhét một số lệnh dẫn trình dịch. Và Option Base là một trong những lệnh dẫn này (Option Explicit là lệnh dẫn thứ hai)

arr = .Range("N8:AG10").Value là lệnh gán trị của Range vào mảng. Lệnh gán này gọi một hàm kín của đối tượng Range. Hàm này lấy trị Range và tự động xác định chiều cùng phạm vi chỉ số của mảng (có thể coi như nó gọi lệnh Redim), và mặc định chỉ số dưới, tức trị LBound là (1,1)

Chú: khi làm việc với mảng thì phải tìm hiểu cho rõ mỗi hàm của VBA mặc định chỉ số dưới ra sao.
Bác VetMini,
Về Option Base 1 thì con đã hiểu,còn vấn đề gán từ range vào mảng thì phần tử đầu tiên luôn mặc định là 1,đến ngày hôm nay con mới được biết. :D
Con cảm ơn các Bác đã giải thích và chỉ dẫn ạ.
 
Upvote 0
Dạ con chào Bác!
Hình như cái Help của con ở phiên bản office2016 nó hơi khác ạ :
https://docs.microsoft.com/en-us/of...nce/user-interface-help/array-function#syntax

Con sẽ tìm hiểu hiểu thêm ạ, cảm ơn Bác đã chỉ dẫn.
Có lẽ tôi đã viết rất rõ. Nhập Array là khi bạn chưa biết nhập chi tiết thế nào. Khi ra 1 danh sách thì như hình 1.
array1.JPG
Tôi đã nói rõ là trong danh sách đó thì click vào Using Arrays nhưng bạn lại click vào Array Function (mục đầu tiên trong hình 1).

Nếu bạn cuộn xuống dưới thì bạn sẽ thấy Using Arrays (hình 2) Click vào Declaring Arrays và đọc tiếp. Danh sách có nhiều mục chứ đâu có 1 mục mà bạn.
array2.JPG
 
Upvote 0
Có lẽ tôi đã viết rất rõ. Nhập Array là khi bạn chưa biết nhập chi tiết thế nào. Khi ra 1 danh sách thì như hình 1.
View attachment 216101
Tôi đã nói rõ là trong danh sách đó thì click vào Using Arrays nhưng bạn lại click vào Array Function (mục đầu tiên trong hình 1).

Nếu bạn cuộn xuống dưới thì bạn sẽ thấy Using Arrays (hình 2) Click vào Declaring Arrays và đọc tiếp. Danh sách có nhiều mục chứ đâu có 1 mục mà bạn.
View attachment 216102

Dạ, ý của con là, con đang sử dụng office 2016 nên có thể Help ở dạng Online hơi khác với Help Offline ở các phiên bản Office cũ hơn ạ.
Bác xem đoạn video con thao tác trên máy của con ạ.

Con cảm ơn Bác đã thông tin ạ.
 

File đính kèm

Upvote 0
Dạ, ý của con là, con đang sử dụng office 2016 nên có thể Help ở dạng Online hơi khác với Help Offline ở các phiên bản Office cũ hơn ạ.
Bác xem đoạn video con thao tác trên máy của con ạ.

Con cảm ơn Bác đã thông tin ạ.
Tôi không biết bạn cài Excel thế nào nhưng tôi nghĩ là cũng sẽ có help như của tôi. Không phải phiên bản này giống của tôi và phiên bản khác giống của bạn. Tùy thuộc vào lựa chọn thôi. Tôi không có 2016 nên chỉ đoán thế.

Khi tôi lần đầu tiên dùng help thì cũng của như bạn. Tức khi nhập vd. hichic vào thì có như hình 1. Nhìn thấy "Connected to Office.com"
Sau khi click vào đấy thì như hình 2 và tôi chuyển đánh dấu sang "Show content only from this computer" sau đó đóng cửa sổ. Từ lúc này trở đi thì help sẽ được mở như tôi đã trình bầy, và nhìn thấy lúc này là "Offline" chứ không là "Connected to Office.com"
help1.JPG

help2.JPG

help3.JPG
 
Upvote 0
Xin chào các bạn,
Tôi chạy đoạn code sau:

Mã:
Option Explicit

Sub TesDic()

    Const txt As String = "NhanVien 0001"
    Const tmp As String = "NhanVien 0000"
   
    Dim arr(), i As Long, j As Long
    Dim dic As Scripting.Dictionary
    Set dic = New Scripting.Dictionary
    'Kích hoạt microsoft scripting runtime

    dic.Add "NhanVien 0002", 10
    dic.Add "NhanVien 0003", 8
    dic.Add "NhanVien 0004", 6
    dic.Add tmp, 0
   
    If Not dic.Exists(txt) Then dic.Add txt, 100
    dic.Remove (tmp)
    dic(txt) = 120
   
    i = dic.Count
    ReDim arr(1 To i, 1 To 2)
   
    For j = 0 To i - 1
        arr(j + 1, 1) = dic.Keys(j)
        arr(j + 1, 2) = dic.Items(j)
    Next j
   
    Range("E2").Resize(UBound(arr), UBound(arr, 2)) = arr
   
End Sub

Kết quả OK, không có lỗi.
Nhưng khi thay đổi cách khai báo:
Mã:
Dim dic As Scripting.Dictionary
Set dic = New Scripting.Dictionary
Thành:
Mã:
Dim dic As Object
Set dic = CreateObject("Scripting.Dictionary")
Thì code báo lỗi:
"Property let procedure not defined and property get procedure did not return an object (Error 451)"

Nhờ các bạn chỉ giúp nguyên nhân ạ.
 
Lần chỉnh sửa cuối:
Upvote 0
Xin chào các bạn,
Tôi chạy đoạn code sau:

Mã:
Option Explicit

Sub TesDic()

    Const txt As String = "NhanVien 0001"
    Const tmp As String = "NhanVien 0000"
  
    Dim arr(), i As Long, j As Long
    Dim dic As Scripting.Dictionary
    Set dic = New Scripting.Dictionary
    'Kích hoạt microsoft scripting runtime

    dic.Add "NhanVien 0002", 10
    dic.Add "NhanVien 0003", 8
    dic.Add "NhanVien 0004", 6
    dic.Add tmp, 0
  
    If Not dic.Exists(txt) Then dic.Add txt, 100
    dic.Remove (tmp)
    dic(txt) = 120
  
    i = dic.Count
    ReDim arr(1 To i, 1 To 2)
  
    For j = 0 To i - 1
        arr(j + 1, 1) = dic.Keys(j)
        arr(j + 1, 2) = dic.Items(j)
    Next j
  
    Range("E2").Resize(UBound(arr), UBound(arr, 2)) = arr
  
End Sub

Kết quả OK, không có lỗi.
Nhưng khi thay đổi cách khai báo:
Mã:
Dim dic As Scripting.Dictionary
Set dic = New Scripting.Dictionary
Thành:
Mã:
Dim dic As Object
Set dic = CreateObject("Scripting.Dictionary")
Thì code báo lỗi:
"Property let procedure not defined and property get procedure did not return an object (Error 451)"

Nhờ các bạn chỉ giúp nguyên nhân ạ.
Nguyên nhân là khai báo dic muộn (late binding), còn trường hợp trên là khai báo dic sớm (early binding)
 
Upvote 0
Nguyên nhân là khai báo dic muộn (late binding), còn trường hợp trên là khai báo dic sớm (early binding)
Xin chào tam888,
Cảm ơn bạn đã giúp đỡ, vâng OT cũng hiểu sự khác nhau giữa khai báo sớm và khai báo muộn.
Vấn đề khai báo sớm hay khai báo muộn OT nghĩ nó tiện cho việc đỡ khỏi tích vào thư viện "microsoft scripting runtime" không nghĩ rằng nó lại ảnh hưởng đến nhiều vấn đề khác nữa.
Ví dụ như vấn đề OT đang thắc mắc.
 
Upvote 0
Xin chào tam888,
Cảm ơn bạn đã giúp đỡ, vâng OT cũng hiểu sự khác nhau giữa khai báo sớm và khai báo muộn.
Vấn đề khai báo sớm hay khai báo muộn OT nghĩ nó tiện cho việc đỡ khỏi tích vào thư viện "microsoft scripting runtime" không nghĩ rằng nó lại ảnh hưởng đến nhiều vấn đề khác nữa.
Ví dụ như vấn đề OT đang thắc mắc.
Ảnh hưởng này thì sửa được, bằng cách gán .Keys và .Items xuống 2 biến trước, rồi mới khai thác
Nguyên nhân thì chắc là lõi vấn đề trong xử lý khác nhau với khai báo sớm và khai báo muộn của Microsoft - code của họ đóng như hộp đen, nên chỉ có thể suy luận là do
- Khai báo sớm -- thì nó dành cho tạo vùng 1 đối tượng rõ ràng
- Khai báo muộn thì có thể chỉ là vùng ảo, nên khó cấp tiếp cho việc xác lập đối tượng mới Array (.keys, .items - là array)
(tuy thế tất cả là suy luận nên có thể không đúng bản chất)

Ảnh hưởng này thì sửa được, bằng cách gán .Keys và .Items xuống 2 biến trước, rồi mới khai thác
Cái này nên làm với cả 2 trường hợp Khai báo sớm và muộn vì có thể giúp chương trình chạy nhanh hơn, và logic hơn
Vì .Keys, :items --> về bản chất nó là phương thức --> có thể nó phải thực hiện tính toán trong đối tượng dic ==> như vậy mỗi lần gọi thì lại mất thời gian truy xuất.


Vấn đề khai báo sớm hay khai báo muộn OT nghĩ nó tiện cho việc đỡ khỏi tích vào thư viện "microsoft scripting runtime" không nghĩ rằng nó lại ảnh hưởng đến nhiều vấn đề khác nữa.
Còn khác nhau nhiều nữa, vì bản chất cách tạo khác nhau -- không chỉ khắc phục sự lười đâu. tất nhiên cả sự tiện nữa
 
Lần chỉnh sửa cuối:
Upvote 0
...
Nhưng khi thay đổi cách khai báo:
Mã:
Dim dic As Scripting.Dictionary
Set dic = New Scripting.Dictionary
Thành:
Mã:
Dim dic As Object
Set dic = CreateObject("Scripting.Dictionary")
Thì code báo lỗi:
"Property let procedure not defined and property get procedure did not return an object (Error 451)"

Nhờ các bạn chỉ giúp nguyên nhân ạ.
Bạn đã làm quen với VBA lâu ròi, và đã hỏi ở GPE nhiều rồi. Đáng lẽ bạn phải biết rằng "code báo lỗi .... " vẫn chưa đủ diễn tả hết.
Lần sau nhớ thêm chi tiết nó báo lỗi ở dòng nào. Tránh cho người khác phải đoán mò.

Theo code trên thì tôi đoán mò rằng nó lỗi ở dòng này:
arr(j + 1, 1) = dic.Keys(j)

Giải thích:
Vần đề này đã từng được một bạn khác (và tôi) giải thích trong một vài thớt về Dictionary. Hiển nhiên là bạn chưa đọc thớt ấy, hoặc có đọc nhưng chưa hiểu vì không có cơ hội thực tiễn.

Khi kết nối sớm, VBA có đủ tư liệu để đoán một số hàm/thủ tục và dùng dạng mặc định để chấp nhận một số ngữ pháp (qua kỹ thuật wapper hoặc hàm mặc định).
Khi kết nối trễ, VBA không có tư liệu để đoán, và vì vậy các hàm/thủ tục phải được gọi đúng ngữ pháp.

Hàm gọi keys của dictionary gọi theo đúng ngữ pháp là Keys(), và nó trả về một collection.
Ngữ pháp đúng thì phải là
arr(j + 1, 1) = dic.Keys()(j)
Và tương tự như vậy cho hàm Items()

Code trước của bạn không bị lỗi là vì khi kết nối sớm, VBA có đủ tư liệu để đoán hàm này và gọi cái wrapper property (thuộc tính giao diện) để hiểu dic.Keys(j) là cái gì.
 
Upvote 0
Xin chào các bạn,
Tôi chạy đoạn code sau:

Mã:
Option Explicit

Sub TesDic()

    Const txt As String = "NhanVien 0001"
    Const tmp As String = "NhanVien 0000"
  
    Dim arr(), i As Long, j As Long
    Dim dic As Scripting.Dictionary
    Set dic = New Scripting.Dictionary
    'Kích hoạt microsoft scripting runtime

    dic.Add "NhanVien 0002", 10
    dic.Add "NhanVien 0003", 8
    dic.Add "NhanVien 0004", 6
    dic.Add tmp, 0
  
    If Not dic.Exists(txt) Then dic.Add txt, 100
    dic.Remove (tmp)
    dic(txt) = 120
  
    i = dic.Count
    ReDim arr(1 To i, 1 To 2)
  
    For j = 0 To i - 1
        arr(j + 1, 1) = dic.Keys(j)
        arr(j + 1, 2) = dic.Items(j)
    Next j
  
    Range("E2").Resize(UBound(arr), UBound(arr, 2)) = arr
  
End Sub

Kết quả OK, không có lỗi.
Nhưng khi thay đổi cách khai báo:
Mã:
Dim dic As Scripting.Dictionary
Set dic = New Scripting.Dictionary
Thành:
Mã:
Dim dic As Object
Set dic = CreateObject("Scripting.Dictionary")
Thì code báo lỗi:
"Property let procedure not defined and property get procedure did not return an object (Error 451)"

Nhờ các bạn chỉ giúp nguyên nhân ạ.
Trong link sau tôi nói về server COM, kết nối sớm và kết nối trễ, sự khác nhau về bản chất của 2 loại kết nối.


Ở link dưới đây người ta hỏi vấn đề y như của bạn


Bạn đọc các bài viết của tôi trong 2 link sau thì bạn phải hiểu được nguyên nhân, và cách viết phải như thế nào. Và hiểu thêm về Dictionary.


-----------
Sau khi đọc các bài và hiểu thì bạn sẽ theo bài tôi hướng dẫn (bài đầu trong 2 link cuối) và sửa
Mã:
arr(j + 1, 1) = dic.Keys(j)
arr(j + 1, 2) = dic.Items(j)
thành
Mã:
arr(j + 1, 1) = dic.Keys()(j)
arr(j + 1, 2) = dic.Items()(j)
 
Upvote 0
Bạn đã làm quen với VBA lâu ròi, và đã hỏi ở GPE nhiều rồi. Đáng lẽ bạn phải biết rằng "code báo lỗi .... " vẫn chưa đủ diễn tả hết.
Lần sau nhớ thêm chi tiết nó báo lỗi ở dòng nào. Tránh cho người khác phải đoán mò.

Theo code trên thì tôi đoán mò rằng nó lỗi ở dòng này:
arr(j + 1, 1) = dic.Keys(j)

Giải thích:
Vần đề này đã từng được một bạn khác (và tôi) giải thích trong một vài thớt về Dictionary. Hiển nhiên là bạn chưa đọc thớt ấy, hoặc có đọc nhưng chưa hiểu vì không có cơ hội thực tiễn.

Khi kết nối sớm, VBA có đủ tư liệu để đoán một số hàm/thủ tục và dùng dạng mặc định để chấp nhận một số ngữ pháp (qua kỹ thuật wapper hoặc hàm mặc định).
Khi kết nối trễ, VBA không có tư liệu để đoán, và vì vậy các hàm/thủ tục phải được gọi đúng ngữ pháp.

Hàm gọi keys của dictionary gọi theo đúng ngữ pháp là Keys(), và nó trả về một collection.
Ngữ pháp đúng thì phải là
arr(j + 1, 1) = dic.Keys()(j)
Và tương tự như vậy cho hàm Items()

Code trước của bạn không bị lỗi là vì khi kết nối sớm, VBA có đủ tư liệu để đoán hàm này và gọi cái wrapper property (thuộc tính giao diện) để hiểu dic.Keys(j) là cái gì.

Xin chào Bác VetMini
Dạ đúng rồi code lỗi ở dòng:
arr(j + 1, 1) = dic.Keys(j)

Con cảm ơn Bác đã chỉ dẫn ạ, lần này chắc con phải đọc đi đọc lại vài lần những vấn đề con thắc mắc :D
Bài đã được tự động gộp:

Trong link sau tôi nói về server COM, kết nối sớm và kết nối trễ, sự khác nhau về bản chất của 2 loại kết nối.


Ở link dưới đây người ta hỏi vấn đề y như của bạn


Bạn đọc các bài viết của tôi trong 2 link sau thì bạn phải hiểu được nguyên nhân, và cách viết phải như thế nào. Và hiểu thêm về Dictionary.


-----------
Sau khi đọc các bài và hiểu thì bạn sẽ theo bài tôi hướng dẫn (bài đầu trong 2 link cuối) và sửa
Mã:
arr(j + 1, 1) = dic.Keys(j)
arr(j + 1, 2) = dic.Items(j)
thành
Mã:
arr(j + 1, 1) = dic.Keys()(j)
arr(j + 1, 2) = dic.Items()(j)

Xin chào Bác Siwtom,
Con cảm ơn Bác nhiều ạ, thực sự giờ con mới tìm hiểu về Dic và về code T_T
Không biết được bao lâu và sẽ đi đâu ạ.
Con chúc Bác nhiều sức khỏe.
 
Lần chỉnh sửa cuối:
Upvote 0
Mã:
Public Sub Supper_man()
Dim Rng As Range, xCell As Range
Dim xRows As Integer
xTitleId = "Supper_Trinh_ACC"
Set WorkRng = Application.Selection
Set WorkRng = Application.InputBox("Range", xTitleId, WorkRng.Address, Type:=8)
Application.ScreenUpdating = False
Application.DisplayAlerts = False
xRows = WorkRng.Rows.Count
For Each Rng In WorkRng.Columns
For i = 1 To xRows - 1
        For j = i + 1 To xRows
            If Rng.Cells(i, 1).Value <> Rng.Cells(j, 1).Value Then
                Exit For
            End If
        Next
        WorkRng.Parent.Range(Rng.Cells(i, 1), Rng.Cells(j - 1, 1)).Merge
        i = j - 1
    Next
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
nhờ các thầy cô xem giúp em đoạn code trên với ạ. em muốn merge ô lại. nhưng các ô vẫn phải giữ giá trị như ban đầu. (lí do là em để em dùng sumproduct cho nó tính được ạ).
Và có thể giữ nguyên fomat và màu định dạng ban đầu không ạ
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Các bạn giúp mình đoạn VBA này với.

Mình muốn Copy 1 dòng sau đó chèn dòng đã copy vào các dòng phía dưới.
Mình tìm được đoạn code như dưới mà không biết làm tiếp như thế nào. Các bạn xem file đính kèm rồi giúp mình với nha. Thanks.

Mã:
Sub InsertCopiedCells()
    Rows("1:1").Select
    Selection.Copy
    Selection.Insert Shift:=x1Down
    Application.CutCopyMode = False
End Sub
 

File đính kèm

Upvote 0
Các bạn giúp mình đoạn VBA này với.

Mình muốn Copy 1 dòng sau đó chèn dòng đã copy vào các dòng phía dưới.
Mình tìm được đoạn code như dưới mà không biết làm tiếp như thế nào. Các bạn xem file đính kèm rồi giúp mình với nha. Cảm ơn.

Mã:
Sub InsertCopiedCells()
    Rows("1:1").Select
    Selection.Copy
    Selection.Insert Shift:=x1Down
    Application.CutCopyMode = False
End Sub
Ơ mới có copy chưa có paste.
 
Upvote 0
Rows("1:1").Select ' => chọn dòng 1
Selection.Copy ' => Copy dòng đang chọn
Selection.Insert Shift:=x1Down ' => chèn tại dòng đang chọn

Nếu muốn chèn tại dòng 3 thì viết rút gọn như sau:

Rows("1:1").Copy ' => Copy dòng 1
Rows("3:3").Insert Shift:=x1Down ' => chèn tại dòng 3
 
Upvote 0
Rows("1:1").Select ' => chọn dòng 1
Selection.Copy ' => Copy dòng đang chọn
Selection.Insert Shift:=x1Down ' => chèn tại dòng đang chọn

Nếu muốn chèn tại dòng 3 thì viết rút gọn như sau:

Rows("1:1").Copy ' => Copy dòng 1
Rows("3:3").Insert Shift:=x1Down ' => chèn tại dòng 3

Cái đoạn này mình hiểu rùi. Ý mình là mình muốn phát triển đoạn này lên 1 xíu là mình muốn chèn cái đoạn mình copy vào nhiều dòng như sheet "kết quả" trong file của mình ấy.

Kiểu như đoạn code dưới. Nhưng mà đoạn này thì mình viết sai rồi nên bị lỗi
Mã:
Do
    Rows(r.Offset(1, 0), r.Offset(j, 0)).Insert Shift:=x1Down
    Set r = Cells(r.Row + j + 1, 1)
    If r.Offset(1, 0) = "" Then Exit Do
    Loop
216579
Bạn xem giúp mình đoạn này hoặc chỉ mình viết đoạn khác với. Cảm ơn nhiều lắm.
 
Upvote 0
Cái đoạn này mình hiểu rùi. Ý mình là mình muốn phát triển đoạn này lên 1 xíu là mình muốn chèn cái đoạn mình copy vào nhiều dòng như sheet "kết quả" trong file của mình ấy.

Kiểu như đoạn code dưới. Nhưng mà đoạn này thì mình viết sai rồi nên bị lỗi
Mã:
Do
    Rows(r.Offset(1, 0), r.Offset(j, 0)).Insert Shift:=x1Down
    Set r = Cells(r.Row + j + 1, 1)
    If r.Offset(1, 0) = "" Then Exit Do
    Loop
View attachment 216579
Bạn xem giúp mình đoạn này hoặc chỉ mình viết đoạn khác với. Cảm ơn nhiều lắm.
Bạn cho cái file lên nhé.
 
Upvote 0

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

Back
Top Bottom