如何从字符串中获取信息并呈现在漂亮的Excel表格中?

huangapple go评论64阅读模式
英文:

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

huangapple
  • 本文由 发表于 2023年6月22日 14:11:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76529018.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定