编辑:根据评论,我提供了有关代码的更多详细信息。
代码的想法是:
存在范围B6:E6中的字符串(例如B6 ="实际销售",C6 =" SOP11(2015)",D6 =" SOP12( 2015)",E6 =" SOP10(2015)")。
我使用" Mid"来计算整数。如果字符串不是"实际销售"则起作用。
完成后,计算出的整数将使用阵列中的BubbleSort进行排序。
之后,我想将排序整数(SOP_key_B6,SOP_key_C6,SOP_key_D6,SOP_key_E6)与原始字符串(cell_b6,cell_c6,cell_d6,cell_e6)相关联。换句话说,SOP_key_B6和cell_b6等之间存在一对一的对应关系。)
我想要做到以上几点,因为我需要输入到范围L30:O30 基于排序整数的带字符串的排序数组。
我希望这会让这个想法变得清晰,因为它不是很复杂,但是方法本身和代码使它有点令人沮丧(可能是因为我还在学习VB编码)。
以下是代码:
Sub Worksheet_Delta_Update()
'Variables
Dim wb As Workbook, ws_wk_dlt As Worksheet, ws_dash As Worksheet, cell_B6 As Variant, _
cell_C6 As Variant, cell_D6 As Variant, cell_E6 As Variant, SOP_key_B6 As Variant, _
SOP_key_C6 As Variant, SOP_key_D6 As Variant, SOP_key_E6 As Variant
'Referencing
Set wb = ThisWorkbook
Set ws_wk_dlt = wb.Worksheets("t")
Set ws_dash = wb.Worksheets("x")
'Values from pivot stored
cell_B6 = ws_wk_dlt.Range("B6").Value
cell_C6 = ws_wk_dlt.Range("C6").Value
cell_D6 = ws_wk_dlt.Range("D6").Value
cell_E6 = ws_wk_dlt.Range("E6").Value
'If len certain amount of characters then do option 1, or option 2
If cell_B6 <> "" Then
If Len(cell_B6) = 12 And cell_B6 <> "Actual Sales" Then
SOP_key_B6 = CInt(Mid(cell_B6, 4, 2)) + CInt(Mid(cell_B6, 8, 4))
ElseIf Len(cell_B6) = 11 And cell_B6 <> "Actual Sales" Then
SOP_key_B6 = CInt(Mid(cell_B6, 4, 2)) + CInt(Mid(cell_B6, 7, 4))
End If
End If
If cell_C6 <> "" Then
If Len(cell_C6) = 12 And cell_C6 <> "Actual Sales" Then
SOP_key_C6 = CInt(Mid(cell_C6, 4, 2)) + CInt(Mid(cell_C6, 8, 4))
ElseIf Len(cell_C6) = 11 And cell_C6 <> "Actual Sales" Then
SOP_key_C6 = CInt(Mid(cell_C6, 4, 2)) + CInt(Mid(cell_C6, 7, 4))
End If
End If
If cell_D6 <> "" Then
If Len(cell_D6) = 12 And cell_D6 <> "Actual Sales" Then
SOP_key_D6 = CInt(Mid(cell_D6, 4, 2)) + CInt(Mid(cell_D6, 8, 4))
ElseIf Len(cell_D6) = 11 And cell_D6 <> "Actual Sales" Then
SOP_key_D6 = CInt(Mid(cell_D6, 4, 2)) + CInt(Mid(cell_D6, 7, 4))
End If
End If
If cell_E6 <> "" Then
If Len(cell_E6) = 12 And cell_E6 <> "Actual Sales" Then
SOP_key_E6 = CInt(Mid(cell_E6, 4, 2)) + CInt(Mid(cell_E6, 8, 4))
ElseIf Len(cell_E6) = 11 And cell_E6 <> "Actual Sales" Then
SOP_key_E6 = CInt(Mid(cell_E6, 4, 2)) + CInt(Mid(cell_E6, 7, 4))
End If
End If
'Finding the Actual Sales and putting into L30
If cell_B6 = "Actual Sales" Then
ws_dash.Range("L31").Value = cell_B6
ElseIf cell_C6 = "Actual Sales" Then
ws_dash.Range("L31").Value = cell_C6
ElseIf cell_D6 = "Actual Sales" Then
ws_dash.Range("L31").Value = cell_D6
ElseIf cell_E6 = "Actual Sales" Then
ws_dash.Range("L31").Value = cell_E6
End If
'BubbleSort in Descending order
Dim ArrayToSort(0 To 4) As Variant
ArrayToSort(0) = SOP_key_B6
ArrayToSort(1) = SOP_key_C6
ArrayToSort(2) = SOP_key_D6
ArrayToSort(3) = SOP_key_E6
'Moving upwards because of -1
For j = UBound(ArrayToSort) - 1 To LBound(ArrayToSort) Step -1
'Starting at lowest
For i = LBound(ArrayToSort) To j
If ArrayToSort(i) > ArrayToSort(i + 1) Then
vTemp = ArrayToSort(i)
ArrayToSort(i) = ArrayToSort(i + 1)
ArrayToSort(i + 1) = vTemp
End If
Next i
Next j
'Put sorted array into the range
'But how to put the values linked to integers?
'E.g. SOP_key_B6 = cell_B6
ws_dash.Range("L30:O30").Value = ArrayToSort
End Sub
最有可能解决方案是用正确的数组替换数组元素(即SOP_key_B6 = cell_B6
等)?
答案 0 :(得分:1)
您的代码在某些地方臃肿,例如:
Dim ArrayToSort(0 To 4) As Variant
ArrayToSort(0) = SOP_key_B6
ArrayToSort(1) = SOP_key_C6
ArrayToSort(2) = SOP_key_D6
ArrayToSort(3) = SOP_key_E6
可以替换为
Dim ArrayToSort As Variant 'note lack of ()
ArrayToSort = Array(SOP_key_B6, SOP_key_C6, SOP_key_D6, SOP_key_E6)
就你的问题而言,似乎你需要使用一个集合。假设SOP-key_
值和cell_
值之间存在一对一的对应关系(否则,调用它们&#34;键&#34;会产生误导),您可以执行以下操作:
Dim C As New Collection
C.Add cell_B6, CStr(SOP_key_B6)
C.Add cell_C6, CStr(SOP_key_C6)
C.Add cell_D6, CStr(SOP_key_D6)
C.Add cell_E6, CStr(SOP_key_E6)
然后,在排序ArrayToSort
之后,有一个循环:
For i = 0 to 3
Range("L30").Offset(0,i).Value = C(CStr(ArrayToSort(i)))
Next i
我认为这就是你要找的东西 - 但代码似乎在复杂的一面,所以简化它可能不是一个坏主意。
开启编辑:
由于添加注意SOP11(2015)
与SOP10(2016)
不同,但11 + 2015 = 10 + 2016(两者都是等于2026)。相反 - juxtapose :112015不是102016.
此外,将密钥创建拆分为自己的功能是有意义的(所以你不要重复4次相同的代码:
Function ExtractKey(s As Variant) As Long
Dim v As Variant, n As Long
v = Trim(s)
If v Like "*(*)" Then
n = Len(v)
v = Mid(v, n - 7, 7)
v = Replace(v, "(", "")
ExtractKey = CLng(v)
Else
ExtractKey = 0
End If
End Function
请注意,返回类型为Long
- Integer
变量太容易溢出,无法在VBA中使用。
然后 - 这样的事情应该有效:
Sub Worksheet_Delta_Update()
Dim SourceRange As Range, TargetRange As Range
Dim i As Long, j As Long, minKey As Long, minAt As Long
Dim v As Variant
Dim C As New Collection
Set SourceRange = Worksheets("t").Range("B6:E6")
Set TargetRange = Worksheets("t").Range("L30:O30")
For i = 1 To 4
v = SourceRange.Cells(1, i).Value
C.Add Array(ExtractKey(v), v)
Next i
'transfer data
For i = 1 To 4
minAt = -1
For j = 1 To C.Count
If minAt = -1 Or C(j)(0) < minKey Then
minKey = C(j)(0)
minAt = j
End If
Next j
TargetRange.Cells(1, i).Value = C(minAt)(1)
C.Remove minAt
Next i
End Sub
答案 1 :(得分:0)
使用以下修改修复Type mismatch error
:
Function ExtractKey(s As Variant) As Long
Dim v As Variant, n As Long
v = Trim(s) 'remove spaces leave only spaces between words
If v Like "*(*)" Then 'if it's SOPXX (YYYY) then
n = Len(v) 'find number of the characters
If n = 11 Then
v = Mid(v, n - 7, 7) 'find the number of SOP + year in bracket
ElseIf n = 12 Then
v = Mid(v, n - 8, 8)
End If
v = Replace(v, "(", "") 'replace the brackets with nothing
v = Replace(v, " ", "")
ExtractKey = CLng(v) 'error WAS here
Else
ExtractKey = 0
End If
End Function
修改强> 添加了另外几行
If n = 11 Then
v = Right(v, 4) + Left(v, 1)
ElseIf n = 12 Then
v = Right(v, 4) + Left(v, 2)
End If
上述交换年份和号码(例如SOP12(2015)= 122015和交换机201512之后)。这是因为SOP12(2014)在 SOP10(2015)之后被置于,尽管它应该在2014年之前发布。现在像魅力一样工作:)