Tôi không biết dùng Range.Find nên dùng cách duyệt mảng.Em có code tạo mã theo ngày chạy được,các bác ghé qua giúp em như tiêu đề nhé!
Function TaomaCT(maCT As String) As String
Dim lrow As Long, arrData(), i As Long
Dim nam As Long, thang As Long, stt As Long, sttMax As Long, maCT_tk As String, maCTMoi As String
lrow = Sheet1.Cells(Sheet1.Rows.Count, "A").End(xlUp).Row
arrData = Sheets("Sheet1").Range("A2:A" & lrow).Value
curyear = Year(Date): curmonth = Month(Date)
'curyear = Sheet1.Range("E2"): curmonth = Sheet1.Range("D2") '<-- testing
sttMax = 1
For i = 1 To UBound(arrData)
nam = CLng("20" & Left(arrData(i, 1), 2)): thang = CLng(Mid(arrData(i, 1), 3, 2)): stt = CLng(Right(arrData(i, 1), 3))
maCT_tk = Mid(arrData(i, 1), 8, 1)
If nam = curyear And thang = curmonth And maCT_tk = UCase(maCT) Then
If stt > sttMax Then sttMax = stt
End If
Next
TaomaCT = Format(Date, "yymmdd-") & UCase(maCT) & Right("000" & sttMax + 1, 3)
'TaomaCT = Format(DateSerial(curyear, curmonth, Day(Date)), "yymmdd-") & UCase(maCT) & Right("000" & sttMax + 1, 3) '<-- testing
End Function
Xin cảm ơn anh đã giúp nhé! em mới học nên còn mù mờ lắm, anh gửi cả file cho em tham khảo được không?Tôi không biết dùng Range.Find nên dùng cách duyệt mảng.
JavaScript:Function TaomaCT(maCT As String) As String Dim lrow As Long, arrData(), i As Long Dim nam As Long, thang As Long, stt As Long, sttMax As Long, maCT_tk As String, maCTMoi As String lrow = Sheet1.Cells(Sheet1.Rows.Count, "A").End(xlUp).Row arrData = Sheets("Sheet1").Range("A2:A" & lrow).Value curyear = Year(Date): curmonth = Month(Date) 'curyear = Sheet1.Range("E2"): curmonth = Sheet1.Range("D2") '<-- testing sttMax = 1 For i = 1 To UBound(arrData) nam = CLng("20" & Left(arrData(i, 1), 2)): thang = CLng(Mid(arrData(i, 1), 3, 2)): stt = CLng(Right(arrData(i, 1), 3)) maCT_tk = Mid(arrData(i, 1), 8, 1) If nam = curyear And thang = curmonth And maCT_tk = UCase(maCT) Then If stt > sttMax Then sttMax = stt End If Next TaomaCT = Format(Date, "yymmdd-") & UCase(maCT) & Right("000" & sttMax + 1, 3) 'TaomaCT = Format(DateSerial(curyear, curmonth, Day(Date)), "yymmdd-") & UCase(maCT) & Right("000" & sttMax + 1, 3) '<-- testing End Function
N
hoặc X
vào cột Loại. Macro này sẽ dựa trên:E
nếu năm là 2025, F
nếu là 2026...8
cho tháng 8, 9
cho tháng 9)N
hoặc X
theo loạiCột | Tên cột | Vị trí |
---|---|---|
A | STT | 1 |
B | Ngày | 2 |
C | Loại | 3 |
D | Mã Phiếu | 4 |
E | Ghi chú | 5 |
Private Sub Worksheet_Change(ByVal Target As Range)
Dim r As Long
Dim loai As String, ngay As Date
Dim namMa As String, thangMa As String, loaiMa As String
Dim soThuTu As Long, maPhieu As String
Dim ws As Worksheet
Set ws = Me
' Kiểm tra nếu thay đổi ở cột Loại (C)
If Not Intersect(Target, ws.Range("C2:C1000")) Is Nothing Then
Application.EnableEvents = False
For Each cell In Intersect(Target, ws.Range("C2:C1000"))
r = cell.Row
loai = UCase(cell.Value)
' Chỉ xử lý nếu là N hoặc X
If loai = "N" Or loai = "X" Then
If IsDate(ws.Cells(r, 2).Value) Then
ngay = ws.Cells(r, 2).Value
' Tạo mã năm: E = 2025, F = 2026, G = 2027...
namMa = Chr(Asc("E") + Year(ngay) - 2025)
' Mã tháng: số nguyên
thangMa = Month(ngay)
' Loại mã: N hoặc X
loaiMa = loai
' Đếm số phiếu cùng tháng và loại trước đó
soThuTu = 0
For i = 2 To r - 1
If IsDate(ws.Cells(i, 2).Value) Then
If Month(ws.Cells(i, 2).Value) = Month(ngay) And _
Year(ws.Cells(i, 2).Value) = Year(ngay) And _
UCase(ws.Cells(i, 3).Value) = loai Then
soThuTu = soThuTu + 1
End If
End If
Next i
' Tăng số thứ tự lên 1
soThuTu = soThuTu + 1
' Ghép mã phiếu
maPhieu = namMa & thangMa & loaiMa & Format(soThuTu, "000")
' Ghi vào cột Mã Phiếu (D)
ws.Cells(r, 4).Value = maPhieu
End If
End If
Next cell
Application.EnableEvents = True
End If
End Sub
Alt + F11
để vào VBA EditorN
hoặc X
vào cột Loại → cột Mã Phiếu sẽ tự động điền theo quy tắcfile của em chỉ có cột ngày thôi anh!Mình đi nhờ Copilot đây:
Viết giúp mình macro sự kiện để khi nhập N hay X ở cột 'Loại'thì cột mã phiếu sẽ được macro điền tiếp mã phiếu theo qui tắc được ghi ở cột cuối
View attachment 309292
Tuyệt vời! Mình sẽ giúp bạn viết một macro sự kiện Worksheet_Change để tự động điền mã phiếu khi bạn nhậpN
hoặcX
vào cột Loại. Macro này sẽ dựa trên:
Quy tắc tạo mã phiếu
- Ký tự đầu:
E
nếu năm là 2025,F
nếu là 2026...- Ký tự thứ hai: mã tháng (ví dụ:
8
cho tháng 8,9
cho tháng 9)- Ký tự thứ ba:
N
hoặcX
theo loại- Số thứ tự: tăng dần theo từng loại trong cùng tháng
Cấu trúc bảng (giả định)
Cột Tên cột Vị trí A STT 1 B Ngày 2 C Loại 3 D Mã Phiếu 4 E Ghi chú 5 Mã VBA: Gắn vào Sheet chứa dữ liệu
Mã:Private Sub Worksheet_Change(ByVal Target As Range) Dim r As Long Dim loai As String, ngay As Date Dim namMa As String, thangMa As String, loaiMa As String Dim soThuTu As Long, maPhieu As String Dim ws As Worksheet Set ws = Me ' Kiểm tra nếu thay đổi ở cột Loại (C) If Not Intersect(Target, ws.Range("C2:C1000")) Is Nothing Then Application.EnableEvents = False For Each cell In Intersect(Target, ws.Range("C2:C1000")) r = cell.Row loai = UCase(cell.Value) ' Chỉ xử lý nếu là N hoặc X If loai = "N" Or loai = "X" Then If IsDate(ws.Cells(r, 2).Value) Then ngay = ws.Cells(r, 2).Value ' Tạo mã năm: E = 2025, F = 2026, G = 2027... namMa = Chr(Asc("E") + Year(ngay) - 2025) ' Mã tháng: số nguyên thangMa = Month(ngay) ' Loại mã: N hoặc X loaiMa = loai ' Đếm số phiếu cùng tháng và loại trước đó soThuTu = 0 For i = 2 To r - 1 If IsDate(ws.Cells(i, 2).Value) Then If Month(ws.Cells(i, 2).Value) = Month(ngay) And _ Year(ws.Cells(i, 2).Value) = Year(ngay) And _ UCase(ws.Cells(i, 3).Value) = loai Then soThuTu = soThuTu + 1 End If End If Next i ' Tăng số thứ tự lên 1 soThuTu = soThuTu + 1 ' Ghép mã phiếu maPhieu = namMa & thangMa & loaiMa & Format(soThuTu, "000") ' Ghi vào cột Mã Phiếu (D) ws.Cells(r, 4).Value = maPhieu End If End If Next cell Application.EnableEvents = True End If End Sub
Cách sử dụng
- Mở Excel → nhấn
Alt + F11
để vào VBA Editor- Chọn sheet chứa bảng dữ liệu → dán đoạn code vào khung Worksheet Code
- Quay lại Excel → nhập
N
hoặcX
vào cột Loại → cột Mã Phiếu sẽ tự động điền theo quy tắc
Bạn muốn mở rộng thêm để tự động ghi chú, kiểm tra trùng lặp, hay lọc theo ngày không? Mình có thể “chế” tiếp theo ý bạn
Xin cảm ơn anh đã giúp nhé! em mới học nên còn mù mờ lắm, anh gửi cả file cho em tham khảo được không?
Nhưng trong mả hóa đơn lại phải chứa tác vụ nhập hay xuất riêng biệt mà, phải không!file của em chỉ có cột ngày thôi anh!
Đúng rồi anh,file của em cần thêm sub nhỏ là tạo được các mã theo yêu cầu.File của bạn này phụ thuộc vào 1 ô ngày,tháng năm để tạo mã,là tạo mã theo ngày,hết tháng là chốt. Đúng không bạn?
Mã của em phụ thuộc vào 1 ô ngày,tháng,năm.Còn mã nhập xuất là thêm vào theo sub nhỏ.Em đang tìm hiểu code hết ngày,hết tuần,hết tháng và hết năm thì reset lại từ đầu.Anh biết chỉ em với!Nhưng trong mả hóa đơn lại phải chứa tác vụ nhập hay xuất riêng biệt mà, phải không!
Làm sao chương trình nó biết rằng bạn đang 'N' hay 'X'!
Ngoài lề 1 chút để rõ ý của mình:
Trong mã ta chỉ cần mã hóa năm & tháng; Vì 1 điều hiễn nhiên là sau mỗi tháng bạn lại bắt đầu lại số thứ tự nhập hay xuất mà!
[1 điều có thể quan tấm là hóa đơn đầu tháng mười (Tháng 11 :=B & tháng 12 :=C) có thể là EAN000 hay EAX000 (xuất)
chứ không nhất thiết phải là 001]
Cám ơn anh đã giúp! em test file sang tháng 9 thì mã tạo là 002 trở lên (đúng là 001) và xoá hết cột A thì code báo lỗiBạn xem file đính kèm.
File này của bạn chỉ test chơi thôi chứ thực tế không thiết kế kiểu vậy được.
Bạn phải vẽ ra được cái qui trình nhập liệu thực tế, các tham số nào cần đưa vào (như loại CT, ngày CT...) sau đó dựa 2 tham số đó mà tạo phiếu. Như kiểu bác SA đã gợi ý đó.
Số phiếu có số thứ tự liên tục, tháng sau sẽ đánh từ 001Em có code tạo mã theo ngày chạy được,các bác ghé qua giúp em như tiêu đề nhé!
Sub NewPhieuNX(MaPhieu)
Dim arr(), t$, eR&, i&, sp$, myDate As Date
myDate = Date
t = Format(myDate, "yymm??-") & MaPhieu
eR = Sheet1.Range("A" & Rows.Count).End(xlUp).Row
arr = Sheet1.Range("A1:B" & eR).Value
For i = UBound(arr) To 1 Step -1
If Mid(arr(i, 1), 1, 8) Like t Then
sp = Format(myDate, "yymmdd-") & MaPhieu & Format(Right(arr(i, 1), 3) + 1, "000")
Exit For
End If
Next i
If i = 0 Then sp = Format(myDate, "yymmdd-") & MaPhieu & "001"
Sheet1.Range("A" & eR + 1).Value = sp
End Sub
Cám ơn anh đã giúp! Anh thêm giúp ngày tháng phụ thuộc vào ô B5 nhé! (Khi ngày ô này sang thứ 2 thì chạy 001 trở lên đến chủ nhật là mã phiếu cuối)Số phiếu có số thứ tự liên tục, tháng sau sẽ đánh từ 001
Mã:Sub NewPhieuNX(MaPhieu) Dim arr(), t$, eR&, i&, sp$, myDate As Date myDate = Date t = Format(myDate, "yymm??-") & MaPhieu eR = Sheet1.Range("A" & Rows.Count).End(xlUp).Row arr = Sheet1.Range("A1:B" & eR).Value For i = UBound(arr) To 1 Step -1 If Mid(arr(i, 1), 1, 8) Like t Then sp = Format(myDate, "yymmdd-") & MaPhieu & Format(Right(arr(i, 1), 3) + 1, "000") Exit For End If Next i If i = 0 Then sp = Format(myDate, "yymmdd-") & MaPhieu & "001" Sheet1.Range("A" & eR + 1).Value = sp End Sub
Sửa lại cái sub TaoMaCT() chút.Cám ơn anh đã giúp! em test file sang tháng 9 thì mã tạo là 002 trở lên (đúng là 001) và xoá hết cột A thì code báo lỗi
Function TaomaCT(maCT As String) As String
Dim lrow As Long, arrData(), i As Long
Dim nam As Long, thang As Long, curYear As Long, curMonth As Long, stt As Long, sttMax As Long, maCT_tk As String, maCTMoi As String
lrow = Sheet1.Cells(Sheet1.Rows.Count, "A").End(xlUp).Row
curYear = Year(Date): curMonth = Month(Date)
'curYear = Sheet1.Range("E2"): curMonth = Sheet1.Range("D2") '<-- testing
Select Case lrow
Case 1
sttMax = 0
Case 2
sttMax = 1
Case Else
arrData = Sheets("Sheet1").Range("A2:A" & lrow).Value
sttMax = 0
For i = 1 To UBound(arrData)
nam = CLng("20" & Left(arrData(i, 1), 2)): thang = CLng(Mid(arrData(i, 1), 3, 2)): stt = CLng(Right(arrData(i, 1), 3))
maCT_tk = Mid(arrData(i, 1), 8, 1)
If nam = curYear And thang = curMonth And maCT_tk = UCase(maCT) Then
If stt > sttMax Then sttMax = stt
End If
Next
End Select
TaomaCT = Format(Date, "yymmdd-") & UCase(maCT) & Right("000" & sttMax + 1, 3)
'TaomaCT = Format(DateSerial(curYear, curMonth, Day(Date)), "yymmdd-") & UCase(maCT) & Right("000" & sttMax + 1, 3) '<-- testing
End Function
Dò ngược lại của bác HieuCD hay nhỉ, bớt được nhiều vòng lặp.Số phiếu có số thứ tự liên tục, tháng sau sẽ đánh từ 001
Mã:Sub NewPhieuNX(MaPhieu) ... For i = UBound(arr) To 1 Step -1 End Sub
Chỉnh tí . . . .Cám ơn anh đã giúp! Anh thêm giúp ngày tháng phụ thuộc vào ô B5 nhé! (Khi ngày ô này sang thứ 2 thì chạy 001 trở lên đến chủ nhật là mã phiếu cuối)
Sub NewPhieuNX(MaPhieu)
Dim arr(), t&, eR&, i&, sp$, myDate As Date, w&
myDate = Sheet1.Range("B5").Value
w = Int((myDate - 2) / 7)
eR = Sheet1.Range("A" & Rows.Count).End(xlUp).Row
arr = Sheet1.Range("A1:B" & eR).Value
For i = UBound(arr) To 2 Step -1
If Mid(arr(i, 1), 8, 1) = MaPhieu Then
t = DateValue(20 & Mid(arr(i, 1), 1, 2) & "/" & Mid(arr(i, 1), 3, 2) & "/" & Mid(arr(i, 1), 5, 2))
If w = Int((t - 2) / 7) Then
sp = Format(myDate, "yymmdd-") & MaPhieu & Format(Right(arr(i, 1), 3) + 1, "000")
Exit For
End If
End If
Next i
If i = 1 Then sp = Format(myDate, "yymmdd-") & MaPhieu & "001"
Sheet1.Range("A" & eR + 1).Value = sp
End Sub
Cám ơn anh đã giúp! Anh thêm giúp ngày tháng phụ thuộc vào ô B5 nhé! Cứ sau 1 tuần thì mã reset về 001 đém lên. Nếu được bác bỏ 2 ký tự yy (chỉ còn mmdd nhé!)Sửa lại cái sub TaoMaCT() chút.
JavaScript:Function TaomaCT(maCT As String) As String Dim lrow As Long, arrData(), i As Long Dim nam As Long, thang As Long, curYear As Long, curMonth As Long, stt As Long, sttMax As Long, maCT_tk As String, maCTMoi As String lrow = Sheet1.Cells(Sheet1.Rows.Count, "A").End(xlUp).Row curYear = Year(Date): curMonth = Month(Date) 'curYear = Sheet1.Range("E2"): curMonth = Sheet1.Range("D2") '<-- testing Select Case lrow Case 1 sttMax = 0 Case 2 sttMax = 1 Case Else arrData = Sheets("Sheet1").Range("A2:A" & lrow).Value sttMax = 0 For i = 1 To UBound(arrData) nam = CLng("20" & Left(arrData(i, 1), 2)): thang = CLng(Mid(arrData(i, 1), 3, 2)): stt = CLng(Right(arrData(i, 1), 3)) maCT_tk = Mid(arrData(i, 1), 8, 1) If nam = curYear And thang = curMonth And maCT_tk = UCase(maCT) Then If stt > sttMax Then sttMax = stt End If Next End Select TaomaCT = Format(Date, "yymmdd-") & UCase(maCT) & Right("000" & sttMax + 1, 3) 'TaomaCT = Format(DateSerial(curYear, curMonth, Day(Date)), "yymmdd-") & UCase(maCT) & Right("000" & sttMax + 1, 3) '<-- testing End Function
Bài đã được tự động gộp:
Dò ngược lại của bác HieuCD hay nhỉ, bớt được nhiều vòng lặp.
Không đúng như thế nào? Gởii file với ví dụ minh họa.Anh ơi! em test code chạy sai, có phải dùng hàm int trong vba tính không đúng. Nếu được anh bỏ giúp em yy (Chỉ còn mmdd nhé!)
Xin lỗi anh nhé! Em test lại là code chạy đúng rồi. Anh bỏ giúp em yy (Chỉ còn mmdd nhé!) Mã bớt đi 2 ký tự ưa nhìn hơn.Không đúng như thế nào? Gởii file với ví dụ minh họa.
Dữ liệu dùng cho 1 năm hay nhiều năm?Xin lỗi anh nhé! Em test lại là code chạy đúng rồi. Anh bỏ giúp em yy (Chỉ còn mmdd nhé!) Mã bớt đi 2 ký tự ưa nhìn hơn.
. . . . là code chạy đúng rồi. Anh bỏ giúp em yy (Chỉ còn mmdd nhé!) Mã bớt đi 2 ký tự ưa nhìn hơn.
giữ liệu dùng cho nhiều năm, Anh có cách nào bớt ký tự mã đi không vậy? Giúp em nhé!Dữ liệu dùng cho 1 năm hay nhiều năm?
Bằng hàm VBA đi anh! Chuyển mã hoá rất hay đó anh,cảm ơn anh
Nếu bạn muốn thì mình sẽ giúp chuyện mã hóa ngày tháng năm còn 3 ký tự dạng YMD;
Ví dụ E9A := ngày 10 tháng 9 năm 2025;
& FAC:= ngày 12 tháng mười năm sau
Bằng hàm VBA hay băng Name trên trang Excel đều được!?
![]()
Bỏ "YY" mã chứng từ sẽ bị trùng qua các năm, cần xét thêm cột ngày tháng, kết hợp 2 cột làm vùng khóa chính của cơ sở dữ liệu.giữ liệu dùng cho nhiều năm, Anh có cách nào bớt ký tự mã đi không vậy? Giúp em nhé!
Bài đã được tự động gộp:
Bằng hàm VBA đi anh! Chuyển mã hoá rất hay đó anh,cảm ơn anh