英文:
How to get information from string in a nice Excel table?
问题
以下是Excel按钮背后的代码的翻译部分:
Sub Top10Names()
Dim dataSheet As Worksheet
Dim reportSheet As Worksheet
Dim lastRow As Long
Dim dataRange As Range
Dim nameColumn As Range
Dim dateColumn As Range
Dim targetMonth As Long
Dim targetYear As Long
Dim i As Long
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
Set dataSheet = ThisWorkbook.Sheets("TestSheet")
Set reportSheet = ThisWorkbook.Sheets("Makro")
lastRow = dataSheet.Cells(Rows.Count, "A").End(xlUp).Row
Dim columnF As Range
Set columnF = dataSheet.Range("F6:F" & lastRow)
Set dataRange = dataSheet.Range("A6:C" & lastRow)
Set nameColumn = dataRange.Columns(3)
Set dateColumn = dataRange.Columns(1)
targetMonth = InputBox("Please enter the target month (1-12):")
targetYear = InputBox("Please enter the target year:")
For i = 1 To dataRange.Rows.Count
If Month(dateColumn.Cells(i)) = targetMonth And Year(dateColumn.Cells(i)) = targetYear Then
Namex = nameColumn.Cells(i)
If dict.Exists(Namex) Then
dict(Namex) = dict(Namex) + 1
Else
dict(Namex) = 1
End If
End If
Next i
reportSheet.Range("A1") = "Lieferant"
reportSheet.Range("B1") = "Häufigkeit"
reportSheet.Range("A2:B4") = ""
reportSheet.Range("A1:B1").Interior.Color = vbBlack
reportSheet.Range("A1:B1").Font.Color = vbWhite
reportSheet.Range("C1") = "Grund"
reportSheet.Range("C1").Interior.Color = vbBlack
reportSheet.Range("C1").Font.Color = vbWhite
For i = 0 To 9
maxCount = 0
For Each Key In dict.Keys()
If dict(Key) > maxCount Then
maxCount = dict(Key)
maxKey = Key
End If
Next Key
reportSheet.Cells(i + 2, 1) = maxKey
reportSheet.Cells(i + 2, 2) = maxCount
' Find all rows in the data sheet where the name matches maxKey and the date is in the target month and year, and count the frequency of each reason from column F using a dictionary
Dim reasons As Object
Set reasons = CreateObject("Scripting.Dictionary")
For j = 1 To dataRange.Rows.Count
If nameColumn.Cells(j) = maxKey And Month(dateColumn.Cells(j)) = targetMonth And Year(dateColumn.Cells(j)) = targetYear Then
reasonx = columnF.Cells(j)
If reasons.Exists(reasonx) Then
reasons(reasonx) = reasons(reasonx) + 1
Else
reasons(reasonx) = 1
End If
End If
Next j
' Convert the dictionary of reasons and their frequencies into a list of strings
Dim reasonList As String
reasonList = ""
For Each Key In reasons.Keys()
reasonList = reasonList & Key & " (" & reasons(Key) & "), "
Next Key
' Remove the trailing comma and space from the list of reasons
If Len(reasonList) > 0 Then
reasonList = Left(reasonList, Len(reasonList) - 2)
End If
' Write the list of reasons to the report sheet
reportSheet.Cells(i + 2, 3) = reasonList
dict.Remove (maxKey)
Next i
End Sub
希望这有助于您理解代码的翻译。如果您需要进一步的帮助,请随时提问。
英文:
I have following code behind a button in Excel:
Sub Top10Names()
Dim dataSheet As Worksheet
Dim reportSheet As Worksheet
Dim lastRow As Long
Dim dataRange As Range
Dim nameColumn As Range
Dim dateColumn As Range
Dim targetMonth As Long
Dim targetYear As Long
Dim i As Long
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
Set dataSheet = ThisWorkbook.Sheets("TestSheet")
Set reportSheet = ThisWorkbook.Sheets("Makro")
lastRow = dataSheet.Cells(Rows.Count, "A").End(xlUp).Row
Dim columnF As Range
Set columnF = dataSheet.Range("F6:F" & lastRow)
Set dataRange = dataSheet.Range("A6:C" & lastRow)
Set nameColumn = dataRange.Columns(3)
Set dateColumn = dataRange.Columns(1)
targetMonth = InputBox("Bitte geben Sie den Zielmonat ein (1-12):")
targetYear = InputBox("Bitte geben Sie das Zieljahr ein:")
For i = 1 To dataRange.Rows.Count
If Month(dateColumn.Cells(i)) = targetMonth And Year(dateColumn.Cells(i)) = targetYear Then
Namex = nameColumn.Cells(i)
If dict.Exists(Namex) Then
dict(Namex) = dict(Namex) + 1
Else
dict(Namex) = 1
End If
End If
Next i
reportSheet.Range("A1") = "Lieferant"
reportSheet.Range("B1") = "Häufgkeit"
reportSheet.Range("A2:B4") = ""
reportSheet.Range("A1:B1").Interior.Color = vbBlack
reportSheet.Range("A1:B1").Font.Color = vbWhite
reportSheet.Range("C1") = "Grund"
reportSheet.Range("C1").Interior.Color = vbBlack
reportSheet.Range("C1").Font.Color = vbWhite
For i = 0 To 9
maxCount = 0
For Each Key In dict.Keys()
If dict(Key) > maxCount Then
maxCount = dict(Key)
maxKey = Key
End If
Next Key
reportSheet.Cells(i + 2, 1) = maxKey
reportSheet.Cells(i + 2, 2) = maxCount
' Find all rows in the data sheet where the name matches maxKey and the date is in the target month and year, and count the frequency of each reason from column F using a dictionary
Dim reasons As Object
Set reasons = CreateObject("Scripting.Dictionary")
For j = 1 To dataRange.Rows.Count
If nameColumn.Cells(j) = maxKey And Month(dateColumn.Cells(j)) = targetMonth And Year(dateColumn.Cells(j)) = targetYear Then
reasonx = columnF.Cells(j)
If reasons.Exists(reasonx) Then
reasons(reasonx) = reasons(reasonx) + 1
Else
reasons(reasonx) = 1
End If
End If
Next j
' Convert the dictionary of reasons and their frequencies into a list of strings
Dim reasonList As String
reasonList = ""
For Each Key In reasons.Keys()
reasonList = reasonList & Key & " (" & reasons(Key) & "), "
Next Key
' Remove the trailing comma and space from the list of reasons
If Len(reasonList) > 0 Then
reasonList = left(reasonList, Len(reasonList) - 2)
End If
' Write the list of reasons to the report sheet
reportSheet.Cells(i + 2, 3) = reasonList
dict.Remove (maxKey)
Next i
End Sub
The reasons are shown as a string with a number of how much they apear behind it.
I need to build a table, so that every reason is an extra item to every deliverer, with its number of apperiance in an extra cell, so I can work with it.
Tried to split them up but nothing worked out.
答案1
得分: 1
Instead of putting them into a String
that you write into a single cell
使用一个类型为 `Variant` 的二维 `Array`(代表范围),将其写入一系列单元格:
Dim reasonList() As Variant
ReDim reasonList(1 To reasons.Count, 1 To 1) ' 为每个原因创建一个包含 1 列和 x 行的数组
' 逐行用你的字典的原因填充数组
Dim k As Long
For k = 0 To reasons.Count - 1
reasonList(k + 1, 1) = reasons.Keys()(k) & " (" & reasons.Items()(k) & ")"
Next k
然后,你可以将数组输出到一个范围:
Dim StartOutput As Range
Set StartOutput = reportSheet.Cells(i + 2, 3)
' 我们需要调整起始单元格的大小以适应数组的大小(否则数组的数据将会丢失)
StartOutput.Resize(UBound(reasonList, 1), UBound(reasonList, 2)).Value = reasonList
Just a note:
我建议使用 Application.InputBox 方法 并定义参数 Type:=1
,这样用户被强制输入一个数字,以避免错误:
targetMonth = Application.InputBox(Prompt:="Bitte geben Sie den Zielmonat ein (1-12):", Type:=1)
targetYear = Application.InputBox(Prompt:="Bitte geben Sie das Zieljahr ein:", Type:=1)
甚至更好的方法是给用户按下取消按钮的机会,因为如果用户现在按下取消按钮,它将返回 0
作为月份和年份。
使用输入框的更好方法:
Dim targetMonth As Long
Dim RetVal As Variant
RetVal = Application.InputBox(Prompt:="Bitte geben Sie den Zielmonat ein (1-12):", Type:=1)
If VarType(RetVal) = vbBoolean And RetVal = False Then
Exit Sub ' 用户按下取消按钮,因此取消过程
Else
targetMonth = CLng(RetVal)
End If
Dim targetYear As Long
Dim RetVal As Variant
RetVal = Application.InputBox(Prompt:="Bitte geben Sie das Zieljahr ein:", Type:=1)
If VarType(RetVal) = vbBoolean And RetVal = False Then
Exit Sub ' 用户按下取消按钮,因此取消过程
Else
targetYear = CLng(RetVal)
End If
英文:
Instead of putting them into a String
that you write into a single cell
Dim reasonList As String
reasonList = ""
For Each Key In reasons.Keys()
reasonList = reasonList & Key & " (" & reasons(Key) & "), "
Next Key
use a 2-dimensional Array
of type Variant
(which reperesents a range) that you write into a range of cells:
Dim reasonList() As Variant
ReDim reasonList(1 To reasons.Count, 1 To 1) ' create array with 1 column and x rows one for each reason
' fill that array with the reasons of your dictionary row by row
Dim k As Long
For k = 0 To reasons.Count - 1
reasonList(k + 1, 1) = reasons.Keys()(k) & " (" & reasons.Items()(k) & ")"
Next k
Then you can output your array into a range:
Dim StartOutput As Range
Set StartOutput = reportSheet.Cells(i + 2, 3)
' we need to resize the start cell to the size of the array (otherwise data of the array will get lost)
StartOutput.Resize(Ubound(reasonList, 1), Ubound(reasonList, 2)).Value = reasonList
Just a note:
I recommend to use the Application.InputBox method and define the Argument Type:=1
, so the user is forced to input a number and you don't run into errors:
targetMonth = Application.InputBox(Prompt:="Bitte geben Sie den Zielmonat ein (1-12):", Type:=1)
targetYear = Application.InputBox(Prompt:="Bitte geben Sie das Zieljahr ein:", Type:=1)
even better give the user the chance to press the cancel button, because if the user presses cancel now it just returns 0
as month and year.
Better approach with the input box:
Dim targetMonth As Long
Dim RetVal As Variant
RetVal = Application.InputBox(Prompt:="Bitte geben Sie den Zielmonat ein (1-12):", Type:=1)
If VarType(RetVal) = vbBoolean And RetVal = False Then
Exit Sub ' user pressed cancel so cancel the procedure
Else
targetMonth = CLng(RetVal)
End If
Dim targetYear As Long
Dim RetVal As Variant
RetVal = Application.InputBox(Prompt:="Bitte geben Sie das Zieljahr ein:", Type:=1)
If VarType(RetVal) = vbBoolean And RetVal = False Then
Exit Sub ' user pressed cancel so cancel the procedure
Else
targetYear = CLng(RetVal)
End If
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论