gpt4 book ai didi

regex - 在 Excel Vba 中解析字符串

转载 作者:行者123 更新时间:2023-12-03 02:33:52 25 4
gpt4 key购买 nike

我有一个宏,它向服务器发送 XMLHTTP 请求,它得到一个纯文本字符串作为响应,而不是 JSON 格式字符串或其他标准格式(至少据我所知)。

我想解析输出字符串,以便以与此 link 中的 parseJson 子例程相同的方式以结构化方法访问数据。

我的问题是我不擅长正则表达式,并且无法根据需要修改例程。

我需要解析的字符串具有以下结构:

  1. 字符串是单行
  2. 每个单个参数都由其参数名称(等于 simbol)、其值和结尾来定义; “NID=3;”“SID=Test;”
  3. 参数可以收集在以符号 | 开头和结尾的“结构”中他们通过名字后跟 ; 来识别。例如|STEST;NID=3;SID=Test;|
  4. 一个结构还可以包含其他结构

输出字符串的示例如下

|KC;|AD;PE=5;PF=3;|CD;PE=5;HP=test;|CD;PE=3;HP=abc;|

在这种情况下,有一个宏结构KC,其中包含一个结构AD。结构AD由参数PEPF和2个结构CD组成。最后,结构CD具有参数PEHP

所以我想解析字符串以获得反射(reflect)此结构的对象/字典,你能帮助我吗?

在第一个答案后添加

大家好,感谢您的帮助,但我想我应该更清楚地说明我想要得到的输出。对于我拥有的示例字符串,我想要一个具有以下结构的对象:

<KC>
<AD>
<PE>5</PE>
<PF>3</PF>
<CD>
<PE>5</PE>
<HP>test</HP>
</CD>
<CD>
<PE>3</PE>
<HP>abc</HP>
</CD>
</AD>
</KC>

因此,我开始根据 @Nvj 答案和 link 中的答案的一些提示编写可能的工作代码库。

Option Explicit
Option Base 1

Sub Test()

Dim strContent As String
Dim strState As String
Dim varOutput As Variant

strContent = "|KC;|AD;PE=5;PF=3;|CD;PE=5;HP=test;|CD;PE=3;HP=abc;|"
Call ParseString(strContent, varOutput, strState)

End Sub

Sub ParseString(ByVal strContent As String, varOutput As Variant, strState As String)
' strContent - source string
' varOutput - created object or array to be returned as result
' strState - Object|Array|Error depending on processing to be returned as state
Dim objTokens As Object
Dim lngTokenId As Long
Dim objRegEx As Object
Dim bMatched As Boolean

Set objTokens = CreateObject("Scripting.Dictionary")
lngTokenId = 0
Set objRegEx = CreateObject("VBScript.RegExp")
With objRegEx
.Global = True
.MultiLine = True
.IgnoreCase = True
.Pattern = "\|[A-Z]{2};" 'Pattern for the name of structures
Tokenize objTokens, objRegEx, strContent, lngTokenId, bMatched, "str"
.Pattern = "[A-Z]{2}=[^\|=;]+;" 'Pattern for parameters name and values
Tokenize objTokens, objRegEx, strContent, lngTokenId, bMatched, "par"
End With

End Sub

Sub Tokenize(objTokens, objRegEx, strContent, lngTokenId, bMatched, strType)
Dim strKey As String
Dim strKeyPar As String
Dim strKeyVal As String

Dim strWork As String
Dim strPar As String
Dim strVal As String
Dim strLevel As String

Dim strRes As String

Dim lngCopyIndex As Long
Dim objMatch As Object

strRes = ""
lngCopyIndex = 1
With objRegEx
For Each objMatch In .Execute(strContent)
If strType = "str" Then
bMatched = True
With objMatch
strWork = Replace(.Value, "|", "")
strWork = Replace(strWork, ";", "")
strLevel = get_Level(strWork)
strKey = "<" & lngTokenId & strLevel & strType & ">"
objTokens(strKey) = strWork
strRes = strRes & Mid(strContent, lngCopyIndex, .FirstIndex - lngCopyIndex + 1) & strKey
lngCopyIndex = .FirstIndex + .Length + 1
End With
lngTokenId = lngTokenId + 1
ElseIf strType = "par" Then

strKeyPar = "<" & lngTokenId & "par>"
strKeyVal = "<" & lngTokenId & "val>"
strKey = strKeyPar & strKeyVal
bMatched = True
With objMatch
strWork = Replace(.Value, ";", "")
strPar = Split(strWork, "=")(0)
strVal = Split(strWork, "=")(1)
objTokens(strKeyPar) = strPar
objTokens(strKeyVal) = strVal
strRes = strRes & Mid(strContent, lngCopyIndex, .FirstIndex - lngCopyIndex + 1) & strKey
lngCopyIndex = .FirstIndex + .Length + 1
End With
lngTokenId = lngTokenId + 2

End If
Next
strContent = strRes & Mid(strContent, lngCopyIndex, Len(strContent) - lngCopyIndex + 1)
End With
End Sub

Function get_Level(strInput As String) As String

Select Case strInput
Case "KC"
get_Level = "L1"
Case "AD"
get_Level = "L2"
Case "CD"
get_Level = "L3"
Case Else
MsgBox ("Error")
End
End Select

End Function

该函数创建一个字典,其中每个结构名称、参数名称和参数值都有一个项目,如图所示 enter image description here由于函数 get_Level ,与结构关联的项目具有有助于保留数据原始层次结构的级别。

所以我缺少的是一个创建具有输入字符串原始结构的对象的函数。这就是 Retrieve 函数在这个答案 link 中所做的事情。 ,但我不知道如何使其适应我的情况

最佳答案

这看起来像一个简单的嵌套分隔字符串。几个 Split() 函数就可以解决这个问题:

Option Explicit

Function parseString(str As String) As Collection

Dim a1() As String, i1 As Long, c1 As Collection
Dim a2() As String, i2 As Long, c2 As Collection
Dim a3() As String

a1 = Split(str, "|")
Set c1 = New Collection
For i1 = LBound(a1) To UBound(a1)
If a1(i1) <> "" Then
Set c2 = New Collection
a2 = Split(a1(i1), ";")
For i2 = LBound(a2) To UBound(a2)
If a2(i2) <> "" Then
a3 = Split(a2(i2), "=")
If UBound(a3) > 0 Then
c2.Add a3(1), a3(0)
ElseIf UBound(a3) = 0 Then
c2.Add a3(0)
End If
End If
Next i2
c1.Add c2
End If
Next i1

Set parseString = c1

End Function


Sub testParseString()

Dim c As Collection

Set c = parseString("|KC;|AD;PE=5;PF=3;|CD;PE=5;HP=test;|CD;PE=3;HP=abc;|")

Debug.Assert c(1)(1) = "KC"
Debug.Assert c(2)("PE") = "5"
Debug.Assert c(3)(1) = "CD"
Debug.Assert c(4)("HP") = "abc"
Debug.Assert c(4)(3) = "abc"

End Sub

请注意,您可以通过索引和键来寻址值(如果输入中存在键)。如果未提供 key ,您只能通过其索引访问该值。您还可以递归地迭代集合以获取树结构中的所有值。

引人深思:由于您的结构可能有重复的名称(在您的情况下,“CD”结构出现两次),集合/字典会发现优雅地存储它是有问题的(由于键冲突)。解决此问题的另一个好方法是使用 DOMDocument 创建 XML 结构并使用 XPath 访问其元素。请参阅Program with DOM in Visual Basic

更新:我还在下面添加了 XML 示例。看看吧。

关于regex - 在 Excel Vba 中解析字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40832549/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com