Code cho số phiếu

Liên hệ QC

DMQ

Thành viên dốt
Tham gia
21/3/12
Bài viết
713
Được thích
54
Giới tính
Nam
Chào các bạn trong GPE!!!!
Mình có file này, nhò các bạn viết code để nhảy số phiếu khi cột M là SX6, còn không phải là SX6 thì không nhảy số phiếu ạ.
Trong file mình có ghi chú quy luật của số phiếu.
Mong các bạn giúp đỡ.
 

File đính kèm

  • sophieu.xlsb
    16.6 KB · Đọc: 39
Cám ơn Thầy nhiều ạ!!!!
Rất hân hạnh được Thầy @VetMini giúp đỡ.
 
Upvote 0
Em thấy code chạy hơi lâu thầy @VetMini ơi, dữ liệu của em 950 dòng mà chạy gần 15s , hình như mỗi lần chạy là chạy lại từ đầu ( từ dòng đầu đến dòng cuối) , mong thầy chỉnh code để chạy từ dòng mới phát sinh thôi ạ ( từ dòng đang làm thôi)
 
Upvote 0
Đối với tôi, kết quả có đúng không mới quan trọng, code chạy 1/2 giờ cũng chả sao.
Việc viết code chạy cho nhanh có lẽ bạn nên nhờ các bạn khác.
 
Upvote 0
Dạ code chạy cho kết quả đúng rồi ạ. Mong thầy chỉnh code cho chạy khi em có nhập dữ liệu mới vào ạ.
 
Upvote 0
Mong thầy @VetMini chỉnh lại code dùm em ạ. Ví dụ em có 950 dòng đã chạy code lấy số phiếu xong rồi, sang hôm sau em nhập liệu 5 dòng tiếp, thì code chỉ chạy 5 dòng mới nhập thôi ạ, chư không chạy 955 dòng luôn ạ.
 
Upvote 0
Mong thầy @VetMini chỉnh lại code dùm em ạ. Ví dụ em có 950 dòng đã chạy code lấy số phiếu xong rồi, sang hôm sau em nhập liệu 5 dòng tiếp, thì code chỉ chạy 5 dòng mới nhập thôi ạ, chư không chạy 955 dòng luôn ạ.
.

Có thể dùng UDF, sau đó copy => paste value, chỉ cần chừa công thức vài dòng cuối.

.
 
  • Thích
Reactions: DMQ
Upvote 0
Mong thầy @VetMini chỉnh lại code dùm em ạ. Ví dụ em có 950 dòng đã chạy code lấy số phiếu xong rồi, sang hôm sau em nhập liệu 5 dòng tiếp, thì code chỉ chạy 5 dòng mới nhập thôi ạ, chư không chạy 955 dòng luôn ạ.
Thử hàm UDF này xem.
Mã:
Function DocNo(Rng As Range) As String
Dim Arr2(), d&, Lr&, W&, F&, Ngay, Thang, key
Dim Sh As Worksheet, DicDN As Object
Set Sh = Sheets("Issue")
    Lr = Rng.Row
Set DicDN = CreateObject("Scripting.Dictionary")
For W = 2 To Lr
    If Sh.Cells(W, 3) <> Empty Then
        key = Month(Sh.Cells(W, 3))
        If Thang <> key Then F = DicDN.Item(key)
            If Ngay = Day(Sh.Cells(W, 3)) Then
               F = F
            Else
                F = 1 + F
            End If
        Ngay = Day(Sh.Cells(W, 3)): Thang = key
    End If
Next W
DocNo = "SP" & Format(key, "0#") & Format(F, "0#") & "VTF6"
End Function
Cú pháp DocNo( Ô nào đó khác ô đặt công thức)
 
