2

I have a text to scan like this:

   -- FIRST BLOCK
   Begin PRJFW_EDITM.TXT_EDITM TXT_CLIFOR 
      Height          =   300
      Left            =   2685
      DBField         =   "CG44_CLIFOR"
      Caption         =   "Codice cliente fornitore"
      Object.Tag             =   "Codice cliente fornitore"
      MaxWidth        =   8
   End

   -- SECOND BLOCK
   Begin PRJFW_EDITM.TXT_EDITM TXT_CLIFOR 
      Height          =   300
      Left            =   2685
      DBField         =   "CG44_CLIFOR"
      Caption         =   "Codice cliente fornitore"
      Object.Tag             =   "Codice cliente fornitore"
      MaxWidth        =   6
   End

   -- THIRD BLOCK
   Begin PRJFW_EDITM.TXT_EDITM TXT_CLIFOR 
      Height          =   300
      Left            =   2685
      DBField         =   "CG16_ANAG"
      Caption         =   "Codice cliente fornitore"
      Object.Tag             =   "Codice cliente fornitore"
      MaxWidth        =   6
   End

I want to match only blocks where (MaxWidth=6).

I'm doing some tests but something is wrong... for example using this RegEx expression:

(Begin[\s\S]+?(MaxWidth.*=)[\s\S]+?End)

I correctly match the tree blocks visible in my code above.

Then if I try to modify the regEx for matching only the blocks with the value '6' for 'MaxWidth' property:

(Begin[\s\S]+?(MaxWidth.*=   6)[\s\S]+?End)

I correctly match only two blocks but the first one is wrong. First match:

Begin PRJFW_EDITM.TXT_EDITM TXT_CLIFOR 
      Height          =   300
      Left            =   2685
      DBField         =   "CG44_CLIFOR"
      Caption         =   "Codice cliente fornitore"
      Object.Tag             =   "Codice cliente fornitore"
      MaxWidth        =   8
   End

   -- SECOND BLOCK
   Begin PRJFW_EDITM.TXT_EDITM TXT_CLIFOR 
      Height          =   300
      Left            =   2685
      DBField         =   "CG44_CLIFOR"
      Caption         =   "Codice cliente fornitore"
      Object.Tag             =   "Codice cliente fornitore"
      MaxWidth        =   6
   End

It starts with the first 'Begin' and terminate with the correct property value in the second block. That's wrong.

I want that the (MaxWidth=6) is matched inside each Begin...End block. Something like this (referring to my code above):

Fist match:

   Begin PRJFW_EDITM.TXT_EDITM TXT_CLIFOR 
      Height          =   300
      Left            =   2685
      DBField         =   "CG44_CLIFOR"
      Caption         =   "Codice cliente fornitore"
      Object.Tag             =   "Codice cliente fornitore"
      MaxWidth        =   6
   End

Second match:

   Begin PRJFW_EDITM.TXT_EDITM TXT_CLIFOR 
      Height          =   300
      Left            =   2685
      DBField         =   "CG16_ANAG"
      Caption         =   "Codice cliente fornitore"
      Object.Tag             =   "Codice cliente fornitore"
      MaxWidth        =   6
   End

How can I do that? What's wrong in my regEx?

Thank you.

epi82
  • 497
  • 2
  • 10
  • 21

2 Answers2

3

It's possible. Assuming the input file is available at c:\test.txt. Containing the input text.

The module

Option Explicit
'requires Microsoft Scripting Runtime
Public Sub test()
    Dim fields(5) As String
    fields(0) = vbNullChar
    fields(1) = vbNullChar
    fields(2) = """CG44_CLIFOR"""
    fields(3) = vbNullChar
    fields(4) = vbNullChar
    fields(5) = "6"


    Dim fpath$, x
    fpath = "c:\test.txt"
    x = Join(GetBlock(fpath, fields), vbCrLf & vbCrLf & vbCrLf)
    MsgBox x

End Sub

Public Function GetBlock(fpath$, textArr As Variant) As Variant
    Dim results As Variant
    Dim fso As New Scripting.FileSystemObject
    Dim re As New VBScript_RegExp_55.RegExp

    If UBound(textArr) <> 5 Then
        MsgBox "Invalid data provided!"
        Exit Function
    End If

    Dim fields(5) As String
    fields(0) = "Height += +"
    fields(1) = "Left += +"
    fields(2) = "DBField += +"
    fields(3) = "Caption += +"
    fields(4) = "Object\.Tag += +"
    fields(5) = "MaxWidth += +"

    Dim p&, validPos$

    p = 0
    For p = LBound(fields) To UBound(fields)
        If textArr(p) <> vbNullChar Then
            fields(p) = fields(p) & EscapeString(CStr(textArr(p)))
            validPos = validPos & CStr(p) & "|"
        End If
    Next p


    Dim content$, result As Boolean, outText$
    content = fso.OpenTextFile(fpath).ReadAll()
    outText = vbNullChar
    With re
        .Global = True
        .IgnoreCase = True
        .MultiLine = False
        .Pattern = "--[\s\S]+?(?=--)"
        If .test(content) = True Then
            Dim m, posz
            posz = Split(validPos, "|")
            result = True
            Dim mt As Match, mts As MatchCollection
            Set mts = .Execute(content)
            For Each mt In mts
                outText = mt.Value
                Dim po
                For Each po In posz
                    If po <> "" Then
                        m = fields(CStr(po))
                        .Pattern = m
                        result = .test(outText)
                    End If
                Next po
                For Each m In fields

                Next m
                If result = True Then
                    results = results & "<cylian/>" & outText
                End If
            Next mt
        Else
            result = False
        End If
    End With
    GetBlock = Split(results, "<cylian/>", -1, vbBinaryCompare)
End Function

Private Function EscapeString(str$) As String
    'some general replaces
    Dim a$
    a = str
    a = Replace(a, """", """""")
    a = Replace(a, ".", "\.")
    a = Replace(a, "}", "\}")
    a = Replace(a, "{", "\{")
    a = Replace(a, ")", "\)")
    a = Replace(a, "(", "\(")
    a = Replace(a, "+", "\+")
    a = Replace(a, "*", "\*")
    a = Replace(a, "-", "\-")
    a = Replace(a, "\", "\\")
    a = Replace(a, "^", "\^")
    a = Replace(a, "$", "\$")
    EscapeString = a
End Function

The calling (from immediate window)

test

The outcome

enter image description here

Hope this helps.

Cylian
  • 10,970
  • 4
  • 42
  • 55
  • Hello, I've edited my question and add more details... probably what I need is simplier than that you answered me... What's wrong in my regEx? – epi82 Sep 11 '12 at 08:48
1

Yes its possible. Use multiple line option for regex see this article for an example on how to use multiple lines.

VBscript is not able to recognize carriage return and line feed control characters. But it should recognize beginning of line and ending of line.

RetroCoder
  • 2,597
  • 10
  • 52
  • 81