如何在字符串中查找引用文本?

时间:2016-09-05 15:36:08

标签: excel string vba excel-vba double-quotes

实施例

说我有一个字符串:

"I say ""Hello world"" and she says ""Excuse me?"""

VBA会将此字符串解释为:

I say "Hello world" and she says "Excuse me?"

一个更复杂的例子:

我有一个字符串:

"I say ""Did you know that she said """"Hi there!"""""""

VBA将此字符串解释为:

I say "Did you know that she said ""Hi there!"""

如果我们删除“我说”

"Did you know that she said ""Hi there!"""

我们可以继续在vba中解析字符串:

Did you know that she said "Hi there!"

问题

最终我需要一些函数sBasicQuote(quotedStringHierarchy as string),它返回一个包含字符串层次结构中下一级别的字符串。

E.G。

dim s as string
s = "I say ""Did you know that she said """"Hi there!"""""""
s = sBasicQuote(s) ' returns 'I say "Did you know that she said ""Hi there!"""'
s = sBasicQuote(s) ' returns 'Did you know that she said "Hi there!"'
s = sBasicQuote(s) ' returns 'Hi there!'

我只是想不出一个可以解决这个问题的算法...你几乎需要替换所有的双引号,但是当你更换了第n个双引号时你必须跳到第n + 1个双引号?

如何在VBA中实现此功能?

3 个答案:

答案 0 :(得分:1)

你可以做这样的事情

---load-avg--- --io/total-----io/sda------io/md0-- ---procs--- ------memory-usage----- ---paging-- -dsk/total----dsk/sda-----dsk/md0-- ---system-- ----total-cpu-usage---- -net/total-
 1m   5m  15m | read  writ: read  writ: read  writ|run blk new| used  buff  cach  free|  in   out | read  writ: read  writ: read  writ| int   csw |usr sys idl wai hiq siq| recv  send
6.61 6.40 3.83| 292   186 :14.6  0.40 : 283   193 |4.2 1.5 1.6|12.0G 1548k 3685M  147M|   0     0 |  47M   84M: 255k 8192B:  46M   82M|  39k   59k| 22   5  50  22   0   0|  52B  123B
6.06 6.29 3.82| 289   165 :22.8  0.70 : 273   173 |4.2 2.9 1.5|11.9G 1420k 3610M  281M|   0     0 |  45M   75M: 146k 9830B:  45M   77M|  21k   39k| 16   4  58  23   0   0| 884B   68B
5.74 6.22 3.82| 278   172 :20.2  0.70 : 265   177 |3.3 2.5 3.9|11.9G 1124k 3709M  162M|   0     0 |  44M   80M: 294k 9011B:  44M   79M|  34k   51k| 19   4  52  25   0   0|  32B   83B
5.47 6.14 3.82| 351   178 :52.6  1.50 : 305   180 |6.0 2.1   0|11.9G 1092k 3701M  175M|   0     0 |  38M   79M: 669k   26k:  37M   78M|  27k   59k| 24   4  53  18   0   0|  51B   99B
5.09 6.04 3.82| 300   176 :25.4  0.40 : 282   190 |4.2 2.4   0|12.0G  656k 3655M  182M|   0     0 |  45M   80M: 228k 3686B:  45M   82M|  32k   60k| 21   5  55  19   0   0| 228B  103B
4.84 5.95 3.81| 294   172 :24.8  0.50 : 275   175 |3.1 2.4   0|12.0G  648k 3642M  173M|   0     0 |  45M   80M: 264k 8602B:  45M   79M|  38k   48k| 17   4  57  22   0   0|  32B   59B
5.27 6.01 3.85| 295   175 :25.3  1.20 : 276   184 |2.4 2.7 0.7|12.0G  532k 3636M  180M|   0     0 |  44M   80M: 235k   19k:  44M   81M|  33k   59k| 21   4  54  21   0   0|  46B  123B
5.32 5.99 3.87| 315   169 :23.7  0.40 : 301   175 |4.6 2.2 1.4|11.9G  536k 3742M  162M|   0     0 |  50M   76M: 506k 8192B:  49M   76M|  28k   44k| 20   4  52  24   0   0|  60B   99B

另一个略微修改的版本更准确

Public Sub test()

Dim s As String
s = "I say ""Did you know that she said """"Hi there!"""""""

Debug.Print DoubleQuote(s, 0)
Debug.Print DoubleQuote(s, 1)
Debug.Print DoubleQuote(s, 2)

End Sub

Public Function DoubleQuote(strInput As String, intElement As Integer) As String

Dim a() As String

strInput = Replace(strInput, String(2, Chr(34)), String(1, Chr(34)))

a = Split(strInput, chr(34))

DoubleQuote = a(intElement)


End Function

答案 1 :(得分:1)

我认为以下内容将在您的嵌套引用示例中返回您要查找的内容。你的第一个例子实际上不是嵌套引号的情况。

Option Explicit
Sub NestedQuotes()
    Const s As String = "I say ""Did you know that she said """"Hi there!"""""""
    Dim COL As Collection
    Dim Start As Long, Length As Long, sTemp As String, V As Variant

