Sub totalSizeSegmentArrange()
Dim a, b(), z(), i, k&, j&, i0, t&, r%, v&, rg1
a = [B4].Resize(7, 8)
ReDim b(1 To UBound(a) * UBound(a, 2), 1 To 2)
For Each i In a: k = k + 1: b(k, 2) = True
If IsNumeric(i) Then If i > 0 Then b(k, 1) = i: b(k, 2) = False
Next
a = ArraySort(b, 1)
Set rg1 = [B14]
ReDim Preserve z(1 To 7, 1 To 1): j = 1
For i = 1 To k
If Not a(i, 2) Then
v = rg1(9, j).Value
If t + a(i, 1) > v Then
For i0 = 1 To k
If t + a(i0, 1) <= v And Not a(i0, 2) Then
t = t + a(i0, 1): a(i0, 2) = True:
If r + 1 > UBound(z) Then Exit For
r = r + 1: z(r, j) = a(i0, 1)
End If
Next
r = 1: j = j + 1: ReDim Preserve z(1 To 7, 1 To j): t = a(i, 1): z(r, j) = t
Else
t = t + a(i, 1)
If r + 1 > UBound(z) Then
r = 1: j = j + 1: ReDim Preserve z(1 To 7, 1 To j): t = a(i, 1): z(r, j) = t
Else
r = r + 1: z(r, j) = a(i, 1)
End If
End If
a(i, 2) = True
End If
Next
rg1.Resize(UBound(z), j).Value = z
End Sub
Private Function ArraySort(ByVal InputArray, Optional SortColumn% = 0) As Variant
Dim lb1%, ub1&, lb2%, ub2%, i&, j&, k&
Dim t As Variant
On Error Resume Next
ub2 = UBound(InputArray, 2): lb2 = LBound(InputArray, 2)
lb1 = LBound(InputArray, 1): ub1 = UBound(InputArray, 1)
For i = lb1 To ub1 - 1: For j = i + 1 To ub1
If InputArray(i, SortColumn) < InputArray(j, SortColumn) Then
For k = lb2 To ub2
t = InputArray(j, k):InputArray(j, k) = InputArray(i, k):InputArray(i, k) = t
Next k
End If
Next j, i
ArraySort = InputArray
End Function
Bác Sanbi cho hỏi, cách đặt tên biến kiểu vậy (ký tự a,b,i,i0,r,t ...):Công thức Excel khó mà đỡ nổi mục đích bạn muốn.
Bạn tham khảo mã VBA cho đơn giản.
Sao chép mã vào module và chạy thủ tục totalSizeSegmentArrange ngoài trang tính.
JavaScript:Sub totalSizeSegmentArrange() Dim a, b(), z(), i, k&, j&, i0, t&, r%, v&, rg1 a = [B4].Resize(7, 4) ReDim b(1 To UBound(a) * UBound(a), 1 To 2) For Each i In a: k = k + 1: b(k, 1) = i: b(k, 2) = False: Next a = ArraySort(b, 1) Set rg1 = [B14] ReDim Preserve z(1 To 7, 1 To 1): j = 1 For i = 1 To k If Not a(i, 2) Then v = rg1(9, j).Value If t + a(i, 1) > v Then For i0 = 1 To k If t + a(i0, 1) <= v Then t = t + a(i0, 1): a(i0, 2) = True: r = r + 1: z(r, j) = a(i0, 1) End If Next r = 1: j = j + 1: ReDim Preserve z(1 To 7, 1 To j) t = a(i, 1): z(r, j) = t Else t = t + a(i, 1): r = r + 1: z(r, j) = a(i, 1) End If a(i, 2) = True End If Next rg1.Resize(UBound(z), j).Value = z End Sub Private Function ArraySort(ByVal InputArray, Optional SortColumn% = 0) As Variant Dim lb1%, ub1&, lb2%, ub2%, i&, j&, k& Dim t As Variant On Error Resume Next ub2 = UBound(InputArray, 2): lb2 = LBound(InputArray, 2) lb1 = LBound(InputArray, 1): ub1 = UBound(InputArray, 1) For i = lb1 To ub1 - 1: For j = i + 1 To ub1 If InputArray(i, SortColumn) < InputArray(j, SortColumn) Then For k = lb2 To ub2 If iTrim Then t = Trim(InputArray(j, k)) InputArray(j, k) = Trim(InputArray(i, k)) Else t = InputArray(j, k) InputArray(j, k) = InputArray(i, k) End If InputArray(i, k) = t Next k End If Next j, i ArraySort = InputArray End Function
Dim a, b(), z(), i, k&, j&, i0, t&, r%, v&, rg1
Mình cũng lăn tăn chỗ đặt biến. Sau khi thử đặt biến ngắn thì sau mò lỗi tè le. Thế là cần thì đặt hẳn biến dài. VD: mangnguon, mangdich, mangtemp123, ... Nhìn rất là chuối. Nói chung là mệt mỏi lắm, không pro được, sau cũng nản, lại quay lại cơ chế xin cho.Bác Sanbi cho hỏi, cách đặt tên biến kiểu vậy (ký tự a,b,i,i0,r,t ...):
Nó không rõ ràng là biến đó của cái gì (Kiểu như người ta thường đặt là sArr, dArr, LastRow ... ). Vậy làm cách nào để khi viết một đoạn code dài (hoặc rất dài), bác có thể nhớ được những biến đã khai báo đó dùng cho cái nào mà không gây ra nhầm lẫn? (Nghĩa là không lẫn giữa "t" qua "r" hay qua "i" hay "i0" gì đó? )Mã:Dim a, b(), z(), i, k&, j&, i0, t&, r%, v&, rg1
Cảm ơn bác đã chia sẻ, viết một đoạn code đơn giản thì đặt biến không là vấn đề. Nhưng viết một code phức tạp thì đúng là phải có quy định rõ ràng không lại nhầm biến này biến nọcác biến r, c, i, j, k, n, m thường là số, các biến a, b, z thường là mảng, e, y thường gán là boolean, w, t, v, s là chuỗi, ...
Khi biến gọi lại, hoặc đồng hành thì thêm 0, 1, 2, cũng có thể là "_"
Với khả năng VBA của bác thì không quá ngạc nhiên về vấn đề nàyNếu bạn có lòng tin thì mã trên tôi viết nó trong 10 phút.
quá ngạc nhiên
Chắc em lại nhờ anh chia sẻ về khúc này nữa quáKhúc nào khó quá lại phải dựng RPA cho nó chạy
Ngày 24h anh có ngồi máy tính tới 23h không mà sao có thời gian soạn được tài liệu này nọ, học python, web, ... tìm hiểu đủ thứ thế nhỉMới soạn được ít tài liệu hướng dẫn...
Ngày 24h anh có ngồi máy tính tới 23h không mà sao có thời gian soạn được tài liệu này nọ, học python, web, ... tìm hiểu đủ thứ thế nhỉ
Được luôn.Khi nào soạn xong, nếu có thể, mong anh chia sẻ nhé!
Câu chuyện này em không hiểu gì luôn . Em chỉ biết nếu theo đúng kịch bản thì thường là cô chủ nhàChiều qua lúc rửa cái bể nước, mình kêu bác chủ nhà lấy cho cái gáo múc nước. Ổng kêu không có, "lấy tạm cái bát củ này cúng được".
...
Không hiểu ổng nói gì luôn, mình có cần củ gì để cúng đâu, hay tại đang dưới bể nghe nhầm. @@
Anh nhớ nhé! Thôi em không lan man xa đề nữa, để mọi người tiếp tục vấn đề của chủ thớt nhé anhĐược luôn.
Option Explicit
Sub sapxep()
Dim i&, j&, k&, max&, data, res(), tmp, sum As Double, remain As Double
Dim dic As Object, key
Set dic = CreateObject("Scripting.Dictionary")
data = Range("B4:E10").Value
ReDim res(1 To UBound(data) * UBound(data, 2), 1 To 1)
For i = 1 To UBound(data)
For j = 1 To UBound(data, 2)
k = k + 1: res(k, 1) = data(i, j)
Next
Next
For i = 1 To UBound(res) - 1
For j = i + 1 To UBound(res)
If res(i, 1) < res(j, 1) Then tmp = res(j, 1): res(j, 1) = res(i, 1): res(i, 1) = tmp
Next
Next
For i = 1 To UBound(res)
dic.Add i, res(i, 1)
Next
ReDim res(1 To 100, 1 To 100)
For j = 1 To 10
remain = 6000: i = 0
For Each key In dic.keys
remain = remain - dic(key)
If remain > 0 Then
i = i + 1: res(i, j) = dic(key): dic.Remove (key)
Else: remain = remain + dic(key)
End If
Next
If i > max Then max = i
Next
[b14].Resize(max, j).Value = res
End Sub
Có lẽ nên thử trường hợp Bác nói.Nếu theo yêu cầu bằng lời từ chủ thớt, nghĩa là xếp theo thứ tự giảm dần, khi đạt mức <=6000 thì lấy
thì code sau cũng ra kết quả như HeSanbi
Tuy nhiên nhìn kỹ thì dường như không phải vậy.PHP:Option Explicit Sub sapxep() Dim i&, j&, k&, max&, data, res(), tmp, sum As Double, remain As Double Dim dic As Object, key Set dic = CreateObject("Scripting.Dictionary") data = Range("B4:E10").Value ReDim res(1 To UBound(data) * UBound(data, 2), 1 To 1) For i = 1 To UBound(data) For j = 1 To UBound(data, 2) k = k + 1: res(k, 1) = data(i, j) Next Next For i = 1 To UBound(res) - 1 For j = i + 1 To UBound(res) If res(i, 1) < res(j, 1) Then tmp = res(j, 1): res(j, 1) = res(i, 1): res(i, 1) = tmp Next Next For i = 1 To UBound(res) dic.Add i, res(i, 1) Next ReDim res(1 To 100, 1 To 100) For j = 1 To 10 remain = 6000: i = 0 For Each key In dic.keys remain = remain - dic(key) If remain > 0 Then i = i + 1: res(i, j) = dic(key): dic.Remove (key) Else: remain = remain + dic(key) End If Next If i > max Then max = i Next [b14].Resize(max, j).Value = res End Sub
Cột thứ 3, số 900 thay bằng 780+780 = 1560 để đạt mức dư là ít nhất.
Vậy rốt cuộc bài toán trở thành tìm các đoạn cây kết hợp cho ra số thừa là ít nhất?