Chuyên đề giải đáp những thắc mắc về code VBA

Liên hệ QC

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:
PHP:
Sub Chon_O_Cuoi()
'  Range1 = Union(Range("A2:B3"), [C1: D9])        '
    Sheets("Sheet1").Range("Range1").Select
    Selection(Selection.Rows.Count, Selection.Columns.Count).Select
    MsgBox Selection.Address
End Sub
Vấn đề là thế nào là ô cuối: ' Range1 = Union(Range("A2:A13"), [C1: D9])
Dùng vòng Do While để tính ô cuối
 
Upvote 0
Mã:
Sub Chon_o_cuoi()
  Sheets("Sheet1").Range("mang1").Select
  Selection(Selection.Rows.Count, Selection.Columns.Count).Select
End Sub
Em cảm ơn bác ạ. Code rất đúng ý em ạ.
Bài đã được tự động gộp:

PHP:
Sub Chon_O_Cuoi()
    Sheets("Sheet1").Range("mang1").Select
    With Selection
        If .Columns.Count = 1 Then
            .Offset()(.Rows.Count).Select
        Else
            .Offset()(.Cells.Count).Select
        End If
        MsgBox Selection.Address
    End With
End Sub
Em cảm ơn bác ạ. Code rất đúng ý em ạ!
 
Upvote 0
Cho em hỏi tại sao với code sau:
Mã:
Sub ThemNgayNghiLe2()
    Dim Parts() As String
    Dim Default
    Default = "01/31/2019,02/04/2019,02/05/2019,02/06/2019,02/07/2019,02/08/2019"
    On Error GoTo NoText
    Parts = Split(Replace(InputBox("Enter the values separated by commas", "List of HOLIDAY (mm/dd/yyyy)", Default, 10000, 1000), ", ", ","), ",")
    Range("A15:A30").Select
    With Selection
        .ClearContents
        .NumberFormat = "dd/mm/yyyy"
    End With
    With Range("A15").Resize(1 + UBound(Parts))
        .Cells = Application.Transpose(Parts)
    End With
NoText:
End Sub
Khi nhập giá trị ngày tháng theo kiểu dd/mm/yyyy vào inputbox thì khi ra sheet nó lại thành kiểu mm/dd/yyyy.
Có cách nào nhập trên inputbox dạng dd/mm/yyyy, ..., cách nhau dấu phẩy thì vào A15 của sheet theo kiểu dd/mm/yyyy ah?
 
Upvote 0
Cho em hỏi tại sao với code sau:
Mã:
Sub ThemNgayNghiLe2()
    Dim Parts() As String
    Dim Default
    Default = "01/31/2019,02/04/2019,02/05/2019,02/06/2019,02/07/2019,02/08/2019"
    On Error GoTo NoText
    Parts = Split(Replace(InputBox("Enter the values separated by commas", "List of HOLIDAY (mm/dd/yyyy)", Default, 10000, 1000), ", ", ","), ",")
    Range("A15:A30").Select
    With Selection
        .ClearContents
        .NumberFormat = "dd/mm/yyyy"
    End With
    With Range("A15").Resize(1 + UBound(Parts))
        .Cells = Application.Transpose(Parts)
    End With
NoText:
End Sub
Khi nhập giá trị ngày tháng theo kiểu dd/mm/yyyy vào inputbox thì khi ra sheet nó lại thành kiểu mm/dd/yyyy.
Có cách nào nhập trên inputbox dạng dd/mm/yyyy, ..., cách nhau dấu phẩy thì vào A15 của sheet theo kiểu dd/mm/yyyy ah?
Nhìn
Default = "01/31/2019,02/04/2019,02/05/2019,02/06/2019,02/07/2019,02/08/2019"
...
Parts = Split(Replace(InputBox("Enter the values separated by commas", "List of HOLIDAY (mm/dd/yyyy)", Default, 10000, 1000), ", ", ","), ",")
thì là bạn đang hướng dẫn người ta nhập theo dạng mm/dd/yyyy chứ đâu phải như bây giờ bạn viết là
Khi nhập giá trị ngày tháng theo kiểu dd/mm/yyyy vào inputbox

