Chia số lượng các cỡ theo điều kiện để đóng thùng

Liên hệ QC

Hoangquyenbong

Thành viên hoạt động
Tham gia
13/7/18
Bài viết
199
Được thích
38
Em chào các thành viên của diễn đàn ạ !
Em có 1 file excel xin nhờ cả nhà viết giúp em câu lệnh VBA để em có thể làm nhanh hơn ạ.
Chi tiết cụ thể em đã ghi trong file đính kèm.
Rất mong nhận được sự giúp đỡ của các bác, các anh, các chị ạ !
Em xin cảm ơn !
 

File đính kèm

  • Nhung..xlsx
    27.7 KB · Đọc: 29
Tôi làm rõ các vấn đề để các bạn khác có bắt tay vào làm thì lưu ý thôi. Bài này không đơn giản kể cả khi dùng VBA.
Dạ, em cũng nghĩ giống thầy ạ...
Có những trường hợp "không thể và có thể" xẩy ra nhiều mà mình không lường trước được...
Nghĩ giải thuật chưa ra ... hazzz
 
Upvote 0
Tôi nghĩ xử lý điều kiện ít nhất 2 cỡ như thế này
- Tạo mảng kết quả cho từng màu đảm bảo thỏa các điều kiện khác (bỏ qua điều kiện ít nhất 2 cỡ)
- Xét dòng cuối có dư, nếu R00 chỉ có 1 cỡ thì
+ Kiểm tra lại các dòng trên, dòng nào có số >1 ở mảng kết quả thì giảm 1, mang qua R00 đang xét
+ Nếu còn R00 có 1 cỡ mà không còn dòng có số >1 thì lại kiểm tra các dòng trên, dòng nào có số =1 và R00 của nó có 3 cỡ thì giảm 1, mang qua R00 đang xét
+ Nếu vẫn còn R00 có 1 cỡ thì chấp nhận không thỏa điều kiện
- Lặp lại với màu khác
 
Upvote 0
Em chào các thành viên của diễn đàn ạ !
Em có 1 file excel xin nhờ cả nhà viết giúp em câu lệnh VBA để em có thể làm nhanh hơn ạ.
Chi tiết cụ thể em đã ghi trong file đính kèm.
Rất mong nhận được sự giúp đỡ của các bác, các anh, các chị ạ !
Em xin cảm ơn !
Mình đã làm cho bạn.
Mình nghiệm ra rằng: vì xếp vào thùng 1 cỡ tối đa là 5 và thùng được xếp tối đa là 12 nên chắc chắn khi xếp đầy thùng thì phải có ít nhất 2 cỡ ( dĩ nhiên là trùng màu) trở lên !!! nên bài toán lại đơn giản hóa đi!
Bạn coi file nha.
Mình không giới hạn cột kết quả, không giới hạn dòng dữ liệu, không cố định mỗi một loại màu có mấy cỡ hết!
trải nghiện thử nha... """:::":\
 

File đính kèm

  • ArrangeToBox-GPE.xlsm
    68.2 KB · Đọc: 7
Upvote 0
Đề bạn phức tạp quá, mình chỉ làm được tới đây. Còn thiếu điều kiện có ít nhất 2 cỡ có cùng giá trị trong mỗi R00.
Bạn xem thử:
 

File đính kèm

  • Nhung..xlsx
    37.3 KB · Đọc: 9
Upvote 0
Đề bạn phức tạp quá, mình chỉ làm được tới đây. Còn thiếu điều kiện có ít nhất 2 cỡ có cùng giá trị trong mỗi R00.
Bạn xem thử:
Wow... Công thức...
Mình phải xách cặp học bạn thôi...
Hic... công thức mình tệ lắm!!!
 
Upvote 0
Mình đã làm cho bạn.
Mình nghiệm ra rằng: vì xếp vào thùng 1 cỡ tối đa là 5 và thùng được xếp tối đa là 12 nên chắc chắn khi xếp đầy thùng thì phải có ít nhất 2 cỡ ( dĩ nhiên là trùng màu) trở lên !!! nên bài toán lại đơn giản hóa đi!
Bạn coi file nha.
Mình không giới hạn cột kết quả, không giới hạn dòng dữ liệu, không cố định mỗi một loại màu có mấy cỡ hết!
trải nghiện thử nha... """:::":\
Cảm ơn bạn !
Sáng giờ thỉnh thoảng mình lại vào diễn đàn mong thông báo. Số liệu chạy ok nhưng còn 1 chỗ bạn chỉnh giúp mình được không. Ví dụ như thùng R011 và thùng R016, nó đang chỉ còn có 1 cỡ. nếu như vậy thì mình sẽ không thể đóng được. Bạn có thể bớt số lượng của thùng trước nó là R010 và R015 ( chỉ cần 1 chiếc của cỡ khác) cũng được chuyển qua 2 thùng R011 và R016 để được đóng hết thùng.
Một lần nữa cảm ơn bạn đã nhiệt tình giúp mình !
 