Set COL = New Collection
sTemp = s
COL.Add sTemp
Do Until InStr(sTemp, Chr(34)) = 0
    sTemp = COL(COL.Count)
    sTemp = Replace(sTemp, String(2, Chr(34)), String(1, Chr(34)))
        Start = InStr(sTemp, Chr(34)) + 1
        Length = InStrRev(sTemp, Chr(34)) - Start
    sTemp = Mid(sTemp, Start, Length)
    COL.Add sTemp
Loop

For Each V In COL
    Debug.Print V
Next V

End Sub

答案 2 :(得分:0)

我的解决方案

我花了更多时间思考并提出了这个解决方案。

Function sMineDoubleQuoteHierarchy(s As String) As String
    'Check the number of quotes in the string are even - sanity check
    If (Len(s) - Len(Replace(s, """", ""))) Mod 2 <> 0 Then sMineDoubleQuoteHierarchy = "Error - Odd number of quotes found in sMineDoubleQuoteHierarchy() function": Exit Function

    'First thing to do is find the first and last *single* quote in the string
    Dim lStart, lEnd, i As Long, fs As String
    lStart = InStr(1, s, """")
    lEnd = InStrRev(s, """")

    'After these have been found we need to remove them.
    s = Mid(s, lStart + 1, lEnd - lStart - 1)

    'Start at the first character
    i = 1

    Do While True
        'Find where the next double quote is
        i = InStr(1, s, """""")

        'if no double quote is found then concatenate with fs with the remainder of s
        If i = 0 Then Exit Do

        'Else add on the string up to the char before the ith quote
        fs = fs & Left(s, i - 1)

        'Replace the ith double quote with a single quote
        s = Left(s, i - 1) & Replace(s, """""", """", i, 1)

        'Increment by 1 (ensuring the recently converted double quote is no longer a single quote
        i = i + 1
    Loop

    'Return fs
    sMineDoubleQuoteHierarchy = s
End Function

此解决方案中发生了什么?

该过程的第一部分是从字符串中删除第一个和最后一个单引号并在它们之间返回文本。然后我们遍历字符串,替换""的每个实例并将其替换为"。我们每次执行此操作时都会跳到下一个字符,以确定""""之类的字符串不会转到""而不是"

还有其他人有更好/更紧凑的解决方案吗?

修改

在本论坛的所有建议之后,我解决了这个问题。它有一些额外的错误捕获来查找验证嵌套字符串。

Public Function DoubleQuoteExtract(ByVal s As String, Optional ByRef ErrorLevel As Boolean) As String
    'This effectively parses the string like BASIC does by removing incidents of "" and replacing them with "

    'SANITY CHECK - Check even number of quotes
    Dim countQuote As Double
    countQuote = Len(s) - Len(Replace(s, """", ""))

    'Calculate whether or not quote hierarchy is correct:
    '"..."          - Is okay           - Count Quotes = 2      - Count Quotes / 2 = 1
    '""...""        - Is not okay       - Count Quotes = 4      - Count Quotes / 2 = 2
    '"""..."""      - Is okay           - Count Quotes = 6      - Count Quotes / 2 = 3
    '""""...""""    - Is not okay       - Count Quotes = 8      - Count Quotes / 2 = 4
    'etc.
    'Ultimately: IF CountQuotes/2 = Odd The string hierarchy is setup fine
    '            IF CountQuotes/2 = Even, The string Hierarchy is setup incorrectly.

    Dim X As Double: X = countQuote / 2
    Dim ceil As Long: ceil = Int(X) - (X - Int(X) > 0)
    If ceil Mod 2 <> 0 Then sDoubleQuoteExtract = "#Error - Incorrect number of double quotes forming an incomplete hierarchy.": GoTo ErrorOccurred

    'If an odd number of quotes are found then they cannot be paired correctly, thus throw error
    If countQuote Mod 2 <> 0 Then sDoubleQuoteExtract = "#Error - Odd number of quotes found in sMineDoubleQuoteHierarchy() function": GoTo ErrorOccurred


    'Find the next incident of single quote. Trim the string to this
    s = Mid(s, InStr(1, s, String(1, Chr(34))))

    'replace all instances of "" with "
    s = Replace(s, String(2, Chr(34)), String(1, Chr(34)))

    'Finally trim off the first and last quotes
    DoubleQuoteExtract = Mid(s, 2, Len(s) - 2)
    ErrorLevel = False
    Exit Function
ErrorOccurred:
    ErrorLevel = True
End Function