Vấn đề khác: khi bạn nhập tay trên sheet ngày tháng chuẩn thì sẽ hiển thị là mm/dd/yyyy hay dd/mm/yyyy. Nói cách khác, thiết lập trong CP là thế nào? Đừng bắt là dd/mm/yyyy hay mm/dd/yyyy. Chỉ nên bắt đúng theo thiết lập trong CP. Còn nó là cái này hay cái kia thì do CP quyết định.
 
Upvote 0
Tại em khó diễn đạt quá. Với code:
Mã:
Sub ThemNgayNghiLe3()
    Dim Parts() As String
    Dim Default
    Default = "31/01/2019,04/02/2019,05/02/2019,06/02/2019,07/02/2019,08/02/2019"
    On Error GoTo NoText
    Parts = Split(Replace(InputBox("Enter the values separated by commas", "List of HOLIDAY", Default, 10000, 1000), ", ", ","), ",")
    Range("A15:A30").Select
    With Selection
        .ClearContents
        .NumberFormat = "dd/mm/yyyy"
    End With
    With Range("A15").Resize(1 + UBound(Parts))
        .Cells = Application.Transpose(Parts)
    End With
NoText:
End Sub
Thì với 31/01/2019 thì nó dạng text, còn lại thì dạng dd/mm/yyyy nhưng lại hiển thị kiểu mm/dd/yyyy ah

Còn khi vào nhập dữ liệu vào box kiểu tháng trước ngày sau thì kết quả ở sheet lại chuẩn kiểu dd/mm/yyyy. Mà em thì muốn kiểu VN.
1.png
 
Upvote 0
Thôi tôi cũng không đi sâu vào vấn đề nữa.
Bạn thử sửa thành
Mã:
.NumberFormat = "m/d/yyyy"
thì kết quả test sẽ thế nào?
 
Upvote 0
Khi dùng code, người ta luôn luôn tránh tình trạng ngày tháng không thống nhất.
Trước khi ghi dữ liệu, luôn luôn đưa nó về dạng chuẩn. Bạn có hai cách:
1. dùng hàm dateserials để đổi chuỗi thành dạng số - chịu khó tìm, trên diễn đàn có nhiều rồi.
2. dùng dạng chuẩn của CSDL, tức là "yyyy/mm/dd". Khi Excel gặp dữ liệu loại này, nó tự động đổi thành ngày đúng như mong muốn.

Mã:
Sub ThemNgayNghiLe2()
    Dim Parts() As String
    Dim Default
    Default = "01/31/2019,02/04/2019,02/05/2019,02/06/2019,02/07/2019,02/08/2019"
    On Error GoTo NoText
    Parts = Split(Replace(InputBox("Enter the values separated by commas", "List of HOLIDAYS (mm/dd/yyyy)", Default, 10000, 1000), ", ", ","), ",")
    Range("A15:A30").Select
    With Selection
        .ClearContents
        .NumberFormat = "dd/mm/yyyy"
    End With
    For Default = LBound(Parts) To UBound(Parts)
        Parts(Default) = UniversalDate(Parts(Default), "US") ' nếu nhập dạng dd/mm/yyyy thì dùng tham "EU"
    Next Default
    Range("A15").Resize(1 + UBound(Parts)).Cells = Application.Transpose(Parts)
NoText:
End Sub

Function UniversalDate(ByVal d As String, Optional inTyp As String = "US") As String
' function to change date string from dd/mm/yyyy (inTyp="EU"), or mm/dd/yyyy (inTyp="US") to yyyy/mm/dd
Dim x() As String
x = Split(d, "/")
If Len(x(2)) < 4 Then x(2) = CStr(2000 + Val(x2)) ' normalise year
If UCase(inTyp) = "US" Then
UniversalDate = x(2) & "/" & x(0) & "/" & x(1)
Else
UniversalDate = x(2) & "/" & x(1) & "/" & x(0)
End If
End Function

(tôi chỉ mách cho cách giải quyết dữ liệu ngày tháng thôi. Code của bạn có hiệu quả hay không là chuyện khác)
 