Upvote 0
Cảm ơn bạn !
Sáng giờ thỉnh thoảng mình lại vào diễn đàn mong thông báo. Số liệu chạy ok nhưng còn 1 chỗ bạn chỉnh giúp mình được không. Ví dụ như thùng R011 và thùng R016, nó đang chỉ còn có 1 cỡ. nếu như vậy thì mình sẽ không thể đóng được. Bạn có thể bớt số lượng của thùng trước nó là R010 và R015 ( chỉ cần 1 chiếc của cỡ khác) cũng được chuyển qua 2 thùng R011 và R016 để được đóng hết thùng.
Một lần nữa cảm ơn bạn đã nhiệt tình giúp mình !

Tôi đã làm theo lời bạn nói mà...

Dạ nếu gặp trường hợp đặc biệt như vậy thì đành phải bỏ lại thôi ạ. không thỏa mãn các điều kiện ạ.
 
Upvote 0
Đề bạn phức tạp quá, mình chỉ làm được tới đây. Còn thiếu điều kiện có ít nhất 2 cỡ có cùng giá trị trong mỗi R00.
Bạn xem thử:
Cảm ơn bạn nhiều !
Bạn cũng siêu thật !
Chỉ còn mắc ở R011 và R016 để cho R011 và R016 có thể đủ điều kiện để đóng thùng.
Bài đã được tự động gộp:

Tôi đã làm theo lời bạn nói mà...
Kết quả như file bạn cho đối với mình là quá tuyệt rồi ! nhưng nếu chuẩn để hàng được đóng hết thì thùng R010 cỡ 0M7 mình sẽ chỉ lấy 2 và chừa lại 1 cho thùng R011 ( thay vì cho 3 vào R010)
Còn như ví dụ bác @huuthang_bd hỏi thì phải bỏ lại thật. Kiểu bác giả sử cột F chỉ có 1 cỡ duy nhất của màu đó có dư thôi ý.
 
Lần chỉnh sửa cuối:
Upvote 0
Nếu thêm điều kiện tối ưu để số lượng thùng là thấp nhất thì khó hơn nữa.
Mã:
Sub GPE()
Dim Sh As Worksheet, lMaxQ As Long, aData As Variant, aResult() As Variant, i As Long, m As Long, n As Long, k As Long, lTmp As Long
Dim lRi As Long, lQr As Long, lZr As Long, lFr As Long, lTo As Long
Set Sh = ActiveSheet
Sh.Range("G4").Resize(1000, 1000).ClearContents
lMaxQ = Sh.Range("D3").Value
aData = Sh.Range("B4:E" & Sh.Cells(&H100000, 1).End(xlUp).Row)
ReDim aResult(1 To UBound(aData, 1) - 1, 1 To 1)
lRi = 1: lFr = 1
For i = 1 To UBound(aData, 1) - 1
    If aData(i, 4) > 0 Then
        If lZr = lMaxQ Then
            lRi = lRi + 1: lQr = 0: lZr = 0
            ReDim Preserve aResult(1 To UBound(aResult, 1), 1 To lRi)
            If k > 0 Then
                i = k - 1: k = 0
                GoTo Next_i
            End If
        End If
        lTmp = aData(i, 4)
        If lTmp > (lMaxQ - lZr) Then lTmp = (lMaxQ - lZr)
        If lTmp > 5 Then lTmp = 5
        aResult(i, lRi) = lTmp: aData(i, 4) = aData(i, 4) - lTmp: lQr = lQr + 1: lZr = lZr + lTmp
        If aData(i, 4) > 0 And k = 0 Then k = i
    End If
    If aData(i + 1, 1) <> aData(i, 1) Then
        If lQr = 1 Then
            For m = lRi - 1 To 1 Step -1
                lTmp = 0
                For n = i - 1 To lFr Step -1
                    If aResult(n, m) > 0 Then
                        lTmp = lTmp + 1
                        If aResult(n, m) > 1 Or lTmp > 2 Then
                            aResult(n, m) = aResult(n, m) - 1
                            aResult(n, lRi) = 1
                            If aResult(n, m) = 0 Then aResult(n, m) = Empty
                            GoTo Check_k
                        End If
                    End If
                Next
            Next
        End If
