Nhờ các cao thủ thông não giúp e với ạ. trình độ e còn xanh quá nên ko hiểu cái này là như thế nào cả... cảm ơn các bác
Option Explicit
Type BarElement
Mark As String
Diameter As Byte
Quantity As Long
No As Long
Length As Double
End Type
Type BarDetail
Dia As Byte
MaxNum As Byte
TotalNum As Integer
CurrentNum As Integer
Mark As String
Length As Double
MinLength As Double
End Type
Public Type SumLength
Value As Double
Note As String
End Type
Public maxLength As Double
Public maxResult As Double
Public maxString As String
Public tmpBar As Integer
Public tmpNum As Byte
Public barIndex As Long
Public cutIndex As Long
Public lapLength As Double
Public devLength As Double
Public cutOption As Byte
Public constPI As Double
Public isDemo As Boolean
Public Sub CutBarMainControl()
Call GetInitialData
'isDemo = True
'If InStr(Application.Caption, "REGISTERED") <> 0 Then isDemo = True
'isDemo = True
'If isDemo = True Then
' If MsgBox("Not registered vesion. Run DEMO program?", vbInformation + vbYesNoCancel, "Before running") = vbYes Then
' 'Call mdlCreateRandom.CreateRandom
' Call SortInputData
' Else
' If MsgBox("Not registered vesion. Run DEMO program?", vbInformation + vbYesNoCancel, "Before running") = vbNo Then
' Load frmActivate
' frmActivate.Show
' End If
' End If
' Else
Call SortInputData
'End If
End Sub
Private Sub GetInitialData()
maxLength = Sheets("Input").Cells(2, 6)
devLength = Sheets("Input").Cells(3, 6)
lapLength = Sheets("Input").Cells(4, 6)
cutOption = Sheets("Input").Cells(5, 6)
cutIndex = 0
constPI = Application.WorksheetFunction.Pi()
'Clear old data in sheet Result
Sheets("Result").Activate
Cells(1, 5) = 0
Range("A4:K65536").Clear 'Number of row in a sheet is 65536
End Sub
Private Sub SortInputData()
ActiveWorkbook.Application.StatusBar = "Analyzing and sorting data..."
Dim arrDiameter(1 To 15) As Byte
Dim arrWeight(1 To 15) As Double
Dim arrBar(1 To 15, 1 To 500) As BarElement
Dim arrNum(1 To 15) As Long
Dim curBarDia As Byte
Dim curBarLength As Double
Dim curBarMark As String
Dim curBarQuantity As Long
Dim curBarNo As Long
Dim i&, j&, l&
Dim k As Byte
Dim tmpMu As Integer
'Initilize list of support Diameters
For i = 1 To 15
arrDiameter(i) = Sheets("Input").Cells(2, i + 8)
Next i
For i = 1 To 15
arrNum(i) = 0
arrWeight(i) = 0
Next i
'Set initial Cell Index
i = 9
Sheets("Input").Activate
Do While Trim(Cells(i, 4)) <> "" 'Cot duong kinh khac 0
Cells(i, 2) = i - 8
curBarNo = i - 8
curBarMark = Trim(Cells(i, 3))
curBarDia = Trim(Cells(i, 4))
curBarQuantity = Trim(Cells(i, 5))
curBarLength = Trim(Cells(i, 6))
For j = 1 To 15
If arrDiameter(j) = curBarDia Then
arrNum(j) = arrNum(j) + 1
arrBar(j, arrNum(j)).No = curBarNo
arrBar(j, arrNum(j)).Mark = curBarMark
arrBar(j, arrNum(j)).Diameter = curBarDia
arrBar(j, arrNum(j)).Quantity = curBarQuantity
arrBar(j, arrNum(j)).Length = curBarLength
arrWeight(j) = arrWeight(j) + (((curBarDia ^ 2 * constPI / 4) * curBarLength) * 7850 * curBarQuantity) / 1000000
Exit For
End If
Next j
i = i + 1
Loop
Range("B9:G" & i - 1).Select
Call FormatInputTable
Range("B9:C" & i - 1).Select
Selection.HorizontalAlignment = xlCenter
'Dien DK va khoi luong vao Remain
For i = 1 To 15
Sheets("Remain").Cells(i + 3, 7) = arrDiameter(i)
Sheets("Remain").Cells(i + 3, 8) = arrWeight(i)
Next i
Sheets("Result").Activate
For j = 1 To 15
If arrNum(j) > 0 Then
ActiveWorkbook.Application.StatusBar = "Filtering data to Diameter: " & arrDiameter(j)
'Get current row index
barIndex = Cells(1, 5)
'Transfer data to ActiveSheet
l = 0
For i = 1 To arrNum(j)
l = l + 1
If arrBar(j, i).Length > maxLength Then
tmpMu = Int(arrBar(j, i).Length / (maxLength - lapLength * arrDiameter(j) / 1000))
Cells(barIndex + l + 3, 1) = arrBar(j, i).No
Cells(barIndex + l + 3, 2) = arrBar(j, i).Diameter
Cells(barIndex + l + 3, 3) = arrBar(j, i).Mark
Cells(barIndex + l + 3, 4) = arrBar(j, i).Quantity * tmpMu
Cells(barIndex + l + 3, 5) = maxLength
l = l + 1
arrBar(j, i).Length = arrBar(j, i).Length - tmpMu * (maxLength - lapLength * arrDiameter(j) / 1000)
End If
Cells(barIndex + l + 3, 1) = arrBar(j, i).No
Cells(barIndex + l + 3, 2) = arrBar(j, i).Diameter
Cells(barIndex + l + 3, 3) = arrBar(j, i).Mark
Cells(barIndex + l + 3, 4) = arrBar(j, i).Quantity
Cells(barIndex + l + 3, 5) = arrBar(j, i).Length
Next i
Cells(1, 5) = Cells(1, 5) + l
'Sort data
Range("A" & barIndex + 3 & ":E" & barIndex + l + 3).Select
Selection.Sort key1:=Range("E" & barIndex + 3), Order1:=xlDescending, Header:=xlGuess, OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom
ActiveWorkbook.Application.StatusBar = "Opimizing cutting bar for Diameter: " & arrDiameter(j)
'Format data from column A to D
Range("A" & barIndex + 4 & "
![Big Grin :D :D](https://cdn.jsdelivr.net/joypixels/assets/8.0/png/unicode/64/1f600.png)
" & barIndex + l + 3).Select
Selection.NumberFormat = "0"
Selection.HorizontalAlignment = xlCenter
'Format data from column A to E
Range("E" & barIndex + 4 & ":E" & barIndex + l + 3).Select
Selection.NumberFormat = "0.000"
'Format cell borders
Range("A" & barIndex + 4 & ":E" & barIndex + l + 3).Select
Call FormatInputTable
Call CutbarAnalyze(arrDiameter(j))
Range("A" & barIndex + 3 & ":E" & barIndex + l + 3).Select
Selection.Sort key1:=Range("A" & barIndex + 3), Order1:=xlAscending, Header:=xlGuess, OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom
End If
Next j
ActiveWorkbook.Application.StatusBar = "Controlling remain steel for the next usage"
Cells(1, 9) = "Optimization finished!"
Call ControlRemainSteel
ActiveWorkbook.Application.StatusBar = "Ready"
End Sub
Private Sub ClearCurrentSheet(intCount As Long)
Dim i&, j&
Cells(1, 6) = ""
i = 4
Do While Trim(Cells(i, 5) <> "")
i = i + 1
Loop
j = i
If intCount >= j Then j = intCount
Rows("4:" & j).Select
Selection.Delete Shift:=xlUp
End Sub
Private Sub CutbarAnalyze(curBarDiameter)
Dim i&, j&, k&, l&, m&, iPos&
Dim sCnt&, iCnt&
Dim MaxBar As Long
Dim iniLength As Double
Dim useLength As Double
Dim resLength As Double
Dim maxNumUse As Long
Dim strKey As String
Dim strAnl As String
Dim curMaxNum As Byte
Dim curBar() As BarDetail
Dim curNum() As Integer
Dim curFac() As Integer
Dim curSumLength(1 To 500) As SumLength
Dim curSumMin(1 To 500) As SumLength
Dim curCOM(1 To 500) As SumLength
Dim strNum(1 To 500) As String
Dim strDisplay As String
'Get MaxBar form current sheet
MaxBar = Cells(1, 5)
'ReDefined array
If MaxBar > 0 Then
ReDim curBar(1 To MaxBar) As BarDetail
ReDim curNum(1 To MaxBar) As Integer
ReDim curFac(1 To MaxBar) As Integer
iniLength = 0
useLength = 0
For i = barIndex + 1 To MaxBar
curBar(i).Mark = Cells(i + 3, 3)
curBar(i).TotalNum = Cells(i + 3, 4)
curBar(i).CurrentNum = Cells(i + 3, 4)
curBar(i).Length = Cells(i + 3, 5)
iniLength = iniLength + curBar(i).Length * curBar(i).TotalNum
curBar(i).MinLength = curBar(i).Length * (1 - devLength)
curBar(i).MaxNum = Fix(maxLength / curBar(i).MinLength)
Next i
'Cells index to put result
i = 1
iPos = 4
Do While i <= MaxBar
Do While curBar(i).CurrentNum > 0
sCnt = 0
For j = 1 To minValue(curBar(i).MaxNum, curBar(i).CurrentNum)
sCnt = sCnt + 1
curSumLength(sCnt).Value = j * curBar(i).Length
curSumMin(sCnt).Value = j * curBar(i).MinLength
curSumLength(sCnt).Note = "Bar" & i & "Num" & j
Next j
k = i + 1
Do While k <= MaxBar
If curBar(k).CurrentNum > 0 Then
m = 0
For iCnt = 1 To sCnt
For l = 1 To minValue(curBar(k).MaxNum, curBar(k).CurrentNum)
'curSumLength(iCnt).Value + l * curBar(k).Length <= maxlength Or
If curSumMin(iCnt).Value + l * curBar(k).MinLength <= maxLength Then
m = m + 1
curSumLength(sCnt + m).Value = curSumLength(iCnt).Value + l * curBar(k).Length
curSumMin(sCnt + m).Value = curSumMin(iCnt).Value + l * curBar(k).MinLength
curSumLength(sCnt + m).Note = curSumLength(iCnt).Note & "Bar" & k & "Num" & l
End If
Next l
Next iCnt
sCnt = sCnt + m
End If
k = k + 1
Loop
Call get_MaxResult(curSumLength, sCnt)
'Get conresponded num of bar in this case -> curNum(1 To MaxBar)
For j = 1 To MaxBar
curNum(j) = 0
Next j
j = 2
Do While j <= Len(maxString)
strKey = Mid(maxString, j, 3)
If strKey = "Bar" Then
strAnl = Left(maxString, j - 1)
Call get_NumBar(strAnl)
curNum(tmpBar) = tmpNum
maxString = Right(maxString, Len(maxString) - j + 1)
j = 2
Else
j = j + 1
End If
Loop
Call get_NumBar(maxString)
curNum(tmpBar) = tmpNum
'Get maximun combination in this case -> maxNumUse(curNum, curBar.CurrentNum)
For j = 1 To MaxBar
If curNum(j) <> 0 Then
curFac(j) = curBar(j).CurrentNum \ curNum(j)
Else
curFac(j) = 0
End If
Next j
maxNumUse = maxArray(curFac)
For j = 1 To MaxBar
If maxNumUse >= curFac(j) Then
If curFac(j) > 0 Then
maxNumUse = curFac(j)
End If
End If
Next j
'Write analysis result to sheet
'Writing diameter
'barIndex = get_CurrentIndex()
Cells(cutIndex + iPos, 7) = curBarDiameter
'Writing cut No.
Cells(cutIndex + iPos, 8) = iPos - 3
strDisplay = ""
resLength = 0
For j = 1 To MaxBar
If curNum(j) > 0 Then
strDisplay = strDisplay & curNum(j) & "*[" & curBar(j).Mark & "]+"
resLength = resLength + curNum(j) * curBar(j).Length
End If
Next j
strDisplay = Left(strDisplay, Len(strDisplay) - 1)
Cells(cutIndex + iPos, 9) = strDisplay
Cells(cutIndex + iPos, 10) = maxNumUse
Cells(cutIndex + iPos, 11) = resLength
useLength = useLength + maxLength * maxNumUse
For j = 1 To MaxBar
curBar(j).CurrentNum = curBar(j).CurrentNum - maxNumUse * curNum(j)
Next j
iPos = iPos + 1
Loop
i = i + 1
Loop
'Format cell borders
Range("G" & cutIndex + 4 & ":K" & cutIndex + iPos - 1).Select
Call FormatInputTable
'Number format
Range("K" & cutIndex + 4 & ":K" & cutIndex + iPos - 1).Select
Selection.NumberFormat = "0.000"
cutIndex = cutIndex + iPos - 4
End If
End Sub
Private Sub ControlRemainSteel()
Dim arrDiameter(1 To 15) As Byte
Dim arrMinLength(1 To 15) As Double
Dim arrRealWeigth(1 To 15) As Double
Dim tmpWeight As Double
Dim i%, j%, k%
Dim curMinLength As Double
For i = 1 To 15
arrMinLength(i) = Sheets("Input").Cells(3, i + 8)
arrDiameter(i) = Sheets("Input").Cells(2, i + 8)
Next i
'Clear old data in this sheet
Sheets("Remain").Activate
Range("A4:E65536").Clear
'For i = 1 To 15
'Filter remain steel for next usage
j = 4
k = 0
Do While Trim(Sheets("Result").Cells(j, 9)) <> ""
For i = 1 To 15
If Sheets("Result").Cells(j, 7) = arrDiameter(i) Then
curMinLength = arrMinLength(i)
Exit For
End If
Next i
If maxLength - Sheets("Result").Cells(j, 11) >= curMinLength Then
k = k + 1
Cells(k + 3, 1) = k
Cells(k + 3, 2) = Sheets("Result").Cells(j, 7)
Cells(k + 3, 3) = Sheets("Result").Cells(j, 8)
Cells(k + 3, 4) = Sheets("Result").Cells(j, 10)
Cells(k + 3, 5) = maxLength - Sheets("Result").Cells(j, 11)
End If
j = j + 1
Loop
'Format number
Range("E4:E" & k + 3).Select
Selection.NumberFormat = "0.000"
'Format range
Range("A4:E" & k + 3).Select
Call FormatInputTable
'Get reality weight
j = 4
Do While Trim(Sheets("Result").Cells(j, 9)) <> ""
For i = 1 To 15
If Sheets("Result").Cells(j, 7) = arrDiameter(i) Then
tmpWeight = arrDiameter(i) ^ 2 * constPI / 4 / 10 ^ 6
tmpWeight = tmpWeight * Sheets("Result").Cells(j, 10) * maxLength * 7850
arrRealWeigth(i) = arrRealWeigth(i) + tmpWeight
Exit For
End If
Next i
j = j + 1
Loop
'Writing data
For i = 1 To 15
Cells(i + 3, 9) = arrRealWeigth(i)
Next i
'Next i
End Sub
Public Function minValue(valA, valB) As Double
minValue = valA
If minValue >= valB Then minValue = valB
End Function
Private Sub get_MaxResult(arrBar() As SumLength, arrCnt As Long)
maxResult = arrBar(1).Value
maxString = arrBar(1).Note
Dim i&
For i = 1 To arrCnt
If arrBar(i).Value >= maxResult Then
maxResult = arrBar(i).Value
maxString = arrBar(i).Note
End If
Next i
End Sub
Private Sub get_NumBar(strGet)
tmpNum = 0
tmpBar = 0
Dim i1 As Integer
For i1 = 1 To Len(strGet)
If Mid(strGet, i1, 3) = "Num" Then
tmpBar = Right(Left(strGet, i1 - 1), Len(Left(strGet, i1 - 1)) - 3)
tmpNum = Right(Right(strGet, Len(strGet) - i1 + 1), Len(Right(strGet, Len(strGet) - i1 + 1)) - 3)
Exit For
End If
Next i1
End Sub
Private Function maxArray(arrFac() As Integer) As Integer
maxArray = 0
Dim iArr As Integer
For iArr = LBound(arrFac) To UBound(arrFac)
If maxArray <= arrFac(iArr) Then maxArray = arrFac(iArr)
Next iArr
End Function
Private Function Num2Char(intNum As Integer) As String
Num2Char = ""
Do While intNum > 26
Num2Char = Chr(64 + intNum Mod 26) & Num2Char
intNum = intNum \ 26
Loop
Num2Char = Chr(64 + intNum) & Num2Char
End Function
Private Function get_CurrentIndex()
Dim cIndex As Long
cIndex = 4
Do While Trim(Cells(cIndex, 7)) <> ""
cIndex = cIndex + 1
Loop
get_CurrentIndex = cIndex
End Function
Private Sub FormatInputTable()
Selection.Borders(xlDiagonalDown).LineStyle = xlNone
Selection.Borders(xlDiagonalUp).LineStyle = xlNone
With Selection.Borders(xlEdgeLeft)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeTop)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeRight)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlInsideVertical)
.LineStyle = xlContinuous
.Weight = xlHairline
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlInsideHorizontal)
.LineStyle = xlContinuous
.Weight = xlHairline
.ColorIndex = xlAutomatic
End With
End Sub