Upvote 0
Nếu tôi không lầm thì bạn nên nhập ở dạng "mm/dd/yyyy" như bạn đang làm bây giờ và
Mã:
.NumberFormat = "m/d/yyyy"
Lúc đó mang sang máy nào cũng chuẩn, chả cần thêm code gì cả.

Tôi trình bầy với 2 thiết lập Ba Lan và Việt Nam ở máy tôi. Bạn chạy ở máy bạn xem thế nào.

Khi bạn đã hỏi và có người trả lời thì nên thông báo lại là vấn đề có được giải quyết hay không. "Lặng lẽ" chuồn là không nên.

Nếu trên máy bạn lại khác thì thông báo để tôi biết nhé.
 

File đính kèm

  • test.rar
    717.8 KB · Đọc: 4
Upvote 0
Nếu tôi không lầm thì bạn nên nhập ở dạng "mm/dd/yyyy" như bạn đang làm bây giờ và
Mã:
.NumberFormat = "m/d/yyyy"
Lúc đó mang sang máy nào cũng chuẩn, chả cần thêm code gì cả.
...
Điểm này tôi đồng ý với bác. VBA luôn luôn mặc định biến đổi ngày theo dạng của Mẽo. Vì vậy nhập ở dạng mm/dd/yyy thì máy nào cũng ra được ngày như nhau cả.

Tôi nghĩ người hỏi bài bị rối (confused) ở chỗ 31/01/2019 vẫn ra giống như 01/31/2019. Cho nên mới phải đem lên đây hỏi.
Câu trả lời là: tuy VBA mặc định dạng mm/dd/yyyy nhưng nếu gặp tháng lớn hơn 12 thì nó tự động hiểu như dạng dd/mm/yyyy

Bác bảo immediate
? #01/31/2019#, #31/01/2019#
sẽ thấy nó in ra cả hai đều là ngày 31 tháng giêng
 
Upvote 0
Bác bảo immediate
? #01/31/2019#, #31/01/2019#
sẽ thấy nó in ra cả hai đều là ngày 31 tháng giêng
Thì thế tôi mới nói là phải nhập ở dạng "mm/dd/yyyy". Nếu muốn nhập 31 tháng Một năm 2019 thì phải nhập 01/31/2019 - dạng "mm/dd/yyyy" như yêu cầu, chứ không nên nhập 31/01/2019 - dạng "dd/mm/yyyy" không như yêu cầu.

Mà người hỏi cũng nhập

"01/31/2019,02/04/2019,02/05/2019,02/06/2019,02/07/2019,02/08/2019"

chứ có nhập

"31/01/2019,02/04/2019,02/05/2019,02/06/2019,02/07/2019,02/08/2019"

đâu.
 
Upvote 0
Thì thế tôi mới nói là phải nhập ở dạng "mm/dd/yyyy". Nếu muốn nhập 31 tháng Một năm 2019 thì phải nhập 01/31/2019 - dạng "mm/dd/yyyy" như yêu cầu, chứ không nên nhập 31/01/2019 - dạng "dd/mm/yyyy" không như yêu cầu.

Mà người hỏi cũng nhập

"01/31/2019,02/04/2019,02/05/2019,02/06/2019,02/07/2019,02/08/2019"

chứ có nhập

"31/01/2019,02/04/2019,02/05/2019,02/06/2019,02/07/2019,02/08/2019"

đâu.
Ở bài #1873 người hỏi bị lủng củng kiểu nhập.

Tại em khó diễn đạt quá. Với code:
Mã:
Sub ThemNgayNghiLe3()
    Dim Parts() As String
    Dim Default
    Default = "31/01/2019,04/02/2019,05/02/2019,06/02/2019,07/02/2019,08/02/2019"
    On Error GoTo NoText
    Parts = Split(Replace(InputBox("Enter the values separated by commas", "List of HOLIDAY", Default, 10000, 1000), ", ", ","), ",")
    Range("A15:A30").Select
    With Selection
        .ClearContents
        .NumberFormat = "dd/mm/yyyy"
    End With
    With Range("A15").Resize(1 + UBound(Parts))
        .Cells = Application.Transpose(Parts)
    End With