Check_k:
        lZr = lMaxQ
        If k > 0 Then
            i = k - 1: k = 0
        Else
            lFr = i + 1
        End If
    End If
Next_i:
Next
Sh.Range("G4").Resize(UBound(aResult, 1), lRi).Value = aResult
End Sub
 
Upvote 0
Nếu thêm điều kiện tối ưu để số lượng thùng là thấp nhất thì khó hơn nữa.
Mã:
Sub GPE()
Dim Sh As Worksheet, lMaxQ As Long, aData As Variant, aResult() As Variant, i As Long, m As Long, n As Long, k As Long, lTmp As Long
Dim lRi As Long, lQr As Long, lZr As Long, lFr As Long, lTo As Long
Set Sh = ActiveSheet
Sh.Range("G4").Resize(1000, 1000).ClearContents
lMaxQ = Sh.Range("D3").Value
aData = Sh.Range("B4:E" & Sh.Cells(&H100000, 1).End(xlUp).Row)
ReDim aResult(1 To UBound(aData, 1) - 1, 1 To 1)
lRi = 1: lFr = 1
For i = 1 To UBound(aData, 1) - 1
    If aData(i, 4) > 0 Then
        If lZr = lMaxQ Then
            lRi = lRi + 1: lQr = 0: lZr = 0
            ReDim Preserve aResult(1 To UBound(aResult, 1), 1 To lRi)
            If k > 0 Then
                i = k - 1: k = 0
                GoTo Next_i
            End If
        End If
        lTmp = aData(i, 4)
        If lTmp > (lMaxQ - lZr) Then lTmp = (lMaxQ - lZr)
        If lTmp > 5 Then lTmp = 5
        aResult(i, lRi) = lTmp: aData(i, 4) = aData(i, 4) - lTmp: lQr = lQr + 1: lZr = lZr + lTmp
        If aData(i, 4) > 0 And k = 0 Then k = i
    End If
    If aData(i + 1, 1) <> aData(i, 1) Then
        If lQr = 1 Then
            For m = lRi - 1 To 1 Step -1
                lTmp = 0
                For n = i - 1 To lFr Step -1
                    If aResult(n, m) > 0 Then
                        lTmp = lTmp + 1
                        If aResult(n, m) > 1 Or lTmp > 2 Then
                            aResult(n, m) = aResult(n, m) - 1
                            aResult(n, lRi) = 1
                            If aResult(n, m) = 0 Then aResult(n, m) = Empty
                            GoTo Check_k
                        End If
                    End If
                Next
            Next
        End If
Check_k:
        lZr = lMaxQ
        If k > 0 Then
            i = k - 1: k = 0
        Else
            lFr = i + 1
        End If
    End If
Next_i:
Next
Sh.Range("G4").Resize(UBound(aResult, 1), lRi).Value = aResult
End Sub
Dạ cảm ơn bác nhiều ạ !
Code này đã khắc phục được thùng R016 nhưng thùng R011 kết quả dư cuối đang chưa đúng ạ. Màu 03 cỡ 0M6 vẫn đang còn tồn dư 2 chiêc ở cột F ạ.
 