Lần chỉnh sửa cuối:
Upvote 0
Chào các bạn trong GPE!!!!
Mình có file này, nhò các bạn viết code để nhảy số phiếu khi cột M là SX6, còn không phải là SX6 thì không nhảy số phiếu ạ.
Trong file mình có ghi chú quy luật của số phiếu.
Mong các bạn giúp đỡ.
Thử cái này.
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim i As Long, a As Long
Application.ScreenUpdating = False
Application.EnableEvents = False
    If Not Intersect(Target, Range("M2:M1000")) Is Nothing Then
        If Target.Value = "SX6" Then
            For i = Target.Row - 1 To 2 Step -1
                If Range("M" & i).Value = "SX6" Then
                   a = i
                   Exit For
                End If
            Next i
            If a Then
                If Month(Target.Offset(, -10).Value) > Month(Range("C" & a).Value) Then
                        Target.Offset(, -9).Value = "SP" & Month(Target.Offset(, -10).Value) & "01" & "SX6"
                ElseIf Month(Target.Offset(, -10).Value) = Month(Range("C" & a).Value) Then
                    If Day(Target.Offset(, -10).Value) > Day(Range("C" & a).Value) Then
                       Target.Offset(, -9).Value = Left(Range("D" & a).Value, 4) & Format((CLng(Mid(Range("D" & a).Value, 5, 2)) + 1), "00") & "SX6"
                    Else
                       Target.Offset(, -9).Value = Range("D" & a).Value
                    End If
            Else
                Target.Offset(, -9).Value = "SP" & Month(Target.Offset(, -10).Value) & "01" & "SX6"
            End If
           End If
       End If
   End If
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
 
Upvote 0
Mong thầy @VetMini chỉnh lại code dùm em ạ. Ví dụ em có 950 dòng đã chạy code lấy số phiếu xong rồi, sang hôm sau em nhập liệu 5 dòng tiếp, thì code chỉ chạy 5 dòng mới nhập thôi ạ, chư không chạy 955 dòng luôn ạ.
Góp vui cho thêm phần rộn ràng.
Mã:
Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range) ' code cua HUONGHCKT

Application.ScreenUpdating = False
Application.EnableEvents = False

If Not Intersect(Target, Range("G6:G100000")) Is Nothing Then
   
    Dim Sh As Worksheet
    Dim DicDN As Object, Arr2(), R2&
    Dim Ngay, Thang
    Dim Z&, F&, W&

d = Target.Row
    If IsArray(Target) Then
        dong = Target.Rows.Count
        dArr = Range("E" & d).Resize(dong, 3).Value
        R = UBound(dArr)
    Else
        dong = 1
        dArr = Range("E" & d).Resize(dong, 3).Value
        R = 1
End If

For i = d To d + dong - 1
    Range("D" & i) = DocNo(Range("C" & i))
Next i

Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
và thêm 1 modul
Mã:
Function DocNo(Rng As Range) As String
Dim Arr2(), d&, Lr&, W&, F&, Ngay, Thang, key
Dim Sh As Worksheet, DicDN As Object
Set Sh = Sheets("Issue")
    Lr = Rng.Row
Set DicDN = CreateObject("Scripting.Dictionary")
For W = 2 To Lr
    If Sh.Cells(W, 3) <> Empty Then
        key = Month(Sh.Cells(W, 3))
        If Thang <> key Then F = DicDN.Item(key)
            If Ngay = Day(Sh.Cells(W, 3)) Then  F = F  Else  F = 1 + F
        Ngay = Day(Sh.Cells(W, 3)): Thang = key
    End If
Next W
DocNo = "SP" & Format(key, "0#") & Format(F, "0#") & "VTF6"
End Function
nó sẽ chạy kể cả khi copy 1 số dòng paste vào cột G.
 