NoText:
End Sub
Thì với 31/01/2019 thì nó dạng text, còn lại thì dạng dd/mm/yyyy nhưng lại hiển thị kiểu mm/dd/yyyy ah

Còn khi vào nhập dữ liệu vào box kiểu tháng trước ngày sau thì kết quả ở sheet lại chuẩn kiểu dd/mm/yyyy. Mà em thì muốn kiểu VN.
View attachment 211992
.
31/01/2019 ở dạng text là vì hàm Transpose không tự động chuyển từ dd/mm sang mm/dd được. Và bảng tính không nhận nó là ngày.
04/02/2019 được dịch ra là ngày 2 tháng tư, lên bảng tính bạn định dạng thành ra 02/04/2019
Nếu bạn đặt ở ô B16, hàm =A16+1 thì sẽ thấy là 03/04/2019
 
Upvote 0
Ở bài #1873 người hỏi bị lủng củng kiểu nhập.
Thì thế bài #1872 tôi mới thắc mắc - vì lủng củng ngay từ bài #1871 rồi - vì tôi không hiểu.
Nhìn
Default = "01/31/2019,02/04/2019,02/05/2019,02/06/2019,02/07/2019,02/08/2019"
...
Parts = Split(Replace(InputBox("Enter the values separated by commas", "List of HOLIDAY (mm/dd/yyyy)", Default, 10000, 1000), ", ", ","), ",")

thì là bạn đang hướng dẫn người ta nhập theo dạng mm/dd/yyyy chứ đâu phải như bây giờ bạn viết là
Khi nhập giá trị ngày tháng theo kiểu dd/mm/yyyy vào inputbox

Rõ ràng hướng dẫn cho người khác ở trên trời, à nhầm, ở tiêu đề InputBox, là phải nhập dạng mm/dd/yyyy - List of HOLIDAY (mm/dd/yyyy), và cả ở dưới đất, à nhầm, ở Default, là phải nhập dạng mm/dd/yyyy - "01/31/2019,02/04/2019,02/05/2019,02/06/2019,02/07/2019,02/08/2019". Nhưng tới khi mình nhập thì lại nhập dạng dd/mm/yyyy - Khi nhập giá trị ngày tháng theo kiểu dd/mm/yyyy vào inputbox.

Tuy nhiên do tác giả không giải thích cho tôi sự mâu thuẫn trong cách hành sử của mình nên tôi bỏ qua
Thôi tôi cũng không đi sâu vào vấn đề nữa.

Tôi đề nghị mm/dd/yyyy + .NumberFormat = "m/d/yyyy" là để kết quả luôn hiển theo đúng như thiết lập trên máy hiện hành. Tức hiển thị sao cho đúng như người sử dụng hàng ngày vẫn quen. Bởi nếu dùng code
Mã:
Sub ThemNgayNghiLe2()
    Dim Parts() As String
    Dim Default
    Default = "01/31/2019,02/04/2019,02/05/2019,02/06/2019,02/07/2019,02/08/2019"
    On Error GoTo NoText
    Parts = Split(Replace(InputBox("Enter the values separated by commas", "List of HOLIDAY (" & Format(Date, "Short Date") & ")", Default, 10000, 1000), ", ", ","), ",")
    Range("A15:A30").Select
    With Selection
        .ClearContents
        .NumberFormat = "dd/mm/yyyy"
    End With
    With Range("A15").Resize(1 + UBound(Parts))
        .Cells = Application.Transpose(Parts)
    End With
NoText:
End Sub
thì trên máy tôi kết quả đúng là ngày tháng (định dạng Custom: dd-mm-yyyy) nhưng là
31-01-2019
04-02-2019
05-02-2019
06-02-2019
07-02-2019
08-02-2019

Nó làm cho người dùng hơi bị bất ngờ tuy người ta vẫn hiểu, và không đúng chuẩn Ba Lan. Chuẩn là
2019-01-31
2019-02-04
2019-02-05
2019-02-06
2019-02-07
2019-02-08