Upvote 0
Dạ cảm ơn bác nhiều ạ !
Code này đã khắc phục được thùng R016 nhưng thùng R011 kết quả dư cuối đang chưa đúng ạ. Màu 03 cỡ 0M6 vẫn đang còn tồn dư 2 chiêc ở cột F ạ.
Có chút nhầm lẫn, bạn thử lại với code này.
Mã:
Sub GPE()
Dim Sh As Worksheet, lMaxQ As Long, aData As Variant, aResult() As Variant, i As Long, m As Long, n As Long, k As Long, lTmp As Long
Dim lRi As Long, lQr As Long, lZr As Long, lFr As Long, lTo As Long
Set Sh = ActiveSheet
Sh.Range("G4").Resize(1000, 1000).ClearContents
lMaxQ = Sh.Range("D3").Value
aData = Sh.Range("B4:E" & Sh.Cells(&H100000, 1).End(xlUp).Row)
ReDim aResult(1 To UBound(aData, 1) - 1, 1 To 1)
lRi = 1: lFr = 1
For i = 1 To UBound(aData, 1) - 1
    If aData(i, 4) > 0 Then
        If lZr = lMaxQ Then
            lRi = lRi + 1: lQr = 0: lZr = 0
            ReDim Preserve aResult(1 To UBound(aResult, 1), 1 To lRi)
            If k > 0 Then
                i = k - 1: k = 0
                GoTo Next_i
            End If
        End If
        lTmp = aData(i, 4)
        If lTmp > (lMaxQ - lZr) Then lTmp = (lMaxQ - lZr)
        If lTmp > 5 Then lTmp = 5
        aResult(i, lRi) = lTmp: aData(i, 4) = aData(i, 4) - lTmp: lQr = lQr + 1: lZr = lZr + lTmp
        If aData(i, 4) > 0 And k = 0 Then k = i
    End If
    If aData(i + 1, 1) <> aData(i, 1) Then
        lTo = i
        If lQr = 1 Then
            For m = lRi - 1 To 1 Step -1
                lTmp = 0
                For n = lTo To lFr Step -1
                    If aResult(n, m) > 0 And aResult(n, lRi) = 0 Then
                        lTmp = lTmp + 1
                        If aResult(n, m) > 1 Or lTmp > 2 Then
                            aResult(n, m) = aResult(n, m) - 1
                            aResult(n, lRi) = 1
                            If aResult(n, m) = 0 Then aResult(n, m) = Empty
                            GoTo Check_k
                        End If
                    End If
                Next
            Next
        End If
Check_k:
        lZr = lMaxQ
        If k > 0 Then
            i = k - 1: k = 0
        Else
            lFr = i + 1
        End If
    End If
Next_i:
Next
Sh.Range("G4").Resize(UBound(aResult, 1), lRi).Value = aResult
End Sub
 
Upvote 0
Có chút nhầm lẫn, bạn thử lại với code này.
Mã:
Sub GPE()
Dim Sh As Worksheet, lMaxQ As Long, aData As Variant, aResult() As Variant, i As Long, m As Long, n As Long, k As Long, lTmp As Long
Dim lRi As Long, lQr As Long, lZr As Long, lFr As Long, lTo As Long
Set Sh = ActiveSheet
Sh.Range("G4").Resize(1000, 1000).ClearContents
lMaxQ = Sh.Range("D3").Value
aData = Sh.Range("B4:E" & Sh.Cells(&H100000, 1).End(xlUp).Row)
ReDim aResult(1 To UBound(aData, 1) - 1, 1 To 1)
lRi = 1: lFr = 1
For i = 1 To UBound(aData, 1) - 1
    If aData(i, 4) > 0 Then
        If lZr = lMaxQ Then
            lRi = lRi + 1: lQr = 0: lZr = 0
            ReDim Preserve aResult(1 To UBound(aResult, 1), 1 To lRi)
            If k > 0 Then
                i = k - 1: k = 0
                GoTo Next_i
            End If
        End If
        lTmp = aData(i, 4)
        If lTmp > (lMaxQ - lZr) Then lTmp = (lMaxQ - lZr)
        If lTmp > 5 Then lTmp = 5
        aResult(i, lRi) = lTmp: aData(i, 4) = aData(i, 4) - lTmp: lQr = lQr + 1: lZr = lZr + lTmp
        If aData(i, 4) > 0 And k = 0 Then k = i
    End If
    If aData(i + 1, 1) <> aData(i, 1) Then
        lTo = i
        If lQr = 1 Then
            For m = lRi - 1 To 1 Step -1
                lTmp = 0
                For n = lTo To lFr Step -1
                    If aResult(n, m) > 0 And aResult(n, lRi) = 0 Then
                        lTmp = lTmp + 1
                        If aResult(n, m) > 1 Or lTmp > 2 Then
                            aResult(n, m) = aResult(n, m) - 1
                            aResult(n, lRi) = 1
                            If aResult(n, m) = 0 Then aResult(n, m) = Empty
                            GoTo Check_k
                        End If
                    End If
                Next
            Next
        End If