Upvote 0
Mong thầy @VetMini chỉnh lại code dùm em ạ. Ví dụ em có 950 dòng đã chạy code lấy số phiếu xong rồi, sang hôm sau em nhập liệu 5 dòng tiếp, thì code chỉ chạy 5 dòng mới nhập thôi ạ, chư không chạy 955 dòng luôn ạ.
PHP:
Sub t()
    Const MAHIEU = "SX6"
    Const COLOFFSET = 9        ' offset den cot mahieu
    Const SOPHIEU = "SP#SX6"
    'Bo sung thong tin xac dinh thoi diem bat dau danh lai so phieu
    With Sheets("Sheet1")
        lstD = .Range("D" & Rows.Count).End(xlUp).Row
        lstM = .Range("M" & Rows.Count).End(xlUp).Row
        If lstD = 1 Then
            Thang = Ngay = ngayThu = 0
        Else
            Thang = Month(.Range("D" & lstD).Offset(0, -1))
            Ngay = Day(.Range("D" & lstD).Offset(0, -1))
            ngayThu = Mid(Replace(.Range("D" & lstD), MAHIEU, ""), 5, 10) * 1
        End If
    End With
    'Kiem tra
    If Not lstD < lstM Then: Exit Sub
  
    For Each cll In Range("D" & lstD & ":D" & lstM)
        If cll.Offset(0, COLOFFSET) = MAHIEU Then
            thangl = Month(cll.Offset(0, -1))        ' doc ngay thang
            ngayl = Day(cll.Offset(0, -1))
            If thangl <> Thang Then        ' xet xem co phai thang moi
            Thang = thangl
            Ngay = 0
            ngayThu = 0
        End If
        If ngayl <> Ngay Then        ' neu khac ngay thi tang so
        Ngay = ngayl
        ngayThu = ngayThu + 1
    End If
    cll.Value = Replace(SOPHIEU, "#", _
                Right(10000 + Thang * 100 + ngayThu, 4))
End If
Next cll
End Sub

Theo mong muốn của bạn, từ code của anh VetMini, chỉ bổ sung thêm điều kiện bắt đầu đánh số phiếu khi có dòng mới.

P/s:
(1) Bạn nên tham khảo thêm code bài #9 , bài #10, bài #11 để thuận tiện công tác đánh số, vì nó bắt sự kiện bạn nhập vào bảng tính và tự động đánh số phiếu.
(2) Code mình chạy thấy rất nhanh, chưa rõ sao có thể chậm 15s như bạn mô tả được.
 
Lần chỉnh sửa cuối:
  • Thích
Reactions: DMQ
Upvote 0
PHP:
...
            Thang = Ngay = ngayThu = 0
...

...
(2) Code mình chạy thấy rất nhanh, chưa rõ sao có thể chậm 15s như bạn mô tả được.
Nhanh hay không chưa biết. Nhưng theo bạn thì cái dòng trên cho ra kết quả gì?

Gợi ý: VBA cốt lõi là Basic, không thuộc dòng họ C.
 
Upvote 0
Giải thích cho bài #13:

Basic (Q-Basic, Visual Basic, VBA, VBScript,...) là dòng họ thuộc ngôn ngữ lập trình thế hệ 3.0
1. không có khái niệm "truyền ống/piping". Tức là kết quả của một lệnh (lệnh chứ không phải biểu thức) khong chuyền vào làm tham số cho lệnh kế.
2. Dấu = có hai ý nghĩa: mọt là phép gán và hai là phép so sánh. Và complier diich theo ngữ cảnh:
Tức là mọt lênh nếu có vế trái, kế tiếp là dấu bằng thì đó là lệnh gán kết quả biểu thức bên phải dấu bằng vào biến bên trái dấu bằng. Vì bên phải được tính là biểu thức cho nên tất cả các dấu bằng trong biểu thức ấy được tính là phép so sánh.
Thang = Ngay = ngayThu = 0
Được hiểu là phép gán biểu thức (Ngay = ngayThu = 0) vào biến Thang
Hai dấu bằng trong biểu thức trên là cùng đẳng cáo cho nên sẽ được thanh toán từ trái qua phải.
Ngay = ngaythu có kết quả True/False. Ở đây vì chưa khởi trị cho nên cả hai được ép kiểu (có lẽ coi như nhau) và kết quả là True
Đem so sánh với 0 thì lại ép kiểu lần nữa (-1 = 0) = False.
Trị này gán cho Thang. Cuối cùng ta được Thang = False. Các biến còn lại vẫn chưa khởi trị.

C là dòng họ theo quan niệm thế hệ ngôn ngữ tạm gọi là 3.2 (Algol 60, Pascal là thế hệ 3.1)
3. Đặt nặng khái niệm piping để tăng tốc. Một lệnh bắt đầu bằng một dấu hiệu phân cách (thường là dấu ; chấm phẩy) và có thể gồm nhiều lệnh con, trong đó kết quả của lệnh con này đưa vào làm tham số cho lệnh kế.
4. Dấu = chỉ có nghĩa là phép gán. Phép so sánh thường là ==
Thang = Ngay = ngayThu = 0
Sẽ được tính là (tạm coi như 3 lệnh con): lệnh con 1 đem 0 gán cho ngayThu, lệnh con 2 đem kết quả lệnh con 1 gán cho Ngay, lệnh con 3 lại đem kết quả lệnh con 2 gán cho Ngay. Cuối cùng ta được cả 3 biến mang giá trị 0

