【问题标题】:Excel String ParsingExcel 字符串解析
【发布时间】:2012-09-19 22:36:57
【问题描述】:

我有一个电子表格,它使用字符串约定来传达有关各个“案例”的详细程度。

约定如下:字符串中的数据有5个主要类别。 1=类别,2=工具,3=文档,4=过程,5=工作帮助。

每个类别可以有多个子类别,每 5 个类别按 1a、1b、1c 或 2a、2b、2c 等细分。

主类与子类用“:”分隔,子类与子类用“,”分隔,而子类与新的主类用“;”分隔

字符串示例:“1:1i;2:2a;3:3a,3d,3l;4:4a”

以下是按值分类的示例:

CATEGORY    1
Incorrect:VG:QOC    1i

TOOLS   2
Macro:Used  2a

DOCUMENTATION   3
TAT:Missing 3a
ROUTING:Missing 3d
STORY:Missing Impact to Health  3i

PROCESS 4
CNX Checklist Not Used  4a

我希望能够以文本形式提取标记了哪些主要类别和子类别。

查询示例:
在所有字符串中,主要类别 4 被标记了多少次? 在所有 4 个标记中,4a 标记了多少次? 在一个“案例”或字符串上标记的所有元素是什么?

我可以构建字符串,但我无法解析它们。请帮忙... :)

【问题讨论】:

    标签: string parsing excel vba


    【解决方案1】:

    您要查找的函数是Split(此链接适用于 VB 函数,但在 VBA 中的行为几乎相同)。您可以将特定字符串传递给它并指定分隔符,它将返回每个值的数组。

    在你的情况下,由于你的字符串有多个分隔符,你需要做多次。

    第一个潜在问题是,如果您没有给定类别的子类别怎么办?如果您的字符串中的每个类别始终至少有子类别,那很好,但如果可能存在没有子类别的情况,那么您需要确保您的最高级别分组仍然由 ; 分隔.

    由于您没有说明信息将如何呈现给用户,因此下面的示例将在 Excel 的中间窗口中打印出与您所期望的内容相近的内容。

    Option Explicit
    
    Sub SplitExample()
    Dim inputString As String
    Dim categories() As String
    Dim subCategories() As String
    Dim individualSubCat() As String
    Dim cat As Variant
    Dim subCat As Variant
    Dim cnt As Integer
    
        inputString = "1:1i;2:2a;3:3a,3d,3l;4:4a"
    
        categories = Split(inputString, ";")
    
        For Each cat In categories
    
            subCategories = Split(cat, ":")
    
            If UBound(subCategories) >= 0 Then
                Debug.Print ("Category " & subCategories(0))
    
                If UBound(subCategories) > 0 Then
                    individualSubCat = Split(subCategories(1), ",")
                    Debug.Print (vbTab & "Has " & UBound(individualSubCat) - LBound(individualSubCat) + 1 & " flag(s)")
    
                    For Each subCat In individualSubCat
                        Debug.Print (vbTab & subCat & " was flagged " & CountSubCategory(individualSubCat, subCat) & " time(s)")
                    Next
    
                Else
                    Debug.Print (vbTab & "No Subcategories flagged")
                End If
    
                Debug.Print ("")
    
            End If
    
            Erase subCategories
            Erase individualSubCat
    
        Next
    
    End Sub
    

    这是一个可以轻松计算子类别的函数

    Private Function CountSubCategory(individualSubCategories() As String, ByVal subCat As String) As Integer
    Dim cnt As Integer
    Dim value As Variant
    
        cnt = 0
    
        For Each value In individualSubCategories
            If value = subCat Then cnt = cnt + 1
        Next
    
        CountSubCategory = cnt
    
    End Function
    

    并使用您的示例字符串作为输入,上面的代码将打印:

    Category 1
        Has 1 flag(s)
        1i was flagged 1 time(s)
    
    Category 2
        Has 1 flag(s)
        2a was flagged 1 time(s)
    
    Category 3
        Has 3 flag(s)
        3a was flagged 1 time(s)
        3d was flagged 1 time(s)
        3l was flagged 1 time(s)
    
    Category 4
        Has 1 flag(s)
        4a was flagged 1 time(s)
    

    上面的代码将打印每个标志,即使有重复。你没有说这是否是理想的行为。从数组中过滤或分组重复项并不简单,但最好使用 VBA 中的 Collection 或 Dictionary 类来完成。 (请查看 this question 以帮助过滤数组中的重复项)。

    上面的代码只是一个示例,展示了需要做什么以及如何完成解析(因为那是您的具体要求)。要真正将其变为工作代码,您需要做两件事:

    1. 在 VBA 中创建一个 Function 或 Sub 并使用上面的代码解析它(基本上是上面 SplitExample() 的内容)并为其命名(如 ParseErrorCodes),并让它接受一个名为 inputString 的字符串参数.然后,您将从构建字符串的方法中调用它(您说过您已经可以这样做)并将该字符串传递给该方法。
    2. 决定如何输出结果。实际上,您可以将 Debug.Print 行替换为可以在某处输出结果的内容(可能是另一个 Excel 电子表格,这样您就可以创建您正在寻找的图表)。

    基本思路是:

    Sub OutputErrorCodes()
    Dim inputString as String
    
        ' You code to read your string values from where-ever you keep them
        '  and build the inputString
        ' this source could be a file, or a worksheet in the Excel Workbook
        '  or could be an external datasource like a database or even an internet 
        '  location
        ' once you build your inputString, you just need to call ParseErrorCodes 
    
        ParseErrorCodes inputString
    
    End Sub
    
    Sub ParseErrorCodes(input as String)
    
        ' MyCode from above with some modifications
        '  - You need to remove the Dim for inputString and the assignment for 
        '     inputString
        '  - You need to replace the Debug.Print lines with your method of 
        '     defining the output
        '    *  this can be via outputing directly to an excel spreadsheet or 
        '        maybe a global variable
        '    *  outputing to an excel spreadsheet would probably be the best 
        '        option and allow for more dynamic flags, but you need to decide 
        '        where to output it in the code
    
    End Sub
    
    Private Function CountSubCategory(individualSubCategories() As String, 
                                      ByVal subCat As String) As Integer)
    
        ' this code can probably be taken directly from my example
    
    End Function
    

    【讨论】:

    • 感谢您的回复,非常有帮助。一个问题:上面的代码是如何输入到 VBA 的?理想情况下,有一张表,其一列具有多行代码。我需要提取所有代码并将它们转化为趋势以进行根本原因分析,然后绘制最高缺陷区域(3a 或 3l)等。
    • 在我的示例中,我刚刚使用您的示例字符串定义了一个字符串:inputString = "1:1i;2:2a;3:3a,3d,3l;4:4a"。您将不得不从另一个读取您的输入的方法(可能是一个 excel 电子表格)向它提供一个特定的字符串
    • @user1005237 我在答案中添加了一些更基本的使用细节。但这大部分假设您对 excel 中的 VBA 以及如何调用方法以及从 excel 电子表格和其他基本 I/O 读取/写入数据有基本的了解。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-01
    • 2010-11-07
    相关资源
    最近更新 更多