Добрый день! Приложила файл в котором есть функция поиска в текстовой строке кода и циферного значения количества, выглядит это следующим образом: текст_код - количество шт в таком виде функция срабатывает, но если попадается такая схема: текст_код_текст - количество шт то функция не срабатывает помогите добавить в мою функцию еще одно условие, чтобы всё сработало
Добрый день! Приложила файл в котором есть функция поиска в текстовой строке кода и циферного значения количества, выглядит это следующим образом: текст_код - количество шт в таком виде функция срабатывает, но если попадается такая схема: текст_код_текст - количество шт то функция не срабатывает помогите добавить в мою функцию еще одно условие, чтобы всё сработалоhatter
Function ff$(ss$) If r Is Nothing Then Set r = CreateObject("vbscript.regexp"): r.Global = True: r.ignorecase = True: r.MultiLine = True r.Pattern = "арт\.(?::((?:\s*[\w/]*\s*-\s*\d+\s*(?:шт\.,)?)+)|([^\s]*).*?-(\d+)\s?шт\.)" End If Set m = r.Execute(Trim(ss) & "шт."): ff = "" For i = 0 To m.Count - 1 If Len(m(i).submatches(0)) Then x = Split(m(i).submatches(0), ",") For j = 0 To UBound(x) ff = ff & ", " & Trim(Split(x(j), "-")(0)) & " - " & Val(Trim(Split(x(j), "-")(1))) Next j Else ff = ff & ", " & m(i).submatches(1) & " - " & m(i).submatches(2) End If Next If Len(ff) Then ff = Mid(ff, 3) End Function
[/vba] не возьмусь утверждать, что нельзя использовать более простую регулярку. но приходится учитывать случаи, когда исходная строка последовательностью артикулов не заканчивается, отдельно стоящие артикулы и, иногда, отсутствие "шт."
ну, пусть будет так [vba]
Код
Dim r As Object, m As Object
Function ff$(ss$) If r Is Nothing Then Set r = CreateObject("vbscript.regexp"): r.Global = True: r.ignorecase = True: r.MultiLine = True r.Pattern = "арт\.(?::((?:\s*[\w/]*\s*-\s*\d+\s*(?:шт\.,)?)+)|([^\s]*).*?-(\d+)\s?шт\.)" End If Set m = r.Execute(Trim(ss) & "шт."): ff = "" For i = 0 To m.Count - 1 If Len(m(i).submatches(0)) Then x = Split(m(i).submatches(0), ",") For j = 0 To UBound(x) ff = ff & ", " & Trim(Split(x(j), "-")(0)) & " - " & Val(Trim(Split(x(j), "-")(1))) Next j Else ff = ff & ", " & m(i).submatches(1) & " - " & m(i).submatches(2) End If Next If Len(ff) Then ff = Mid(ff, 3) End Function
[/vba] не возьмусь утверждать, что нельзя использовать более простую регулярку. но приходится учитывать случаи, когда исходная строка последовательностью артикулов не заканчивается, отдельно стоящие артикулы и, иногда, отсутствие "шт."ikki
чччёрт!!! не сходил по ссылке до этого - поверил на слово. hatter, если бы я раньше увидел, что на последний ответ в теме Вам реагировать влом - ничего не стал бы делать, чессло! ну а сейчас... пусть остаётся.
чччёрт!!! не сходил по ссылке до этого - поверил на слово. hatter, если бы я раньше увидел, что на последний ответ в теме Вам реагировать влом - ничего не стал бы делать, чессло! ну а сейчас... пусть остаётся.ikki
помощь по Excel и VBA ikki@fxmail.ru, icq 592842413, skype alex.ikki
Ага... Зато я для себя подумал - и настрадал похожую штучку (и код ikki не видел же до этого )
Там зато хорошо видно, где, что и как (и почему рекурсия, и почему именно Split... и, наверное, ТС найдет, где именно надо заменить ; и = на другие знаки).
Внутри последовательности артикулов это приводит сразу к неоднозначности, а вот если не хватает "конечного" "шт" - кто запрещает дописать эту гадость сразу в конец параметра (в начале функции F())? - ведь "лишнее" под шаблон всё равно не попадёт...
[vba]
Код
Dim rNew As Object, mNew As Object
Const gcPattern = "([a-z]*\d+)(.*)(-{1}\s*)(\d+)"
Function fNew$(s$) s = s & "шт." p2 = InStrRev(s, "шт.") If p2 > 0 Then p1 = InStrRev(s, " арт.", p2) Else p1 = 0 If p1 = 0 Then fNew = "" Else If rNew Is Nothing Then Set rNew = CreateObject("vbscript.regexp") With rNew .Global = False: .IgnoreCase = True: .MultiLine = False: .Pattern = gcPattern End With End If cLeft = fNew(Left(s, p1)) fNew = IIf(Len(cLeft) = 0, "", cLeft & " ; ") & fParse(Mid(s, p1 + 5, p2 + 3 - p1 - 5)) End If End Function
Function fParse$(s$) fParse = "" a = Split(s, "шт.") For i = 0 To UBound(a) - 1 Set mNew = rNew.Execute(a(i)) If mNew.Count Then fParse = fParse & ", " & mNew.Item(0).Submatches.Item(0) & "=" & mNew.Item(0).Submatches.Item(3) End If Next fParse = Mid(fParse, 3) End Function
[/vba]
Ага... Зато я для себя подумал - и настрадал похожую штучку (и код ikki не видел же до этого )
Там зато хорошо видно, где, что и как (и почему рекурсия, и почему именно Split... и, наверное, ТС найдет, где именно надо заменить ; и = на другие знаки).
Внутри последовательности артикулов это приводит сразу к неоднозначности, а вот если не хватает "конечного" "шт" - кто запрещает дописать эту гадость сразу в конец параметра (в начале функции F())? - ведь "лишнее" под шаблон всё равно не попадёт...
[vba]
Код
Dim rNew As Object, mNew As Object
Const gcPattern = "([a-z]*\d+)(.*)(-{1}\s*)(\d+)"
Function fNew$(s$) s = s & "шт." p2 = InStrRev(s, "шт.") If p2 > 0 Then p1 = InStrRev(s, " арт.", p2) Else p1 = 0 If p1 = 0 Then fNew = "" Else If rNew Is Nothing Then Set rNew = CreateObject("vbscript.regexp") With rNew .Global = False: .IgnoreCase = True: .MultiLine = False: .Pattern = gcPattern End With End If cLeft = fNew(Left(s, p1)) fNew = IIf(Len(cLeft) = 0, "", cLeft & " ; ") & fParse(Mid(s, p1 + 5, p2 + 3 - p1 - 5)) End If End Function
Function fParse$(s$) fParse = "" a = Split(s, "шт.") For i = 0 To UBound(a) - 1 Set mNew = rNew.Execute(a(i)) If mNew.Count Then fParse = fParse & ", " & mNew.Item(0).Submatches.Item(0) & "=" & mNew.Item(0).Submatches.Item(3) End If Next fParse = Mid(fParse, 3) End Function
Это пять! Плюс в репу тому, кто реально сможет "вкратце" обьяснить :)
А зачем умничать оффтопами? "вкратце" - это значит достаточно дать определение знакам в шаблоне: ?::, \s,\d , в интернете сложно найти подобную информацию.
Это пять! Плюс в репу тому, кто реально сможет "вкратце" обьяснить :)
А зачем умничать оффтопами? "вкратце" - это значит достаточно дать определение знакам в шаблоне: ?::, \s,\d , в интернете сложно найти подобную информацию.hatter
И смотрим на некий источник: http://www.script-coding.com/WSH/RegExp.html Иначе, что даст одно только "знание регулярок", без знания объектной модели и конкретного систаксиса конкретной реализации?..
И смотрим на некий источник: http://www.script-coding.com/WSH/RegExp.html Иначе, что даст одно только "знание регулярок", без знания объектной модели и конкретного систаксиса конкретной реализации?..AndreTM
Skype: andre.tm.007 Donate: Qiwi: 9517375010
Сообщение отредактировал AndreTM - Среда, 10.09.2014, 14:42
конечно, "в идеале", наверное, так оно и должно быть - получил на форуме помощь в виде решения плюс к этому подробное объяснение (на нужном тебе уровне) этого решения. так что, если у кого-то так получается - это, конечно, замечательно. велкам. но беда в том, что не каждый хороший специалист одновременно с этим является хорошим "объясняльщиком". я - не являюсь вдобавок, соглашусь с Сергеем:
Плюс в репу тому, кто реально сможет "вкратце" объяснить
"вкратце" - можно, если собеседник достаточно подготовлен и шаблон в целом ему более-менее понятен, но отдельные фрагменты вызывают вопросы. иначе - "вкратце" не будет ниразу. я не возьмусь.
здесь два элемента: так называемая "группировка без обратной связи" (?:шаблон) и собственно символ двоеточия, с которого должен начинаться шаблон внутри этой самой группировки.
пс. по регуляркам в русской википедии вполне неплохая статья - без зауми, но всё основное есть. один нюанс - диалект регулярок в VBA поддерживает не все из этих возможностей. но про интересующие Вас \s и \d там есть. в разделе 3.1.3 Символьные классы.
конечно, "в идеале", наверное, так оно и должно быть - получил на форуме помощь в виде решения плюс к этому подробное объяснение (на нужном тебе уровне) этого решения. так что, если у кого-то так получается - это, конечно, замечательно. велкам. но беда в том, что не каждый хороший специалист одновременно с этим является хорошим "объясняльщиком". я - не являюсь вдобавок, соглашусь с Сергеем:
Плюс в репу тому, кто реально сможет "вкратце" объяснить
"вкратце" - можно, если собеседник достаточно подготовлен и шаблон в целом ему более-менее понятен, но отдельные фрагменты вызывают вопросы. иначе - "вкратце" не будет ниразу. я не возьмусь.
здесь два элемента: так называемая "группировка без обратной связи" (?:шаблон) и собственно символ двоеточия, с которого должен начинаться шаблон внутри этой самой группировки.
пс. по регуляркам в русской википедии вполне неплохая статья - без зауми, но всё основное есть. один нюанс - диалект регулярок в VBA поддерживает не все из этих возможностей. но про интересующие Вас \s и \d там есть. в разделе 3.1.3 Символьные классы.ikki
помощь по Excel и VBA ikki@fxmail.ru, icq 592842413, skype alex.ikki
Сообщение отредактировал ikki - Среда, 10.09.2014, 21:17
здесь два элемента: так называемая "группировка без обратной связи" (?:шаблон) и собственно символ двоеточия, с которого должен начинаться шаблон внутри этой самой группировки.
пс. по регуляркам в русской википедии вполне неплохая статья - без зауми, но всё основное есть. один нюанс - диалект регулярок в VBA поддерживает не все из этих возможностей. но про интересующие Вас \s и \d там есть. в разделе 3.1.3 Символьные классы.
Спасибо, такой ответ меня устроил очень даже - теперь я хоть знаю, что это регулярные выражения
Что и зачем я делаю я решаю сам и отчитываться никому не обязан. Захотел запостить оффтоп - запостил.
ваши решения если они бесполезны, никакой функции, кроме как засорения форума не имеют, тем более в свете попытки высмеять не умеющего, но имеющего желание разобраться в теме, человека......но за ссылку и вам отдельное спасибо - так бы и сразу.
здесь два элемента: так называемая "группировка без обратной связи" (?:шаблон) и собственно символ двоеточия, с которого должен начинаться шаблон внутри этой самой группировки.
пс. по регуляркам в русской википедии вполне неплохая статья - без зауми, но всё основное есть. один нюанс - диалект регулярок в VBA поддерживает не все из этих возможностей. но про интересующие Вас \s и \d там есть. в разделе 3.1.3 Символьные классы.
Спасибо, такой ответ меня устроил очень даже - теперь я хоть знаю, что это регулярные выражения
Что и зачем я делаю я решаю сам и отчитываться никому не обязан. Захотел запостить оффтоп - запостил.
ваши решения если они бесполезны, никакой функции, кроме как засорения форума не имеют, тем более в свете попытки высмеять не умеющего, но имеющего желание разобраться в теме, человека......но за ссылку и вам отдельное спасибо - так бы и сразу.hatter
"арт\.(?::((?:\s*[\w/]*\s*-\s*\d+\s*(?:шт\.,)?)+)|([^\s]*).*?-(\d+)\s?шт\.)" первые четыре символа - постоянные "арт\." точка "экранирована" символом \, т.к. нас интересует именно точка, а в регулярках неэкранированная точка - метасимвол, означающий "любой символ" далее - группировка без обратной связи (гбос) (т.е. (?:шаблон)) т.е. то, что внутри этой группы, должно следовать сразу за текстом "арт." "без обратной" - потому что целиком нам это запоминать для дальнейшего использования не надо. внутри шаблона - две альтернативы, разделенные символом | (имеющим спец.значение) :((?:\s*[\w/]*\s*-\s*\d+\s*(?:шт\.,)?)+)|([^\s]*).*?-(\d+)\s?шт\. первая альтернатива: :((?:\s*[\w/]*\s*-\s*\d+\s*(?:шт\.,)?)+) : - собственно символ двоеточия, т.е. первая альтернатива обязательно должна начинаться с этого символа далее - "запоминающая" группировка (шаблон) запоминающая - это потому что нам это значение надо получить и использовать дальше. т.к. это первые по порядку запоминающие скобки, то всё, что в них попадёт, будет в первом сабматче (с индексом 0) если ничего не попадёт (т.е. сработает вторая альтернатива или вообще ни одна) - сабматч будет содержать пустую строку после двоеточия - еще одна гбос(?:\s*[\w/]*\s*-\s*\d+\s*(?:шт\.,)?)+ символ + после группировки означает, что мы ищем то, что находится внутри гбос, один или более раз т.е. символ + играет здесь роль квантификатора, аналогичный *, но немножко другой итак, какие же повторения мы ищем? вот эти: \s*[\w/]*\s*-\s*\d+\s*(?:шт\.,)? \s* означает "любой "пробельный" символ (\s) любое количество раз (в т.ч. - ни одного такого символа) - за это отвечает * * - это тоже квантификатор, аналогичный +, но немножко другой. затем идёт символьный класс [\w/], означающий любой символ внутри этого класса в данном случае для задания нужных нам символов используется метасимвол \w (любая буква, цифра или знак подчёркивания) и, вдобавок к нему, символ / после символьного класса идёт уже знакомый нам квантификатор * кстати, здесь более логично было бы использовать квантификатор + (почему - это Д.З.) под этот шаблон [\w/]* попадут строки "abc12", "ab_535", "123", "_", "123/d5" но не "abc-12", "ab+535", "123#" дальше проще \s* - уже встречалось - - здесь собственно знак дефиса \s* - опять \d+ - любые цифры в количестве от одной штуки \s* - опять (?:шт\.,)? - необязательная (за это отвечает квантификатор ?) подстрока "шт.," точка здесь опять экранирована
т.образом, шаблон \s*[\w/]*\s*-\s*\d+\s*(?:шт\.,)? подойдёт под такие строки, как " abc123 - 15шт.,"; "abc123 -5"; "12/ab_-0шт.,"; "123/45-100шт.," и т.п. но не для " abc$ - 15шт.,"; "abc123 -5шт."; "12/ab_-10,"
ну и вспоминаем про квантификатор +: (?:\s*[\w/]*\s*-\s*\d+\s*(?:шт\.,)?)+ т.е. одна или более подходящих последовательностей подряд.
над заметить следующее: если вместо "шт.," в тексте будет для какого-нибудь артикула записано "шт." или "шт" или "шт," или ",", то эта часть под шаблон не попадёт. а дальше - всё зависит от того, для какого артикула в последовательности такое встретится. если для последнего - то "неподходящая" часть будет просто отброшена (благодаря квантификатору ? в (?:шт\.,)?) т.е. мы получим такой сабматч (выделен синим) "бла-бла-бла арт.:abc123 - 15шт.,abc123 -5 шт., 12/ab_-0шт.,123/45-100шт." а вот если в середине - то часть артикулов мы можем потерять: "бла-бла-бла арт.:abc123 - 15шт.,abc123 -5шт.; 12/ab_-0шт.,123/45-100шт."
если первая альтернатива не находится - регулярка переходит к проверке второй: ([^\s]*).*?-(\d+)\s?шт\. обратите внимание - вторая альтернатива, в отличие от первой, в принципе, не должна начинаться с символа : т.е. мы не требуем такого условия. но фактически - читай чуть ниже. здесь для обозначения артикула использован другой шаблон ([^\s]*) [^\s] - любой символ, кроме "пробельного" * - любое кол-во раз (...) - запоминающие скобки (второй сабматч) кстати, более логично было бы использовать всё же прежний шаблон - [\w/]* а ещё лучше - [\w/]+ почему я использовал [^\s]* - не спрашивайте (я не знаю кстати, вернёмся к символу : в начале второй альтернативы. "благодаря" слишком общему шаблону [^\s]*, он вполне себе может быть. просто в этом случае артикул будет начинаться именно с этого символа. так что лучше всё-таки [^\s]* заменить на [\w/]+
итак, запомнили артикул, потом по условиям задачи может быть "любой текст", потом дефис, число, обозначение "шт." .*?-(\d+)\s?шт\. здесь: .* - это как раз "любой текст" (более строго - любая, в т.ч. нулевой длины последовательность любых символов) ? - здесь у этого символа другая роль - он обозначает не квантификатор (который у нас уже есть - *), а "ограничитель жадности" (тоже Д.З.). - - собственно символ "-" (\d+) - одна или более цифр в третьих по счёту запоминающих скобках. \s? - один (или ни одного) "пробельный" символ шт\. - подстрока "шт." нюансы: как видим, пробел(ы) перед дефисом не заданы явно, но они могут быть и войдут в шаблон .*? а вот после дефиса пробел не задан (значит, недопустим) "шт." обязательно должно присутствовать и обязательно в таком виде (хотя после точки может идти что угодно)
фух... ну вроде всё... это если коротенько. :D
всё же попробуем коротенько пробежаться...
"арт\.(?::((?:\s*[\w/]*\s*-\s*\d+\s*(?:шт\.,)?)+)|([^\s]*).*?-(\d+)\s?шт\.)" первые четыре символа - постоянные "арт\." точка "экранирована" символом \, т.к. нас интересует именно точка, а в регулярках неэкранированная точка - метасимвол, означающий "любой символ" далее - группировка без обратной связи (гбос) (т.е. (?:шаблон)) т.е. то, что внутри этой группы, должно следовать сразу за текстом "арт." "без обратной" - потому что целиком нам это запоминать для дальнейшего использования не надо. внутри шаблона - две альтернативы, разделенные символом | (имеющим спец.значение) :((?:\s*[\w/]*\s*-\s*\d+\s*(?:шт\.,)?)+)|([^\s]*).*?-(\d+)\s?шт\. первая альтернатива: :((?:\s*[\w/]*\s*-\s*\d+\s*(?:шт\.,)?)+) : - собственно символ двоеточия, т.е. первая альтернатива обязательно должна начинаться с этого символа далее - "запоминающая" группировка (шаблон) запоминающая - это потому что нам это значение надо получить и использовать дальше. т.к. это первые по порядку запоминающие скобки, то всё, что в них попадёт, будет в первом сабматче (с индексом 0) если ничего не попадёт (т.е. сработает вторая альтернатива или вообще ни одна) - сабматч будет содержать пустую строку после двоеточия - еще одна гбос(?:\s*[\w/]*\s*-\s*\d+\s*(?:шт\.,)?)+ символ + после группировки означает, что мы ищем то, что находится внутри гбос, один или более раз т.е. символ + играет здесь роль квантификатора, аналогичный *, но немножко другой итак, какие же повторения мы ищем? вот эти: \s*[\w/]*\s*-\s*\d+\s*(?:шт\.,)? \s* означает "любой "пробельный" символ (\s) любое количество раз (в т.ч. - ни одного такого символа) - за это отвечает * * - это тоже квантификатор, аналогичный +, но немножко другой. затем идёт символьный класс [\w/], означающий любой символ внутри этого класса в данном случае для задания нужных нам символов используется метасимвол \w (любая буква, цифра или знак подчёркивания) и, вдобавок к нему, символ / после символьного класса идёт уже знакомый нам квантификатор * кстати, здесь более логично было бы использовать квантификатор + (почему - это Д.З.) под этот шаблон [\w/]* попадут строки "abc12", "ab_535", "123", "_", "123/d5" но не "abc-12", "ab+535", "123#" дальше проще \s* - уже встречалось - - здесь собственно знак дефиса \s* - опять \d+ - любые цифры в количестве от одной штуки \s* - опять (?:шт\.,)? - необязательная (за это отвечает квантификатор ?) подстрока "шт.," точка здесь опять экранирована
т.образом, шаблон \s*[\w/]*\s*-\s*\d+\s*(?:шт\.,)? подойдёт под такие строки, как " abc123 - 15шт.,"; "abc123 -5"; "12/ab_-0шт.,"; "123/45-100шт.," и т.п. но не для " abc$ - 15шт.,"; "abc123 -5шт."; "12/ab_-10,"
ну и вспоминаем про квантификатор +: (?:\s*[\w/]*\s*-\s*\d+\s*(?:шт\.,)?)+ т.е. одна или более подходящих последовательностей подряд.
над заметить следующее: если вместо "шт.," в тексте будет для какого-нибудь артикула записано "шт." или "шт" или "шт," или ",", то эта часть под шаблон не попадёт. а дальше - всё зависит от того, для какого артикула в последовательности такое встретится. если для последнего - то "неподходящая" часть будет просто отброшена (благодаря квантификатору ? в (?:шт\.,)?) т.е. мы получим такой сабматч (выделен синим) "бла-бла-бла арт.:abc123 - 15шт.,abc123 -5 шт., 12/ab_-0шт.,123/45-100шт." а вот если в середине - то часть артикулов мы можем потерять: "бла-бла-бла арт.:abc123 - 15шт.,abc123 -5шт.; 12/ab_-0шт.,123/45-100шт."
если первая альтернатива не находится - регулярка переходит к проверке второй: ([^\s]*).*?-(\d+)\s?шт\. обратите внимание - вторая альтернатива, в отличие от первой, в принципе, не должна начинаться с символа : т.е. мы не требуем такого условия. но фактически - читай чуть ниже. здесь для обозначения артикула использован другой шаблон ([^\s]*) [^\s] - любой символ, кроме "пробельного" * - любое кол-во раз (...) - запоминающие скобки (второй сабматч) кстати, более логично было бы использовать всё же прежний шаблон - [\w/]* а ещё лучше - [\w/]+ почему я использовал [^\s]* - не спрашивайте (я не знаю кстати, вернёмся к символу : в начале второй альтернативы. "благодаря" слишком общему шаблону [^\s]*, он вполне себе может быть. просто в этом случае артикул будет начинаться именно с этого символа. так что лучше всё-таки [^\s]* заменить на [\w/]+
итак, запомнили артикул, потом по условиям задачи может быть "любой текст", потом дефис, число, обозначение "шт." .*?-(\d+)\s?шт\. здесь: .* - это как раз "любой текст" (более строго - любая, в т.ч. нулевой длины последовательность любых символов) ? - здесь у этого символа другая роль - он обозначает не квантификатор (который у нас уже есть - *), а "ограничитель жадности" (тоже Д.З.). - - собственно символ "-" (\d+) - одна или более цифр в третьих по счёту запоминающих скобках. \s? - один (или ни одного) "пробельный" символ шт\. - подстрока "шт." нюансы: как видим, пробел(ы) перед дефисом не заданы явно, но они могут быть и войдут в шаблон .*? а вот после дефиса пробел не задан (значит, недопустим) "шт." обязательно должно присутствовать и обязательно в таком виде (хотя после точки может идти что угодно)