Check_k:
        lZr = lMaxQ
        If k > 0 Then
            i = k - 1: k = 0
        Else
            lFr = i + 1
        End If
    End If
Next_i:
Next
Sh.Range("G4").Resize(UBound(aResult, 1), lRi).Value = aResult
End Sub
Dạ cảm ơn bác ạ !
Kết quả chuẩn rồi ạ.
Cuối cùng bác vẫn phải xuất chiêu mặc dù bác đã từ chối ạ.
 
Upvote 0
Cảm ơn bạn !
Sáng giờ thỉnh thoảng mình lại vào diễn đàn mong thông báo. Số liệu chạy ok nhưng còn 1 chỗ bạn chỉnh giúp mình được không. Ví dụ như thùng R011 và thùng R016, nó đang chỉ còn có 1 cỡ. nếu như vậy thì mình sẽ không thể đóng được. Bạn có thể bớt số lượng của thùng trước nó là R010 và R015 ( chỉ cần 1 chiếc của cỡ khác) cũng được chuyển qua 2 thùng R011 và R016 để được đóng hết thùng.
Một lần nữa cảm ơn bạn đã nhiệt tình giúp mình !
vậy thì thử cái này nè....
 

File đính kèm

  • ArrangeToBox-GPE - (2).xlsm
    76.2 KB · Đọc: 10
Lần chỉnh sửa cuối:
Upvote 0
@thnghiachau : Tôi sử dụng mảng còn bạn đọc ghi dữ liệu trực tiếp thì chậm hơn là phải rồi.
--
Sửa lại code một chút cho chặt chẽ hơn.
Mã:
Sub GPE()
Dim Sh As Worksheet, lMaxQ As Long, aData As Variant, aResult() As Variant, i As Long, m As Long, n As Long, k As Long, lTmp As Long
Dim lRi As Long, lQr As Long, lZr As Long, lFr As Long, lTo As Long
Set Sh = ActiveSheet
Sh.Range("G4").Resize(1000, 1000).ClearContents
lMaxQ = Sh.Range("D3").Value
aData = Sh.Range("B4:E" & Sh.Cells(&H100000, 1).End(xlUp).Row)
ReDim aResult(1 To UBound(aData, 1) - 1, 1 To 1)
lRi = 1: lFr = 1
For i = 1 To UBound(aData, 1) - 1
    If aData(i, 4) > 0 Then
        If lZr = lMaxQ Then
            lRi = lRi + 1: lQr = 0: lZr = 0
            ReDim Preserve aResult(1 To UBound(aResult, 1), 1 To lRi)
            If k > 0 Then
                i = k - 1: k = 0
                GoTo Next_i
            End If
        End If
        lTmp = aData(i, 4)
        If lTmp > (lMaxQ - lZr) Then lTmp = (lMaxQ - lZr)
        If lTmp > 5 Then lTmp = 5
        aResult(i, lRi) = lTmp: aData(i, 4) = aData(i, 4) - lTmp: lQr = lQr + 1: lZr = lZr + lTmp
        If aData(i, 4) > 0 And k = 0 Then k = i
    End If
    If aData(i + 1, 1) <> aData(i, 1) Then
        lTo = i
        If lQr = 1 Then
            For m = lRi - 1 To 1 Step -1
                lTmp = 0
                For n = lTo To lFr Step -1
                    If aResult(n, m) > 0 Then
                        lTmp = lTmp + 1
                        If aResult(n, lRi) = 0 Then
                            If aResult(n, m) > 1 Or lTmp > 2 Then
                                aResult(n, m) = aResult(n, m) - 1
                                aResult(n, lRi) = 1
                                If aResult(n, m) = 0 Then aResult(n, m) = Empty
                                GoTo Check_k
                            End If
                        End If
                    End If
                Next
            Next
        End If
