Парсинг строк vba excel

This article will demonstrate how to parse a string in VBA.

Often we will use Excel to import data from other files. Occasionally this data might be in a format that is not very user friendly, or that we need to amend to bring the information into Excel in a logical way. There are a number of string functions we can use in Excel VBA to extract the data correctly from the string that is brought in.

VBA Split Function

If the string comes into Excel as a delimited string (ie separated by commas, semi-colons, etc.), we can easily split the string into the individual values by using the Split function.

For example, say we have this string of names:

“John, Mary, Jack, Fred, Melanie, Steven, Paul, Robert”

Using the split function, we can return these names to Excel individually:

Sub SplitText()
 Dim strT As String
 Dim strArray() As String
 Dim name As Variant

'populate the string with names
 strT = "John,Mary,Jack,Fred,Melanie,Steven,Paul,Robert"

'populate the array and indicate the delmiter
 strArray = Split(strT, ",")

'loop through each name and display in immediate window
 For Each name In strArray
   Debug.Print name
 Next
End Sub

VBASplit Example

VBA Left, Right and Mid Functions

We can also extract data from strings by using the Left, Right and Mid functions.  They are not as efficient as using the Split function to get multiple values from a string, but if you need to separate a line into specific areas, they can be useful.

For example, say our file name is “C:DataTestFile.xls” .  Now this includes the drive, the folder on the drive, the name of the file and the file extension.

To get the drive that the file is stored on we can use:

LEFT(“C:DataTestFile.xls”, 1) – which will return C.

To get the Path including the drive we can use:

LEFT(“C:DataTestFile.xls”, 7) – which will return C:Data.

To get the name of the file only, we can use MID:

MID(“C:DataTestFile.xls”, 9,8) – which will return TestFile

To get the extension of the file we can use:

RIGHT(“C:DataTestFile.xls”, 3)

Sub ExtractData()
 Dim strData As String
 Dim strLeft As String
 Dim strRight As String
 Dim strMid As String

'populate the string
 strData = "C:DataTestFile.xls"

'break down the name
 strLeft = Left(strData, 7)
 strMid = Mid(strData, 9, 8)
 strRight = Right(strData, 3)

'return the results
 MsgBox "The path is " & strLeft & ", the File name is " & strMid & " and the extension is " & strRight
End Sub

The result of which would be:

VBASplit Left

VBA Replace Function

Another useful string function to manipulate strings in Excel, is the Replace function. This can be used to remove anything from a string and replace it with something else. This is particularly useful if the string that you have brought into Excel has characters that your coding will not recognize, or will mess up your data.

For example:

Consider the following string:

“John””Mary””Jack””Fred””Melanie””Steven””Paul””Robert”””

We can replace the double-quotes with commas using the Replace function.