Nói túm lại, nếu quy vị viết code script cho google sheets thì lệnh này sẽ cho kết quả mong muốn. (Google Script theo sát tiêu chuẩn JavaScript, dòng họ C)
 
Upvote 0
dữ liệu của em 950 dòng mà chạy gần 15s
Tôi thử trên file dữ liệu mẫu, 332 dòng, thời gian 0.024 giây. Làm bài toán quy tắc tam suất thì 15 giây phải chạy được 207,500 dòng. Máy yếu, chỉ chạy được 1 nửa là 100 ngàn, yếu hơn nữa được 1/4, cũng phải 50 ngàn dòng. Máy bạn loại nào mà chỉ chạy 1000 dòng?
 
Upvote 0
Theo mong muốn của bạn, từ code của anh VetMini, chỉ bổ sung thêm điều kiện bắt đầu đánh số phiếu khi có dòng mới.
Nếu từ code anh VetMini, chỉ cần tìm dòng cuối cột D, để nguyên code chạy từ đó trở xuống, sửa code ít
Chỉ cần thay
Mã:
ngay = 0
thang = 0
ngayt = 0
For Each cll In Range(Cells(2, "D"), Cells(Cells(10000, "C").End(xlUp).Row, "D"))
Bằng
Mã:
LastRw = Cells(10000, "D").End(xlUp).Row
ngay = 0
ngayt = Val(Mid(Cells(LastRw, "D"), 5, 2))
thang = Val(Mid(Cells(LastRw, "D"), 3, 2))
For Each cll In Range(Cells(LastRw + 1, "D"), _
    Cells(Cells(10000, "C").End(xlUp).Row, "D"))

Không thêm bớt mắm muối gì khác.
(1) Bạn nên tham khảo thêm code bài #9 , bài #10, bài #11 để thuận tiện công tác đánh số, vì nó bắt sự kiện bạn nhập vào bảng tính và tự động đánh số phiếu.

Nếu dùng sự kiện (mà tôi lại ghét dùng sự kiện), thì gọi chính code t() này ra chạy, khỏi tham khảo đâu hết
 
Lần chỉnh sửa cuối:
Upvote 0
Tuy tôi không biết multitasking nhưng tôi biết lợi dụng thời gian chờ chuyện này để làm chuyện khác.
Code VBA chạy dưới một vài phút thì chả làm được việc gì nhiều, ngoài việc gặm mẩu bánh mì thịt.
Nhưng trên nữa thì có thể lợi dụng thời gian làm viecj khác, không có công việc khác thì tham khảo thêm chút kiến thức.
Cỡ nửa tiếng và lúc không bị dòm ngó thì có thể lợi dụng chuồn đi uống cà phê.

Chỉ trừ những lúc mình làm tính công giờ thì mới suy nghĩ đến tăng tốc. Làm tính giờ mà chậm quá thì không khỏi bị lương tâm nghề nghiệp cắn rứt chứ cỡ tôi nói láo với khách hàng dễ như bợm nhậu nhai miếng chả chó.
* tính công giờ: một giờ của dân chuyên nghiệp chia ra 10 múi, mỗi múi 6 phút. Lúc làm việc thì mở đồng hồ lên, lúc nghỉ tay thì ghi lại giờ tạm ngưng và số múi; bắt đầu trở lại thì lại mở lên... Cuối cùng cộng các múi lại, gởi hóa đơn cho khách hàng.
 
Upvote 0
Em lấy code của thầy @ptm0412 thay vào code của anh @VetMini .
Em thử, thì thấy sao cùng ngày mà lại nhảy số thầy @ptm0412 ơi.
Mong thầy xem giúp em.
 

File đính kèm

  • sophieu (1).xlsb
    25 KB · Đọc: 7
Upvote 0
Web KT

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

Back
Top Bottom