Доброго времени суток. Вот наваял своим мизерным VBA опытом. Наверное, это все может быть значительно короче. Мне лично осталось усвоить, как таблицу умножения, метасимволы.
Function regex(strInput As String, strPattern As String, strWhat As String, strWith As String) As String Dim inputRegexObj As New VBScript_RegExp_55.RegExp Dim inputMatches As Object Dim replaceNumber As Integer Dim i As Integer Dim substr As String
With inputRegexObj .Global = True .MultiLine = True .IgnoreCase = False .Pattern = strPattern End With
Set inputMatches = inputRegexObj.Execute(strInput)
If inputMatches.Count = 0 Then
regex = strInput
Else
replaceNumber = inputMatches.Count
For i = 0 To replaceNumber - 1
With inputRegexObj .Global = False .MultiLine = True .IgnoreCase = False .Pattern = strPattern End With
Set inputMatches = inputRegexObj.Execute(strInput) substr = inputMatches(0).Value regex = Left(strInput, inputMatches(0).FirstIndex) & Replace(substr, strWhat, strWith) _ & Right(strInput, (Len(strInput) - inputMatches(0).FirstIndex - inputMatches(0).Length)) strInput = regex Next End If
End Function
Но, работает и заявленную задачу выполняет. Буду признателен, если кто пожелает упростить (поправить), или дать конструктивное замечание.
Прилагаю простенький файл. Повторюсь, что шаблоны (собственно и задачи) могут быть любыми с использованием метасимволов RegExp. Спасибо
Уважаемый Jungl. Речь изначально идет о функции. Что касается моей маски в примере (три цыфры, пробел и три цыфры), то если двигать ее по строке, найдем только одно вхождение, и уже в этом вхождении найдем только 1 пробел. Видимо я ошибаюсь в символике шаблонов, но это не принципиально, здесь все "нарастет". Нужна функция с аргументами, которую, как UDF, я мог бы использовать в любом проекте EXCEL. При этом для каждого случая подставлять нужные мне значения (исходная строка, шаблон поиска, подстрока поиска, подстрока замены). Ну и речь также идет не об одном символе, а о подстроке. Для разового вычисления Вы (вероятно) правы. Но зачем мне каждый раз менять аргументы в процедуре, не удобнее ли это делать при вводе формулы в ячейку? К тому же каждый раз сохранять файл перед процессом, ведь макрос не обеспечивает отката. С функцией проще. Постановка "из чего что?" здесь бесполезна. Сегодня я захочу менять пробелы на тире, а завтра наоборот, или Марина на Таня, причем по всему столбцу таблицы. И Ctrl-H здесь тоже не поможет.
Уважаемый sv2013. Спасибо за отклик. Я плохо объяснил. Мне казалось пример здесь не нужен, потому что планируется универсальная функция. Особенности: четыре аргумента 1 - сама строка любых символов, с которой работаем 2 - значение маски Pattern 3 - значение фрагмента вхождения в найденных подстроках 4 - значение их замен То есть имеем 2 уровня, первый - определение вхождений паттерна, а второй - замена в найденных вхождениях, но не фиксированным значением, а заданной парой What и With. Для примера строка
то есть любая строка (даже с мнимыми символами) для нее задаю аргументом строковое значение Pattern (любой, какой мне нужен, например "\d\d\d\s\d\d\d") для второго уровня задаю аргументом значение, что менять (например пробел " ") и значение, чем менять (например "-") В таком случае будет результат
912-914 20 35, Марина marina@therm.com, (495) 300-76 Картина Репина Новости
Уважаемый Jungl. Я так понял, что Вы предлагаете вариант Сначала заменить вхождения чем-то фиксированным, а потом уже проводить замену What With. Это не то. В любом случае спасибо за отклик.
Я пытался решить, пока не решил, думаю копать перебором вхождений Matches.
Здравствуйте! По найденному на Вашем сайте нижеприведенному программному коду вопросов нет. Прошу Вас помочь внедрить в эту функцию строковые переменные (аргументы) ReplaceWhat и ReplaceWith вместо традиционного фиксированного значения .Replace, с тем чтобы функция возвращала исходную строку, в которой в найденных вхождениях заменяется уже конкретно заданное "внутреннее" вхождение (если таковое найдено) заданным значением. Например фрагменты по маске "\s\d\d\s\d\d\d", в них заменить "7 5" (если найдены по фильтру ReplaceWhat) на "5 7" (значение ReplaceWith) Прошу ограничиться VBScript Regular Expressions, если это возможно вообще. Пытаюсь использовать Replace(String, What, Whith) но опыта нет в синтаксисе. С уважением и Спасибо
Код
'Поиск по регулярному выражению и замена.
Public Function RegExpFindReplace(str As String, _
Pattern As String, _
Replace As String, _
Optional Globa1 As Boolean = True, _
Optional IgnoreCase As Boolean = False, _
Optional Multiline As Boolean = False) _
As String
RegExpFindReplace = str 'Пока ничего не меняли
If Not str Like "" And Not Pattern Like "" Then
Dim RegExp As Object 'Для регулярного выражения
Set RegExp = CreateObject("VBScript.RegExp")
With RegExp
.Global = Globa1 'Все совпадения или только первое?
.IgnoreCase = IgnoreCase 'Регистр неважен?
.Multiline = Multiline 'Игнорировать переносы строк?
.Pattern = Pattern 'Регулярка
End With
'Найти/заменить
On Error Resume Next
RegExpFindReplace = RegExp.Replace(str, Replace)
Set RegExp = Nothing 'Очистка памяти
End If
End Function
Здравствуйте. У меня была такая проблема, долго не решалась без отключения Personal.XLSB. Я ее решил для себя, по крайней мере она ушла после следующих настроек.
РАЗРАБОТЧИК - Visual Basic - View - Project Explorer Правым кликом на VBAProject (Personal.XLSB)
Уважаемый Skif-f! Судя по желанному результату Вы правильно все поняли. Я не профи, По любому, мой код - чайниковский. не узрел возможности спрятать справочник в массив и обойтись без Vlookup. Результат верный, но я ограничиваюсь обработкой только текущей записи основного листа. У меня такая технология, некоторые записи по ходу приходится обрабатывать, некоторые удалять. Практика покажет, может быть удобнее сначала обработать весь базовый лист, как у вас. Спасибо большое, Вы мне очень помогли. Буду мудрить дальше. Вторая часть задачи (например в результате убрать для записи аккумуляторы с промежуточной ценой) не настолько важна, постараюсь решить самостоятельно. RAVILOGO.
Всем ЗДРАВСТВУЙТЕ. Помогите дилетанту. Что сумел наваять прилагаю, файл тоже. Есть Лист1, в нем: Наименование объекта, Тип объекта, Линки (в ячейке через разделители) на значения ЗИП в таблице справочного листа PARTS. PARTS сейчас около 1000 строк. Число Значений в ячейке линков не более 100. Формат всех ячеек ОБЩИЙ. Длина PARTS не фиксированная, обновляется. Значения в ячейках Линков отсортированы по числовой последовательности. Соответствующие ячейки PARTS также. Задача: Под каждым объектом вставить строки со значениями ЗИП из PARTS. Лист1 около 3000 строк. Можно и без массива, как эффективнее не знаю. Часть с перебором в цикле работает, а выемку из справочника оформить НЕ МОГУ. Делал макрос с вставкой строк, и затем использовал ВПР. СПАСИБО. Второй вопрос, уж и неудобно грузить. Встречаются множественные ЗИП для одного объекта, но с разной ценой, как бы из них оставить только минимум и мксимум. Хотя часть по VLOOKUP из третьего столбца PARTS я еще не мудрил. КОД:
Sub InserParts()
' Сочетание клавиш: Ctrl+Shift+P ' Формат данных - ОБЩИЙ
Dim x As String Dim MyArray() As String
ActiveCell.Offset(0, 0).Range("A1").Select ' актуализация ячейки. Стоим на ячейке ' применяемости в листе Лист1
x = Selection.Value ' Присвоение. В строке находятся числа с разрядностью ' от 1 до 4 в текстовом десятичном представлении, причем отсортированные ' в числовом порядке, например "12 15 59 111 206". Это первый столбец листа PARTS. ' Повторов нет
For i& = LBound(MyArray) To UBound(MyArray) - 1 ActiveCell.Offset(1, 0).Range("A1").Select ' Переход на ячейку вниз ActiveCell.EntireRow.Insert ' вставки пустой строки со сдвижкой вниз ActiveCell.Offset(0, 1).Range("A1").Select ' актуализация ячейки 'With Range("H2:H2000") 'В справочнике не более 2000 строк '.FormulaR1C1 = "=VLOOKUP(Лист1!RC[-1],PARTS!R[-235]C[-5]:R[761]C[-4],2)" '.Value = .Value 'End With Selection.Value = MyArray(i) ' эта директива только для проверки цикла, ее удалить ' Selection.Value = Application.VLookup([MyArray(i)], PARTS!A2:B2000, 2) ' ВОТ 'ЗДЕСЬ У МЕНЯ ЗАТЫК, с ним бы разобраться ActiveCell.Offset(1, -1).Range("A1").Select Next i
End Sub
Изменено: RAVILOGO - 16.10.2015 14:33:38(Ввод программного кода.)