Sub ExtractData()
  Dim StrData As String
  StrData = "John""Mary""Jack""Fred""Melanie""Steven""Paul""Robert"""
  StrData = Replace(StrData, """", ",")
  MsgBox StrData
End Sub

VBASplit Replace

VBA Coding Made Easy

Stop searching for VBA code online. Learn more about AutoMacro — A VBA Code Builder that allows beginners to code procedures from scratch with minimal coding knowledge and with many time-saving features for all users!
vba save as

Learn More!

I have a macro that send an XMLHTTP request to a server and it gets as response a plain text string, not a JSON format string or other standard formats (at least for what I know).

I would like to parse the output string in order to access the data in an structured approach in the same fashion as the parseJson subroutine in this link

My problem is I am not good with regular expressions and I am not able to modify the routine for my needs.

The string that I need to parse has the following structure:

  1. The string is a single line
  2. Each single parameter is defined by its parameter name the equal simbol, its value and ending with; «NID=3;» or «SID=Test;»
  3. Parameter can be collected in «structures» starts and end with the symbol | and they are identified with their name followed by ; such as |STEST;NID=3;SID=Test;|
  4. A structure can contain also other structures

An example of a output string is the following

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

In this case there is a macro structure KC which contains a structure AD. The structure AD is composed by the parameters PE, PF and 2 structures CD. And finaly the structures CD have the parameters PE and HP

So I would like to parse the string to obtain an Object/Dictionary that reflects this structure, can you help me?

Adds after the first answers

Hi all, thank you for your help, but I think I should make more clear the output that I would like to get.
For the example string that I have, I would like to have an object with the following structure:

<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>

So I started to wrote a possible working code base on some hint from @Nvj answer and the answer in this 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

This function creates a dictionary with an item for each structure name, parameter name and parameter value as shown in the figure
enter image description here
Thanks to the function get_Level the items associated to structures have a level that should help to preserve the original hierarchy of the data.

So what I am missing is a function to create an object that has the original structure of the input string. This is what the Retrieve function do in this answer link, but I do not know how to adapt it to my case

Если использовать тип Long, то файл ограничится размером в 2Гб, думаю тогда можно сделать тип Single. Встречал в интернете, что некоторым нужно было обрабатывать большие файлы, размером в 10Гб.

Размер буфера я пробовал менять от 100Кб до 10Мб, особой разницы я не заметил, зато при 10Мб требуется мегабайт 20 оперативки дополнительно. Величина в 512Кб вполне подходит и по скорости и по объему оперативки.

scripting.fso не использовал, т.к. посчитал что данный способ простой и вполне понятный, мне кажется это на скорость не повлияет, т.к. операций чтения файла происходит немного, и при этом эта библиотека все равно не имеет операторов, чтобы читать файл задом наперед построчно.

Обработку ошибок при открытии файла не писал, т.к. сроки поджимали, важно было сделать сам алгоритм

Модуль и вправду большой получился. Оформлять в виде класса идея хорошая, может и сделаю, пока не до этого.
Всем спасибо. Может кому пригодится.

Парсинг текстовой строки (обрезка строки)

Murdoc

Дата: Пятница, 07.03.2014, 12:01 |
Сообщение № 1

Группа: Пользователи

Ранг: Прохожий

Сообщений: 2


Репутация:

0

±

Замечаний:
0% ±


Excel 2010

Доброй всем пятницы. К сожалению поиск не дал конкретных результатов или похожих примеров. Помогите пожалуйста разобраться с написанием макроса для обработки текстовой строки и вычленению из нее необходимой информации.

Строка может быть двух видов:
[текст1][ABCD_**][текст2][текст3]текст4
или [текст1][**-ABCD_**][текст2][текст3]текст4

ABCD — то что нужно вычленить из строки, количество символов неизвестно

В теории достаточно будет сначала обрезать все слева до первого вхождения символа «_«, а потом пройтись по полученому куску уже справа на лево до первого вхождения символа «[» или же символа ««. Это в теории, как реализовать это на практике пока даже не знаю в какую сторону копать. Буду рад любой помощи.

Заранее спасибо.

 

Ответить

Hugo

Дата: Пятница, 07.03.2014, 14:00 |
Сообщение № 2

Группа: Друзья

Ранг: Участник клуба

Сообщений: 3140


Репутация:

670

±

Замечаний:
0% ±


2010, теперь уже с PQ

[vba]

Код

Sub tt()
     Dim s$, rez$, arr
     s = «[текст1][ABCD_**][текст2][текст3]текст4»
     ‘s = «[текст1][**-ABCD_**][текст2][текст3]текст4»
     rez = Split(s, «_»)(0)
     rez = Replace(rez, «-«, «[«)
     arr = Split(rez, «[«)
     rez = arr(UBound(arr))
     MsgBox rez
End Sub

[/vba]


excel@nxt.ru
webmoney: R418926282008 Z422237915069

 

Ответить

ikki

Дата: Пятница, 07.03.2014, 15:04 |
Сообщение № 3

Группа: Друзья

Ранг: Старожил

Сообщений: 1906


Репутация:

504

±

Замечаний:
0% ±


Excel 2003, 2010

[vba]

Код

Sub tt()
     s = «[текст1][ABCD_**][текст2][текст3]текст4»
     ‘s = «[текст1][**-ABCD_**][текст2][текст3]текст4»
     With CreateObject(«vbscript.regexp»)
         .Pattern = «[-[]([^-[]*?)_»
         MsgBox .Execute(s)(0).submatches(0)
     End With
End Sub

[/vba]


помощь по Excel и VBA
ikki@fxmail.ru, icq 592842413, skype alex.ikki

 

Ответить

ikki

Дата: Пятница, 07.03.2014, 15:29 |
Сообщение № 4

Группа: Друзья

Ранг: Старожил

Сообщений: 1906


Репутация:

504

±

Замечаний:
0% ±


Excel 2003, 2010

или даже ещё проще
[vba]

Код

Sub tt()
     s = «[текст1][ABCD_**][текст2][текст3]текст4»
     ‘s = «[текст1][**-ABCD_**][текст2][текст3]текст4»
     With CreateObject(«vbscript.regexp»)
         .Pattern = «[^-[]*?(?=_)»
         MsgBox .Execute(s)(0)
     End With
End Sub

[/vba]


помощь по Excel и VBA
ikki@fxmail.ru, icq 592842413, skype alex.ikki

 

Ответить

Murdoc

Дата: Пятница, 07.03.2014, 17:15 |
Сообщение № 5

Группа: Пользователи

Ранг: Прохожий

Сообщений: 2


Репутация:

0

±

Замечаний:
0% ±


Excel 2010

Всем огромное спасибо за помощь, использовал вариант предложенный Hugo. Все работает как было необходимо. Тему можно закрывать

 

Ответить

RAN

Дата: Пятница, 07.03.2014, 20:50 |
Сообщение № 6

Группа: Друзья

Ранг: Экселист

Сообщений: 5645

Ну, хоть на форуме The_Prist отписался, что тутошние решения ему больше ндравятся.


Быть или не быть, вот в чем загвоздка!

 

Ответить

ikki

Дата: Пятница, 07.03.2014, 21:54 |
Сообщение № 7

Группа: Друзья

Ранг: Старожил

Сообщений: 1906


Репутация:

504

±

Замечаний:
0% ±


Excel 2003, 2010

а где эта историческая отписка?


помощь по Excel и VBA
ikki@fxmail.ru, icq 592842413, skype alex.ikki

 

Ответить

RAN

Дата: Пятница, 07.03.2014, 22:30 |
Сообщение № 8

Группа: Друзья

Ранг: Экселист

Сообщений: 5645


Быть или не быть, вот в чем загвоздка!

 

Ответить

ikki

Дата: Пятница, 07.03.2014, 22:34 |
Сообщение № 9

Группа: Друзья

Ранг: Старожил

Сообщений: 1906


Репутация:

504

±

Замечаний:
0% ±


Excel 2003, 2010

не нашёл ничего подобного.

upd. всё, понял. ступил поначалу.
думал — сам The_Prist сказал нечто подобное :D
понять-то можно было именно так.


помощь по Excel и VBA
ikki@fxmail.ru, icq 592842413, skype alex.ikki

Сообщение отредактировал ikkiПятница, 07.03.2014, 22:36

 

Ответить

RAN

Дата: Пятница, 07.03.2014, 22:39 |
Сообщение № 10

Группа: Друзья

Ранг: Экселист

Сообщений: 5645

Звиняйте! :D

PS Саш, ссылка только для тебя. :)

PPS Для Администрации — ссылка по просьбе зрителей. :p


Быть или не быть, вот в чем загвоздка!

Сообщение отредактировал RANПятница, 07.03.2014, 22:45

 

Ответить

Пользовательские функции VBA Excel для парсинга сайтов, html-страниц и файлов, возвращающие их текстовое содержимое. Примеры записи текста в переменную.

Парсинг html-страниц (msxml2.xmlhttp)

Пользовательская функция GetHTML1 (VBA Excel) для извлечения (парсинга) текстового содержимого из html-страницы сайта по ее URL-адресу с помощью объекта «msxml2.xmlhttp»:

Function GetHTML1(ByVal myURL As String) As String

On Error Resume Next

    With CreateObject(«msxml2.xmlhttp»)

        .Open «GET», myURL, False

        .send

        Do: DoEvents: Loop Until .readyState = 4

        GetHTML1 = .responseText

    End With

End Function

Парсинг сайтов (WinHttp.WinHttpRequest.5.1)

Пользовательская функция GetHTML2 (VBA Excel) для извлечения (парсинга) текстового содержимого из html-страницы сайта по ее URL-адресу с помощью объекта «WinHttp.WinHttpRequest.5.1»:

Function GetHTML2(ByVal myURL As String) As String

On Error Resume Next

    With CreateObject(«WinHttp.WinHttpRequest.5.1»)

        .Open «GET», myURL, False

        .send

        Do: DoEvents: Loop Until .readyState = 4

        GetHTML2 = .responseText

    End With

End Function

Парсинг файлов (ADODB.Stream)

Пользовательская функция GetText (VBA Excel) для извлечения (парсинга) текстового содержимого из файла (.txt, .csv, .mhtml), сохраненного на диск компьютера, по его полному имени (адресу) с помощью объекта «ADODB.Stream»:

Function GetText(ByVal myFile As String) As String

On Error Resume Next

    With CreateObject(«ADODB.Stream»)

        .Charset = «utf-8»

        .Open

        .LoadFromFile myFile

        GetText = .ReadText

        .Close

    End With

End Function

Примеры записи текста в переменную

Общая формула записи текста, извлеченного с помощью пользовательских функций VBA Excel, в переменную:

Dim htmlText As String

htmlText = GetHTML1(«Адрес сайта (html-страницы)»)

htmlText = GetHTML2(«Адрес сайта (html-страницы)»)

htmlText = GetText(«Полное имя файла»)

Конкретные примеры:

htmlText = GetHTML1(«https://internettovary.ru/nabor-dlya-vyrashchivaniya-veshenki/»)

htmlText = GetHTML2(«https://internettovary.ru/nabor-dlya-vyrashchivaniya-veshenki/»)

htmlText = GetText(«C:UsersEvgeniyDownloadsНовый текстовый документ.txt»)

htmlText = GetText(«C:UsersEvgeniyDownloadsИспользование msxml2.xmlhttp в Excel VBA.mhtml»)

В понятие «парсинг», кроме извлечения текстового содержимого сайтов, html-страниц или файлов, входит поиск и извлечение конкретных данных из всего полученного текстового содержимого.

Пример извлечения email-адресов из текста, присвоенного переменной, смотрите в последнем параграфе статьи: Регулярные выражения (объекты, свойства, методы).

Парсинг содержимого тегов

Извлечение содержимого тегов с помощью метода getElementsByTagName объекта HTMLFile:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

Sub Primer1()

Dim myHtml As String, myFile As Object, myTag As Object, myTxt As String

    ‘Извлекаем содержимое html-страницы в переменную myHtml с помощью функции GetHTML1

    myHtml = GetHTML1(«https://internettovary.ru/sadovaya-nozhovka-sinitsa/»)

    ‘Создаем объект HTMLFile

    Set myFile = CreateObject(«HTMLFile»)

    ‘Записываем в myFile текст из myHtml

    myFile.body.innerHTML = myHtml

    ‘Присваиваем переменной myTag коллекцию одноименных тегов, имя которого

    ‘указанно в качестве аргумента метода getElementsByTagName

    Set myTag = myFile.getElementsByTagName(«p»)

    ‘Выбираем, содержимое какого тега по порядку, начинающегося с 0, нужно извлечь

    myTxt = myTag(5).innerText

    MsgBox myTxt

    ‘Большой текст может не уместиться в MsgBox, тогда для просмотра используйте окно Immediate

    ‘Debug.Print myTxt

End Sub

С помощью этого кода извлекается текст, расположенный между открывающим и закрывающим тегами. В примере — это текст 6-го абзаца (p) между 5-й (нумерация с 0) парой отрывающего <p> и закрывающего </p> тегов.

Примеры тегов, используемых в html: "p", "title", "h1", "h2", "table", "div", "script".

Пример извлечения содержимого тега "title":

Sub Primer2()

Dim myHtml As String, myFile As Object, myTag As Object, myTxt As String

    myHtml = GetHTML1(«https://internettovary.ru/sadovaya-nozhovka-sinitsa/»)

    Set myFile = CreateObject(«HTMLFile»)

    myFile.body.innerHTML = myHtml

    Set myTag = myFile.getElementsByTagName(«title»)

    myTxt = myTag(0).innerText

    MsgBox myTxt

End Sub

Парсинг содержимого Id

Извлечение текстового содержимого html-элементов, имеющих уникальный идентификатор — Id, с помощью метода getElementById объекта HTMLFile:

Sub Primer3()

Dim myHtml As String, myFile As Object, myTag As Object, myTxt As String

    myHtml = GetHTML1(«https://internettovary.ru/sadovaya-nozhovka-sinitsa/»)

    Set myFile = CreateObject(«HTMLFile»)

    myFile.body.innerHTML = myHtml

    ‘Присваиваем переменной myTag html-элемент по указанному в скобках Id

    Set myTag = myFile.getElementById(«attachment_465»)

    ‘Присваиваем переменной myTxt текстовое содержимое html-элемента с Id

    myTxt = myTag.innerText

    MsgBox myTxt

    ‘Большой текст может не уместиться в MsgBox, тогда для просмотра используйте окно Immediate

    ‘Debug.Print myTxt

End Sub

Для реализации представленных здесь примеров могут понадобиться дополнительные библиотеки. В настоящее время у меня подключены следующие (к данной теме могут относиться последние шесть):

  • Visual Basic For Applications
  • Microsoft Excel 16.0 Object Library
  • OLE Automation
  • Microsoft Office 16.0 Object Library
  • Microsoft Forms 2.0 Object Library
  • Ref Edit Control
  • Microsoft Scripting Runtime
  • Microsoft Word 16.0 Object Library
  • Microsoft Windows Common Controls 6.0 (SP6)
  • Microsoft ActiveX Data Objects 6.1 Library
  • Microsoft ActiveX Data Objects Recordset 6.0 Library
  • Microsoft HTML Object Library
  • Microsoft Internet Controls
  • Microsoft Shell Controls And Automation
  • Microsoft XML, v6.0

С этим набором библиотек все примеры работают. Тестирование проводилось в VBA Excel 2016.


Понравилась статья? Поделить с друзьями:
  • Парсинг сайта с помощью excel
  • Парсинг сайта в excel онлайн
  • Парсинг нетабличных данных с сайтов в excel
  • Парсинг на python вывод в excel
  • Парсинг котировок в excel