Chính vì thế mà tôi yêu sách là phải làm sao trả về đúng ngày tháng. Còn chuyện nó có dạng thư thế nào trên máy hiện hành thì không nên can thiệp. Cứ cứng nhắc là phải nhìn thấy 31/01/2019 là không được. Phải làm sao để anh Việt nhìn thấy 31/01/2019 nhưng cũng tập tin đó, code đó thì anh Ba Lan phải nhìn thấy 2019-01-31, anh Anh cũng phải nhìn thấy như mình hàng ngày vẫn thấy.

Mọi code viết chỉ để cố tình định dạng kết quả theo một dạng cứng nhắc theo tôi là không nên dùng. Chỉ phải trả kết quả đúng là ngày tháng. Còn dạng như thế nào thì để Excel tự xác định dựa trên thiết lập trong CP của máy hiện hành
 
Lần chỉnh sửa cuối:
Upvote 0
Dạ em cảm ơn ah, tại tối muộn mà sáng lại đi trực nên chưa reply and like các Thầy ah! em đang làm cái bảng cho bên kho quỹ tính công bốc xếp, chấm công..... Em đang test các kiểu. em sẽ báo lại sau khi hoàn chỉnh ah!
 
Upvote 0
Mã:
Sub Test()
'
    Dim r1, r2, c1, c2 As Long
    Sheets("Sheet1").Select
    Range("mang1").Select
    Selection(1, 1).Select
    r1 = Application.Selection.Row
    c1 = Application.Selection.Column
    Sheets("Sheet2").Select
    Range("mang2").Select
    Selection(1, 1).Select
    r2 = Application.Selection.Row - r1
    c2 = Application.Selection.Column - c1
    Sheets("Sheet1").Range("mang1").FormulaR1C1 = "=Data!R[r2]C[c2]"
'
End Sub
Các anh cho em hỏi tại dòng code 14: "=Data!R[r2]C[c2]" thì có cách nào đưa biến r2, c2 vào công thức muốn chèn không ạ. Em đưa vào bị lỗi không chạy được.
Mục đích code VBA để chèn công thức từ mang1 ở Sheet 1 lấy dữ liệu tương ứng từ mang2 ở Sheet2 trong khi mảng 2 không cố định vị trí.
Trân trọng cảm ơn!
 
Lần chỉnh sửa cuối:
Upvote 0
Mã:
Sub Test()
'
    Dim r1, r2, c1, c2 As Long
    Sheets("Sheet1").Select
    Range("mang1").Select
    Selection(1, 1).Select
    r1 = Application.Selection.Row
    c1 = Application.Selection.Column
    Sheets("Sheet2").Select
    Range("mang2").Select
    Selection(1, 1).Select
    r2 = Application.Selection.Row - r1
    c2 = Application.Selection.Column - c1
    Sheets("Sheet1").Range("mang1").FormulaR1C1 = "=Data!R[r2]C[c2]"
'
End Sub
Các anh cho em hỏi tại dòng code 14: "=Data!R[r2]C[c2]" thì có cách nào đưa biến r2, c2 vào công thức muốn chèn không ạ. Em đưa vào bị lỗi không chạy được.
Mục đích code VBA để chèn công thức từ mang1 ở Sheet 1 lấy dữ liệu tương ứng từ mang2 ở Sheet2 trong khi mảng 2 không cố định vị trí.
Trân trọng cảm ơn!
"=Data!R[r2]C[c2]" là 1 chuỗi, bạn thu sua lại the này xem sao
"=Data!R[" & r2 & "]C[" & c2 & "]"
 
Upvote 0
Mã:
'Sheets("Sheet1").Range("mang1").FormulaR1C1 = "=Sheet2!R["&r2&"]C["&c2&"]"
Sheets("Sheet1").Range("mang1").FormulaR1C1 = "=Sheet2!R[" & r2 & "]C[" & c2 & "]"
Bạn thay dòng trên bằng dòng dưới là ok. Lỗi là do thiếu dấu phân cách

Hay quá, mình đã làm được rồi, cảm ơn bạn nhiều nhé!
 
Upvote 0
Web KT
Back
Top Bottom