Check_k:
        lZr = lMaxQ
        If k > 0 Then
            i = k - 1: k = 0
        Else
            lFr = i + 1
        End If
    End If
Next_i:
Next
Sh.Range("G4").Resize(UBound(aResult, 1), lRi).Value = aResult
End Sub
 
Upvote 0
@thnghiachau : Tôi sử dụng mảng còn bạn đọc ghi dữ liệu trực tiếp thì chậm hơn là phải rồi.
--
Sửa lại code một chút cho chặt chẽ hơn.
Mã:
Sub GPE()
Dim Sh As Worksheet, lMaxQ As Long, aData As Variant, aResult() As Variant, i As Long, m As Long, n As Long, k As Long, lTmp As Long
Dim lRi As Long, lQr As Long, lZr As Long, lFr As Long, lTo As Long
Set Sh = ActiveSheet
Sh.Range("G4").Resize(1000, 1000).ClearContents
lMaxQ = Sh.Range("D3").Value
aData = Sh.Range("B4:E" & Sh.Cells(&H100000, 1).End(xlUp).Row)
ReDim aResult(1 To UBound(aData, 1) - 1, 1 To 1)
lRi = 1: lFr = 1
For i = 1 To UBound(aData, 1) - 1
    If aData(i, 4) > 0 Then
        If lZr = lMaxQ Then
            lRi = lRi + 1: lQr = 0: lZr = 0
            ReDim Preserve aResult(1 To UBound(aResult, 1), 1 To lRi)
            If k > 0 Then
                i = k - 1: k = 0
                GoTo Next_i
            End If
        End If
        lTmp = aData(i, 4)
        If lTmp > (lMaxQ - lZr) Then lTmp = (lMaxQ - lZr)
        If lTmp > 5 Then lTmp = 5
        aResult(i, lRi) = lTmp: aData(i, 4) = aData(i, 4) - lTmp: lQr = lQr + 1: lZr = lZr + lTmp
        If aData(i, 4) > 0 And k = 0 Then k = i
    End If
    If aData(i + 1, 1) <> aData(i, 1) Then
        lTo = i
        If lQr = 1 Then
            For m = lRi - 1 To 1 Step -1
                lTmp = 0
                For n = lTo To lFr Step -1
                    If aResult(n, m) > 0 Then
                        lTmp = lTmp + 1
                        If aResult(n, lRi) = 0 Then
                            If aResult(n, m) > 1 Or lTmp > 2 Then
                                aResult(n, m) = aResult(n, m) - 1
                                aResult(n, lRi) = 1
                                If aResult(n, m) = 0 Then aResult(n, m) = Empty
                                GoTo Check_k
                            End If
                        End If
                    End If
                Next
            Next
        End If
Check_k:
        lZr = lMaxQ
        If k > 0 Then
            i = k - 1: k = 0
        Else
            lFr = i + 1
        End If
    End If
Next_i:
Next
Sh.Range("G4").Resize(UBound(aResult, 1), lRi).Value = aResult
End Sub

Thầy @huuthang_bd ơi, Code thầy hay quá, ngắn gọn, chạy nhanh siêu tốc
Em ngưỡng mộ và học thầy hoài mà chưa áp dụng được... hic...
------
Đúng là của thầy toàn xử lý trên mảng, còn em vừa làm vừa ghi nên chạy chậm hơn nhiều...
 
Upvote 0
Web KT
Back
Top Bottom